From 7f3d4cb00f0e2d1a4e512872ab0c85f2dfbca604 Mon Sep 17 00:00:00 2001 From: "MSI\\derek" Date: Mon, 7 Jul 2025 18:32:11 +0800 Subject: [PATCH] update pick order --- .../ffii/fpsms/m18/service/M18TokenService.kt | 2 +- .../pickOrder/service/PickOrderService.kt | 1 + .../modules/qc/entity/QcResultRepository.kt | 1 + .../qc/entity/projection/QcResultInfo.kt | 6 +- .../modules/qc/service/QcResultService.kt | 3 + .../modules/qc/web/QcResultController.kt | 5 + .../stock/entity/StockOutLIneRepository.kt | 4 + .../modules/stock/entity/StockOutLine.kt | 2 + .../entity/projection/StockOutLineInfo.kt | 8 +- .../stock/service/StockInLineService.kt | 20 +++ .../stock/service/StockOutLineService.kt | 145 ++++++++++++++++-- .../modules/stock/service/StockOutService.kt | 4 +- .../stock/web/StockOutLineController.kt | 18 ++- .../stock/web/model/SaveStockInRequest.kt | 1 - .../stock/web/model/SaveStockOutRequest.kt | 31 ++-- ...磅包) Pings BOM Template v3 repeat.xlsx | Bin 0 -> 28719 bytes 16 files changed, 214 insertions(+), 37 deletions(-) create mode 100644 src/main/resources/bomImport/058 PP2088淨牛腩粒(2磅包) Pings BOM Template v3 repeat.xlsx diff --git a/src/main/java/com/ffii/fpsms/m18/service/M18TokenService.kt b/src/main/java/com/ffii/fpsms/m18/service/M18TokenService.kt index d406957..515cb7c 100644 --- a/src/main/java/com/ffii/fpsms/m18/service/M18TokenService.kt +++ b/src/main/java/com/ffii/fpsms/m18/service/M18TokenService.kt @@ -15,7 +15,7 @@ open class M18TokenService( private val m18Config: M18Config ) { - @Bean +// @Bean fun run() { // val params: MutableMap = mutableMapOf( // "grant_type" to m18Config.GRANT_TYPE, diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt index d67e202..ceb65e9 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt @@ -153,6 +153,7 @@ open class PickOrderService( + " i.name as itemName, " + " pol.qty as qty, " + " max(uc.code) as uom, " + + " group_concat(JSON_ARRAY(ill.id)) as lotLineId, " + " group_concat(JSON_ARRAY(w.name)) as warehouse, " + " group_concat(JSON_ARRAY(il.lotNo)) as suggestedLotNo " + " from pick_order po " diff --git a/src/main/java/com/ffii/fpsms/modules/qc/entity/QcResultRepository.kt b/src/main/java/com/ffii/fpsms/modules/qc/entity/QcResultRepository.kt index d2ca04b..42259e8 100644 --- a/src/main/java/com/ffii/fpsms/modules/qc/entity/QcResultRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/qc/entity/QcResultRepository.kt @@ -8,4 +8,5 @@ import org.springframework.stereotype.Repository @Repository interface QcResultRepository: AbstractRepository { fun findQcResultInfoByStockInLineIdAndDeletedFalse(stockInLineId: Long): List + fun findQcResultInfoByStockOutLineIdAndDeletedFalse(stockOutLineId: Long): List } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/qc/entity/projection/QcResultInfo.kt b/src/main/java/com/ffii/fpsms/modules/qc/entity/projection/QcResultInfo.kt index 47d972f..c89f1f5 100644 --- a/src/main/java/com/ffii/fpsms/modules/qc/entity/projection/QcResultInfo.kt +++ b/src/main/java/com/ffii/fpsms/modules/qc/entity/projection/QcResultInfo.kt @@ -10,7 +10,9 @@ interface QcResultInfo { val name: String @get:Value("#{target.qcItem.code}") val code: String - @get:Value("#{target.stockInLine.id}") - val stockInLineId: Long + @get:Value("#{target.stockInLine?.id}") + val stockInLineId: Long? + @get:Value("#{target.stockOutLine?.id}") + val stockOutLineId: Long? val failQty: Double } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/qc/service/QcResultService.kt b/src/main/java/com/ffii/fpsms/modules/qc/service/QcResultService.kt index 8861559..ed86038 100644 --- a/src/main/java/com/ffii/fpsms/modules/qc/service/QcResultService.kt +++ b/src/main/java/com/ffii/fpsms/modules/qc/service/QcResultService.kt @@ -57,4 +57,7 @@ open class QcResultService( open fun getAllQcResultInfoByStockInLineId(stockInLineId: Long): List { return qcResultRepository.findQcResultInfoByStockInLineIdAndDeletedFalse(stockInLineId) } + open fun getAllQcResultInfoByStockOutLineId(stockOutLineId: Long): List { + return qcResultRepository.findQcResultInfoByStockOutLineIdAndDeletedFalse(stockOutLineId) + } } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/qc/web/QcResultController.kt b/src/main/java/com/ffii/fpsms/modules/qc/web/QcResultController.kt index c004a1c..a816fbc 100644 --- a/src/main/java/com/ffii/fpsms/modules/qc/web/QcResultController.kt +++ b/src/main/java/com/ffii/fpsms/modules/qc/web/QcResultController.kt @@ -23,4 +23,9 @@ class QcResultController( fun getAllQcResultInfoByStockInLineId(@PathVariable stockInLineId: Long): List { return qcResultService.getAllQcResultInfoByStockInLineId(stockInLineId) } + + @GetMapping("/pick-order/{stockOutLineId}") + fun getAllQcResultInfoByStockOutLineId(@PathVariable stockOutLineId: Long): List { + return qcResultService.getAllQcResultInfoByStockOutLineId(stockOutLineId) + } } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/stock/entity/StockOutLIneRepository.kt b/src/main/java/com/ffii/fpsms/modules/stock/entity/StockOutLIneRepository.kt index 609084f..26355de 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/entity/StockOutLIneRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/entity/StockOutLIneRepository.kt @@ -10,4 +10,8 @@ interface StockOutLIneRepository: AbstractRepository { fun findAllByStockOutIdAndDeletedFalse(stockOutId: Long): List // fun findAllByStockOutIdAndDeletedFalse(stockOutId: Long, status: StockOutStatus): List fun findAllByPickOrderLineIdAndDeletedFalse(pickOrderLineId: Long): List + + fun findAllByIdIn(id: List): List + + fun findStockOutLineInfoById(id: Long): StockOutLineInfo } diff --git a/src/main/java/com/ffii/fpsms/modules/stock/entity/StockOutLine.kt b/src/main/java/com/ffii/fpsms/modules/stock/entity/StockOutLine.kt index d451e2f..7e51865 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/entity/StockOutLine.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/entity/StockOutLine.kt @@ -20,11 +20,13 @@ open class StockOutLine: BaseEntity() { @Column(name = "qty") open var qty: Double? = null + @JsonBackReference @NotNull @ManyToOne @JoinColumn(name = "stockOutId") open var stockOut: StockOut? = null + @JsonBackReference @ManyToOne @JoinColumn(name = "inventoryLotLineId") open var inventoryLotLine: InventoryLotLine? = null diff --git a/src/main/java/com/ffii/fpsms/modules/stock/entity/projection/StockOutLineInfo.kt b/src/main/java/com/ffii/fpsms/modules/stock/entity/projection/StockOutLineInfo.kt index ad357da..5f1f911 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/entity/projection/StockOutLineInfo.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/entity/projection/StockOutLineInfo.kt @@ -10,17 +10,21 @@ interface StockOutLineInfo { val itemId: Long @get:Value("#{target.item?.name}") val itemName: String? + @get:Value("#{target.item?.code}") val itemNo: String val qty: BigDecimal @get:Value("#{target.stockOut?.id}") val stockOutId: Long + @get:Value("#{target.pickOrderLine?.id}") - val pickOrderLineId: Long + val pickOrderLineId: Long? @get:Value("#{target.inventoryLotLine?.id}") val inventoryLotLineId: Long? - + @get:Value("#{target.inventoryLotLine?.inventoryLot?.lotNo}") + val lotNo: String? val status: String + val pickTime: LocalDateTime? } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/stock/service/StockInLineService.kt b/src/main/java/com/ffii/fpsms/modules/stock/service/StockInLineService.kt index 4c20021..1a3ad2e 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/service/StockInLineService.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/service/StockInLineService.kt @@ -193,6 +193,26 @@ open class StockInLineService( @Transactional fun updatePurchaseOrderLineStatus(request: SaveStockInLineRequest) { println(request.status) + if (request.status == StockInLineStatus.RECEIVING.status) { + val unQcedLines = stockInLineRepository.findStockInLineInfoByPurchaseOrderLineIdAndDeletedFalse(purchaseOrderLineId = request.purchaseOrderLineId) + .filter { + it.status != StockInLineStatus.RECEIVING.status + && it.status != StockInLineStatus.RECEIVED.status + && it.status != StockInLineStatus.COMPLETE.status + && it.status != StockInLineStatus.REJECT.status + } + if (unQcedLines.isEmpty()) { + // all stock in lines finished + // change status of purchase order line + val purchaseOrderLine = polRepository.findById(request.purchaseOrderLineId).orElseThrow() + purchaseOrderLine.apply { + status = PurchaseOrderLineStatus.RECEIVING + } + polRepository.saveAndFlush(purchaseOrderLine) + } else { + // still have unQcedLines lines + } + } if (request.status == StockInLineStatus.COMPLETE.status || request.status == StockInLineStatus.REJECT.status) { // val unfinishedLines = stockInLineRepository.findStockInLineInfoByPurchaseOrderLineIdAndStatusNotAndDeletedFalse(purchaseOrderLineId = request.purchaseOrderLineId, status = request.status!!) val unfinishedLines = stockInLineRepository.findStockInLineInfoByPurchaseOrderLineIdAndDeletedFalse(purchaseOrderLineId = request.purchaseOrderLineId) diff --git a/src/main/java/com/ffii/fpsms/modules/stock/service/StockOutLineService.kt b/src/main/java/com/ffii/fpsms/modules/stock/service/StockOutLineService.kt index e0147fe..b3fb1ab 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/service/StockOutLineService.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/service/StockOutLineService.kt @@ -5,12 +5,11 @@ import com.ffii.core.support.JdbcDao import com.ffii.fpsms.modules.master.entity.ItemsRepository import com.ffii.fpsms.modules.master.web.models.MessageResponse import com.ffii.fpsms.modules.pickOrder.entity.PickOrderLineRepository +import com.ffii.fpsms.modules.pickOrder.enums.PickOrderLineStatus import com.ffii.fpsms.modules.stock.entity.* import com.ffii.fpsms.modules.stock.entity.projection.StockOutLineInfo -import com.ffii.fpsms.modules.stock.web.model.SaveStockOutLineRequest -import com.ffii.fpsms.modules.stock.web.model.SaveStockOutRequest -import com.ffii.fpsms.modules.stock.web.model.StockOutLineStatus -import com.ffii.fpsms.modules.stock.web.model.StockOutStatus +import com.ffii.fpsms.modules.stock.web.model.* +import org.springframework.data.repository.query.Param import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional import java.io.IOException @@ -61,21 +60,30 @@ open class StockOutLineService( } @Transactional - open fun create(request: SaveStockOutLineRequest): MessageResponse { + open fun create(request: CreateStockOutLineRequest): MessageResponse { + // pick flow step 1 +// println(request.pickOrderLineId) val stockOut = stockOutRepository.findByConsoPickOrderCode(request.consoCode).orElseThrow() - val pickOrderLine = pickOrderLineRepository.findById(request.pickOrderLineId).orElseThrow() - val item = itemRepository.findById(request.itemId).orElseThrow() + val pickOrderLine = pickOrderLineRepository.saveAndFlush( + pickOrderLineRepository.findById(request.pickOrderLineId).orElseThrow() + .apply { + this.status = PickOrderLineStatus.PICKING + } + ) + val item = itemRepository.findById(pickOrderLine.item!!.id!!).orElseThrow() val inventoryLotLine = inventoryLotLineRepository.findById(request.inventoryLotLineId).orElseThrow() val stockOutLine = StockOutLine() .apply { this.item = item this.qty = request.qty this.stockOut = stockOut - this.inventoryLotLine + this.inventoryLotLine = inventoryLotLine this.pickOrderLine = pickOrderLine this.status = StockOutLineStatus.PENDING.status } val savedStockOutLine = saveAndFlush(stockOutLine) + val mappedSavedStockOutLine = stockOutLineRepository.findStockOutLineInfoById(savedStockOutLine.id!!) +// println("triggering") return MessageResponse( id = savedStockOutLine.id, name = savedStockOutLine.inventoryLotLine!!.inventoryLot!!.lotNo, @@ -83,13 +91,126 @@ open class StockOutLineService( type = savedStockOutLine.status, message = "success", errorPosition = null, - entity = savedStockOutLine, + entity = mappedSavedStockOutLine, ) } @Transactional - open fun update(request: SaveStockOutLineRequest) { - val stockOutLine = stockOutLineRepository.findById(request.id!!).orElseThrow() - + fun handleQc(stockOutLine: StockOutLine, request: UpdateStockOutLineRequest): List { + var newStockOutLine: StockOutLine? = null + if (request.qty < stockOutLine.qty!!) { + newStockOutLine = StockOutLine().apply { + this.pickOrderLine = stockOutLine.pickOrderLine + this.stockOut = stockOutLine.stockOut + this.item = stockOutLine.item + this.qty = stockOutLine.qty!! - request.qty + this.status = StockOutLineStatus.DETERMINE1.status // escalated + } + } + val inventoryLotLine = if (request.inventoryLotLineId != null) + inventoryLotLineRepository.findById(request.inventoryLotLineId).orElseThrow() + else null + stockOutLine.apply { + this.inventoryLotLine = inventoryLotLine ?: stockOutLine.inventoryLotLine + this.qty = request.qty + this.status = StockOutLineStatus.COMPLETE.status // complete + } + return listOf(stockOutLine, newStockOutLine) + } + @Transactional + fun handleLotChangeApprovalOrReject(stockOutLine: StockOutLine, request: UpdateStockOutLineRequest): List { + /** + * @param request.qty + * qty that requires lot change + */ + var newStockOutLine: StockOutLine? = null + + if (request.qty < stockOutLine.qty!!) { + newStockOutLine = StockOutLine().apply { + this.pickOrderLine = stockOutLine.pickOrderLine + this.stockOut = stockOutLine.stockOut + this.item = stockOutLine.item + this.qty = stockOutLine.qty!! - request.qty + this.status = StockOutLineStatus.REJECTED.status // original status + } + } + stockOutLine.apply { + this.qty = request.qty + this.status = StockOutLineStatus.LOT_CHANGE_APPROVAL.status // require new lot no + } + return listOf(stockOutLine, newStockOutLine) + } + +// @Transactional +// fun assignNewLotLine(stockOutLine: StockOutLine, request: UpdateStockOutLineRequest): List { +// val newInventoryLotLine = inventoryLotLineRepository.findById(request.inventoryLotLineId).orElseThrow() +// return listOf(stockOutLine.apply { +// this.inventoryLotLine = newInventoryLotLine +// }) +// } + private fun checkIsStockOutLineCompleted(pickOrderLineId: Long) { + val unfinishedLine = stockOutLineRepository + .findAllByPickOrderLineIdAndDeletedFalse(pickOrderLineId) + .filter { + it.status != StockOutLineStatus.COMPLETE.status + || it.status != StockOutLineStatus.REJECTED.status + } + if (unfinishedLine.isEmpty()) { + // set pick order line status to complete + val pol = pickOrderLineRepository.findById(pickOrderLineId).orElseThrow() + pickOrderLineRepository.save( + pol.apply { + this.status = PickOrderLineStatus.COMPLETED + } + ) + } else { + // return unfinished ids to frontend + } + } + @Transactional + open fun update(request: UpdateStockOutLineRequest): MessageResponse { + val stockOutLine = stockOutLineRepository.findById(request.id).orElseThrow() + var stockOutLineEntries: List = listOf() + // pick flow step 2 + if (request.status == StockOutLineStatus.COMPLETE.status) { // doing qc + println("doing sth") + if (request.qty <= 0) { + return MessageResponse( + id = null, + code = null, + name = null, + type = "qty == 0", + message = "qty cannot be 0", + errorPosition = "request.qty", + ) + } + stockOutLineEntries = handleQc(stockOutLine, request) + } + if (request.status == StockOutLineStatus.LOT_CHANGE_APPROVAL.status) { + if (request.qty < 0) { + return MessageResponse( + id = null, + code = null, + name = null, + type = "qty < 0", + message = "qty cannot be smaller than 0", + errorPosition = "request.qty", + ) + } + stockOutLineEntries = handleLotChangeApprovalOrReject(stockOutLine, request) + } + checkIsStockOutLineCompleted(pickOrderLineId = stockOutLine.pickOrderLine!!.id!!) + + val savedEntries = stockOutLineRepository.saveAllAndFlush(stockOutLineEntries.filterNotNull()) + val lineInfoList = stockOutLineRepository.findAllByIdIn(savedEntries.map { it.id!! }) + return MessageResponse( + id = 0, + name = "id: ${lineInfoList.map { it.id }.joinToString(separator = ",")}", + code = stockOutLine.stockOut!!.consoPickOrderCode, + type = lineInfoList.joinToString(separator = ",") { it.status }, + message = "success", + errorPosition = null, + entity = lineInfoList, + ) } } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/stock/service/StockOutService.kt b/src/main/java/com/ffii/fpsms/modules/stock/service/StockOutService.kt index 360416c..c113541 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/service/StockOutService.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/service/StockOutService.kt @@ -44,7 +44,7 @@ open class StockOutService( var sum = 0.0 when (status) { StockOutLineStatus.PENDING.status -> sum += it.qty ?: 0.0; - StockOutLineStatus.PICKED.status -> sum -= it.qty ?: 0.0; +// StockOutLineStatus.PICKED.status -> sum -= it.qty ?: 0.0; } sum == 0.0 } @@ -62,7 +62,7 @@ open class StockOutService( val baseLines = allLines.filter { stockOutLine -> stockOutLine.status === StockOutLineStatus.PENDING.status} // update pick record to complete val pickLines = allLines - .filter { stockOutLine -> stockOutLine.status === StockOutLineStatus.PICKED.status} +// .filter { stockOutLine -> stockOutLine.status === StockOutLineStatus.PICKED.status} .map { stockOutLine -> stockOutLine.apply { status = StockOutLineStatus.COMPLETE.status diff --git a/src/main/java/com/ffii/fpsms/modules/stock/web/StockOutLineController.kt b/src/main/java/com/ffii/fpsms/modules/stock/web/StockOutLineController.kt index 0e6d0fb..dc2ceff 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/web/StockOutLineController.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/web/StockOutLineController.kt @@ -1,16 +1,15 @@ package com.ffii.fpsms.modules.stock.web +import com.ffii.fpsms.modules.master.web.models.MessageResponse import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrderLine import com.ffii.fpsms.modules.stock.entity.StockOutLine import com.ffii.fpsms.modules.stock.entity.projection.StockOutLineInfo import com.ffii.fpsms.modules.stock.service.StockInLineService import com.ffii.fpsms.modules.stock.service.StockOutLineService +import com.ffii.fpsms.modules.stock.web.model.CreateStockOutLineRequest +import com.ffii.fpsms.modules.stock.web.model.UpdateStockOutLineRequest import jakarta.validation.Valid -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.PathVariable -import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RestController +import org.springframework.web.bind.annotation.* @RestController @RequestMapping("/stockOutLine") @@ -22,4 +21,13 @@ class StockOutLineController( return stockOutLineService.getAllStockOutLineByPickOrderLineId(pickOrderLineId) } + @PostMapping("/create") + fun create(@Valid @RequestBody request: CreateStockOutLineRequest): MessageResponse { + return stockOutLineService.create(request) + } + @PostMapping("/update") + fun update(@Valid @RequestBody request: UpdateStockOutLineRequest): MessageResponse { + println("triggering") + return stockOutLineService.update(request) + } } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/stock/web/model/SaveStockInRequest.kt b/src/main/java/com/ffii/fpsms/modules/stock/web/model/SaveStockInRequest.kt index 56b4270..47eb4b1 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/web/model/SaveStockInRequest.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/web/model/SaveStockInRequest.kt @@ -10,7 +10,6 @@ enum class StockInStatus(val status: String) { COMPLETE("completed"), // CANCELLED("cancelled") } -class GameScore(val grade: String) enum class StockInLineStatus(val status: String) { PENDING("pending"), QC("qc"), diff --git a/src/main/java/com/ffii/fpsms/modules/stock/web/model/SaveStockOutRequest.kt b/src/main/java/com/ffii/fpsms/modules/stock/web/model/SaveStockOutRequest.kt index abd290e..d56ade3 100644 --- a/src/main/java/com/ffii/fpsms/modules/stock/web/model/SaveStockOutRequest.kt +++ b/src/main/java/com/ffii/fpsms/modules/stock/web/model/SaveStockOutRequest.kt @@ -1,8 +1,9 @@ package com.ffii.fpsms.modules.stock.web.model +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.NotNull import java.time.LocalDate import java.time.LocalDateTime - enum class StockOutStatus(val status: String) { PENDING("pending"), COMPLETE("completed"), @@ -10,11 +11,12 @@ enum class StockOutStatus(val status: String) { } enum class StockOutLineStatus(val status: String) { PENDING("pending"), - PICKED("picked"), - COMPLETE("completed"), -// CANCELLED("cancelled") + DETERMINE1("determine1"), // qc failed qty? + LOT_CHANGE_APPROVAL("lot-change"), // just a flag for frontend + REJECTED("rejected"), + COMPLETE("completed"), // == picked } -data class SaveStockOutRequest( +data class SaveStockOutRequest( // not usable val id: Long?, val type: String, // delivery || pick || etc val deliveryOrderCode: String?, @@ -25,17 +27,22 @@ data class SaveStockOutRequest( val handler: Long?, val targetOutletId: Long?, val remarks: String?, - val stockOutLine: List + val stockOutLine: List ) - -data class SaveStockOutLineRequest( - val id: Long?, +data class CreateStockOutLineRequest( val consoCode: String, + val pickOrderLineId: Long, + val inventoryLotLineId: Long, + val qty: Double, +) +data class UpdateStockOutLineRequest( + val id: Long, val itemId: Long, val qty: Double, val pickOrderLineId: Long, - val inventoryLotLineId: Long, - val status: StockOutLineStatus?, + val status: String, + + val inventoryLotLineId: Long?, val pickTime: LocalDateTime?, - val pickerId: Long? +// val pickerId: Long? ) diff --git a/src/main/resources/bomImport/058 PP2088淨牛腩粒(2磅包) Pings BOM Template v3 repeat.xlsx b/src/main/resources/bomImport/058 PP2088淨牛腩粒(2磅包) Pings BOM Template v3 repeat.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..10937a4e6a4554e9bb10113715913060d0b79e74 GIT binary patch literal 28719 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