diff --git a/src/main/java/com/ffii/fpsms/modules/master/entity/ProductionScheduleLine.kt b/src/main/java/com/ffii/fpsms/modules/master/entity/ProductionScheduleLine.kt index c5fe86c..35af7c9 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/entity/ProductionScheduleLine.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/entity/ProductionScheduleLine.kt @@ -37,4 +37,7 @@ open class ProductionScheduleLine : BaseEntity() { @Column(name = "itemPriority") open var itemPriority: Long = 0L + + @Column(name = "weightingRef") + open var weightingRef: Double = 0.0 } diff --git a/src/main/java/com/ffii/fpsms/modules/master/service/ItemsService.kt b/src/main/java/com/ffii/fpsms/modules/master/service/ItemsService.kt index 65947c7..9f73316 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/service/ItemsService.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/service/ItemsService.kt @@ -12,6 +12,7 @@ import org.springframework.transaction.annotation.Transactional import java.io.IOException import java.time.LocalDateTime import java.time.format.DateTimeFormatter +import java.time.temporal.TemporalAdjusters @Service open class ItemsService( @@ -33,15 +34,14 @@ open class ItemsService( val lastMonthEnd = now.minusDays(now.dayOfMonth.toLong()).withHour(23).withMinute(59).withSecond(59) // End of last month val curMonthStart = now.withDayOfMonth(1) // Start of last month - val curMonthEnd = now.withDayOfMonth(31).withHour(23).withMinute(59).withSecond(59) // End of last month + val curMonthEnd = now.with(TemporalAdjusters.lastDayOfMonth()).withHour(23).withMinute(59).withSecond(59) // End of last month // Format dates if needed val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") - //TODO: change back to use last month for production val args = mapOf( - "lastMonthStart" to curMonthStart.format(formatter), - "lastMonthEnd" to curMonthEnd.format(formatter) + "lastMonthStart" to lastMonthStart.format(formatter), + "lastMonthEnd" to lastMonthEnd.format(formatter) ) println("lastMonthStart:" + args.get("lastMonthStart")) 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 60b259f..40dd0ce 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 @@ -45,8 +45,8 @@ open class ProductionScheduleService( return jdbcDao.queryForInt(sql.toString(), args); } - open fun generateDetailScheduleByDay(assignDate: Int, selectedDate: LocalDateTime) { - val detailScheduleOutputList = ArrayList() + open fun generateDetailedScheduleByDay(assignDate: Int, selectedDate: LocalDateTime) { + val detailedScheduleOutputList = ArrayList() //increasement available var idleProductionCount = 22000.0 - getDailyProductionCount(assignDate, selectedDate); @@ -63,7 +63,7 @@ open class ProductionScheduleService( //用缺口決定生產順序 val productionPriorityMap: HashMap = HashMap(); - //TODO: update to use SQL get shop order record for detail scheduling (real prodQty and openBal) + //TODO: update to use SQL get shop order record for detailed scheduling (real prodQty and openBal) for (record in scheduledList){ println("Object - " + record.toString() ); val tempRecord= record; @@ -86,7 +86,7 @@ open class ProductionScheduleService( if(idleProductionCount - prodDifference >= 0){ //have enough quoter for adjustment idleProductionCount -= prodDifference; - detailScheduleOutputList.add(updatedScheduleRecord) + detailedScheduleOutputList.add(updatedScheduleRecord) accProdCount += updatedScheduleRecord.prodQty fgCount++ } @@ -95,12 +95,20 @@ open class ProductionScheduleService( } } - saveDetailScheduleOutput(detailScheduleOutputList, accProdCount, fgCount) + // Sort detailedScheduleOutputList by item priority + val sortedOutputList = detailedScheduleOutputList.sortedBy { it.weightingRef }.toMutableList() - //return detailScheduleOutput + // Update itemPriority in the sorted list + var tempPriority = 1L + sortedOutputList.forEach { record -> + record.itemPriority = tempPriority + tempPriority++ + } + + saveDetailedScheduleOutput(sortedOutputList, accProdCount, fgCount) } - open fun saveDetailScheduleOutput(sortedEntries: List, accProdCount: Double, fgCount: Long) { + open fun saveDetailedScheduleOutput(sortedEntries: List, accProdCount: Double, fgCount: Long) { val tempObj = ProductionSchedule() tempObj.id = -1; tempObj.scheduleAt = LocalDateTime.now() @@ -128,7 +136,8 @@ open class ProductionScheduleService( savedItem.prodQty = detailedScheduleObj.prodQty savedItem.type = "detailed" savedItem.assignDate = detailedScheduleObj.assignDate; - savedItem.itemPriority = detailedScheduleObj.itemPriority //TODO: to be updated + savedItem.weightingRef = detailedScheduleObj.weightingRef + savedItem.itemPriority = detailedScheduleObj.itemPriority productionScheduleLineRepository.saveAndFlush(savedItem) } catch (e: Exception) { @@ -140,12 +149,20 @@ open class ProductionScheduleService( open class ProductionScheduleRecord : ProductionScheduleLine() { //SQL record in general with item name open var name: String = "" //item name + open var isDark: Number = 0 + open var isFloat: Number = 0 + open var isDense: Number = 0 open var targetMinStock: Double = 0.0; override fun toString(): String { - return "ProductionScheduleRecord(name='$name', targetMinStock=$targetMinStock)" + return "ProductionScheduleLine(prodScheduleId=$prodScheduleId," + + " itemId=$itemId, lastMonthAvgSales=$lastMonthAvgSales," + + " prodQty=$prodQty, estCloseBal=$estCloseBal, type='$type'," + + " approverId=$approverId, refScheduleId=$refScheduleId," + + " assignDate=$assignDate, itemPriority=$itemPriority)" + + " productionScheduleRecord(name='$name', targetMinStock=$targetMinStock)" + + " isDark=$isDark, isFloat=$isFloat, isDense=$isDense, weightingRef=$weightingRef" } - } open fun getProductionScheduleRecord(args: Map): List { @@ -156,6 +173,9 @@ open class ProductionScheduleService( + " psl.itemPriority, " + " psl.itemId, " + " i.name, " + + " COALESCE(b.isDark, 0) AS isDark, " + + " COALESCE(b.isFloat, 0) AS isFloat, " + + " COALESCE(b.isDense, 0) AS isDense, " + " psl.lastMonthAvgSales, " + " psl.lastMonthAvgSales*2 AS targetMinStock, " + " psl.prodQty, " @@ -165,6 +185,7 @@ open class ProductionScheduleService( + " FROM production_schedule ps " + " LEFT JOIN production_schedule_line psl ON psl.prodScheduleId = ps.id " + " LEFT JOIN items i ON psl.itemId = i.id " + + " LEFT JOIN bom b ON i.id = b.itemId " + " WHERE ps.deleted = FALSE " + " AND psl.deleted = FALSE " ); @@ -186,6 +207,15 @@ open class ProductionScheduleService( val resultList = jdbcDao.queryForList(sql.toString(), args, ); + val DARK_MAX_VALUE = 1; + val FLOAT_MAX_VALUE = 5; + val DENSE_MAX_VALUE = 5; + val DARK_WEIGHTING = 0.34; + val FLOAT_WEIGHTING = 0.33; + val DENSE_WEIGHTING = 0.33; + + + //TODO: update here // Convert the list of maps to a list of ProductionScheduleRecord return resultList.map { row -> ProductionScheduleRecord().apply { @@ -199,6 +229,14 @@ open class ProductionScheduleService( this.estCloseBal = row["estCloseBal"].toString().toDouble() this.type = row["type"] as String this.assignDate = row["assignDate"].toString().toLong() + + this.isDark = row["isDark"].toString().toInt() + this.isDense = row["isDense"].toString().toInt() + this.isFloat = row["isFloat"].toString().toInt() + this.weightingRef = + (DARK_MAX_VALUE - row["isDark"].toString().toInt() ) / DARK_MAX_VALUE.toDouble() * DARK_WEIGHTING + + (DENSE_MAX_VALUE - row["isDense"].toString().toInt()) / DENSE_MAX_VALUE.toDouble() * DENSE_WEIGHTING + + (FLOAT_MAX_VALUE - row["isFloat"].toString().toInt()) / FLOAT_MAX_VALUE.toDouble() * FLOAT_WEIGHTING } } } diff --git a/src/main/java/com/ffii/fpsms/modules/master/web/ProductionScheduleController.kt b/src/main/java/com/ffii/fpsms/modules/master/web/ProductionScheduleController.kt index 055481a..424e9ee 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/web/ProductionScheduleController.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/web/ProductionScheduleController.kt @@ -27,7 +27,7 @@ class ProductionScheduleController( @RequestMapping(value = ["/testDetailSchedule"], method = [RequestMethod.GET]) fun generateDetailSchedule(request: HttpServletRequest?): Int { try { - productionScheduleService.generateDetailScheduleByDay(1, LocalDateTime.of(2025,5,28,0,0,0)) + productionScheduleService.generateDetailedScheduleByDay(1, LocalDateTime.of(2025,6,18,0,0,0)) return 200 } catch (e: Exception) { throw RuntimeException("Error generate schedule: ${e.message}", e) diff --git a/src/main/resources/db/changelog/changes/20250619_01_jason_lam/01_update_production_schedule_line_with_weightingRef.sql b/src/main/resources/db/changelog/changes/20250619_01_jason_lam/01_update_production_schedule_line_with_weightingRef.sql new file mode 100644 index 0000000..b294119 --- /dev/null +++ b/src/main/resources/db/changelog/changes/20250619_01_jason_lam/01_update_production_schedule_line_with_weightingRef.sql @@ -0,0 +1,4 @@ +--liquibase formatted sql +--changeset jason_lam:update production schedule line with weightingRef + +ALTER TABLE production_schedule_line ADD `weightingRef` DECIMAL(16,2) NOT NULL DEFAULT 0.0 ;