From dec57e041dd8d940ad5038223a44a37acefaca6d Mon Sep 17 00:00:00 2001 From: "CANCERYS\\kw093" Date: Tue, 30 Dec 2025 14:05:28 +0800 Subject: [PATCH] bag --- .../com/ffii/fpsms/modules/bag/entity/Bag.kt | 24 +++ .../bag/entity/BagLotLineRepository.kt | 16 ++ .../fpsms/modules/bag/entity/BagRepository.kt | 17 ++ .../modules/bag/entity/JoBagConsumption.kt | 45 +++++ .../fpsms/modules/bag/entity/bagLotLine.kt | 42 +++++ .../bag/entity/joBagConsumptionRepository.kt | 16 ++ .../fpsms/modules/bag/service/bagService.kt | 156 ++++++++++++++++++ .../fpsms/modules/bag/web/bagController.kt | 50 ++++++ .../fpsms/modules/bag/web/model/bagReponse.kt | 19 +++ .../fpsms/modules/bag/web/model/bagRequest.kt | 33 ++++ .../fpsms/modules/jobOrder/entity/JobOrder.kt | 5 +- .../entity/PickOrderLineRepository.kt | 1 + .../stock/service/StockInLineService.kt | 7 + .../stock/service/StockOutLineService.kt | 100 ++++++++++- 14 files changed, 524 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/ffii/fpsms/modules/bag/entity/Bag.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/bag/entity/BagLotLineRepository.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/bag/entity/BagRepository.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/bag/entity/JoBagConsumption.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/bag/entity/bagLotLine.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/bag/entity/joBagConsumptionRepository.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/bag/service/bagService.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/bag/web/bagController.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/bag/web/model/bagReponse.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/bag/web/model/bagRequest.kt diff --git a/src/main/java/com/ffii/fpsms/modules/bag/entity/Bag.kt b/src/main/java/com/ffii/fpsms/modules/bag/entity/Bag.kt new file mode 100644 index 0000000..8ce9f9e --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/bag/entity/Bag.kt @@ -0,0 +1,24 @@ +package com.ffii.fpsms.modules.bag.entity + +import com.fasterxml.jackson.annotation.JsonManagedReference +import com.ffii.core.entity.BaseEntity +import com.ffii.fpsms.m18.entity.M18DataLog +import jakarta.persistence.* +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Size +import java.time.LocalDateTime +@Entity +@Table(name = "bag") +open class Bag: BaseEntity() { + @Column(name = "itemId", nullable = false) + open var itemId: Long? = null + + @Column(name = "itemCode", nullable = false) + open var itemCode: String? = null + + @Column(name = "itemName", nullable = false) + open var itemName: String? = null + + @Column(name = "takenBagBalance", nullable = false) + open var takenBagBalance: Int? = null +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/bag/entity/BagLotLineRepository.kt b/src/main/java/com/ffii/fpsms/modules/bag/entity/BagLotLineRepository.kt new file mode 100644 index 0000000..0c83834 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/bag/entity/BagLotLineRepository.kt @@ -0,0 +1,16 @@ +package com.ffii.fpsms.modules.bag.entity + +import com.ffii.core.support.AbstractRepository +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Query +import org.springframework.data.repository.query.Param +import org.springframework.data.domain.Page +import org.springframework.data.domain.Pageable +import org.springframework.stereotype.Repository +import java.io.Serializable +import java.time.LocalDateTime + +@Repository +interface BagLotLineRepository : AbstractRepository { + fun findAllByBagId(bagId: Long): List +} diff --git a/src/main/java/com/ffii/fpsms/modules/bag/entity/BagRepository.kt b/src/main/java/com/ffii/fpsms/modules/bag/entity/BagRepository.kt new file mode 100644 index 0000000..20a294a --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/bag/entity/BagRepository.kt @@ -0,0 +1,17 @@ +package com.ffii.fpsms.modules.bag.entity + +import com.ffii.core.support.AbstractRepository +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Query +import org.springframework.data.repository.query.Param +import org.springframework.data.domain.Page +import org.springframework.data.domain.Pageable +import org.springframework.stereotype.Repository +import java.io.Serializable +import java.time.LocalDateTime + +@Repository +interface BagRepository : AbstractRepository { + fun findAllByDeletedIsFalse(): List + fun findByItemIdAndDeletedIsFalse(itemId: Long): Bag? +} diff --git a/src/main/java/com/ffii/fpsms/modules/bag/entity/JoBagConsumption.kt b/src/main/java/com/ffii/fpsms/modules/bag/entity/JoBagConsumption.kt new file mode 100644 index 0000000..248bc8e --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/bag/entity/JoBagConsumption.kt @@ -0,0 +1,45 @@ +package com.ffii.fpsms.modules.bag.entity + +import com.fasterxml.jackson.annotation.JsonManagedReference +import com.ffii.core.entity.BaseEntity +import com.ffii.fpsms.m18.entity.M18DataLog +import jakarta.persistence.* +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Size +import java.time.LocalDate +import java.time.LocalDateTime +@Entity +@Table(name = "jo_bag_consumption") +open class JoBagConsumption: BaseEntity() { + @Column(name = "bagId", nullable = false) + open var bagId: Long? = null + + @Column(name = "bagLotLineId", nullable = false) + open var bagLotLineId: Long? = null + + @Column(name = "jobId", nullable = false) + open var jobId: Long? = null + + @Column(name = "jobOrderCode", nullable = false) + open var jobOrderCode: String? = null + @Column(name = "stockOutLineId", nullable = false) + open var stockOutLineId: Long? = null + + @Column(name = "startQty", nullable = false) + open var startQty: Int? = null + + @Column(name = "consumedQty", nullable = false) + open var consumedQty: Int? = null + + @Column(name = "scrapQty", nullable = false) + open var scrapQty: Int? = null + + @Column(name = "endQty", nullable = false) + open var endQty: Int? = null + + @Column(name = "date", nullable = false) + open var date: LocalDate? = null + + @Column(name = "time", nullable = false) + open var time: LocalDateTime? = null +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/bag/entity/bagLotLine.kt b/src/main/java/com/ffii/fpsms/modules/bag/entity/bagLotLine.kt new file mode 100644 index 0000000..3c2367f --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/bag/entity/bagLotLine.kt @@ -0,0 +1,42 @@ +package com.ffii.fpsms.modules.bag.entity + +import com.fasterxml.jackson.annotation.JsonManagedReference +import com.ffii.core.entity.BaseEntity +import com.ffii.fpsms.m18.entity.M18DataLog +import jakarta.persistence.* +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Size +import java.time.LocalDateTime +import java.time.LocalDate +import java.time.LocalTime +@Entity +@Table(name = "bag_lot_line") +open class BagLotLine: BaseEntity() { + @Column(name = "bagId", nullable = false) + open var bagId: Long? = null + @Column(name = "stockOutLineId", nullable = false) + open var stockOutLineId: Long? = null + @Column(name = "lotId", nullable = false) + open var lotId: Long? = null + + @Column(name = "lotNo", nullable = false) + open var lotNo: String? = null + + @Column(name = "firstUseDate", nullable = false) + open var firstUseDate: LocalDate? = null + + @Column(name = "lastUseDate", nullable = false) + open var lastUseDate: LocalDate? = null + + @Column(name = "startQty", nullable = false) + open var startQty: Int? = null + + @Column(name = "consumedQty", nullable = false) + open var consumedQty: Int? = null + + @Column(name = "scrapQty", nullable = false) + open var scrapQty: Int? = null + + @Column(name = "balanceQty", nullable = false) + open var balanceQty: Int? = null +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/bag/entity/joBagConsumptionRepository.kt b/src/main/java/com/ffii/fpsms/modules/bag/entity/joBagConsumptionRepository.kt new file mode 100644 index 0000000..4e5a7b9 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/bag/entity/joBagConsumptionRepository.kt @@ -0,0 +1,16 @@ +package com.ffii.fpsms.modules.bag.entity + +import com.ffii.core.support.AbstractRepository +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.data.jpa.repository.Query +import org.springframework.data.repository.query.Param +import org.springframework.data.domain.Page +import org.springframework.data.domain.Pageable +import org.springframework.stereotype.Repository +import java.io.Serializable +import java.time.LocalDateTime + +@Repository +interface JoBagConsumptionRepository : AbstractRepository { + +} diff --git a/src/main/java/com/ffii/fpsms/modules/bag/service/bagService.kt b/src/main/java/com/ffii/fpsms/modules/bag/service/bagService.kt new file mode 100644 index 0000000..9546713 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/bag/service/bagService.kt @@ -0,0 +1,156 @@ +package com.ffii.fpsms.modules.bag.service + +import com.ffii.fpsms.modules.bag.entity.Bag +import com.ffii.fpsms.modules.bag.entity.BagLotLine +import com.ffii.fpsms.modules.bag.entity.JoBagConsumption +import org.springframework.stereotype.Service +import com.ffii.fpsms.modules.bag.web.model.* +import com.ffii.fpsms.modules.bag.entity.BagRepository +import com.ffii.fpsms.modules.bag.entity.BagLotLineRepository +import com.ffii.fpsms.modules.bag.entity.JoBagConsumptionRepository +import com.ffii.fpsms.modules.master.web.models.MessageResponse +import com.ffii.fpsms.modules.stock.entity.InventoryLotRepository +import java.time.LocalTime +import java.time.LocalDateTime +import java.time.LocalDate +import com.ffii.fpsms.modules.jobOrder.entity.JobOrderRepository +@Service +open class BagService( + private val bagRepository: BagRepository, + private val bagLotLineRepository: BagLotLineRepository, + private val joBagConsumptionRepository: JoBagConsumptionRepository, + private val inventoryLotRepository: InventoryLotRepository, + private val jobOrderRepository: JobOrderRepository +) { +open fun createBagLotLinesByBagId(request: CreateBagLotLineRequest): MessageResponse { + val bag = bagRepository.findById(request.bagId).orElse(null) + val lot = inventoryLotRepository.findByLotNoAndItemId(request.lotNo, request.itemId) + val bagLotLine = BagLotLine().apply { + this.bagId = bag?.id + this.lotId = lot?.id + this.lotNo = lot?.lotNo + this.startQty = request.stockQty + this.consumedQty = 0 + this.stockOutLineId = request.stockOutLineId + this.scrapQty = 0 + this.balanceQty = request.stockQty + } + bagLotLineRepository.save(bagLotLine) + bag.takenBagBalance = (bag.takenBagBalance ?: 0) + (bagLotLine.balanceQty ?: 0) + bagRepository.save(bag) + + return MessageResponse( + id = null, + code = null, + name = null, + type = null, + message = null, + errorPosition = null, + entity = null, + ) +} + +fun createJoBagConsumption(request: CreateJoBagConsumptionRequest): MessageResponse { + val bag = bagRepository.findById(request.bagId).orElse(null) + println("bagId: ${bag?.id}") + println(request.toString()) + if (bag == null) { + return MessageResponse( + id = null, + code = null, + name = null, + type = "error", + message = "Bag not found with id: ${request.bagId}", + errorPosition = null, + entity = null, + ) + } + + val bagLotLine = bagLotLineRepository.findById(request.bagLotLineId).orElse(null) + println("bagLotLineId: ${bagLotLine?.id}") + if (bagLotLine == null) { + return MessageResponse( + id = null, + code = null, + name = null, + type = "error", + message = "BagLotLine not found with id: ${request.bagLotLineId}", + errorPosition = null, + entity = null, + ) + } + val startQty = bagLotLine.startQty ?: 0 + if (startQty < request.consumedQty + request.scrapQty) { + return MessageResponse( + id = null, + code = null, + name = null, + type = "error", + message = "Insufficient balance. Available: $startQty, Requested: ${request.consumedQty + request.scrapQty}", + errorPosition = null, + entity = null, + ) + } + + val newBalanceQty = startQty - request.consumedQty - request.scrapQty + if (bagLotLine.firstUseDate == null) + { + bagLotLine.firstUseDate = LocalDate.now() + bagLotLineRepository.save(bagLotLine) + } + bagLotLine.consumedQty = (bagLotLine.consumedQty ?: 0) + request.consumedQty + bagLotLine.scrapQty = (bagLotLine.scrapQty ?: 0) + request.scrapQty + bagLotLine.balanceQty = newBalanceQty + bagLotLine.lastUseDate = LocalDate.now() + + bagLotLineRepository.save(bagLotLine) + + val consumedTotal = request.consumedQty + request.scrapQty + val jobOrder = jobOrderRepository.findById(request.jobId).orElse(null) + bag.takenBagBalance = (bag.takenBagBalance ?: 0) - consumedTotal + bagRepository.save(bag) + + val joBagConsumption = JoBagConsumption().apply { + this.bagId = request.bagId + this.bagLotLineId = request.bagLotLineId + this.jobId = request.jobId + this.stockOutLineId = bagLotLine.stockOutLineId + this.jobOrderCode=jobOrder?.code?:"" + this.startQty = startQty + this.consumedQty = request.consumedQty + this.scrapQty = request.scrapQty + this.endQty = newBalanceQty + this.date = LocalDate.now() + this.time = LocalDateTime.now() + } + joBagConsumptionRepository.save(joBagConsumption) + return MessageResponse( + id = null, + code = null, + name = null, + type = null, + message = null, + errorPosition = null, + entity = null, + ) +} + +open fun getAllBagInfo(): List { + val bags = bagRepository.findAllByDeletedIsFalse() + return bags.flatMap { bag -> + val bagLotLines = bagLotLineRepository.findAllByBagId(bag.id) + bagLotLines.map { bagLotLine -> + BagInfo( + id = bagLotLine.id, + bagId = bag.id, + bagName = bag?.itemName?:"", + lotId = bagLotLine.lotId ?: 0L, + lotNo = bagLotLine.lotNo ?: "", + stockOutLineId = bagLotLine.stockOutLineId ?: 0L, + code = bag?.itemCode ?: "", + balanceQty = bagLotLine.balanceQty ?: 0, + ) + } + } +} +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/bag/web/bagController.kt b/src/main/java/com/ffii/fpsms/modules/bag/web/bagController.kt new file mode 100644 index 0000000..0fb62dc --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/bag/web/bagController.kt @@ -0,0 +1,50 @@ +package com.ffii.fpsms.modules.bag.web + +import com.ffii.core.response.RecordsRes +import com.ffii.fpsms.modules.bag.service.BagService +import jakarta.validation.Valid +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.ModelAttribute +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController +import com.ffii.fpsms.modules.jobOrder.service.JoPickOrderService +import com.ffii.fpsms.modules.productProcess.service.ProductProcessService +import com.ffii.fpsms.modules.jobOrder.web.model.* +import com.ffii.fpsms.modules.jobOrder.web.model.ExportPickRecordRequest +import com.ffii.fpsms.modules.jobOrder.web.model.PrintPickRecordRequest +import com.ffii.fpsms.modules.jobOrder.web.model.SecondScanSubmitRequest +import com.ffii.fpsms.modules.jobOrder.web.model.SecondScanIssueRequest +import jakarta.servlet.http.HttpServletResponse +import net.sf.jasperreports.engine.JasperExportManager +import net.sf.jasperreports.engine.JasperPrint +import org.aspectj.weaver.tools.UnsupportedPointcutPrimitiveException +import org.springframework.context.NoSuchMessageException +import java.io.OutputStream +import java.io.UnsupportedEncodingException +import java.text.ParseException +import org.springframework.web.bind.annotation.* +import org.springframework.web.bind.annotation.RequestParam +import com.ffii.fpsms.modules.jobOrder.web.model.UpdateJoPickOrderHandledByRequest +import com.ffii.fpsms.modules.jobOrder.entity.projections.JobOrderInfo +import com.ffii.fpsms.modules.jobOrder.entity.projections.JobOrderInfoWithTypeName +import com.ffii.fpsms.modules.jobOrder.web.model.ExportFGStockInLabelRequest +import com.ffii.fpsms.modules.bag.web.model.* +import com.ffii.fpsms.modules.master.web.models.MessageResponse +@RestController +@RequestMapping("/bag") +class BagController( + private val bagService: BagService +) { + + @GetMapping("/bagInfo") + fun getBagInfo(): List { + return bagService.getAllBagInfo() + } + @PostMapping("/createJoBagConsumption") + fun createJoBagConsumption(@RequestBody request: CreateJoBagConsumptionRequest): MessageResponse { + return bagService.createJoBagConsumption(request) + } +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/bag/web/model/bagReponse.kt b/src/main/java/com/ffii/fpsms/modules/bag/web/model/bagReponse.kt new file mode 100644 index 0000000..b61c3d4 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/bag/web/model/bagReponse.kt @@ -0,0 +1,19 @@ +package com.ffii.fpsms.modules.bag.web.model + +data class GetAllBagInfoResponse( + val bagId: Long, + val bagName: String, + val bags: List +) + +data class BagInfo( + val id: Long, + val bagId: Long, + val bagName: String, + val lotId: Long, + val lotNo: String, + val stockOutLineId: Long, + val code: String, + val balanceQty: Int, + +) \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/bag/web/model/bagRequest.kt b/src/main/java/com/ffii/fpsms/modules/bag/web/model/bagRequest.kt new file mode 100644 index 0000000..ca06eaa --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/bag/web/model/bagRequest.kt @@ -0,0 +1,33 @@ +package com.ffii.fpsms.modules.bag.web.model +import java.time.LocalDate; +import java.time.LocalTime; +data class PickBagRequest( + val bags: List +) +data class BagRequest( + val bagId: Long, + val consumedQty: Int, + val scrapQty: Int +) + +data class CreateBagLotLineRequest( + val bagId: Long, + val stockOutLineId: Long, + val lotId: Long, + val itemId: Long, + val lotNo: String, + val stockQty: Int, + val date: LocalDate, + val time: LocalTime, +) + +data class CreateJoBagConsumptionRequest( + val bagId: Long, + val bagLotLineId: Long, + val jobId: Long, + //val startQty: Int, + val consumedQty: Int, + val scrapQty: Int, + //val date: LocalDate, + //val time: LocalTime, +) \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/JobOrder.kt b/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/JobOrder.kt index ceb269b..ca745c1 100644 --- a/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/JobOrder.kt +++ b/src/main/java/com/ffii/fpsms/modules/jobOrder/entity/JobOrder.kt @@ -13,7 +13,7 @@ import jakarta.validation.constraints.NotNull import jakarta.validation.constraints.Size import java.math.BigDecimal import java.time.LocalDateTime - +import com.ffii.fpsms.modules.productProcess.entity.ProductProcess @Entity @Table(name = "job_order") open class JobOrder : BaseEntity() { @@ -76,7 +76,8 @@ open class JobOrder : BaseEntity() { @JsonManagedReference @OneToMany(mappedBy = "jobOrder", cascade = [CascadeType.ALL], orphanRemoval = true) open var stockInLines: MutableList = mutableListOf() - + @OneToOne(mappedBy = "jobOrder", fetch = FetchType.LAZY) + open var productProcess: ProductProcess? = null @Column(name = "jobTypeId") open var jobTypeId: Long? = null diff --git a/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickOrderLineRepository.kt b/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickOrderLineRepository.kt index 3554e5c..f708c46 100644 --- a/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickOrderLineRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickOrderLineRepository.kt @@ -21,4 +21,5 @@ fun findAllPickOrdersByItemId(@Param("itemId") itemId: Long): List WHERE pol.pickOrder.id = :pickOrderId AND pol.deleted = false """) fun findAllByPickOrderId(@Param("pickOrderId") pickOrderId: Long): List +fun findAllByPickOrderIdAndDeletedFalse(pickOrderId: Long): List } \ 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 37294b1..c66ea52 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 @@ -479,6 +479,13 @@ open class StockInLineService( this.inventoryLot = stockInLine.inventoryLot ?: savedInventoryLot this.lotNo = stockInLine.lotNo ?: savedInventoryLot?.lotNo } + if (stockInLine.jobOrder != null) { + val jo = stockInLine.jobOrder + jo?.apply { + status = JobOrderStatus.STORING + } + jobOrderRepository.save(jo!!) + } } else { return MessageResponse( id = null, 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 f0fc852..c7cea19 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 @@ -32,10 +32,13 @@ import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderLineRecord import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatus import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderLineRecordRepository import com.ffii.fpsms.modules.stock.web.model.UpdateStockOutLineStatusByQRCodeAndLotNoRequest - +import com.ffii.fpsms.modules.bag.entity.BagRepository +import com.ffii.fpsms.modules.bag.web.model.CreateBagLotLineRequest import com.ffii.fpsms.modules.common.CodeGenerator import org.springframework.context.annotation.Lazy +import com.ffii.fpsms.modules.bag.service.BagService +import java.time.LocalTime @Service open class StockOutLineService( private val jdbcDao: JdbcDao, @@ -51,10 +54,12 @@ open class StockOutLineService( private val inventoryLotRepository: InventoryLotRepository, private val doPickOrderRepository: DoPickOrderRepository, private val doPickOrderRecordRepository: DoPickOrderRecordRepository, +private val bagRepository: BagRepository, private val deliveryOrderRepository: DeliveryOrderRepository, private val doPickOrderLineRepository: DoPickOrderLineRepository, private val doPickOrderLineRecordRepository: DoPickOrderLineRecordRepository, -private val inventoryLotLineService: InventoryLotLineService +private val inventoryLotLineService: InventoryLotLineService, + private val bagService: BagService ): AbstractBaseEntityService(jdbcDao, stockOutLineRepository) { @Throws(IOException::class) @Transactional @@ -541,7 +546,53 @@ private fun getStockOutIdFromPickOrderLine(pickOrderLineId: Long): Long { } val savedStockOutLine = stockOutLineRepository.saveAndFlush(stockOutLine) println("Updated StockOutLine: ${savedStockOutLine.id} with status: ${savedStockOutLine.status}") - + try { + val item = savedStockOutLine.item + val inventoryLotLine = savedStockOutLine.inventoryLotLine + + // 只在状态为 completed 或 partially_completed,且数量增加时创建 BagLotLine + val isCompletedOrPartiallyCompleted = request.status == "completed" || + request.status == "partially_completed" || + request.status == "PARTIALLY_COMPLETE" + + if (item?.isBag == true && + inventoryLotLine != null && + isCompletedOrPartiallyCompleted && + request.qty != null && + request.qty > 0) { + + println(" Item isBag=true, creating BagLotLine...") + + val bag = bagRepository.findByItemIdAndDeletedIsFalse(item.id!!) + + if (bag != null) { + val lotNo = inventoryLotLine.inventoryLot?.lotNo + if (lotNo != null) { + val createBagLotLineRequest = CreateBagLotLineRequest( + bagId = bag.id!!, + lotId = inventoryLotLine.inventoryLot?.id ?: 0L, + itemId = item.id!!, + lotNo = lotNo, + stockQty = request.qty.toInt(), + date = LocalDate.now(), + time = LocalTime.now(), + stockOutLineId = savedStockOutLine.id + ) + + bagService.createBagLotLinesByBagId(createBagLotLineRequest) + println(" ✓ BagLotLine created successfully for item ${item.code}") + } else { + println(" ⚠️ Warning: lotNo is null, skipping BagLotLine creation") + } + } else { + println(" ⚠️ Warning: Bag not found for itemId ${item.id}, skipping BagLotLine creation") + } + } + } catch (e: Exception) { + println(" ⚠️ Error creating BagLotLine: ${e.message}") + e.printStackTrace() + // 不中断主流程,只记录错误 + } // 3. 如果被拒绝,触发特殊处理 if (request.status == "rejected" || request.status == "REJECTED") { println("=== TRIGGERING LOT REJECTION LOGIC ===") @@ -554,8 +605,9 @@ private fun getStockOutIdFromPickOrderLine(pickOrderLineId: Long): Long { checkIsStockOutLineCompleted(pickOrderLine.id) // 5. 自动刷 pickOrder 状态 val pickOrder = pickOrderLine.pickOrder - if (pickOrder != null) { - val allLines = pickOrder.pickOrderLines + if (pickOrder != null && pickOrder.id != null) { + // ✅ 修复:使用 repository 查询所有 lines,避免懒加载问题 + val allLines = pickOrderLineRepository.findAllByPickOrderIdAndDeletedFalse(pickOrder.id!!) val allCompleted = allLines.all { it.status == PickOrderLineStatus.COMPLETED } if (allCompleted && allLines.isNotEmpty()) { pickOrder.status = PickOrderStatus.COMPLETED @@ -1019,7 +1071,45 @@ open fun newBatchSubmit(request: QrPickBatchSubmitRequest): MessageResponse { ) ) } + try { + val stockOutLine = stockOutLines[line.stockOutLineId] + val item = stockOutLine?.item + val inventoryLotLine = line.inventoryLotLineId?.let { lotLines[it] } + + if (item?.isBag == true && inventoryLotLine != null && submitQty > BigDecimal.ZERO) { + println(" Item isBag=true, creating BagLotLine...") + + // 根据 itemId 查找对应的 Bag + val bag = bagRepository.findByItemIdAndDeletedIsFalse(item.id!!) + + if (bag != null) { + val lotNo = inventoryLotLine.inventoryLot?.lotNo + if (lotNo != null) { + val createBagLotLineRequest = CreateBagLotLineRequest( + bagId = bag.id!!, + lotId = inventoryLotLine.inventoryLot?.id ?: 0L, + itemId = item.id!!, + stockOutLineId = stockOutLine.id , + lotNo = lotNo, + stockQty = submitQty.toInt(), // 转换为 Int + date = LocalDate.now(), + time = LocalTime.now() + ) + bagService.createBagLotLinesByBagId(createBagLotLineRequest) + println(" ✓ BagLotLine created successfully for item ${item.code}") + } else { + println(" ⚠️ Warning: lotNo is null, skipping BagLotLine creation") + } + } else { + println(" ⚠️ Warning: Bag not found for itemId ${item.id}, skipping BagLotLine creation") + } + } + } catch (e: Exception) { + println(" ⚠️ Error creating BagLotLine: ${e.message}") + e.printStackTrace() + // 不中断主流程,只记录错误 + } processedIds += line.stockOutLineId println(" ✓ Line processed successfully") } catch (e: Exception) {