Browse Source

[detailed scheduling] update logic for priority & add db new field

production_process
jason.lam 2 months ago
parent
commit
3481a80ecc
5 changed files with 60 additions and 15 deletions
  1. +3
    -0
      src/main/java/com/ffii/fpsms/modules/master/entity/ProductionScheduleLine.kt
  2. +4
    -4
      src/main/java/com/ffii/fpsms/modules/master/service/ItemsService.kt
  3. +48
    -10
      src/main/java/com/ffii/fpsms/modules/master/service/ProductionScheduleService.kt
  4. +1
    -1
      src/main/java/com/ffii/fpsms/modules/master/web/ProductionScheduleController.kt
  5. +4
    -0
      src/main/resources/db/changelog/changes/20250619_01_jason_lam/01_update_production_schedule_line_with_weightingRef.sql

+ 3
- 0
src/main/java/com/ffii/fpsms/modules/master/entity/ProductionScheduleLine.kt View File

@@ -37,4 +37,7 @@ open class ProductionScheduleLine : BaseEntity<Long>() {

@Column(name = "itemPriority")
open var itemPriority: Long = 0L

@Column(name = "weightingRef")
open var weightingRef: Double = 0.0
}

+ 4
- 4
src/main/java/com/ffii/fpsms/modules/master/service/ItemsService.kt View File

@@ -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"))


+ 48
- 10
src/main/java/com/ffii/fpsms/modules/master/service/ProductionScheduleService.kt View File

@@ -45,8 +45,8 @@ open class ProductionScheduleService(
return jdbcDao.queryForInt(sql.toString(), args);
}

open fun generateDetailScheduleByDay(assignDate: Int, selectedDate: LocalDateTime) {
val detailScheduleOutputList = ArrayList<ProductionScheduleRecord>()
open fun generateDetailedScheduleByDay(assignDate: Int, selectedDate: LocalDateTime) {
val detailedScheduleOutputList = ArrayList<ProductionScheduleRecord>()

//increasement available
var idleProductionCount = 22000.0 - getDailyProductionCount(assignDate, selectedDate);
@@ -63,7 +63,7 @@ open class ProductionScheduleService(
//用缺口決定生產順序
val productionPriorityMap: HashMap<ProductionScheduleRecord, Double> = 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<ProductionScheduleRecord>, accProdCount: Double, fgCount: Long) {
open fun saveDetailedScheduleOutput(sortedEntries: List<ProductionScheduleRecord>, 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<String, Any>): List<ProductionScheduleRecord> {
@@ -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
}
}
}


+ 1
- 1
src/main/java/com/ffii/fpsms/modules/master/web/ProductionScheduleController.kt View File

@@ -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)


+ 4
- 0
src/main/resources/db/changelog/changes/20250619_01_jason_lam/01_update_production_schedule_line_with_weightingRef.sql View File

@@ -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 ;

Loading…
Cancel
Save