|
|
|
@@ -0,0 +1,79 @@ |
|
|
|
package com.ffii.fpsms.modules.master.service |
|
|
|
|
|
|
|
import com.ffii.fpsms.modules.master.entity.Bom |
|
|
|
import com.ffii.fpsms.modules.master.entity.BomRepository |
|
|
|
import com.ffii.fpsms.modules.settings.entity.BomWeightingScoreRepository |
|
|
|
import org.springframework.stereotype.Service |
|
|
|
import org.springframework.transaction.annotation.Transactional |
|
|
|
import java.math.BigDecimal |
|
|
|
import java.math.RoundingMode |
|
|
|
|
|
|
|
@Service |
|
|
|
open class BomScoreRecalculateService( |
|
|
|
private val bomRepository: BomRepository, |
|
|
|
private val bomWeightingScoreRepository: BomWeightingScoreRepository, |
|
|
|
) { |
|
|
|
|
|
|
|
/** |
|
|
|
* Recalculate baseScore for all non-deleted BOMs and persist the result. |
|
|
|
*/ |
|
|
|
@Transactional |
|
|
|
open fun recalculateAllBaseScores(): Int { |
|
|
|
val boms: List<Bom> = bomRepository.findAllByDeletedIsFalse() |
|
|
|
if (boms.isEmpty()) return 0 |
|
|
|
|
|
|
|
boms.forEach { bom -> |
|
|
|
val newScore = calculateBaseScoreForBom(bom) |
|
|
|
bom.baseScore = newScore |
|
|
|
} |
|
|
|
|
|
|
|
bomRepository.saveAll(boms) |
|
|
|
return boms.size |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Same logic as BomService.calculateBaseScore, |
|
|
|
* duplicated to avoid modifying BomService.kt. |
|
|
|
*/ |
|
|
|
private fun calculateBaseScoreForBom(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: List<Pair<String, BigDecimal>> = 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 |
|
|
|
} |
|
|
|
} |