| @@ -574,6 +574,7 @@ open class ProductProcessService( | |||
| jobOrderCode = jobOrder?.code?:"", | |||
| jobOrderStatus = jobOrder?.status?.value?:"", | |||
| jobType = jobType?.name?:"", | |||
| bomDescription = bom?.description?:"", | |||
| itemId = bom?.item?.id?:0, | |||
| itemCode = bom?.item?.code?:"", | |||
| itemName = bom?.item?.name?:"", | |||
| @@ -650,8 +651,8 @@ open class ProductProcessService( | |||
| // 使用 bom_material.uom_name 而不是关联的 uom 对象 | |||
| val uom = uomConversionRepository.findByCodeAndDeletedFalse(bomMaterial?.uomName?:"") | |||
| val uomName = uom?.udfShortDesc | |||
| val shortUom = uom?.udfShortDesc | |||
| val uomName = uom?.udfudesc | |||
| val shortUom = uom?.udfudesc | |||
| // 然后遍历 bomProcessIds 找到第一个匹配的 BomProcessMaterial | |||
| val bomProcessMaterial = bomMaterial?.id?.let { bomMaterialId -> | |||
| bomProcessIds.firstNotNullOfOrNull { bomProcessId -> | |||
| @@ -684,7 +685,7 @@ open class ProductProcessService( | |||
| } | |||
| } | |||
| open fun createProductProcessByJobOrderId(jobOrderId: Long): MessageResponse { | |||
| open fun createProductProcessByJobOrderId(jobOrderId: Long, productionPriority: Int?=50): MessageResponse { | |||
| val jobOrder = jobOrderRepository.findById(jobOrderId).orElse(null) | |||
| val bom = bomRepository.findById(jobOrder?.bom?.id ?: 0L).orElse(null) | |||
| // val bom = jobOrder.bom.let { bomRepository.findById(it).orElse(null) } | |||
| @@ -701,7 +702,7 @@ open class ProductProcessService( | |||
| this.status = ProductProcessStatus.PENDING | |||
| this.date = jobOrder?.planEnd?.toLocalDate() | |||
| this.bom = bom | |||
| this.productionPriority = 50 | |||
| this.productionPriority = productionPriority | |||
| } | |||
| productProcessRepository.save(productProcess) | |||
| @@ -919,7 +920,14 @@ open class ProductProcessService( | |||
| } | |||
| open fun getJobOrderProcessLineDetail(productProcessLineId: Long): JobOrderProcessLineDetailResponse { | |||
| val productProcessLine = productProcessLineRepository.findById(productProcessLineId).orElse(null) | |||
| val bomProcess = bomProcessRepository.findById(productProcessLine?.bomProcess?.id?:0L).orElse(null) | |||
| val bomProcessId = productProcessLine?.bomProcess?.id | |||
| println("bomProcessId ${bomProcessId}") | |||
| val bomProcess: BomProcess? = bomProcessId?.let { | |||
| bomProcessRepository.findAll().firstOrNull { it.id == bomProcessId } | |||
| } | |||
| println("bomProcess ${bomProcess?.id}") | |||
| println("bomProcess durationInMinute ${bomProcess?.durationInMinute}") | |||
| val productProcessIssue = productionProcessIssueRepository.findByProductProcessLineId(productProcessLineId).filter{it.status == "Paused"}.firstOrNull() | |||
| // ✅ 计算所有已恢复的暂停记录的总暂停时间(毫秒) | |||
| @@ -939,7 +947,7 @@ open class ProductProcessService( | |||
| operatorId = productProcessLine.operator?.id?:0, | |||
| operatorName = productProcessLine.operator?.name?:"", | |||
| handlerId = productProcessLine.handler?.id?:0, | |||
| durationInMinutes = bomProcess?.durationInMinute?:0, | |||
| durationInMinutes = bomProcess?.durationInMinute, | |||
| productProcessIssueId = productProcessIssue?.id?:0, | |||
| productProcessIssueStatus = productProcessIssue?.status?:"", | |||
| @@ -974,6 +982,7 @@ open class ProductProcessService( | |||
| byproductUom = productProcessLine.byproductUom?:"" | |||
| ) | |||
| } | |||
| open fun updateProductProcessLineStatus(productProcessLineId: Long, status: String): MessageResponse { | |||
| println("📋 Service: Updating ProductProcessLine Status: $productProcessLineId") | |||
| val productProcessLine = productProcessLineRepository.findById(productProcessLineId).orElse(null) | |||
| @@ -994,15 +1003,53 @@ open class ProductProcessService( | |||
| errorPosition = null, | |||
| ) | |||
| } | |||
| open fun passProductProcessLine(productProcessLineId: Long): MessageResponse { | |||
| val productProcessLine = productProcessLineRepository.findById(productProcessLineId).orElse(null) | |||
| val productProcess = productProcessRepository.findById(productProcessLine?.productProcess?.id?:0L).orElse(null) | |||
| // 如果 startTime 为空,才设置它(保留已存在的 startTime) | |||
| println("📋 Service: ProductProcessLine StartTime: ${productProcessLine.startTime}") | |||
| println("📋 Service: ProductProcess StartTime: ${productProcess.startTime}") | |||
| if (productProcessLine.startTime == null) { | |||
| productProcessLine.startTime = LocalDateTime.now() | |||
| productProcessLineRepository.save(productProcessLine) | |||
| } | |||
| if (productProcess.startTime == null) { | |||
| productProcess.startTime = LocalDateTime.now() | |||
| productProcessRepository.save(productProcess) | |||
| } | |||
| // 总是设置 endTime(因为 Pass 意味着完成) | |||
| productProcessLine.endTime = LocalDateTime.now() | |||
| productProcessLineRepository.save(productProcessLine) | |||
| println("📋 Service: ProductProcessLine EndTime: ${productProcessLine.endTime}") | |||
| // 更新状态为 "Pass" | |||
| updateProductProcessLineStatus(productProcessLineId, "Pass") | |||
| // 检查是否所有 lines 都完成(Completed 或 Pass) | |||
| // 注意:这里应该传入 productProcessId,而不是 productProcessLineId | |||
| val productProcessId = productProcessLine?.productProcess?.id ?: 0L | |||
| ifAllLinesCompletedOrPassed(productProcessId) | |||
| return MessageResponse( | |||
| id = productProcessLineId, | |||
| code = "200", | |||
| name = "ProductProcessLine Passed", | |||
| type = "success", | |||
| message = "ProductProcessLine Passed", | |||
| errorPosition = null, | |||
| ) | |||
| } | |||
| open fun CompleteProductProcessStatusIfAllLinesCompleted(productProcessId: Long): MessageResponse { | |||
| val productProcess = productProcessRepository.findById(productProcessId).orElse(null) | |||
| println("📋 Service: ProductProcess: $productProcess") | |||
| val productProcessLines = productProcessLineRepository.findByProductProcess_Id(productProcessId) | |||
| println("📋 Service: ProductProcessLines: $productProcessLines") | |||
| if(productProcessLines.all { it.status == "Completed" }) { | |||
| if(productProcessLines.all { it.status == "Completed" || it.status == "Pass" }) { | |||
| productProcess.status = ProductProcessStatus.COMPLETED | |||
| if (productProcess.endTime == null) { | |||
| productProcess.endTime = LocalDateTime.now() | |||
| } | |||
| productProcessRepository.save(productProcess) | |||
| println("📋 Service: ProductProcess Status Updated: ${productProcess.status}") | |||
| } | |||
| @@ -1115,7 +1162,9 @@ open class ProductProcessService( | |||
| val itemUom = itemUomRepository.findByItemIdAndStockUnitIsTrueAndDeletedIsFalse(productProcesses.item?.id?:0L) | |||
| val bomUom = uomConversionRepository.findById(itemUom?.uom?.id?:0L).orElse(null) | |||
| //val silHandlerId = stockInLine?.escalationLog?.firstOrNull { it.status == "pending" }?.handler?.id | |||
| val timeNeedToComplete = bomProcessRepository.findByBomId(productProcesses.bom?.id ?: 0L) | |||
| .filter { !it.deleted } | |||
| .sumOf { it.durationInMinute ?: 0 } | |||
| AllJoborderProductProcessInfoResponse( | |||
| id = productProcesses.id ?: 0L, | |||
| productProcessCode = productProcesses.productProcessCode, | |||
| @@ -1131,9 +1180,11 @@ open class ProductProcessService( | |||
| "pending" | |||
| }, | |||
| RequiredQty = jobOrder?.reqQty?.toInt() ?: 0, | |||
| Uom = bomUom?.udfShortDesc, | |||
| Uom = bomUom?.udfudesc, | |||
| productionPriority = productProcesses.productionPriority, | |||
| date = productProcesses.date, | |||
| bomId = productProcesses.bom?.id, | |||
| TimeNeedToComplete = timeNeedToComplete, | |||
| assignedTo = pickOrder?.assignTo?.id, | |||
| itemName = productProcesses.item?.name, | |||
| itemCode = productProcesses.item?.code, | |||
| @@ -1270,7 +1321,7 @@ open class ProductProcessService( | |||
| val productProcess = productProcessRepository.findById(productProcessId).orElse(null) | |||
| val jobOrder = jobOrderRepository.findById(productProcess?.jobOrder?.id?:0L).orElse(null) | |||
| if(jobOrder != null) { | |||
| jobOrder.status = JobOrderStatus.STORING | |||
| jobOrder.status = JobOrderStatus.PENDING_QC | |||
| jobOrderRepository.save(jobOrder) | |||
| stockInLineService.create( | |||
| SaveStockInLineRequest( | |||
| @@ -1295,6 +1346,47 @@ open class ProductProcessService( | |||
| errorPosition = null, | |||
| ) | |||
| } | |||
| open fun ifAllLinesCompletedOrPassed(productProcessId: Long): MessageResponse { | |||
| // 获取所有 product process lines | |||
| val allproductProcessLines = productProcessLineRepository.findByProductProcess_Id(productProcessId) | |||
| // 检查是否所有 lines 都是 "Completed" 或 "Pass" | |||
| if(allproductProcessLines.all { it.status == "Completed" || it.status == "Pass" }) { | |||
| // 更新 product process 的 endTime 和状态 | |||
| updateProductProcessEndTime(productProcessId) | |||
| updateProductProcessStatus(productProcessId, ProductProcessStatus.COMPLETED) | |||
| val productProcess = productProcessRepository.findById(productProcessId).orElse(null) | |||
| val jobOrder = jobOrderRepository.findById(productProcess?.jobOrder?.id ?: 0L).orElse(null) | |||
| if(jobOrder != null) { | |||
| jobOrder.status = JobOrderStatus.STORING | |||
| jobOrderRepository.save(jobOrder) | |||
| stockInLineService.create( | |||
| SaveStockInLineRequest( | |||
| itemId = productProcess?.item?.id ?: 0L, | |||
| acceptedQty = jobOrder?.reqQty ?: BigDecimal.ZERO, | |||
| productLotNo = jobOrder?.code, | |||
| productionDate = LocalDate.now(), | |||
| jobOrderId = jobOrder.id, | |||
| acceptQty = jobOrder?.reqQty ?: BigDecimal.ZERO, | |||
| expiryDate = null, | |||
| status = "", | |||
| ) | |||
| ) | |||
| } | |||
| } | |||
| return MessageResponse( | |||
| id = productProcessId, | |||
| code = "200", | |||
| name = "ProductProcess Check Completed", | |||
| type = "success", | |||
| message = "ProductProcess Check Completed", | |||
| errorPosition = null, | |||
| ) | |||
| } | |||
| open fun SaveProductProcessIssueTime(request: SaveProductProcessIssueTimeRequest): MessageResponse { | |||
| println("📋 Service: Saving ProductProcess Issue Time: ${request.productProcessLineId}") | |||