From 05f1fc25ab5fb5eb0f3dfa088026e94651ed9a35 Mon Sep 17 00:00:00 2001 From: Fai Luk Date: Sun, 1 Feb 2026 17:34:59 +0800 Subject: [PATCH 1/3] make a fake onhand for scheduling --- .../modules/master/service/ProductionScheduleService.kt | 9 ++++++--- .../db/changelog/changes/20260201_fai/01_fake.sql | 6 ++++++ 2 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 src/main/resources/db/changelog/changes/20260201_fai/01_fake.sql 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 98549a6..061f699 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 @@ -656,12 +656,14 @@ open class ProductionScheduleService( WHERE dol.itemId = items.id -- AND MONTH(do.estimatedArrivalDate) = MONTH(DATE_SUB(NOW(), INTERVAL 1 MONTH)) - AND do.estimatedArrivalDate >= '2025-12-01' AND do.estimatedArrivalDate < '2025-12-11' + AND do.estimatedArrivalDate >= '2026-01-12' AND do.estimatedArrivalDate < '2026-01-16' GROUP BY do.estimatedArrivalDate) AS d) AS avgQtyLastMonth, (select sum(reqQty) from job_order where bomId = bom.id and status != 'completed') AS pendingJobQty, - - inventory.onHandQty - 500 AS stockQty, + + CASE WHEN item_fake_onhand.onHandQty is not null THEN item_fake_onhand.onHandQty + ELSE inventory.onHandQty - 500 END AS stockQty, + bom.outputQty, bom.outputQtyUom, (SELECT @@ -706,6 +708,7 @@ open class ProductionScheduleService( bom LEFT JOIN items ON bom.itemId = items.id LEFT JOIN inventory ON items.id = inventory.itemId + left join item_fake_onhand on items.code = item_fake_onhand.itemCode WHERE bom.itemId != 16771) AS i WHERE 1 diff --git a/src/main/resources/db/changelog/changes/20260201_fai/01_fake.sql b/src/main/resources/db/changelog/changes/20260201_fai/01_fake.sql new file mode 100644 index 0000000..a33d83e --- /dev/null +++ b/src/main/resources/db/changelog/changes/20260201_fai/01_fake.sql @@ -0,0 +1,6 @@ +--liquibase formatted sql +--changeset author:vin fake onhand +CREATE TABLE `fpsmsdb`.`item_fake_onhand` ( + `itemCode` VARCHAR(100) NOT NULL, + `onHandQty` DECIMAL(14,2) NULL, + PRIMARY KEY (`itemCode`)); From 7b0918329ae3964629dd6172aadb969f22798f48 Mon Sep 17 00:00:00 2001 From: Fai Luk Date: Mon, 2 Feb 2026 00:53:05 +0800 Subject: [PATCH 2/3] no message --- .../fpsms/modules/master/service/ProductionScheduleService.kt | 1 + 1 file changed, 1 insertion(+) 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 061f699..c94b1eb 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 @@ -654,6 +654,7 @@ open class ProductionScheduleService( delivery_order_line dol LEFT JOIN delivery_order do ON dol.deliveryOrderId = do.id WHERE + do.deleted = 0 and dol.itemId = items.id -- AND MONTH(do.estimatedArrivalDate) = MONTH(DATE_SUB(NOW(), INTERVAL 1 MONTH)) AND do.estimatedArrivalDate >= '2026-01-12' AND do.estimatedArrivalDate < '2026-01-16' From a1df788e26740ec655573b2e61029fb40a7c7551 Mon Sep 17 00:00:00 2001 From: "kelvin.yau" Date: Mon, 2 Feb 2026 08:55:27 +0800 Subject: [PATCH 3/3] importBoM, baseScore calculation --- .../ffii/fpsms/modules/master/entity/Bom.kt | 3 + .../modules/master/service/BomService.kt | 57 ++++++++++++++++++- .../settings/entity/BomWeightingScore.kt | 5 +- .../entity/BomWeightingScoreRepository.kt | 1 + .../01_add_baseScore_to_bom.sql | 5 ++ 5 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 src/main/resources/db/changelog/changes/20260202_KelvinY/01_add_baseScore_to_bom.sql diff --git a/src/main/java/com/ffii/fpsms/modules/master/entity/Bom.kt b/src/main/java/com/ffii/fpsms/modules/master/entity/Bom.kt index 4360004..d8ecfb5 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/entity/Bom.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/entity/Bom.kt @@ -80,4 +80,7 @@ open class Bom : BaseEntity() { @Column(name = "m18LastModifyDate") open var m18LastModifyDate: LocalDateTime? = null + + @Column(name = "baseScore", precision = 14, scale = 2) + open var baseScore: BigDecimal? = null } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/service/BomService.kt b/src/main/java/com/ffii/fpsms/modules/master/service/BomService.kt index db74f18..81579fa 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/service/BomService.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/service/BomService.kt @@ -17,6 +17,9 @@ import java.nio.file.Paths import java.nio.file.Files; import java.nio.file.StandardCopyOption import com.ffii.fpsms.modules.master.entity.EquipmentDetailRepository +import com.ffii.fpsms.modules.settings.entity.BomWeightingScoreRepository +import java.math.BigDecimal +import java.math.RoundingMode @Service @@ -32,6 +35,7 @@ open class BomService( private val equipmentRepository: EquipmentRepository, private val processRepository: ProcessRepository, private val equipmentDetailRepository: EquipmentDetailRepository, + private val bomWeightingScoreRepository: BomWeightingScoreRepository, ) { open fun findAll(): List { return bomRepository.findAll() @@ -112,6 +116,7 @@ open class BomService( this.uom = uom // this.excelUom = req.excelUom } + bom.baseScore = calculateBaseScore(bom) val savedBom = bomRepository.saveAndFlush(bom) // println("saved: ${savedBom.id}") return savedBom @@ -337,8 +342,12 @@ open class BomService( when { //use fix row column by index not by search value contain later - tempCellVal.contains("深淺") -> request.isDark = calculateColourScore(getCellValueAsString(leftTargetValueCell)) - tempCellVal.contains("浮沉") -> request.isFloat = calculateFloatScore(getCellValueAsString(leftTargetValueCell)) + tempCellVal.contains("深淺") -> request.isDark = if (leftTargetValueCell?.cellType == CellType.NUMERIC) + leftTargetValueCell.numericCellValue.toInt() + else 0 + tempCellVal.contains("浮沉") -> request.isFloat = if (leftTargetValueCell?.cellType == CellType.NUMERIC) + leftTargetValueCell.numericCellValue.toInt() + else 0 tempCellVal.contains("過敏原 (如有)") -> request.allergicSubstances = calculateAllergicSubstancesScore(getCellValueAsString(leftTargetValueCell)) tempCellVal.contains("濃淡") -> request.isDense = if (leftTargetValueCell?.cellType == CellType.NUMERIC) leftTargetValueCell.numericCellValue.toInt() @@ -622,6 +631,50 @@ open class BomService( } } } + + /** + * Calculates baseScore from BOM basic info using bom_weighting_score (code = BOM column name). + * For isDark, isFloat, isDense, allergicSubstances, timeSequence, complexity: (extractedScore / range) * weighting * 100. + * For equipmentConflict: weighting * 100 only. + */ + private fun calculateBaseScore(bom: Bom): BigDecimal { + val scale = 2 + val roundingMode = RoundingMode.HALF_UP + var sum = BigDecimal.ZERO.setScale(scale, roundingMode) + + // Score columns: contribution = (extractedScore / range) * weighting * 100 + val scoreColumns = listOf( + "isDark" to (bom.isDark?.toBigDecimal() ?: BigDecimal.ZERO), + "isFloat" to (bom.isFloat?.toBigDecimal() ?: BigDecimal.ZERO), + "isDense" to (bom.isDense?.toBigDecimal() ?: BigDecimal.ZERO), + "allergicSubstances" to (bom.allergicSubstances?.toBigDecimal() ?: BigDecimal.ZERO), + "timeSequence" to (bom.timeSequence?.toBigDecimal() ?: BigDecimal.ZERO), + "complexity" to (bom.complexity?.toBigDecimal() ?: BigDecimal.ZERO), + ) + for ((code, extractedScore) in scoreColumns) { + val row = bomWeightingScoreRepository.findByCodeAndDeletedFalse(code) ?: continue + val range = (row.range ?: 1).toBigDecimal() + val weighting = row.weighting ?: continue + if (range.compareTo(BigDecimal.ZERO) == 0) continue + val contribution = extractedScore + .divide(range, scale, roundingMode) + .multiply(weighting) + .multiply(BigDecimal(100)) + .setScale(scale, roundingMode) + sum = sum.add(contribution) + } + + // equipmentConflict: contribution = weighting * 100 only + val equipmentConflictRow = bomWeightingScoreRepository.findByCodeAndDeletedFalse("equipmentConflict") + if (equipmentConflictRow?.weighting != null) { + val contribution = equipmentConflictRow.weighting!! + .multiply(BigDecimal(100)) + .setScale(scale, roundingMode) + sum = sum.add(contribution) + } + + return sum.setScale(scale, roundingMode) + } open fun exportProblematicBOM() { val resolver = PathMatchingResourcePatternResolver() val successExcel = resolver.getResources("file:C:/Users/2Fi/Desktop/fail/*.xlsx") diff --git a/src/main/java/com/ffii/fpsms/modules/settings/entity/BomWeightingScore.kt b/src/main/java/com/ffii/fpsms/modules/settings/entity/BomWeightingScore.kt index f82fcc9..4de712c 100644 --- a/src/main/java/com/ffii/fpsms/modules/settings/entity/BomWeightingScore.kt +++ b/src/main/java/com/ffii/fpsms/modules/settings/entity/BomWeightingScore.kt @@ -10,9 +10,12 @@ import java.math.BigDecimal @Entity open class BomWeightingScore: BaseEntity() { @Column - open var name: String? = null + open var code: String? = null @Column + open var name: String? = null + + @Column(name = "`range`") open var range: Int? = null @Column diff --git a/src/main/java/com/ffii/fpsms/modules/settings/entity/BomWeightingScoreRepository.kt b/src/main/java/com/ffii/fpsms/modules/settings/entity/BomWeightingScoreRepository.kt index 70f17cf..5538e2b 100644 --- a/src/main/java/com/ffii/fpsms/modules/settings/entity/BomWeightingScoreRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/settings/entity/BomWeightingScoreRepository.kt @@ -3,4 +3,5 @@ package com.ffii.fpsms.modules.settings.entity import com.ffii.core.support.AbstractRepository interface BomWeightingScoreRepository: AbstractRepository { + fun findByCodeAndDeletedFalse(code: String): BomWeightingScore? } \ No newline at end of file diff --git a/src/main/resources/db/changelog/changes/20260202_KelvinY/01_add_baseScore_to_bom.sql b/src/main/resources/db/changelog/changes/20260202_KelvinY/01_add_baseScore_to_bom.sql new file mode 100644 index 0000000..64b6cfb --- /dev/null +++ b/src/main/resources/db/changelog/changes/20260202_KelvinY/01_add_baseScore_to_bom.sql @@ -0,0 +1,5 @@ +-- liquibase formatted sql +-- changeset KelvinY:add_baseScore_to_bom + +ALTER TABLE `fpsmsdb`.`bom` + ADD COLUMN `baseScore` DECIMAL(14, 2) NULL DEFAULT NULL AFTER `complexity`; \ No newline at end of file