From a2a01c2f02d8899c8d78f7276b4af96527a8b9a6 Mon Sep 17 00:00:00 2001 From: "CANCERYS\\kw093" Date: Tue, 30 Dec 2025 14:02:50 +0800 Subject: [PATCH] open new column, product porcess and created job order --- .../entity/projections/JobOrderInfo.kt | 4 +- .../modules/jobOrder/enums/JobOrderEnum.kt | 3 +- .../jobOrder/service/JoPickOrderService.kt | 78 +++++++++++++++++-- .../jobOrder/service/JobOrderService.kt | 65 ++++++++++++++-- .../jobOrder/web/JobOrderController.kt | 12 ++- .../web/model/CreateJobOrderRequest.kt | 21 ++++- .../entity/projections/ProductProcessInfo.kt | 5 +- .../service/ProductProcessService.kt | 2 +- .../web/ProductProcessController.kt | 10 ++- .../web/model/SaveProductProcessRequest.kt | 4 +- .../20251224_01_Enson/01_alter_table.sql | 7 ++ .../20251224_01_Enson/02_alter_table.sql | 5 ++ .../20251230_01_Enson/01_alter_table.sql | 5 ++ 13 files changed, 196 insertions(+), 25 deletions(-) create mode 100644 src/main/resources/db/changelog/changes/20251224_01_Enson/01_alter_table.sql create mode 100644 src/main/resources/db/changelog/changes/20251224_01_Enson/02_alter_table.sql create mode 100644 src/main/resources/db/changelog/changes/20251230_01_Enson/01_alter_table.sql diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/projections/JobOrderInfo.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/projections/JobOrderInfo.kt index 7ec3c4e..784bfd5 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/projections/JobOrderInfo.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/projections/JobOrderInfo.kt @@ -35,7 +35,8 @@ interface JobOrderInfo { // @get:Value("#{target.bom.item.itemUoms.^[salesUnit == true && deleted == false]?.uom}") //// @get:Value("#{target.bom.item.itemUoms.^[salesUnit == true && deleted == false]?.uom.udfudesc}") // val uom: UomConversion; - + @get:Value("#{target.productProcess?.productionPriority}") + val productionPriority: Int?; @get:Value("#{target.status.value}") val status: String; @@ -62,6 +63,7 @@ data class JobOrderInfoWithTypeName( val insufficientCount: Int?, val silHandlerId: Long?, val planStart: LocalDateTime?, + val productionPriority: Int?, val status: String, val jobTypeId: Long?, val jobTypeName: String? diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/enums/JobOrderEnum.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/enums/JobOrderEnum.kt index e90c8af..307e4c7 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/enums/JobOrderEnum.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/enums/JobOrderEnum.kt @@ -3,8 +3,9 @@ package com.ffii.fpsms.modules.jobOrder.enums enum class JobOrderStatus(val value: String) { PLANNING("planning"), PENDING("pending"), - PROCESSING("processing"), PACKAGING("packaging"), + PROCESSING("processing"), + PENDING_QC("pendingQC"), STORING("storing"), COMPLETED("completed") } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt index 79da10d..c045326 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JoPickOrderService.kt @@ -2050,34 +2050,96 @@ open fun getJobOrderLotsHierarchicalByPickOrderId(pickOrderId: Long): JobOrderLo } } -open fun updateHandledByForItem(pickOrderId: Long, itemId: Long, userId: Long): JoPickOrder? { +open fun updateHandledByForItem(pickOrderId: Long, itemId: Long, userId: Long): MessageResponse { val joPickOrderOpt = joPickOrderRepository.findByPickOrderIdAndItemId(pickOrderId, itemId) if (joPickOrderOpt.isEmpty) { println("⚠️ JoPickOrder not found for pickOrderId: $pickOrderId, itemId: $itemId") - return null + return MessageResponse( + id = 0, + code = "404", + name = "Not Found", + type = "error", + message = "JoPickOrder not found", + errorPosition = "operator" + ) } - + val joPickOrder = joPickOrderOpt.get() + if (userId != null && joPickOrder.handledBy != null) { + val existingOperatorId = joPickOrder.handledBy + val newOperatorId = userId + + // 如果不是同一个用户,拒绝更新 + if (existingOperatorId != null && existingOperatorId != newOperatorId) { + return MessageResponse( + id = joPickOrder.id, + code = "409", + name = "Conflict", + type = "error", + message = "This pick order is already assigned to another user", + errorPosition = "operator" + ) + } + } joPickOrder.handledBy = userId + joPickOrderRepository.save(joPickOrder) // Don't update other fields - only handledBy - return joPickOrderRepository.save(joPickOrder) + return MessageResponse( + id = joPickOrder.id, + code = null, + name = null, + type = null, + message = "Pick order handled by updated", + errorPosition = null + ) } -open fun updateRecordHandledByForItem(pickOrderId: Long, itemId: Long, userId: Long): JoPickOrderRecord? { +open fun updateRecordHandledByForItem(pickOrderId: Long, itemId: Long, userId: Long): MessageResponse { val joPickOrderRecordOpt = joPickOrderRecordRepository.findByPickOrderIdAndItemId(pickOrderId, itemId) if (joPickOrderRecordOpt.isEmpty) { println("⚠️ JoPickOrderRecord not found for pickOrderId: $pickOrderId, itemId: $itemId") - return null + return MessageResponse( + id = 0, + code = "404", + name = "Not Found", + type = "error", + message = "JoPickOrderRecord not found", + errorPosition = "operator" + ) } - + val joPickOrderRecord = joPickOrderRecordOpt.get() + if (userId != null && joPickOrderRecord.handledBy != null) { + val existingOperatorId = joPickOrderRecord.handledBy + val newOperatorId = userId + + // 如果不是同一个用户,拒绝更新 + if (existingOperatorId != null && existingOperatorId != newOperatorId) { + return MessageResponse( + id = joPickOrderRecord.id, + code = "409", + name = "Conflict", + type = "error", + message = "This pick order is already assigned to another user", + errorPosition = "operator" + ) + } + } joPickOrderRecord.handledBy = userId + joPickOrderRecordRepository.save(joPickOrderRecord) // Don't update other fields - only handledBy - return joPickOrderRecordRepository.save(joPickOrderRecord) + return MessageResponse( + id = joPickOrderRecord.id, + code = null, + name = null, + type = null, + message = "Pick order record handled by updated", + errorPosition = null + ) } @Transactional(rollbackFor = [Exception::class]) open fun deleteJoPickOrderJobOrderProductProcessPickOrder(jobOrderId: Long): MessageResponse { diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt index 6ed4024..3ed0e53 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/service/JobOrderService.kt @@ -27,8 +27,7 @@ import org.springframework.data.domain.PageRequest import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.math.BigDecimal -import java.time.LocalDate -import java.time.LocalDateTime + import java.time.format.DateTimeFormatter import kotlin.jvm.optionals.getOrNull import com.ffii.fpsms.modules.jobOrder.entity.JobTypeRepository @@ -62,8 +61,10 @@ import com.ffii.fpsms.modules.stock.service.QrContent import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import kotlin.math.exp +import com.ffii.fpsms.modules.productProcess.entity.ProductProcessRepository - +import java.time.LocalDate +import java.time.LocalDateTime @Service open class JobOrderService( val jobOrderRepository: JobOrderRepository, @@ -81,7 +82,8 @@ open class JobOrderService( private val printerService: PrinterService, val jobTypeRepository: JobTypeRepository, val inventoryRepository: InventoryRepository, - val stockInLineRepository: StockInLineRepository + val stockInLineRepository: StockInLineRepository, + val productProcessRepository: ProductProcessRepository ) { open fun allJobOrdersByPage(request: SearchJobOrderInfoRequest): RecordsRes { @@ -176,6 +178,7 @@ open class JobOrderService( insufficientCount = insufficientCount, silHandlerId = info.silHandlerId, planStart = info.planStart, + productionPriority = info.productionPriority, status = info.status, jobTypeId = info.jobTypeId, jobTypeName = info.jobTypeId?.let { jobTypes[it]?.name } @@ -192,7 +195,7 @@ open class JobOrderService( val notCompletedPutaway = info.stockInLineStatus != "completed" jobTypeNameMatch && notCompletedPutaway - } + }.sortedByDescending { it.productionPriority } // 修复:使用 response.totalElements,这是过滤后的总数 val total = response.totalElements @@ -749,5 +752,55 @@ open class JobOrderService( open fun getAllJobTypes(): List { return jobTypeRepository.findAll().map { JobTypeResponse(it.id, it.name) } } - + open fun updateJoPlanStart(request: UpdateJoPlanStartRequest): MessageResponse { + val jo = request.id.let { jobOrderRepository.findById(it).getOrNull() } ?: throw NoSuchElementException() + + // 将 String 转换为 LocalDateTime + val planStartDateTime = if (request.planStart.isNotBlank()) { + try { + // 支持 ISO 格式: "YYYY-MM-DDTHH:mm:ss" 或 "YYYY-MM-DD" + if (request.planStart.contains("T")) { + LocalDateTime.parse(request.planStart) + } else { + // 如果只有日期,设置为当天的 00:00:00 + LocalDate.parse(request.planStart).atStartOfDay() + } + } catch (e: Exception) { + throw BadRequestException("Invalid date format: ${request.planStart}") + } + } else { + null + } + + jo.apply { + planStart = planStartDateTime + } + jobOrderRepository.save(jo) + val planStartDate = planStartDateTime?.toLocalDate() + val productProcesses = productProcessRepository.findByJobOrder_Id(jo.id) + productProcesses.forEach { productProcess -> + productProcess.apply { + date = planStartDate + } + productProcessRepository.save(productProcess) + } + return MessageResponse( + id = jo.id, + code = jo.code, + name = jo.bom?.name, + type = null, + message = null, + errorPosition = null, + entity = mapOf("status" to jo.status?.value) + ) + } + /* + open fun checkJobOrderCreated(request: CheckJobOrderCreatedRequest): CheckJobOrderCreatedResponse { + val jobOrders = jobOrderRepository.findByBomIdAndDate(request.bomId, request.date) + return CheckJobOrderCreatedResponse( + isCreated = jobOrders.isNotEmpty(), + jobOrders = jobOrders.map { JobOrderBasicInfoResponse(it.id, it.code, it.bom?.name, it.reqQty) } + ) + } +*/ } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt index 8f29c24..264d05e 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/JobOrderController.kt @@ -99,7 +99,7 @@ class JobOrderController( } jobOrderBomMaterialService.createJobOrderBomMaterialsByJoId(jo.id) jobOrderProcessService.createJobOrderProcessesByJoId(jo.id) - productProcessService.createProductProcessByJobOrderId(jo.id) + productProcessService.createProductProcessByJobOrderId(jo.id, request.productionPriority) return jo } @GetMapping("/all-lots-hierarchical/{userId}") @@ -306,4 +306,14 @@ fun updateJoPickOrderHandledBy(@Valid @RequestBody request: UpdateJoPickOrderHan fun deleteJoPickOrderJobOrderProductProcessPickOrder(@PathVariable jobOrderId: Long): MessageResponse { return joPickOrderService.deleteJoPickOrderJobOrderProductProcessPickOrder(jobOrderId) } +@PostMapping("/update-jo-plan-start") +fun updateJoPlanStart(@Valid @RequestBody request: UpdateJoPlanStartRequest): MessageResponse { + return jobOrderService.updateJoPlanStart(request) +} + /* +@PostMapping("/checkJobOrderCreated") +fun checkJobOrderCreated(@Valid @RequestBody request: CheckJobOrderCreatedRequest): Boolean { + return jobOrderService.checkJobOrderCreated(request) +} + */ } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/CreateJobOrderRequest.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/CreateJobOrderRequest.kt index 8321250..5ba740e 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/CreateJobOrderRequest.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/web/model/CreateJobOrderRequest.kt @@ -3,7 +3,7 @@ package com.ffii.fpsms.modules.jobOrder.web.model import com.ffii.fpsms.modules.jobOrder.enums.JobOrderBomMaterialStatus import java.math.BigDecimal import java.time.LocalDateTime - +import java.time.LocalDate data class CreateJobOrderRequest ( val bomId: Long?, val planStart: LocalDateTime? = null, @@ -15,6 +15,7 @@ data class CreateJobOrderRequest ( val approverId: Long? = null, val prodScheduleLineId: Long? = null, val status: String = "planning", + val productionPriority: Int?=50, ) data class CreateJobOrderBomMaterialRequest ( @@ -130,4 +131,22 @@ data class JobOrderListForPrintQrCodeResponse( val stockInLineQty: Double, val stockInLineStatus: String, val finihedTime: LocalDateTime, +) +data class UpdateJoPlanStartRequest( + val id: Long, + val planStart: String, +) +data class CheckJobOrderCreatedRequest( + val bomId: Long, + val date: LocalDate, +) +data class CheckJobOrderCreatedResponse( + val isCreated: Boolean, + val jobOrders: List, +) +data class JobOrderInfoResponse( + val jobOrderId: Long, + val code: String, + val itemName: String, + val reqQty: BigDecimal, ) \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/productProcess/entity/projections/ProductProcessInfo.kt b/src/main/java/com/ffii/fpsms/modules/productProcess/entity/projections/ProductProcessInfo.kt index 565fc28..74b9fb1 100644 --- a/src/main/java/com/ffii/fpsms/modules/productProcess/entity/projections/ProductProcessInfo.kt +++ b/src/main/java/com/ffii/fpsms/modules/productProcess/entity/projections/ProductProcessInfo.kt @@ -10,9 +10,9 @@ data class ProductProcessInfo( val id: Long?, val productProcessCode: String?, val status: ProductProcessStatus?, - @JsonFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "MM-dd HH:mm") val startTime: LocalDateTime?, - @JsonFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "MM-dd HH:mm") val endTime: LocalDateTime?, @JsonFormat(pattern = "yyyy-MM-dd") val date: LocalDate?, @@ -23,6 +23,7 @@ data class ProductProcessInfo( val jobOrderCode: String?, val jobOrderStatus: String?, val jobType: String?, + val bomDescription: String?, val isDark: String?, val isDense: Int?, val isFloat: String?, diff --git a/src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt b/src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt index 48ece90..db504da 100644 --- a/src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt +++ b/src/main/java/com/ffii/fpsms/modules/productProcess/service/ProductProcessService.kt @@ -685,7 +685,7 @@ open class ProductProcessService( } } - open fun createProductProcessByJobOrderId(jobOrderId: Long): MessageResponse { + open fun createProductProcessByJobOrderId(jobOrderId: Long,productionPriority: Int?): 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) } diff --git a/src/main/java/com/ffii/fpsms/modules/productProcess/web/ProductProcessController.kt b/src/main/java/com/ffii/fpsms/modules/productProcess/web/ProductProcessController.kt index 395fced..eed6bbb 100644 --- a/src/main/java/com/ffii/fpsms/modules/productProcess/web/ProductProcessController.kt +++ b/src/main/java/com/ffii/fpsms/modules/productProcess/web/ProductProcessController.kt @@ -160,9 +160,9 @@ class ProductProcessController( fun demojoid(@PathVariable joid: Long): List { return productProcessService.productProcessDetailfindbyjoid(joid) } - @PostMapping("/demo/joid/{joid}") - fun democreate(@PathVariable joid: Long): MessageResponse { - return productProcessService.createProductProcessByJobOrderId(joid) + @PostMapping("/demo/joid/{joid}/{productionPriority}") + fun democreate(@PathVariable joid: Long, @PathVariable productionPriority: Int): MessageResponse { + return productProcessService.createProductProcessByJobOrderId(joid, productionPriority) } @PostMapping("/Demo/update") fun demoupdate(@RequestBody request: UpdateProductProcessLineOperatorIdOrEquipmentIdRequest): MessageResponse { @@ -213,4 +213,8 @@ class ProductProcessController( fun updateProductProcessPriority(@PathVariable productProcessId: Long, @PathVariable productionPriority: Int): MessageResponse { return productProcessService.UpdateProductProcessPriority(productProcessId, productionPriority) } + @PostMapping("/Demo/ProcessLine/pass/{lineId}") + fun passProductProcessLine(@PathVariable lineId: Long): MessageResponse { + return productProcessService.passProductProcessLine(lineId) + } } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/productProcess/web/model/SaveProductProcessRequest.kt b/src/main/java/com/ffii/fpsms/modules/productProcess/web/model/SaveProductProcessRequest.kt index f2fd4b0..ef8bf03 100644 --- a/src/main/java/com/ffii/fpsms/modules/productProcess/web/model/SaveProductProcessRequest.kt +++ b/src/main/java/com/ffii/fpsms/modules/productProcess/web/model/SaveProductProcessRequest.kt @@ -169,13 +169,15 @@ data class AllJoborderProductProcessInfoResponse( val RequiredQty: Int?, val Uom: String?, val jobOrderId: Long?, + val productionPriority: Int?, val jobOrderCode: String?, val assignedTo: Long?, val pickOrderId: Long?, val pickOrderStatus: String?, val productProcessLineCount: Int, val FinishedProductProcessLineCount: Int, - val stockInLineId: Long?, + val stockInLineId: Long?, + val TimeNeedToComplete: Int?, val lines: List ) data class ProductProcessInfoResponse( diff --git a/src/main/resources/db/changelog/changes/20251224_01_Enson/01_alter_table.sql b/src/main/resources/db/changelog/changes/20251224_01_Enson/01_alter_table.sql new file mode 100644 index 0000000..030b209 --- /dev/null +++ b/src/main/resources/db/changelog/changes/20251224_01_Enson/01_alter_table.sql @@ -0,0 +1,7 @@ +-- liquibase formatted sql +-- changeset Enson:add_column + +ALTER TABLE `fpsmsdb`.`bag_lot_line` +CHANGE COLUMN `firstUseDate` `firstUseDate` DATETIME NULL , +CHANGE COLUMN `lastUseDate` `lastUseDate` DATETIME NULL , +ADD COLUMN `stockOutLineId` BIGINT NULL AFTER `bagId`; \ No newline at end of file diff --git a/src/main/resources/db/changelog/changes/20251224_01_Enson/02_alter_table.sql b/src/main/resources/db/changelog/changes/20251224_01_Enson/02_alter_table.sql new file mode 100644 index 0000000..08b0d3b --- /dev/null +++ b/src/main/resources/db/changelog/changes/20251224_01_Enson/02_alter_table.sql @@ -0,0 +1,5 @@ +-- liquibase formatted sql +-- changeset Enson:add_column + +ALTER TABLE `fpsmsdb`.`jo_bag_consumption` +ADD COLUMN `stockOutLineId` BIGINT NULL AFTER `jobOrderCode`; \ No newline at end of file diff --git a/src/main/resources/db/changelog/changes/20251230_01_Enson/01_alter_table.sql b/src/main/resources/db/changelog/changes/20251230_01_Enson/01_alter_table.sql new file mode 100644 index 0000000..ac9f4f1 --- /dev/null +++ b/src/main/resources/db/changelog/changes/20251230_01_Enson/01_alter_table.sql @@ -0,0 +1,5 @@ +-- liquibase formatted sql +-- changeset Enson:add_column + +ALTER TABLE `fpsmsdb`.`productprocess` +ADD COLUMN `submitedBagRecord`TINYINT(1) NULL DEFAULT 0 AFTER `productionPriority`; \ No newline at end of file