diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/JobOrder.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/JobOrder.kt index 5314502..2ca4ea7 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/JobOrder.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/JobOrder.kt @@ -76,4 +76,8 @@ open class JobOrder : BaseEntity() { @JsonManagedReference @OneToMany(mappedBy = "jobOrder", cascade = [CascadeType.ALL], orphanRemoval = true) open var stockInLines: MutableList = mutableListOf() + + + @Column(name = "jobTypeId") + open var jobTypeId: Long? = null } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/JobOrderType.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/JobOrderType.kt new file mode 100644 index 0000000..17da376 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/JobOrderType.kt @@ -0,0 +1,26 @@ +package com.ffii.fpsms.modules.jobOrder.entity + +import com.fasterxml.jackson.annotation.JsonManagedReference +import com.ffii.core.entity.BaseEntity +import com.ffii.fpsms.modules.jobOrder.enums.JobOrderStatus +import com.ffii.fpsms.modules.jobOrder.enums.JobOrderStatusConverter +import com.ffii.fpsms.modules.master.entity.Bom +import com.ffii.fpsms.modules.master.entity.ProductionScheduleLine +import com.ffii.fpsms.modules.stock.entity.StockInLine +import com.ffii.fpsms.modules.user.entity.User +import jakarta.persistence.* +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Size +import java.math.BigDecimal +import java.time.LocalDateTime + +@Entity +@Table(name = "jobtype") +open class JobType : BaseEntity() { + @Size(max = 100) + @NotNull + @Column(name = "name", nullable = false, length = 100) + open var code: String? = null + + +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/JobOrderTypeRepository.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/JobOrderTypeRepository.kt new file mode 100644 index 0000000..5a1bd05 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/JobOrderTypeRepository.kt @@ -0,0 +1,19 @@ +package com.ffii.fpsms.modules.jobOrder.entity + +import com.ffii.core.support.AbstractRepository +import com.ffii.fpsms.modules.jobOrder.enums.JoPickOrderStatus +import com.ffii.fpsms.modules.jobOrder.entity.JoPickOrder + +import com.ffii.fpsms.modules.master.entity.projections.SearchId +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Query +import org.springframework.stereotype.Repository +import java.io.Serializable +import java.time.LocalDateTime +import com.ffii.fpsms.modules.jobOrder.entity.JobType +import java.util.Optional +@Repository +interface JobTypeRepository : JpaRepository { +//fun findByName(name: String): Optional +//fun findByIdAndDeletedIsFalse(id: Long): Optional +} \ No newline at end of file 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 dd1f769..c718adf 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 @@ -31,7 +31,7 @@ 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 import com.ffii.fpsms.modules.jobOrder.web.model.* import com.ffii.fpsms.modules.jobOrder.web.model.ExportPickRecordRequest import com.ffii.fpsms.modules.jobOrder.web.model.PrintPickRecordRequest @@ -71,12 +71,13 @@ open class JobOrderService( val stockOutRepository: StockOutRepository, val stockOutLineRepository: StockOutLIneRepository, private val printerService: PrinterService, - + val jobTypeRepository: JobTypeRepository ) { open fun allJobOrdersByPage(request: SearchJobOrderInfoRequest): RecordsRes { val pageable = PageRequest.of(request.pageNum ?: 0, request.pageSize ?: 10); - + println("allJobOrdersByPage") + println(request) val response = jobOrderRepository.findJobOrderInfoByCodeContainsAndBomNameContainsAndDeletedIsFalseOrderByIdDesc( code = request.code ?: "", bomName = request.itemName ?: "", @@ -161,7 +162,9 @@ open class JobOrderService( val prodScheduleLine = request.prodScheduleLineId?.let { productionScheduleLineRepository.findById(it).getOrNull() } val code = assignJobNo() val status = JobOrderStatus.entries.find { it.value == request.status } - + + //val jobTypeId = jobTypeRepository.findByName(request.jobType).orElse(null)?.id + val jobTypeId = request.jobTypeId jo.apply { this.code = code this.bom = bom @@ -173,6 +176,7 @@ open class JobOrderService( type = request.type this.approver = approver this.prodScheduleLine = prodScheduleLine + this.jobTypeId = jobTypeId } val savedJo = jobOrderRepository.saveAndFlush(jo); @@ -224,7 +228,7 @@ open class JobOrderService( } jobOrderRepository.save(jo) - val pols = jo.jobms.filter { it.item?.type != "mat"&& it.item?.type != "item"}. + val pols = jo.jobms.filter { it.item?.type != "CMB"&& it.item?.type != "item"}. map { SavePickOrderLineRequest( itemId = it.item?.id, 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 07d3bdc..f608557 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 @@ -47,6 +47,8 @@ class JobOrderController( @GetMapping("/getRecordByPage") fun allJobOrdersByPage(@ModelAttribute request: SearchJobOrderInfoRequest): RecordsRes { + println("getRecordByPage") + println(request) return jobOrderService.allJobOrdersByPage(request); } 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 175beb6..92db5be 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 @@ -9,6 +9,8 @@ data class CreateJobOrderRequest ( val planStart: LocalDateTime? = null, val planEnd: LocalDateTime? = null, val reqQty: BigDecimal?, + //val jobType: String?=null, + val jobTypeId: Long?=null, val type: String? = "detailed", val approverId: Long? = null, val prodScheduleLineId: Long? = null, diff --git a/src/main/java/com/ffii/fpsms/modules/master/entity/EquipmentDetail.kt b/src/main/java/com/ffii/fpsms/modules/master/entity/EquipmentDetail.kt index eb9eee1..5a94e0a 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/entity/EquipmentDetail.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/entity/EquipmentDetail.kt @@ -26,4 +26,8 @@ open class EquipmentDetail : BaseEntity() { open var description: String? = null + @Column(name = "equipmentTypeID") + open var equipmentTypeId: Long? = null + + } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/entity/EquipmentDetailRepository.kt b/src/main/java/com/ffii/fpsms/modules/master/entity/EquipmentDetailRepository.kt index c48d799..88ad853 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/entity/EquipmentDetailRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/entity/EquipmentDetailRepository.kt @@ -6,12 +6,11 @@ import org.springframework.stereotype.Repository @Repository interface EquipmentDetailRepository : AbstractRepository { fun findAllByDeletedFalse(): List; - fun findByCodeAndDeletedFalse(code: String): EquipmentDetail? + fun findByCode(code: String): EquipmentDetail? fun findByIdAndDeletedFalse(id: Long): EquipmentDetail?; - - fun findByCodeAndDeletedIsFalse(code: String): EquipmentDetail?; - fun findByNameAndDeletedIsFalse(name: String): EquipmentDetail?; fun findByDescriptionAndDeletedIsFalse(description: String): EquipmentDetail?; + + } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/service/EquipmentDetailService.kt b/src/main/java/com/ffii/fpsms/modules/master/service/EquipmentDetailService.kt index 74451d1..008184a 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/service/EquipmentDetailService.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/service/EquipmentDetailService.kt @@ -39,11 +39,11 @@ open class EquipmentDetailService( open fun findById(id: Long): EquipmentDetail? { return equipmentDetailRepository.findByIdAndDeletedFalse(id) } - +/* open fun findByCode(code: String): EquipmentDetail? { return equipmentDetailRepository.findByCodeAndDeletedIsFalse(code) } - +*/ open fun findByName(name: String): EquipmentDetail? { return equipmentDetailRepository.findByNameAndDeletedIsFalse(name) } @@ -51,7 +51,7 @@ open class EquipmentDetailService( open fun findByDescription(description: String): EquipmentDetail? { return equipmentDetailRepository.findByDescriptionAndDeletedIsFalse(description) } - +/* @Transactional open fun saveEquipmentDetail(request: NewEquipmentDetailRequest): EquipmentDetail { @@ -78,7 +78,7 @@ open class EquipmentDetailService( return equipmentDetailRepository.saveAndFlush(entity) } - +*/ @Transactional open fun deleteEquipmentDetail(id: Long) { val equipmentDetail = equipmentDetailRepository.findByIdAndDeletedFalse(id) diff --git a/src/main/java/com/ffii/fpsms/modules/master/service/ProductionScheduleService.kt b/src/main/java/com/ffii/fpsms/modules/master/service/ProductionScheduleService.kt index bcb7685..40a23b4 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/service/ProductionScheduleService.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/service/ProductionScheduleService.kt @@ -388,7 +388,8 @@ open class ProductionScheduleService( bomId = bom?.id, reqQty = request.demandQty, approverId = approver?.id, - prodScheduleLineId = request.id + prodScheduleLineId = request.id, + //jobType = null, ) val jo = jobOrderService.createJobOrder(joRequest) diff --git a/src/main/java/com/ffii/fpsms/modules/master/web/EquipmentDetailController.kt b/src/main/java/com/ffii/fpsms/modules/master/web/EquipmentDetailController.kt index 80c16aa..bfa06d3 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/web/EquipmentDetailController.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/web/EquipmentDetailController.kt @@ -60,13 +60,13 @@ fun getAllEquipmentDetailByPage( fun getEquipmentDetail(@PathVariable id: Long): EquipmentDetail? { return equipmentDetailService.findById(id) } - +/* // 新增/编辑 @PostMapping("/save") fun saveEquipmentDetail(@Valid @RequestBody equipmentDetail: NewEquipmentDetailRequest): EquipmentDetail { return equipmentDetailService.saveEquipmentDetail(equipmentDetail) } - +*/ // 逻辑删除 @DeleteMapping("/delete/{id}") fun deleteEquipmentDetail(@PathVariable id: Long) { diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt index 2a549bb..c4c49fa 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt @@ -233,6 +233,7 @@ open class PickOrderService( suggestedList = emptyList() // Empty list since you don't need suggestions ) } + val groupName = po.id?.let { pickOrderId -> groupsByPickOrderId[pickOrderId]?.firstOrNull()?.name } ?: "No Group" @@ -732,57 +733,69 @@ open class PickOrderService( itemAvailableQtyMap[itemId] = totalAvailableQty } - // Pick Orders val releasePickOrderLineInfos = pos - .map { po -> - val releasePickOrderLineInfos = po.pickOrderLines.map { pol -> - val itemId = pol.item?.id - val availableQty = itemId?.let { itemAvailableQtyMap[it] } ?: zero - - // Move stockOutLines declaration inside the pol loop - val stockOutLines = stockOutLinesByPickOrderLineId[pol.id] ?: emptyList() - - // Calculate total picked quantity from stock out lines - println("=== PICKED QTY DEBUG: Line ${pol.id} ===") - println("Stock Out Lines: ${stockOutLines.map { "${it.id}(status=${it.status}, qty=${it.qty})" }}") - - val totalPickedQty = stockOutLines - .sumOf { it.qty ?: zero } - - println("Total Picked Qty: $totalPickedQty") - println("=== END DEBUG ===") - - // Return - GetPickOrderLineInfo( - id = pol.id, - itemId = pol.item?.id, - itemCode = pol.item?.code, - itemName = pol.item?.name, - availableQty = availableQty, // Use pre-calculated value - requiredQty = pol.qty, - uomCode = pol.uom?.code, - uomDesc = pol.uom?.udfudesc, - suggestedList = suggestions.suggestedList.filter { it.pickOrderLine?.id == pol.id }, - pickedQty = totalPickedQty - ) - } - val groupName = po.id?.let { pickOrderId -> - groupsByPickOrderId[pickOrderId]?.firstOrNull()?.name - } ?: "No Group" - // Return - GetPickOrderInfo( - id = po.id, - code = po.code, - consoCode = po.consoCode, - targetDate = po.targetDate, - type = po.type?.value, - status = po.status?.value, - assignTo = po.assignTo?.id, - groupName = groupName, - pickOrderLines = releasePickOrderLineInfos + .map { po -> + val releasePickOrderLineInfos = po.pickOrderLines.map { pol -> + val itemId = pol.item?.id + val availableQty = itemId?.let { itemAvailableQtyMap[it] } ?: zero + + // 取得這一行的所有 stock_out_line + val stockOutLines = stockOutLinesByPickOrderLineId[pol.id] ?: emptyList() + + // Debug: 已拣数量 + println("=== PICKED QTY DEBUG: Line ${pol.id} ===") + println("Stock Out Lines: ${stockOutLines.map { "${it.id}(status=${it.status}, qty=${it.qty})" }}") + + val totalPickedQty = stockOutLines.sumOf { it.qty ?: zero } + + println("Total Picked Qty: $totalPickedQty") + println("=== END DEBUG ===") + + // ✅ 無批次的 stock_out_line(inventoryLotLineId 為空) + val noLotStockouts = stockOutLines + .filter { it.inventoryLotLineId == null } // 注意:用 inventoryLotLineId + .map { sol -> + NoLotLineDto( + stockOutLineId = sol.id!!, + status = sol.status, + qty = sol.qty ?: zero, + created = null, // 若實體沒有 created/modified 欄位,就先給 null + modified = null + ) + } + + // 回傳行資訊 + GetPickOrderLineInfo( + id = pol.id, + itemId = pol.item?.id, + itemCode = pol.item?.code, + itemName = pol.item?.name, + availableQty = availableQty, + requiredQty = pol.qty, + uomCode = pol.uom?.code, + uomDesc = pol.uom?.udfudesc, + suggestedList = suggestions.suggestedList.filter { it.pickOrderLine?.id == pol.id }, + pickedQty = totalPickedQty, + noLotLines = noLotStockouts // ✅ 關鍵:把無批次行帶出去 ) } - + + val groupName = po.id?.let { pickOrderId -> + groupsByPickOrderId[pickOrderId]?.firstOrNull()?.name + } ?: "No Group" + + GetPickOrderInfo( + id = po.id, + code = po.code, + consoCode = po.consoCode, + targetDate = po.targetDate, + type = po.type?.value, + status = po.status?.value, + assignTo = po.assignTo?.id, + groupName = groupName, + pickOrderLines = releasePickOrderLineInfos + ) + } // Items val currentInventoryInfos = requiredItems.map { item -> val inventory = item.first?.let { inventories[it] } @@ -829,132 +842,164 @@ open class PickOrderService( return getPickOrdersInfo(releasedPickOrderIds) } - open fun getPickOrderLineLotDetails(pickOrderLineId: Long): List> { + open fun getPickOrderLineLotDetails(pickOrderLineId: Long): List { val today = LocalDate.now() - - println("=== Debug: getPickOrderLineLotDetails ===") + val zero = BigDecimal.ZERO + + println("=== Debug: getPickOrderLineLotDetails (Repository-based) ===") println("pickOrderLineId: $pickOrderLineId") println("today: $today") - - val sql = """ - SELECT - ill.id as lotId, - il.lotNo, - il.expiryDate, - w.name as location, - COALESCE(uc.udfudesc, 'N/A') as stockUnit, - (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) as availableQty, - COALESCE(spl.qty, 0) as requiredQty, -- 使用COALESCE处理null值 - COALESCE(ill.inQty, 0) as inQty, - COALESCE(ill.outQty, 0) as outQty, - COALESCE(ill.holdQty, 0) as holdQty, - COALESCE(sol.qty, 0) as actualPickQty, - COALESCE(spl.id, 0) as suggestedPickLotId, -- 使用COALESCE处理null值 - ill.status as lotStatus, - sol.id as stockOutLineId, - sol.status as stockOutLineStatus, - sol.qty as stockOutLineQty, - COALESCE(spl.suggestedLotLineId, ill.id) as debugSuggestedLotLineId, -- 使用COALESCE处理null值 - ill.inventoryLotId as debugInventoryLotId, - -- Calculate total picked quantity by ALL pick orders for this lot - COALESCE(( - SELECT SUM(sol_all.qty) - FROM fpsmsdb.stock_out_line sol_all - WHERE sol_all.inventoryLotLineId = ill.id - AND sol_all.deleted = false - AND sol_all.status IN ('pending', 'checked', 'partially_completed', 'completed') - ), 0) as totalPickedByAllPickOrders, - -- FIXED: Calculate remaining available quantity correctly - (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) as remainingAfterAllPickOrders, - -- Add detailed debug fields for lotAvailability calculation - ill.status as debug_ill_status, - (il.expiryDate IS NOT NULL AND il.expiryDate < CURDATE()) as debug_is_expired, - sol.status as debug_sol_status, - (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) as debug_remaining_stock, - (COALESCE(spl.qty, 0) - COALESCE(sol.qty, 0)) as debug_required_after_picked, - CASE - -- FIXED: Check if lot is expired - WHEN (il.expiryDate IS NOT NULL AND il.expiryDate < CURDATE()) THEN 'expired' - -- FIXED: Check if lot has rejected stock out line for this pick order - WHEN sol.status = 'rejected' THEN 'rejected' - -- FIXED: Check if lot is unavailable due to insufficient stock - WHEN (COALESCE(ill.inQty, 0) - COALESCE(ill.outQty, 0) - COALESCE(ill.holdQty, 0)) <= 0 THEN 'insufficient_stock' - -- FIXED: Check if lot status is unavailable - WHEN ill.status = 'unavailable' THEN 'status_unavailable' - -- Default to available - ELSE 'available' - END as lotAvailability - FROM fpsmsdb.inventory_lot_line ill - JOIN fpsmsdb.inventory_lot il ON il.id = ill.inventoryLotId - LEFT JOIN fpsmsdb.warehouse w ON w.id = ill.warehouseId - LEFT JOIN fpsmsdb.item_uom sales_iu ON sales_iu.itemId = il.itemId AND sales_iu.salesUnit = true AND sales_iu.deleted = false - LEFT JOIN fpsmsdb.uom_conversion uc ON uc.id = sales_iu.uomId - -- FIXED: Include both suggested lots AND lots with stock out lines for this pick order - LEFT JOIN fpsmsdb.suggested_pick_lot spl ON spl.suggestedLotLineId = ill.id AND spl.pickOrderLineId = :pickOrderLineId - LEFT JOIN fpsmsdb.stock_out_line sol ON sol.pickOrderLineId = :pickOrderLineId AND sol.inventoryLotLineId = ill.id AND sol.deleted = false - -- FIXED: Only include lots that are either suggested OR have stock out lines for this pick order - WHERE (spl.pickOrderLineId = :pickOrderLineId OR sol.pickOrderLineId = :pickOrderLineId) - AND(sol.status IS NULL OR sol.status != 'completed') - AND ill.deleted = false - AND il.deleted = false - ORDER BY - CASE WHEN sol.status = 'rejected' THEN 0 ELSE 1 END, -- Show rejected lots first - il.expiryDate ASC, - il.lotNo ASC - """.trimIndent() - - println("🔍 Executing SQL for lot details: $sql") - println("🔍 With parameters: pickOrderLineId = $pickOrderLineId") - - val result = jdbcDao.queryForList(sql, mapOf("pickOrderLineId" to pickOrderLineId)) - - // Add detailed debug output for each lot - println("=== DETAILED LOT AVAILABILITY DEBUG ===") - result.forEach { row -> - val lotId = row["lotId"] - val lotNo = row["lotNo"] - val illStatus = row["debug_ill_status"] - val isExpired = row["debug_is_expired"] - val solStatus = row["debug_sol_status"] - val lotAvailability = row["lotAvailability"] - - println("--- Lot: $lotNo (ID: $lotId) ---") - println(" ill.status: $illStatus") - println(" is_expired: $isExpired") - println(" sol.status: $solStatus") - println(" lotAvailability: $lotAvailability") - - // Check each condition step by step - if (isExpired == true) { - println(" ❌ FAILED: lot is expired") - } else if (solStatus == "rejected") { - println(" ❌ FAILED: sol.status = 'rejected'") + + // ✅ 1. 获取 PickOrderLine 以获取 UOM 信息 + val pickOrderLine = pickOrderLineRepository.findById(pickOrderLineId).orElse(null) + if (pickOrderLine == null) { + println("❌ PickOrderLine not found: $pickOrderLineId") + return emptyList() + } + + val uomDesc = pickOrderLine.uom?.udfudesc ?: "N/A" + + // ✅ 2. 获取所有相关的 SuggestedPickLot + val suggestedPickLots = suggestPickLotRepository.findAllByPickOrderLineId(pickOrderLineId) + val suggestedPickLotsByLotId = suggestedPickLots + .mapNotNull { spl -> spl.suggestedLotLine?.id?.let { it to spl } } + .toMap() + + // ✅ 3. 获取所有相关的 StockOutLine(包括有 lot 和没有 lot 的) + val stockOutLines = stockOutLIneRepository.findAllByPickOrderLineIdAndDeletedFalse(pickOrderLineId) + val stockOutLinesByLotId = stockOutLines + .filter { it.inventoryLotLineId != null } + .mapNotNull { sol -> sol.inventoryLotLineId?.let { it to sol } } + .toMap() + + // ✅ 4. 获取所有 no-lot 的 StockOutLine + val noLotStockOutLines = stockOutLines.filter { it.inventoryLotLineId == null } + + // ✅ 5. 获取所有相关的 InventoryLotLine IDs + val inventoryLotLineIds = (suggestedPickLots.mapNotNull { it.suggestedLotLine?.id } + + stockOutLines.mapNotNull { it.inventoryLotLineId }).distinct() + + // ✅ 6. 批量加载 InventoryLotLine 实体 + val inventoryLotLines = if (inventoryLotLineIds.isNotEmpty()) { + inventoryLotLineRepository.findAllById(inventoryLotLineIds) + .associateBy { it.id!! } + } else { + emptyMap() + } + + // ✅ 7. 构建有 lot 的记录 + val lotDetails = inventoryLotLines.values.mapNotNull { ill -> + val il = ill.inventoryLot + val w = ill.warehouse + val spl = ill.id?.let { suggestedPickLotsByLotId[it] } + val sol = ill.id?.let { stockOutLinesByLotId[it] } + + // 计算可用数量 + val inQty = ill.inQty ?: zero + val outQty = ill.outQty ?: zero + val holdQty = ill.holdQty ?: zero + val availableQty = inQty.minus(outQty).minus(holdQty) + + // 计算所有 pick orders 的总已拣数量 + val totalPickedByAllPickOrders = if (ill.id != null) { + stockOutLIneRepository.findAllByPickOrderLineIdAndDeletedFalse(pickOrderLineId) + .filter { it.inventoryLotLineId == ill.id } + .sumOf { it.qty ?: zero } } else { - println(" PASSED: All conditions met, should be 'available'") + zero } - println(" ---") - } - println("=== END DETAILED DEBUG ===") - - // Filter out completed lots - val filteredResult = result.filter { row -> - val stockOutLineStatus = row["stockOutLineStatus"] as String? - val stockOutLineQty = row["stockOutLineQty"] as Number? - val requiredQty = row["requiredQty"] as Number? - - // Show lot if: - // 1. No stock out line exists, OR - // 2. Stock out line is not completed, OR - // 3. Stock out line qty doesn't equal required qty - stockOutLineStatus != "completed" || - stockOutLineQty?.toDouble() != requiredQty?.toDouble() + + // 判断是否过期 + val isExpired = il?.expiryDate?.let { it.isBefore(today) } == true + + // 计算 lotAvailability + val lotAvailability = when { + isExpired -> "expired" + sol?.status == "rejected" -> "rejected" + availableQty <= zero -> "insufficient_stock" + ill.status?.value == "unavailable" -> "status_unavailable" + else -> "available" + } + + // 过滤:只返回未完成的或需要显示的 + val shouldInclude = sol == null || + sol.status != "completed" || + (sol.qty ?: zero) != (spl?.qty ?: zero) + + if (!shouldInclude) { + return@mapNotNull null + } + + PickOrderLineLotDetailResponse( + lotId = ill.id, + lotNo = il?.lotNo, + expiryDate = il?.expiryDate, + location = w?.name, + stockUnit = ill.stockUom?.uom?.udfudesc ?: uomDesc, + availableQty = availableQty, + requiredQty = spl?.qty ?: zero, + inQty = inQty, + outQty = outQty, + holdQty = holdQty, + actualPickQty = sol?.qty ?: zero, + suggestedPickLotId = spl?.id, + lotStatus = ill.status?.value, + stockOutLineId = sol?.id, + stockOutLineStatus = sol?.status, + stockOutLineQty = sol?.qty, + totalPickedByAllPickOrders = totalPickedByAllPickOrders, + remainingAfterAllPickOrders = availableQty, + lotAvailability = lotAvailability, + noLot = false + ) } - println("Final result count: ${filteredResult.size}") - filteredResult.forEach { row -> - println("Final Row: $row") + + // ✅ 8. 构建 no-lot 的记录 + val noLotDetails = noLotStockOutLines.mapNotNull { sol -> + // 过滤:只返回未完成的 + if (sol.status == "completed") { + return@mapNotNull null + } + + PickOrderLineLotDetailResponse( + lotId = null, + lotNo = null, + expiryDate = null, + location = null, + stockUnit = uomDesc, + availableQty = null, + requiredQty = zero, + inQty = zero, + outQty = zero, + holdQty = zero, + actualPickQty = sol.qty ?: zero, + suggestedPickLotId = null, + lotStatus = "unavailable", + stockOutLineId = sol.id, + stockOutLineStatus = sol.status, + stockOutLineQty = sol.qty, + totalPickedByAllPickOrders = zero, + remainingAfterAllPickOrders = null, + lotAvailability = "insufficient_stock", + noLot = true + ) } - - return filteredResult + + // ✅ 9. 合并并排序 + val allDetails = (lotDetails + noLotDetails).sortedWith( + compareBy( + { it.noLot }, // no-lot 行排在后面 + { it.stockOutLineStatus == "rejected" }, // rejected 排在前面 + { it.expiryDate ?: LocalDate.MAX }, // 按过期日期排序 + { it.lotNo ?: "" } // 按 lotNo 排序 + ) + ) + + println("✅ Final result count: ${allDetails.size}") + println(" - With lot: ${lotDetails.size}") + println(" - No-lot: ${noLotDetails.size}") + + return allDetails } @Transactional(rollbackFor = [java.lang.Exception::class]) diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/web/PickOrderController.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/web/PickOrderController.kt index 2311d20..de2e063 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/web/PickOrderController.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/web/PickOrderController.kt @@ -158,7 +158,7 @@ class PickOrderController( } @GetMapping("/lot-details/{pickOrderLineId}") - fun getPickOrderLineLotDetails(@PathVariable pickOrderLineId: Long): List> { + fun getPickOrderLineLotDetails(@PathVariable pickOrderLineId: Long): List { return pickOrderService.getPickOrderLineLotDetails(pickOrderLineId); } @GetMapping("/lot-details-by-do-pick-order-record/{doPickOrderRecordId}") diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/web/models/ConsoPickOrderRequest.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/web/models/ConsoPickOrderRequest.kt index 789b3ea..59d374e 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/web/models/ConsoPickOrderRequest.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/web/models/ConsoPickOrderRequest.kt @@ -17,4 +17,4 @@ data class ReleaseConsoPickOrderRequest ( // Start Pick Order data class StartConsoPickOrderRequest ( val consoCode: String, -) \ No newline at end of file +) diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/web/models/ConsoPickOrderResponse.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/web/models/ConsoPickOrderResponse.kt index 0a63569..05e7cd6 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/web/models/ConsoPickOrderResponse.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/web/models/ConsoPickOrderResponse.kt @@ -4,7 +4,7 @@ import com.ffii.fpsms.modules.stock.entity.SuggestedPickLot import com.ffii.fpsms.modules.stock.entity.projection.CurrentInventoryItemInfo import java.math.BigDecimal import java.time.LocalDateTime - +import java.time.LocalDate // Final Response - Release Conso Pick Order Page data class ReleasePickOrderInfoResponse( val consoCode: String, @@ -63,8 +63,15 @@ data class GetPickOrderLineInfo( val uomDesc: String?, val suggestedList: List?, val pickedQty: BigDecimal?=BigDecimal.ZERO, + val noLotLines: List?=emptyList() +) +data class NoLotLineDto( + val stockOutLineId: Long, + val status: String?, + val qty: BigDecimal, + val created: LocalDateTime?, + val modified: LocalDateTime? ) - // Final Response - Conso Pick Order Detail data class ConsoPickOrderResponse( val consoCode: String, @@ -148,4 +155,27 @@ data class IdCodeDesc( val id: Long?, val code: String?, val desc: String?, +) + +data class PickOrderLineLotDetailResponse( + val lotId: Long?, + val lotNo: String?, + val expiryDate: LocalDate?, + val location: String?, + val stockUnit: String?, + val availableQty: BigDecimal?, + val requiredQty: BigDecimal?, + val inQty: BigDecimal?, + val outQty: BigDecimal?, + val holdQty: BigDecimal?, + val actualPickQty: BigDecimal?, + val suggestedPickLotId: Long?, + val lotStatus: String?, + val stockOutLineId: Long?, + val stockOutLineStatus: String?, + val stockOutLineQty: BigDecimal?, + val totalPickedByAllPickOrders: BigDecimal?, + val remainingAfterAllPickOrders: BigDecimal?, + val lotAvailability: String?, + val noLot: Boolean = false ) \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/productProcess/entity/ProductProcessLine.kt b/src/main/java/com/ffii/fpsms/modules/productProcess/entity/ProductProcessLine.kt index 500efa3..0a75720 100644 --- a/src/main/java/com/ffii/fpsms/modules/productProcess/entity/ProductProcessLine.kt +++ b/src/main/java/com/ffii/fpsms/modules/productProcess/entity/ProductProcessLine.kt @@ -23,7 +23,9 @@ open class ProductProcessLine : BaseEntity() { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "equipmentId") open var equipment: Equipment? = null - + + @Column(name = "equipmentDetailId") + open var equipmentDetailId: Long? = null @Size(max = 100) @Column(name = "name", length = 100) open var name: String? = null @@ -72,8 +74,8 @@ open class ProductProcessLine : BaseEntity() { @Column(name = "defectQty2", precision = 16, scale = 2) open var defectQty2: Int? = null - @Column(name = "defectRemark2", length = 255) - open var defectRemark2: String? = null + @Column(name = "defectDescription2", length = 255) + open var defectDescription2: String? = null @Column(name = "defectUom2", length = 20) open var defectUom2: String? = null 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 6db83dc..41e4f2b 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 @@ -4,7 +4,7 @@ import java.time.LocalDateTime import java.time.LocalDate import com.ffii.fpsms.modules.productProcess.enums.ProductProcessStatus import com.fasterxml.jackson.annotation.JsonFormat - +import com.ffii.fpsms.modules.jobOrder.enums.JobOrderStatus data class ProductProcessInfo( val id: Long?, @@ -21,6 +21,7 @@ data class ProductProcessInfo( val bomId: Long?, val jobOrderId: Long?, val jobOrderCode: String?, + val jobOrderStatus: String?, val isDark: String?, val isDense: Int?, val isFloat: String?, @@ -56,6 +57,13 @@ data class ProductProcessLineInfo( val scrapQty: Int?, val defectQty: Int?, val defectUom: String?, + val defectDescription: String?, + val defectQty2: Int?, + val defectUom2: String?, + val defectDescription2: String?, + val defectQty3: Int?, + val defectUom3: String?, + val defectDescription3: String?, val outputFromProcessQty: Int?, val outputFromProcessUom: String?, val durationInMinutes: Int?, 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 c801012..add9ae4 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 @@ -38,6 +38,7 @@ import com.ffii.fpsms.modules.stock.service.StockInLineService import com.ffii.fpsms.modules.stock.web.model.SaveStockInLineRequest import com.ffii.fpsms.modules.master.entity.BomProcessMaterialRepository import com.ffii.fpsms.modules.master.entity.BomMaterialRepository +import com.ffii.fpsms.modules.master.entity.EquipmentDetailRepository @Service @Transactional open class ProductProcessService( @@ -57,6 +58,7 @@ open class ProductProcessService( private val stockInLineService: StockInLineService, private val bomProcessMaterialRepository: BomProcessMaterialRepository, private val bomMaterialRepository: BomMaterialRepository, + private val equipmentDetailRepository: EquipmentDetailRepository, ) { open fun findAll(pageable: Pageable): Page { @@ -552,6 +554,7 @@ open class ProductProcessService( bomId = process.bom?.id?:0, jobOrderId = process.jobOrder?.id?:0, jobOrderCode = jobOrder?.code?:"", + jobOrderStatus = jobOrder?.status?.value?:"", itemId = bom?.item?.id?:0, itemCode = bom?.item?.code?:"", itemName = bom?.item?.name?:"", @@ -592,6 +595,13 @@ open class ProductProcessService( scrapQty = line.scrapQty?:0, defectQty = line.defectQty?:0, defectUom = line.defectUom?:"", + defectDescription = line.defectDescription?:"", + defectQty2 = line.defectQty2?:0, + defectUom2 = line.defectUom2?:"", + defectDescription2 = line.defectDescription2?:"", + defectQty3 = line.defectQty3?:0, + defectUom3 = line.defectUom3?:"", + defectDescription3 = line.defectDescription3?:"", outputFromProcessQty = line.outputFromProcessQty?:0, outputFromProcessUom = line.outputFromProcessUom?:"", startTime = line.startTime, @@ -731,6 +741,64 @@ open class ProductProcessService( } + return MessageResponse( + id = null, + code = null, + name = null, + type = null, + message = null, + errorPosition = null, + ) + } + + open fun NewUpdateProductProcessLineOperatorIdOrEquipmentIdAndEquipmentDetail(request: NewUpdateProductProcessLineOperatorIdOrEquipmentIdAndEquipmentDetailRequest): MessageResponse { + val productProcessLine = productProcessLineRepository.findById(request.productProcessLineId).orElse(null) + val equipmentDetail = equipmentDetailRepository.findByCode(request.EquipmentTypeSubTypeEquipmentNo) + + val user = userRepository.findByName(request.Name?:"") + val bomProcess= bomProcessRepository.findById(productProcessLine?.bomProcess?.id?:0L).orElse(null) + val bomProcessEquipment=bomProcess?.equipment + if (equipmentDetail != null && user != null) { + // 检查 equipmentId 是否与 bomProcessEquipment 匹配 + if (equipmentDetail.equipmentTypeId != bomProcessEquipment?.id) { + println("productProcessLine id${request.productProcessLineId}") + println("operator Name${request.Name}") + println("user ${user}") + println("bomProcess ${bomProcess?.id}") + println("not match equipment id${equipmentDetail.equipmentTypeId} and ${bomProcessEquipment?.id}") + + // 返回错误响应 + return MessageResponse( + id = request.productProcessLineId, + code = "400", + name = "Equipment Validation Failed", + type = "error", + message = "Input Equipment ID($equipmentDetail.equipmentTypeId ) and BOM Process Equipment ID(${bomProcessEquipment?.id}) not match", + errorPosition = "equipmentId" + ) + } + } + if(equipmentDetail?.equipmentTypeId != null &&( equipmentDetail.equipmentTypeId ==bomProcessEquipment?.id)) { + + val equipment = equipmentRepository.findById(equipmentDetail.equipmentTypeId).orElse(null) + productProcessLine?.equipment = equipment + productProcessLine?.equipmentDetailId = equipmentDetail.id + productProcessLineRepository.save(productProcessLine) + } + else + { println("productProcessLine id${request.productProcessLineId}") + println("operator Name${request?.Name}") + println("user ${user}") + println("bomProcess ${bomProcess?.id}") + println("not match equipment id${equipmentDetail?.equipmentTypeId} and ${bomProcessEquipment?.id}") + + } + if(user != null) { + //productProcessLine.operator = user.name + // productProcessLineRepository.save(productProcessLine) + } + + return MessageResponse( id = null, code = null, @@ -781,6 +849,13 @@ open class ProductProcessService( outputFromProcessUom = productProcessLine.outputFromProcessUom?:"", defectQty = productProcessLine.defectQty?:0, defectUom = productProcessLine.defectUom?:"", + defectDescription = productProcessLine.defectDescription?:"", + defectQty2 = productProcessLine.defectQty2?:0, + defectUom2 = productProcessLine.defectUom2?:"", + defectDescription2 = productProcessLine.defectDescription2?:"", + defectQty3 = productProcessLine.defectQty3?:0, + defectUom3 = productProcessLine.defectUom3?:"", + defectDescription3 = productProcessLine.defectDescription3?:"", scrapQty = productProcessLine.scrapQty?:0, scrapUom = productProcessLine.scrapUom?:"", byproductId = productProcessLine.byproduct?.id?:0, @@ -834,55 +909,86 @@ open class ProductProcessService( ) } -open fun updateProductProcessLineQty(request: UpdateProductProcessLineQtyRequest): MessageResponse { - val outputFromProcessQty = request.outputFromProcessQty - val outputFromProcessUom = request.outputFromProcessUom - val defectQty = request.defectQty - val defectUom = request.defectUom - val scrapQty = request.scrapQty - val scrapUom = request.scrapUom - val byproductName = request.byproductName - val byproductQty = request.byproductQty - val byproductUom = request.byproductUom - val productProcessLine = productProcessLineRepository.findById(request.productProcessLineId).orElse(null) - if(outputFromProcessQty != null) { - productProcessLine.outputFromProcessQty = outputFromProcessQty - } - if(outputFromProcessUom != null) { - productProcessLine.outputFromProcessUom = outputFromProcessUom - } - if(defectQty != null) { - productProcessLine.defectQty = defectQty - } - if(defectUom != null) { - productProcessLine.defectUom = defectUom - } - if(scrapQty != null) { - productProcessLine.scrapQty = scrapQty - } - if(scrapUom != null) { - productProcessLine.scrapUom = scrapUom - } - if(byproductName != null) { - productProcessLine.byproductName = byproductName - } - if(byproductQty != null) { - productProcessLine.byproductQty = byproductQty - } - if(byproductUom != null) { - productProcessLine.byproductUom = byproductUom + open fun updateProductProcessLineQty(request: UpdateProductProcessLineQtyRequest): MessageResponse { + val outputFromProcessQty = request.outputFromProcessQty + val outputFromProcessUom = request.outputFromProcessUom + val defectQty = request.defectQty + val defectUom = request.defectUom + val defectDescription = request.defectDescription + val defect2Qty = request.defect2Qty + val defect2Uom = request.defect2Uom + val defect2Description = request.defectDescription2 + val defect3Qty = request.defect3Qty + val defect3Uom = request.defect3Uom + val defect3Description = request.defectDescription3 + val scrapQty = request.scrapQty + val scrapUom = request.scrapUom + val byproductName = request.byproductName + val byproductQty = request.byproductQty + val byproductUom = request.byproductUom + val productProcessLine = productProcessLineRepository.findById(request.productProcessLineId).orElse(null) + if(outputFromProcessQty != null) { + productProcessLine.outputFromProcessQty = outputFromProcessQty + } + if(outputFromProcessUom != null) { + productProcessLine.outputFromProcessUom = outputFromProcessUom + } + if(defectQty != null) { + productProcessLine.defectQty = defectQty + } + if(defectUom != null) { + productProcessLine.defectUom = defectUom + } + + if(defectDescription != null) { + productProcessLine.defectDescription = defectDescription + } + + if(defect2Qty != null) { + productProcessLine.defectQty2 = defect2Qty + } + if(defect2Uom != null) { + productProcessLine.defectUom2 = defect2Uom + } + if(defect2Description != null) { + productProcessLine.defectDescription2 = defect2Description + } + + if(defect3Qty != null) { + productProcessLine.defectQty3 = defect3Qty + } + if(defect3Uom != null) { + productProcessLine.defectUom3 = defect3Uom + } + if(defect3Description != null) { + productProcessLine.defectDescription3 = defect3Description + } + if(scrapQty != null) { + productProcessLine.scrapQty = scrapQty + } + if(scrapUom != null) { + productProcessLine.scrapUom = scrapUom + } + if(byproductName != null) { + productProcessLine.byproductName = byproductName + } + if(byproductQty != null) { + productProcessLine.byproductQty = byproductQty + } + if(byproductUom != null) { + productProcessLine.byproductUom = byproductUom + } + productProcessLineRepository.save(productProcessLine) + CompleteProductProcessLine(request.productProcessLineId) + return MessageResponse( + id = request.productProcessLineId, + code = "200", + name = "ProductProcessLine Qty Updated", + type = "success", + message = "ProductProcessLine Qty Updated", + errorPosition = null, + ) } - productProcessLineRepository.save(productProcessLine) - CompleteProductProcessLine(request.productProcessLineId) - return MessageResponse( - id = request.productProcessLineId, - code = "200", - name = "ProductProcessLine Qty Updated", - type = "success", - message = "ProductProcessLine Qty Updated", - errorPosition = null, - ) -} open fun getAllJoborderProductProcessInfo(): List { val productProcesses = productProcessRepository.findAllByDeletedIsFalse() @@ -1057,4 +1163,5 @@ open fun updateProductProcessLineQty(request: UpdateProductProcessLineQtyRequest errorPosition = null, ) } -} \ 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 2a2071a..45da477 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 @@ -100,6 +100,13 @@ data class UpdateProductProcessLineQtyRequest( val outputFromProcessUom: String?, val defectQty: Int?, val defectUom: String?, + val defectDescription: String?, + val defect2Qty: Int?, + val defect2Uom: String?, + val defectDescription2: String?, + val defect3Qty: Int?, + val defect3Uom: String?, + val defectDescription3: String?, val scrapQty: Int?, val scrapUom: String?, val byproductName: String?, @@ -127,6 +134,13 @@ data class JobOrderProcessLineDetailResponse( val outputFromProcessUom: String?, val defectQty: Int?, val defectUom: String?, + val defectDescription: String?, + val defectQty2: Int?, + val defectUom2: String?, + val defectDescription2: String?, + val defectQty3: Int?, + val defectUom3: String?, + val defectDescription3: String?, val scrapQty: Int?, val scrapUom: String?, val byproductId: Long?, @@ -166,4 +180,10 @@ data class ProductProcessInfoResponse( data class UpdateProductProcessLineStatusRequest( val productProcessLineId: Long, val status: String +) +data class NewUpdateProductProcessLineOperatorIdOrEquipmentIdAndEquipmentDetailRequest( + val productProcessLineId: Long, + val EquipmentTypeSubTypeEquipmentNo: String, + val staffNo: String?, + val Name: String?, ) \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/stock/service/SuggestedPickLotService.kt b/src/main/java/com/ffii/fpsms/modules/stock/service/SuggestedPickLotService.kt index b6e27c2..4e9af3d 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/service/SuggestedPickLotService.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/service/SuggestedPickLotService.kt @@ -329,6 +329,7 @@ open class SuggestedPickLotService( val stockOutLine = StockOutLine().apply { this.stockOut = stockOut this.pickOrderLine = pickOrderLine + this.item = item this.inventoryLotLine = null // No lot available this.qty = (suggestion.qty ?: BigDecimal.ZERO).toDouble() this.status = StockOutLineStatus.PENDING.status diff --git a/src/main/java/com/ffii/fpsms/modules/user/entity/UserRepository.java b/src/main/java/com/ffii/fpsms/modules/user/entity/UserRepository.java index f23b117..01ec68e 100644 --- a/src/main/java/com/ffii/fpsms/modules/user/entity/UserRepository.java +++ b/src/main/java/com/ffii/fpsms/modules/user/entity/UserRepository.java @@ -3,15 +3,15 @@ package com.ffii.fpsms.modules.user.entity; import java.util.List; import java.util.Optional; -import com.ffii.fpsms.modules.user.entity.projections.UserCombo; import org.springframework.data.repository.query.Param; import com.ffii.core.support.AbstractRepository; +import com.ffii.fpsms.modules.user.entity.projections.UserCombo; public interface UserRepository extends AbstractRepository { List findByName(@Param("name") String name); - + Optional findByUsernameAndDeletedFalse(String username); List findUserComboByTitleNotNullAndDepartmentNotNullAndNameNotNullAndDeletedFalse(); diff --git a/src/main/resources/db/changelog/changes/20251125_01_enson/04_altertable_enson.sql b/src/main/resources/db/changelog/changes/20251125_01_enson/04_altertable_enson.sql new file mode 100644 index 0000000..f3f8c2d --- /dev/null +++ b/src/main/resources/db/changelog/changes/20251125_01_enson/04_altertable_enson.sql @@ -0,0 +1,6 @@ +-- liquibase formatted sql +-- changeset enson:altertable_enson + +ALTER TABLE `fpsmsdb`.`productprocessline` +DROP COLUMN `defectRemark2`, +ADD COLUMN `defectDescription2` VARCHAR(255) AFTER `defectUom2`; diff --git a/src/main/resources/db/changelog/changes/20251126_01_enson/01_altertable_enson.sql b/src/main/resources/db/changelog/changes/20251126_01_enson/01_altertable_enson.sql new file mode 100644 index 0000000..27775e3 --- /dev/null +++ b/src/main/resources/db/changelog/changes/20251126_01_enson/01_altertable_enson.sql @@ -0,0 +1,18 @@ +-- liquibase formatted sql +-- changeset enson:altertable_enson +create table jobType ( + `id` INT NOT NULL AUTO_INCREMENT, + `name` VARCHAR(255) NOT NULL, + `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` VARCHAR(30) NULL DEFAULT NULL, + `version` INT NOT NULL DEFAULT '0', + `modified` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `modifiedBy` VARCHAR(30) NULL DEFAULT NULL, + `deleted` TINYINT(1) NOT NULL DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + + +ALTER TABLE `fpsmsdb`.`user` +ADD COLUMN `staffNo` VARCHAR(255) After `lotusNotesUser`; + diff --git a/src/main/resources/db/changelog/changes/20251126_01_enson/02_altertable_enson.sql b/src/main/resources/db/changelog/changes/20251126_01_enson/02_altertable_enson.sql new file mode 100644 index 0000000..4234235 --- /dev/null +++ b/src/main/resources/db/changelog/changes/20251126_01_enson/02_altertable_enson.sql @@ -0,0 +1,8 @@ +-- liquibase formatted sql +-- changeset enson:altertable_enson + + + +ALTER TABLE `fpsmsdb`.`job_order` +ADD COLUMN `jobTypeId` INT After `type`; +