Quellcode durchsuchen

po detail ui add deleted button and ui update

production
CANCERYS\kw093 vor 1 Tag
Ursprung
Commit
7f62902a62
2 geänderte Dateien mit 69 neuen und 5 gelöschten Zeilen
  1. +64
    -5
      src/main/java/com/ffii/fpsms/modules/stock/service/StockInLineService.kt
  2. +5
    -0
      src/main/java/com/ffii/fpsms/modules/stock/web/StockInLineController.kt

+ 64
- 5
src/main/java/com/ffii/fpsms/modules/stock/service/StockInLineService.kt Datei anzeigen

@@ -31,6 +31,7 @@ import com.ffii.fpsms.modules.jobOrder.enums.JobOrderStatus
import com.ffii.fpsms.modules.master.entity.ItemUomRespository
import com.ffii.fpsms.modules.master.entity.WarehouseRepository
import com.ffii.fpsms.modules.master.service.ItemUomService
//import com.ffii.fpsms.modules.master.service.BomOutputQtyService
import com.ffii.fpsms.modules.master.service.PrinterService
import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrder
import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrderLine
@@ -110,6 +111,7 @@ open class StockInLineService(
@Value("\${scheduler.m18Grn.createEnabled:false}") private val m18GrnCreateEnabled: Boolean,
/** Recent window for PO stock-in alerts (pending / receiving) in nav / list UI. */
@Value("\${fpsms.purchase-stock-in-alert.lookback-days:7}") private val purchaseStockInAlertLookbackDays: Int,
// private val bomOutputQtyService: BomOutputQtyService,
) : AbstractBaseEntityService<StockInLine, Long, StockInLineRepository>(jdbcDao, stockInLineRepository) {

private val logger = LoggerFactory.getLogger(StockInLineService::class.java)
@@ -124,6 +126,63 @@ open class StockInLineService(
return stockInLineRepository.findStockInLineInfoByIdAndStatusAndDeletedFalse(id = stockInLineId, status = StockInLineStatus.RECEIVED.status).orElseThrow()
}

/**
* Soft-delete a PO stock-in line that has not been put away yet.
* Also soft-deletes linked inventory lot / lot lines when no stock was received into inventory.
*/
@Transactional
open fun softDelete(id: Long): MessageResponse {
val sil = stockInLineRepository.findById(id).orElseThrow {
ResponseStatusException(HttpStatus.NOT_FOUND, "stockInLineId $id not found")
}
if (sil.deleted == true) {
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Stock in line already deleted")
}

val status = (sil.status ?: "").lowercase()
if (status == StockInLineStatus.COMPLETE.status || status == StockInLineStatus.PARTIALLY_COMPLETE.status) {
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Cannot delete: stock in line already put away")
}

val lotId = sil.inventoryLot?.id
val putAwayQty = if (lotId != null) {
inventoryLotLineRepository.findAllByInventoryLotId(lotId)
.sumOf { it.inQty ?: BigDecimal.ZERO }
} else {
BigDecimal.ZERO
}
if (putAwayQty > BigDecimal.ZERO) {
throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Cannot delete: stock in line already put away")
}

sil.deleted = true
saveAndFlush(sil)

sil.inventoryLot?.let { lot ->
lot.deleted = true
inventoryLotRepository.saveAndFlush(lot)
inventoryLotLineRepository.findAllByInventoryLotId(lot.id!!).forEach { line ->
line.deleted = true
inventoryLotLineRepository.save(line)
}
}

sil.purchaseOrderLine?.let { pol ->
updatePurchaseOrderLineStatus(pol)
pol.purchaseOrder?.let { updatePurchaseOrderStatus(it) }
}

return MessageResponse(
id = sil.id,
code = sil.itemNo,
name = sil.item?.name,
type = "stock in line deleted",
message = "delete success",
errorPosition = null,
entity = null,
)
}

open fun purchaseStockInAlertSinceDays(overrideDays: Int?): LocalDateTime {
val d = (overrideDays ?: purchaseStockInAlertLookbackDays).coerceIn(1, 90)
return LocalDateTime.now().minusDays(d.toLong())
@@ -366,9 +425,8 @@ open class StockInLineService(
}
// Set demandQty based on source
if (jo != null && jo?.bom != null) {
// For job orders, demandQty comes from BOM's outputQty
//this.demandQty = bomOutputQtyService.stockOutputQty(jo?.bom)
this.demandQty = jo?.bom?.outputQty

} else if (pol != null && item.id != null) {
val m18UomId = pol.uomM18?.id
val qtyM18 = pol.qtyM18
@@ -936,6 +994,7 @@ open class StockInLineService(
// Set demandQty based on source
if (this.jobOrder != null && this.jobOrder?.bom != null) {
// For job orders, demandQty comes from BOM's outputQty
//this.demandQty = this.jobOrder?.bom?.let { bomOutputQtyService.stockOutputQty(it) } ?: this.demandQty
this.demandQty = this.jobOrder?.bom?.outputQty ?: this.demandQty
} else if (this.purchaseOrderLine != null && this.item?.id != null) {
val itemId = this.item!!.id!!
@@ -1020,7 +1079,7 @@ open class StockInLineService(
if (putAwayStockQty >= requiredStockQty) {
val _tStatus = System.nanoTime()
stockInLine.apply {
val isWipJobOrder = stockInLine.jobOrder?.bom?.description == "WIP"
val isWipJobOrder = stockInLine.jobOrder?.bom?.bomKind == "WIP"
this.status = if (isWipJobOrder) {
StockInLineStatus.COMPLETE.status
} else {
@@ -1315,8 +1374,8 @@ open class StockInLineService(
val item = stockInLine.item ?: return

val _tInv = System.nanoTime()
val inventory = inventoryRepository.findFirstByItemIdAndDeletedIsFalseOrderByIdAsc(item.id!!) ?: return
_logStep("inventoryRepository.findFirstByItemIdAndDeletedIsFalseOrderByIdAsc", _tInv)
val inventory = itemUomService.findInventoryForItemBaseUom(item.id!!) ?: return
_logStep("inventoryRepository.findInventoryForItemBaseUom", _tInv)

// ✅ 修复:查询最新的 stock_ledger 记录,基于前一笔 balance 计算
val _tLatest = System.nanoTime()


+ 5
- 0
src/main/java/com/ffii/fpsms/modules/stock/web/StockInLineController.kt Datei anzeigen

@@ -63,6 +63,11 @@ class StockInLineController(
return stockInLineService.update(newItem)
}

@PostMapping("/delete/{stockInLineId}")
fun delete(@PathVariable stockInLineId: Long): MessageResponse {
return stockInLineService.softDelete(stockInLineId)
}

@PostMapping("/download-label")
@Throws(UnsupportedEncodingException::class, NoSuchMessageException::class, ParseException::class, Exception::class)
fun printLabel(@Valid @RequestBody request: ExportQrCodeRequest, response: HttpServletResponse) {


Laden…
Abbrechen
Speichern