| @@ -2,6 +2,7 @@ package com.ffii.fpsms.modules.purchaseOrder.entity | |||
| import com.ffii.core.support.AbstractRepository | |||
| import com.ffii.fpsms.modules.purchaseOrder.entity.projections.PurchaseOrderLineInfo | |||
| import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderLineStatus | |||
| import org.springframework.stereotype.Repository | |||
| import java.io.Serializable | |||
| @@ -10,6 +11,6 @@ interface PurchaseOrderLineRepository : AbstractRepository<PurchaseOrderLine, Lo | |||
| fun findByM18DataLogIdAndDeletedIsFalse(m18datalogId: Serializable): PurchaseOrderLine? | |||
| fun findAllPurchaseOrderLineInfoByPurchaseOrderIdAndDeletedIsFalse(purchaseOrderId: Long): List<PurchaseOrderLineInfo> | |||
| fun findAllByPurchaseOrderIdAndDeletedIsFalse(purchaseOrderId: Long): List<PurchaseOrderLine> | |||
| // fun find | |||
| fun findAllByPurchaseOrderIdAndStatusNotAndDeletedIsFalse(purchaseOrderId: Long, status: PurchaseOrderLineStatus): List<PurchaseOrderLine> | |||
| // fun find | |||
| } | |||
| @@ -6,11 +6,13 @@ import com.ffii.fpsms.m18.entity.M18DataLogRepository | |||
| import com.ffii.fpsms.modules.master.entity.ShopRepository | |||
| import com.ffii.fpsms.modules.master.service.CurrencyService | |||
| import com.ffii.fpsms.modules.master.service.ShopService | |||
| import com.ffii.fpsms.modules.master.web.models.MessageResponse | |||
| import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrder | |||
| import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrderLineRepository | |||
| import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrderRepository | |||
| import com.ffii.fpsms.modules.purchaseOrder.entity.projections.PoLineWithStockInLine | |||
| import com.ffii.fpsms.modules.purchaseOrder.entity.projections.PurchaseOrderInfo | |||
| import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderLineStatus | |||
| import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderStatus | |||
| import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderType | |||
| import com.ffii.fpsms.modules.purchaseOrder.web.model.SavePurchaseOrderRequest | |||
| @@ -131,5 +133,38 @@ open class PurchaseOrderService( | |||
| return savedPurchaseOrder | |||
| } | |||
| fun checkPolAndCompletePo(id: Long): MessageResponse { | |||
| val unfinishedLines = purchaseOrderLineRepository | |||
| .findAllByPurchaseOrderIdAndStatusNotAndDeletedIsFalse( | |||
| purchaseOrderId = id, | |||
| status = PurchaseOrderLineStatus.COMPLETED | |||
| ) | |||
| val po = purchaseOrderRepository.findById(id).orElseThrow() | |||
| if (unfinishedLines.isEmpty()) { | |||
| po.apply { | |||
| status = PurchaseOrderStatus.COMPLETED | |||
| } | |||
| val savedPo = purchaseOrderRepository.saveAndFlush(po) | |||
| return MessageResponse( | |||
| id = savedPo.id, | |||
| name = savedPo.code, | |||
| code = savedPo.code, | |||
| type = PurchaseOrderStatus.COMPLETED.value, | |||
| message = "Update Success", | |||
| errorPosition = null, | |||
| entity = savedPo, | |||
| ) | |||
| } | |||
| val unfinishedIds = unfinishedLines.map { it.id } | |||
| return MessageResponse( | |||
| id = po.id, | |||
| name = po.code, | |||
| code = null, | |||
| type = PurchaseOrderStatus.RECEIVING.value, | |||
| message = "Still have unfinished po lines", | |||
| errorPosition = "Unfinished", | |||
| entity = unfinishedIds, | |||
| ) | |||
| } | |||
| } | |||
| @@ -3,13 +3,11 @@ package com.ffii.fpsms.modules.purchaseOrder.web | |||
| import com.ffii.core.support.JdbcDao | |||
| import com.ffii.fpsms.modules.master.entity.Items | |||
| import com.ffii.fpsms.modules.master.service.ItemsService | |||
| import com.ffii.fpsms.modules.master.web.models.MessageResponse | |||
| import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrder | |||
| import com.ffii.fpsms.modules.purchaseOrder.entity.projections.PurchaseOrderInfo | |||
| import com.ffii.fpsms.modules.purchaseOrder.service.PurchaseOrderService | |||
| import org.springframework.web.bind.annotation.GetMapping | |||
| import org.springframework.web.bind.annotation.PathVariable | |||
| import org.springframework.web.bind.annotation.RequestMapping | |||
| import org.springframework.web.bind.annotation.RestController | |||
| import org.springframework.web.bind.annotation.* | |||
| @RestController | |||
| @RequestMapping("/po") | |||
| @@ -20,8 +18,13 @@ class PurchaseOrderController( | |||
| fun getPoList(): List<PurchaseOrderInfo> { | |||
| return purchaseOrderService.getPoList() | |||
| } | |||
| @GetMapping("/detail/{id}") | |||
| @GetMapping("/detail/{id}") // purchaseOrderId | |||
| fun getDetailedPo(@PathVariable id: Long): Map<String, Any> { | |||
| return purchaseOrderService.getDetailedPo(id) | |||
| } | |||
| @PostMapping("/check/{id}") // purchaseOrderId | |||
| fun checkPolAndCompletePo(@PathVariable id: Long): MessageResponse { | |||
| return purchaseOrderService.checkPolAndCompletePo(id) | |||
| } | |||
| } | |||
| @@ -4,6 +4,8 @@ import org.springframework.beans.factory.annotation.Value | |||
| interface QcResultInfo { | |||
| val id: Long | |||
| @get:Value("#{target.qcItem.id}") | |||
| val qcItemId: Long | |||
| @get:Value("#{target.qcItem.name}") | |||
| val name: String | |||
| @get:Value("#{target.qcItem.code}") | |||
| @@ -11,4 +11,5 @@ interface StockInLineRepository : AbstractRepository<StockInLine, Long> { | |||
| fun findAllStockInLineInfoByStockInIdAndDeletedFalse(stockInId: Long): List<StockInLineInfo> | |||
| fun findStockInLineInfoByIdAndDeletedFalse(id: Long): StockInLineInfo | |||
| fun findStockInLineInfoByIdInAndDeletedFalse(id: List<Long>): List<StockInLineInfo> | |||
| fun findStockInLineInfoByPurchaseOrderLineIdAndStatusNotAndDeletedFalse(purchaseOrderLineId: Long, status: String): List<StockInLineInfo> | |||
| } | |||
| @@ -2,7 +2,6 @@ package com.ffii.fpsms.modules.stock.service | |||
| import com.ffii.core.support.AbstractBaseEntityService | |||
| import com.ffii.core.support.JdbcDao | |||
| import com.ffii.core.utils.JsonUtils | |||
| import com.ffii.core.utils.QrCodeUtil | |||
| import com.ffii.fpsms.modules.common.CodeGenerator | |||
| import com.ffii.fpsms.modules.master.entity.ItemsRepository | |||
| @@ -27,6 +26,10 @@ import java.time.LocalDate | |||
| import java.time.LocalDateTime | |||
| import com.ffii.core.utils.PdfUtils; | |||
| import com.ffii.fpsms.modules.master.entity.WarehouseRepository | |||
| import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrderRepository | |||
| import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderLineStatus | |||
| import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderStatus | |||
| import com.ffii.fpsms.modules.stock.entity.projection.StockInLineInfo | |||
| import java.io.FileNotFoundException | |||
| import java.time.format.DateTimeFormatter | |||
| import kotlinx.serialization.Serializable | |||
| @@ -39,6 +42,7 @@ data class QrContent(val itemId: Long, val stockInLineId: Long) | |||
| @Service | |||
| open class StockInLineService( | |||
| private val jdbcDao: JdbcDao, | |||
| private val purchaseOrderRepository: PurchaseOrderRepository, | |||
| private val polRepository: PurchaseOrderLineRepository, | |||
| private val qcItemsRepository: QcItemRepository, | |||
| private val qcResultRepository: QcResultRepository, | |||
| @@ -51,6 +55,9 @@ open class StockInLineService( | |||
| private val warehouseRepository: WarehouseRepository, | |||
| ): AbstractBaseEntityService<StockInLine, Long, StockInLineRepository>(jdbcDao, stockInLineRepository) { | |||
| open fun getStockInLineInfo(stockInLineId: Long): StockInLineInfo { | |||
| return stockInLineRepository.findStockInLineInfoByIdAndDeletedFalse(stockInLineId) | |||
| } | |||
| @Throws(IOException::class) | |||
| @Transactional | |||
| open fun create(request: SaveStockInLineRequest): MessageResponse { | |||
| @@ -136,6 +143,44 @@ open class StockInLineService( | |||
| } | |||
| return null | |||
| } | |||
| @Throws(IOException::class) | |||
| @Transactional | |||
| fun updatePurchaseOrderStatus(request: SaveStockInLineRequest) { | |||
| if (request.status == StockInLineStatus.COMPLETE.status) { | |||
| val unfinishedLines = polRepository.findAllByPurchaseOrderIdAndStatusNotAndDeletedIsFalse( | |||
| purchaseOrderId = request.purchaseOrderId, | |||
| status = PurchaseOrderLineStatus.COMPLETED | |||
| ) | |||
| if (unfinishedLines.isEmpty()) { | |||
| val po = purchaseOrderRepository.findById(request.purchaseOrderId).orElseThrow() | |||
| po.apply { | |||
| status = PurchaseOrderStatus.COMPLETED | |||
| } | |||
| purchaseOrderRepository.saveAndFlush(po) | |||
| } else { | |||
| } | |||
| } | |||
| } | |||
| @Throws(IOException::class) | |||
| @Transactional | |||
| fun updatePurchaseOrderLineStatus(request: SaveStockInLineRequest) { | |||
| if (request.status == StockInLineStatus.COMPLETE.status) { | |||
| val unfinishedLines = stockInLineRepository.findStockInLineInfoByPurchaseOrderLineIdAndStatusNotAndDeletedFalse(purchaseOrderLineId = request.purchaseOrderLineId, status = request.status!!) | |||
| if (unfinishedLines.isEmpty()) { | |||
| // all stock in lines finished | |||
| // change status of purchase order line | |||
| val purchaseOrderLine = polRepository.findById(request.purchaseOrderLineId).orElseThrow() | |||
| purchaseOrderLine.apply { | |||
| status = PurchaseOrderLineStatus.COMPLETED | |||
| } | |||
| polRepository.saveAndFlush(purchaseOrderLine) | |||
| } else { | |||
| // still have unfinished lines | |||
| } | |||
| } | |||
| } | |||
| @Throws(IOException::class) | |||
| @Transactional | |||
| open fun update(request: SaveStockInLineRequest): MessageResponse { | |||
| @@ -164,6 +209,7 @@ open class StockInLineService( | |||
| if (request.status == StockInLineStatus.COMPLETE.status) { | |||
| savedInventoryLotLine = saveInventoryLotLineWhenStockIn(request = request, stockInLine = stockInLine) | |||
| } | |||
| // println("checkpoint1") | |||
| stockInLine.apply { | |||
| // user = null | |||
| this.productionDate = request.productionDate?.atStartOfDay() // maybe need to change the request to LocalDateTime | |||
| @@ -175,7 +221,12 @@ open class StockInLineService( | |||
| this.lotNo = stockInLine.lotNo ?: savedInventoryLot?.lotNo | |||
| } | |||
| val savedStockInLine = saveAndFlush(stockInLine) | |||
| // check if all line completed | |||
| updatePurchaseOrderLineStatus(request) | |||
| updatePurchaseOrderStatus(request) | |||
| // val allLineByStockInId = find | |||
| val lineInfo = stockInLineRepository.findStockInLineInfoByIdAndDeletedFalse(savedStockInLine.id!!) | |||
| // println("checkpoint2") | |||
| return MessageResponse( | |||
| id = savedStockInLine.id, | |||
| code = null, | |||
| @@ -196,6 +247,11 @@ open class StockInLineService( | |||
| errorPosition = "request.acceptedQty", | |||
| ) | |||
| } | |||
| // var newLineAcceptedQty = 0.0 | |||
| // if (request.rejectQty != null && request.rejectQty!! > BigDecimal.ZERO) { | |||
| // | |||
| // } | |||
| val newStockInLine = StockInLine() | |||
| newStockInLine.apply { | |||
| this.item = stockInLine.item | |||
| @@ -237,6 +293,9 @@ open class StockInLineService( | |||
| val savedEntries = stockInLineRepository.saveAllAndFlush(stockInLineEntries) | |||
| val ids = savedEntries.map { it.id!! } | |||
| val lineInfoList = stockInLineRepository.findStockInLineInfoByIdInAndDeletedFalse(ids) | |||
| // check if all line completed | |||
| updatePurchaseOrderLineStatus(request) | |||
| updatePurchaseOrderStatus(request) | |||
| return MessageResponse( | |||
| id = stockInLine.id, | |||
| @@ -291,5 +350,4 @@ open class StockInLineService( | |||
| "fileName" to qrCodeInfo[0].poCode | |||
| ); | |||
| } | |||
| } | |||
| @@ -1,6 +1,9 @@ | |||
| package com.ffii.fpsms.modules.stock.web | |||
| import com.ffii.fpsms.modules.master.web.models.MessageResponse | |||
| import com.ffii.fpsms.modules.qc.entity.projection.QcResultInfo | |||
| import com.ffii.fpsms.modules.stock.entity.StockInLine | |||
| import com.ffii.fpsms.modules.stock.entity.projection.StockInLineInfo | |||
| import com.ffii.fpsms.modules.stock.service.StockInLineService | |||
| import com.ffii.fpsms.modules.stock.web.model.ExportQrCodeRequest | |||
| import com.ffii.fpsms.modules.stock.web.model.SaveStockInLineRequest | |||
| @@ -9,10 +12,7 @@ import jakarta.validation.Valid | |||
| import net.sf.jasperreports.engine.JasperExportManager | |||
| import net.sf.jasperreports.engine.JasperPrint | |||
| import org.springframework.context.NoSuchMessageException | |||
| 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 org.springframework.web.bind.annotation.* | |||
| import java.io.OutputStream | |||
| import java.io.UnsupportedEncodingException | |||
| import java.text.ParseException | |||
| @@ -23,6 +23,10 @@ import java.text.ParseException | |||
| class StockInLineController( | |||
| private val stockInLineService: StockInLineService | |||
| ) { | |||
| @GetMapping("/{stockInLineId}") | |||
| fun get(@PathVariable stockInLineId: Long): StockInLineInfo { | |||
| return stockInLineService.getStockInLineInfo(stockInLineId) | |||
| } | |||
| @PostMapping("/create") | |||
| fun create(@Valid @RequestBody newItem: SaveStockInLineRequest): MessageResponse { | |||
| return stockInLineService.create(newItem) | |||
| @@ -47,5 +47,6 @@ data class SaveStockInLineRequest( | |||
| var receiptDate: LocalDate?, | |||
| var productionDate: LocalDate?, | |||
| var qcResult: List<SaveQcResultRequest>?, | |||
| var warehouseId: Long? | |||
| var warehouseId: Long?, | |||
| var rejectQty: BigDecimal? | |||
| ) | |||