Browse Source

update

master
CANCERYS\kw093 2 months ago
parent
commit
32b9bfcce6
6 changed files with 191 additions and 1 deletions
  1. +85
    -1
      src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt
  2. +5
    -0
      src/main/java/com/ffii/fpsms/modules/pickOrder/web/PickOrderController.kt
  3. +9
    -0
      src/main/java/com/ffii/fpsms/modules/pickOrder/web/models/LotSubstitutionConfirmRequest.kt
  4. +61
    -0
      src/main/java/com/ffii/fpsms/modules/stock/service/InventoryLotLineService.kt
  5. +6
    -0
      src/main/java/com/ffii/fpsms/modules/stock/web/InventoryLotLineController.kt
  6. +25
    -0
      src/main/java/com/ffii/fpsms/modules/stock/web/model/LotLineInfo.kt

+ 85
- 1
src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt View File

@@ -8,7 +8,6 @@ import com.ffii.fpsms.modules.jobOrder.entity.JobOrderRepository
import com.ffii.fpsms.modules.master.entity.ItemsRepository
import com.ffii.fpsms.modules.master.entity.UomConversionRepository
import com.ffii.fpsms.modules.master.service.ItemUomService
import com.ffii.fpsms.modules.master.web.models.MessageResponse
import com.ffii.fpsms.modules.pickOrder.entity.PickOrder
import com.ffii.fpsms.modules.deliveryOrder.enums.DoPickOrderStatus
import java.time.LocalTime
@@ -57,6 +56,8 @@ import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrder
import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderRecord
import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderRecordRepository
import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderRepository
import com.ffii.fpsms.modules.pickOrder.web.models.LotSubstitutionConfirmRequest
import com.ffii.fpsms.modules.master.web.models.MessageResponse
@Service
open class PickOrderService(
private val jdbcDao: JdbcDao,
@@ -3579,4 +3580,87 @@ open fun getPickOrdersByDateAndStore(storeId: String): Map<String, Any?> {
)
}
}
@Transactional(rollbackFor = [java.lang.Exception::class])
open fun confirmLotSubstitution(req: LotSubstitutionConfirmRequest): MessageResponse {
val zero = BigDecimal.ZERO

// Validate entities
val pol = req.pickOrderLineId.let { pickOrderLineRepository.findById(it).orElse(null) }
?: return MessageResponse(id = null, name = "Pick order line not found", code = "ERROR", type = "pickorder",
message = "Pick order line ${req.pickOrderLineId} not found", errorPosition = null)

val newIll = req.newInventoryLotLineId.let { inventoryLotLineRepository.findById(it).orElse(null) }
?: return MessageResponse(id = null, name = "New lot line not found", code = "ERROR", type = "pickorder",
message = "Inventory lot line ${req.newInventoryLotLineId} not found", errorPosition = null)

// Item consistency check
val polItemId = pol.item?.id
val newItemId = newIll.inventoryLot?.item?.id
if (polItemId == null || newItemId == null || polItemId != newItemId) {
return MessageResponse(
id = null, name = "Item mismatch", code = "ERROR", type = "pickorder",
message = "New lot line item does not match pick order line item", errorPosition = null
)
}

// 1) Update suggested pick lot (if provided): move holdQty from old ILL to new ILL and re-point the suggestion
if (req.originalSuggestedPickLotId != null && req.originalSuggestedPickLotId > 0) {
// Get current suggested ILL id and qty
val row = jdbcDao.queryForMap("""
SELECT spl.suggestedLotLineId AS oldIllId, COALESCE(spl.qty,0) AS qty
FROM suggested_pick_lot spl
WHERE spl.id = :splId
""".trimIndent(), mapOf("splId" to req.originalSuggestedPickLotId)).orElse(null)

if (row != null) {
val oldIllId = (row["oldIllId"] as Number?)?.toLong()
val qty = when (val qtyObj = row["qty"]) {
is BigDecimal -> qtyObj
is Number -> qtyObj.toDouble().toBigDecimal()
is String -> qtyObj.toBigDecimalOrNull() ?: zero
else -> zero
}

if (oldIllId != null && oldIllId != req.newInventoryLotLineId) {
// Decrease hold on old, increase on new
val oldIll = inventoryLotLineRepository.findById(oldIllId).orElse(null)
if (oldIll != null) {
oldIll.holdQty = (oldIll.holdQty ?: zero).minus(qty).max(zero)
inventoryLotLineRepository.save(oldIll)
}
val newIllEntity = inventoryLotLineRepository.findById(req.newInventoryLotLineId).orElse(null)
if (newIllEntity != null) {
newIllEntity.holdQty = (newIllEntity.holdQty ?: zero).plus(qty)
inventoryLotLineRepository.save(newIllEntity)
}
}

// Re-point suggestion to new ILL
jdbcDao.executeUpdate("""
UPDATE suggested_pick_lot
SET suggestedLotLineId = :newIllId
WHERE id = :splId
""".trimIndent(), mapOf("newIllId" to req.newInventoryLotLineId, "splId" to req.originalSuggestedPickLotId))
}
}

// 2) Update stock out line (if provided): re-point to new ILL; keep qty and status unchanged
if (req.stockOutLineId != null && req.stockOutLineId > 0) {
val sol = stockOutLIneRepository.findById(req.stockOutLineId).orElse(null)
if (sol != null) {
sol.inventoryLotLine = newIll
sol.item = pol.item
stockOutLIneRepository.save(sol)
}
}

return MessageResponse(
id = null,
name = "Lot substitution confirmed",
code = "SUCCESS",
type = "pickorder",
message = "Updated suggestion and stock out line to new lot line ${req.newInventoryLotLineId}",
errorPosition = null
)
}
}

+ 5
- 0
src/main/java/com/ffii/fpsms/modules/pickOrder/web/PickOrderController.kt View File

@@ -33,6 +33,7 @@ import java.time.format.DateTimeFormatter
import java.time.LocalDate
import com.ffii.fpsms.modules.pickOrder.entity.projection.PickOrderGroupInfo
import com.ffii.fpsms.modules.pickOrder.web.models.GetPickOrderInfoResponse
import com.ffii.fpsms.modules.pickOrder.web.models.LotSubstitutionConfirmRequest
@RestController
@RequestMapping("/pickOrder")
class PickOrderController(
@@ -282,4 +283,8 @@ fun autoAssignAndReleasePickOrderByTicket(
fun getPickOrdersByStore(@PathVariable storeId: String): Map<String, Any?> {
return pickOrderService.getPickOrdersByDateAndStore(storeId)
}
@PostMapping("/lot-substitution/confirm")
fun confirmLotSubstitution(@RequestBody req: LotSubstitutionConfirmRequest): MessageResponse {
return pickOrderService.confirmLotSubstitution(req)
}
}

+ 9
- 0
src/main/java/com/ffii/fpsms/modules/pickOrder/web/models/LotSubstitutionConfirmRequest.kt View File

@@ -0,0 +1,9 @@

package com.ffii.fpsms.modules.pickOrder.web.models

data class LotSubstitutionConfirmRequest(
val pickOrderLineId: Long,
val stockOutLineId: Long?, // optional
val originalSuggestedPickLotId: Long?, // optional
val newInventoryLotLineId: Long
)

+ 61
- 0
src/main/java/com/ffii/fpsms/modules/stock/service/InventoryLotLineService.kt View File

@@ -34,6 +34,11 @@ import kotlin.jvm.optionals.getOrNull
import com.ffii.fpsms.modules.master.web.models.MessageResponse
import com.ffii.fpsms.modules.stock.web.model.UpdateInventoryLotLineQuantitiesRequest
import com.ffii.fpsms.modules.stock.entity.InventoryRepository
import com.ffii.fpsms.modules.stock.web.model.QrCodeAnalysisRequest
import com.ffii.fpsms.modules.stock.web.model.QrCodeAnalysisResponse
import com.ffii.fpsms.modules.stock.web.model.ScannedLotInfo
import com.ffii.fpsms.modules.stock.web.model.SameItemLotInfo

@Service
open class InventoryLotLineService(
private val inventoryLotLineRepository: InventoryLotLineRepository,
@@ -278,4 +283,60 @@ open fun updateInventoryLotLineQuantities(request: UpdateInventoryLotLineQuantit
)
}
}

open fun analyzeQrCode(request: QrCodeAnalysisRequest): QrCodeAnalysisResponse {
val stockInLine = stockInLineRepository.findById(request.stockInLineId).orElseThrow()

// Try direct link first; fall back to first lot line in the linked inventoryLot
val scannedInventoryLotLine =
stockInLine.inventoryLotLine
?: stockInLine.inventoryLot?.inventoryLotLines?.firstOrNull()
?: throw IllegalStateException("No inventory lot line found for stockInLineId=${request.stockInLineId}")

val item = scannedInventoryLotLine.inventoryLot?.item
?: throw IllegalStateException("Item not found for lot line id=${scannedInventoryLotLine.id}")

// Collect same-item available lots; skip the scanned one; only remainingQty > 0
val sameItemLots = inventoryLotLineRepository
.findAllByInventoryLotItemIdAndStatus(request.itemId, InventoryLotLineStatus.AVAILABLE)
.asSequence()
.filter { it.id != scannedInventoryLotLine.id }
.mapNotNull { lotLine ->
val lot = lotLine.inventoryLot ?: return@mapNotNull null
val lotNo = lot.stockInLine?.lotNo ?: return@mapNotNull null
val uomDesc = lotLine.stockUom?.uom?.udfudesc ?: return@mapNotNull null

val inQty = lotLine.inQty ?: BigDecimal.ZERO
val outQty = lotLine.outQty ?: BigDecimal.ZERO
val holdQty = lotLine.holdQty ?: BigDecimal.ZERO
val remainingQty = inQty.minus(outQty).minus(holdQty)

if (remainingQty > BigDecimal.ZERO)
SameItemLotInfo(
lotNo = lotNo,
inventoryLotLineId = lotLine.id!!,
availableQty = remainingQty,
uom = uomDesc
)
else null
}
.toList()

val scannedLotNo = stockInLine.lotNo
?: stockInLine.inventoryLot?.stockInLine?.lotNo
?: throw IllegalStateException("Lot number not found for stockInLineId=${request.stockInLineId}")

return QrCodeAnalysisResponse(
itemId = request.itemId,
itemCode = item.code ?: "",
itemName = item.name ?: "",
scanned = ScannedLotInfo(
stockInLineId = request.stockInLineId,
lotNo = scannedLotNo,
inventoryLotLineId = scannedInventoryLotLine.id
?: throw IllegalStateException("inventoryLotLineId missing on scanned lot line")
),
sameItemLots = sameItemLots
)
}
}

+ 6
- 0
src/main/java/com/ffii/fpsms/modules/stock/web/InventoryLotLineController.kt View File

@@ -24,6 +24,8 @@ import java.math.BigDecimal
import java.text.ParseException
import com.ffii.fpsms.modules.master.web.models.MessageResponse
import com.ffii.fpsms.modules.stock.web.model.UpdateInventoryLotLineStatusRequest
import com.ffii.fpsms.modules.stock.web.model.QrCodeAnalysisRequest
import com.ffii.fpsms.modules.stock.web.model.QrCodeAnalysisResponse

@RequestMapping("/inventoryLotLine")
@RestController
@@ -100,4 +102,8 @@ class InventoryLotLineController (
fun updateInventoryLotLineQuantities(@RequestBody request: UpdateInventoryLotLineQuantitiesRequest): MessageResponse {
return inventoryLotLineService.updateInventoryLotLineQuantities(request)
}
@PostMapping("/analyze-qr-code")
fun analyzeQrCode(@RequestBody request: QrCodeAnalysisRequest): QrCodeAnalysisResponse {
return inventoryLotLineService.analyzeQrCode(request)
}
}

+ 25
- 0
src/main/java/com/ffii/fpsms/modules/stock/web/model/LotLineInfo.kt View File

@@ -14,4 +14,29 @@ data class LotLineInfo(
data class UpdateInventoryLotLineStatusRequest(
val inventoryLotLineId: Long,
val status: String
)
data class QrCodeAnalysisRequest(
val itemId: Long,
val stockInLineId: Long
)

data class ScannedLotInfo(
val stockInLineId: Long,
val lotNo: String,
val inventoryLotLineId: Long
)

data class SameItemLotInfo(
val lotNo: String,
val inventoryLotLineId: Long,
val availableQty: BigDecimal,
val uom: String
)

data class QrCodeAnalysisResponse(
val itemId: Long,
val itemCode: String,
val itemName: String,
val scanned: ScannedLotInfo,
val sameItemLots: List<SameItemLotInfo>
)

Loading…
Cancel
Save