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 0000000..10937a4 Binary files /dev/null and b/src/main/resources/bomImport/058 PP2088淨牛腩粒(2磅包) Pings BOM Template v3 repeat.xlsx differ