|
|
@@ -1,96 +1,89 @@ |
|
|
package com.ffii.fpsms.py |
|
|
package com.ffii.fpsms.py |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import com.ffii.fpsms.modules.jobOrder.entity.JobOrder |
|
|
import com.ffii.fpsms.modules.jobOrder.entity.JobOrder |
|
|
|
|
|
|
|
|
import com.ffii.fpsms.modules.master.service.ItemUomService |
|
|
import com.ffii.fpsms.modules.master.service.ItemUomService |
|
|
|
|
|
|
|
|
import com.ffii.fpsms.modules.stock.entity.StockInLineRepository |
|
|
import com.ffii.fpsms.modules.stock.entity.StockInLineRepository |
|
|
|
|
|
|
|
|
|
|
|
object PyJobOrderListMapper { |
|
|
|
|
|
|
|
|
|
|
|
private val GRADE_IN_PARENS = Regex("""^P\+\d+$""", RegexOption.IGNORE_CASE) |
|
|
|
|
|
private val PAREN_SEGMENT = Regex("""[((]([^()()]*)[))]""") |
|
|
|
|
|
private val UOM_UNIT_TOKEN = Regex( |
|
|
|
|
|
"""(包|袋|磅|千克|公斤|克|毫升|公升|個|隻|斤|安士|ml|ML|kg|KG|\d+\s*[gG]\b|/包|/[磅千克克])""", |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* True when [segment] looks like stock/pack UOM text (e.g. "1包X2磅", "0.9L/包"), |
|
|
|
|
|
* not usage/grade notes (e.g. "菠菜用", "熟", "P+4"). |
|
|
|
|
|
*/ |
|
|
|
|
|
fun looksLikePackagingUom(segment: String): Boolean { |
|
|
|
|
|
val s = segment.trim() |
|
|
|
|
|
if (s.isEmpty()) return false |
|
|
|
|
|
if (GRADE_IN_PARENS.matches(s)) return false |
|
|
|
|
|
if (!s.any { it.isDigit() }) return false |
|
|
|
|
|
return UOM_UNIT_TOKEN.containsMatchIn(s) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
object PyJobOrderListMapper { |
|
|
|
|
|
|
|
|
/** True if any parenthetical segment in [name] is packaging/UOM-like. */ |
|
|
|
|
|
fun nameAlreadyHasPackagingUom(name: String): Boolean = |
|
|
|
|
|
PAREN_SEGMENT.findAll(name).any { looksLikePackagingUom(it.groupValues[1]) } |
|
|
|
|
|
|
|
|
fun toListItem( |
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
* Append stock [udfudesc] in parentheses when the base name lacks packaging UOM. |
|
|
|
|
|
* Used by Bag3 / bagPrint via GET /py/job-orders. |
|
|
|
|
|
*/ |
|
|
|
|
|
fun buildDisplayItemName(baseName: String?, stockUnitDesc: String?): String? { |
|
|
|
|
|
val stock = stockUnitDesc?.trim().orEmpty() |
|
|
|
|
|
val baseTrim = baseName?.trim().orEmpty() |
|
|
|
|
|
return when { |
|
|
|
|
|
stock.isEmpty() && baseTrim.isEmpty() -> null |
|
|
|
|
|
stock.isEmpty() -> baseTrim |
|
|
|
|
|
baseTrim.isEmpty() -> "($stock)" |
|
|
|
|
|
nameAlreadyHasPackagingUom(baseTrim) -> baseTrim |
|
|
|
|
|
stockAlreadyPresentInName(baseTrim, stock) -> baseTrim |
|
|
|
|
|
else -> "$baseTrim($stock)" |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
jo: JobOrder, |
|
|
|
|
|
|
|
|
private fun stockAlreadyPresentInName(name: String, stockUnitDesc: String): Boolean { |
|
|
|
|
|
val norm = stockUnitDesc.replace(" ", "").lowercase() |
|
|
|
|
|
if (norm.isEmpty()) return false |
|
|
|
|
|
val nameNorm = name.replace(" ", "").lowercase() |
|
|
|
|
|
return nameNorm.contains(norm) |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fun toListItem( |
|
|
|
|
|
jo: JobOrder, |
|
|
printed: PrintedQtyByChannel?, |
|
|
printed: PrintedQtyByChannel?, |
|
|
|
|
|
|
|
|
stockInLineRepository: StockInLineRepository, |
|
|
stockInLineRepository: StockInLineRepository, |
|
|
|
|
|
|
|
|
itemUomService: ItemUomService, |
|
|
itemUomService: ItemUomService, |
|
|
|
|
|
|
|
|
): PyJobOrderListItem { |
|
|
): PyJobOrderListItem { |
|
|
|
|
|
|
|
|
val itemCode = jo.bom?.item?.code ?: jo.bom?.code |
|
|
val itemCode = jo.bom?.item?.code ?: jo.bom?.code |
|
|
|
|
|
|
|
|
val baseName = jo.bom?.name ?: jo.bom?.item?.name |
|
|
val baseName = jo.bom?.name ?: jo.bom?.item?.name |
|
|
|
|
|
|
|
|
val itemId = jo.bom?.item?.id |
|
|
val itemId = jo.bom?.item?.id |
|
|
|
|
|
|
|
|
val stockUnitDesc = itemId?.let { id -> |
|
|
val stockUnitDesc = itemId?.let { id -> |
|
|
|
|
|
|
|
|
itemUomService.findStockUnitByItemId(id)?.uom?.udfudesc |
|
|
itemUomService.findStockUnitByItemId(id)?.uom?.udfudesc |
|
|
|
|
|
|
|
|
}?.trim().orEmpty() |
|
|
|
|
|
|
|
|
|
|
|
val baseTrim = baseName?.trim().orEmpty() |
|
|
|
|
|
|
|
|
|
|
|
val baseAlreadyHasParens = '(' in baseTrim && ')' in baseTrim |
|
|
|
|
|
|
|
|
|
|
|
val itemName = when { |
|
|
|
|
|
|
|
|
|
|
|
stockUnitDesc.isEmpty() && baseTrim.isEmpty() -> null |
|
|
|
|
|
|
|
|
|
|
|
stockUnitDesc.isEmpty() -> baseTrim |
|
|
|
|
|
|
|
|
|
|
|
baseTrim.isEmpty() -> "($stockUnitDesc)" |
|
|
|
|
|
|
|
|
|
|
|
baseAlreadyHasParens -> baseTrim |
|
|
|
|
|
|
|
|
|
|
|
else -> "$baseTrim($stockUnitDesc)" |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
val itemName = buildDisplayItemName(baseName, stockUnitDesc) |
|
|
|
|
|
|
|
|
val stockInLine = jo.id?.let { stockInLineRepository.findFirstByJobOrder_IdAndDeletedFalse(it) } |
|
|
val stockInLine = jo.id?.let { stockInLineRepository.findFirstByJobOrder_IdAndDeletedFalse(it) } |
|
|
|
|
|
|
|
|
val stockInLineId = stockInLine?.id |
|
|
val stockInLineId = stockInLine?.id |
|
|
|
|
|
|
|
|
val lotNo = stockInLine?.lotNo |
|
|
val lotNo = stockInLine?.lotNo |
|
|
|
|
|
|
|
|
val p = printed ?: PrintedQtyByChannel() |
|
|
val p = printed ?: PrintedQtyByChannel() |
|
|
|
|
|
|
|
|
return PyJobOrderListItem( |
|
|
return PyJobOrderListItem( |
|
|
|
|
|
|
|
|
id = jo.id!!, |
|
|
id = jo.id!!, |
|
|
|
|
|
|
|
|
code = jo.code, |
|
|
code = jo.code, |
|
|
|
|
|
|
|
|
planStart = jo.planStart, |
|
|
planStart = jo.planStart, |
|
|
|
|
|
|
|
|
itemCode = itemCode, |
|
|
itemCode = itemCode, |
|
|
|
|
|
|
|
|
itemName = itemName, |
|
|
itemName = itemName, |
|
|
|
|
|
|
|
|
reqQty = jo.reqQty, |
|
|
reqQty = jo.reqQty, |
|
|
|
|
|
|
|
|
stockInLineId = stockInLineId, |
|
|
stockInLineId = stockInLineId, |
|
|
|
|
|
|
|
|
itemId = itemId, |
|
|
itemId = itemId, |
|
|
|
|
|
|
|
|
lotNo = lotNo, |
|
|
lotNo = lotNo, |
|
|
|
|
|
|
|
|
bagPrintedQty = p.bagPrintedQty, |
|
|
bagPrintedQty = p.bagPrintedQty, |
|
|
|
|
|
|
|
|
labelPrintedQty = p.labelPrintedQty, |
|
|
labelPrintedQty = p.labelPrintedQty, |
|
|
|
|
|
|
|
|
laserPrintedQty = p.laserPrintedQty, |
|
|
laserPrintedQty = p.laserPrintedQty, |
|
|
|
|
|
|
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|