Browse Source

update

master
CANCERYS\kw093 1 month ago
parent
commit
23e1ff5c5f
6 changed files with 211 additions and 54 deletions
  1. +95
    -6
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderQueryService.kt
  2. +1
    -0
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderService.kt
  3. +6
    -1
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/DoDetailResponse.kt
  4. +6
    -1
      src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickOrderService.kt
  5. +94
    -46
      src/main/java/com/ffii/fpsms/modules/stock/service/SuggestedPickLotService.kt
  6. +9
    -0
      src/main/resources/db/changelog/changes/20251106_01_enson/01_altertable_enson.sql

+ 95
- 6
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderQueryService.kt View File

@@ -6,13 +6,16 @@ import com.ffii.fpsms.modules.deliveryOrder.enums.DoPickOrderStatus
import com.ffii.fpsms.modules.deliveryOrder.web.models.LaneBtn
import com.ffii.fpsms.modules.deliveryOrder.web.models.LaneRow
import com.ffii.fpsms.modules.deliveryOrder.web.models.StoreLaneSummary
import com.ffii.fpsms.modules.deliveryOrder.web.models.DoPickOrderSummaryItem
import org.springframework.stereotype.Service
import java.time.LocalDate
import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderRecordRepository

@Service
class DoPickOrderQueryService(
private val doPickOrderRepository: DoPickOrderRepository,
private val jdbcDao: JdbcDao
private val jdbcDao: JdbcDao,
private val doPickOrderRecordRepository: DoPickOrderRecordRepository
) {
fun getSummaryByStore(storeId: String, requiredDate: LocalDate?): StoreLaneSummary {
@@ -25,15 +28,25 @@ class DoPickOrderQueryService(
else -> storeId
}
val allRecords = doPickOrderRepository.findByStoreIdAndRequiredDeliveryDateAndTicketStatusIn(
// Query active do_pick_order records (pending, released, completed that haven't been moved yet)
val activeRecords = doPickOrderRepository.findByStoreIdAndRequiredDeliveryDateAndTicketStatusIn(
actualStoreId,
targetDate,
listOf(DoPickOrderStatus.pending, DoPickOrderStatus.released, DoPickOrderStatus.completed)
)
println("🔍 DEBUG: Found ${allRecords.size} records for date $targetDate")
// Query completed records from do_pick_order_record table
val completedRecords = doPickOrderRecordRepository.findByStoreIdAndRequiredDeliveryDateAndTicketStatusIn(
actualStoreId,
targetDate,
listOf(DoPickOrderStatus.completed)
)
val filteredRecords = allRecords.filter { doPickOrder ->
println("🔍 DEBUG: Found ${activeRecords.size} active records for date $targetDate")
println("🔍 DEBUG: Found ${completedRecords.size} completed records for date $targetDate")
// Filter active records (check for non-issue lines)
val filteredActiveRecords = activeRecords.filter { doPickOrder ->
val hasNonIssueLines = checkDoPickOrderHasNonIssueLines(doPickOrder.id!!)
if (!hasNonIssueLines) {
println("🔍 DEBUG: Filtering out DoPickOrder ${doPickOrder.id} - all lines are issues")
@@ -41,9 +54,34 @@ class DoPickOrderQueryService(
hasNonIssueLines
}
println("🔍 DEBUG: After filtering, ${filteredRecords.size} records remain")
// For completed records, check if they have non-issue lines in the record table
val filteredCompletedRecords = completedRecords.filter { record ->
val hasNonIssueLines = checkDoPickOrderRecordHasNonIssueLines(record.id!!)
if (!hasNonIssueLines) {
println("🔍 DEBUG: Filtering out DoPickOrderRecord ${record.id} - all lines are issues")
}
hasNonIssueLines
}
// Combine both lists - need to create a common interface or convert to a common type
// Since both have the same fields we need, we can create a wrapper or use a data class
val allRecords = filteredActiveRecords.map {
DoPickOrderSummaryItem(
truckDepartureTime = it.truckDepartureTime,
truckLanceCode = it.truckLanceCode,
handledBy = it.handledBy
)
} + filteredCompletedRecords.map {
DoPickOrderSummaryItem(
truckDepartureTime = it.truckDepartureTime,
truckLanceCode = it.truckLanceCode,
handledBy = it.handledBy
)
}
println("🔍 DEBUG: After filtering, ${allRecords.size} records remain (${filteredActiveRecords.size} active + ${filteredCompletedRecords.size} completed)")
val grouped = filteredRecords.groupBy { it.truckDepartureTime to it.truckLanceCode }
val grouped = allRecords.groupBy { it.truckDepartureTime to it.truckLanceCode }
.mapValues { (_, list) ->
LaneBtn(
truckLanceCode = list.first().truckLanceCode ?: "",
@@ -72,6 +110,7 @@ class DoPickOrderQueryService(
return StoreLaneSummary(storeId = storeId, rows = timeGroups)
}
private fun checkDoPickOrderHasNonIssueLines(doPickOrderId: Long): Boolean {
return try {
val totalLinesSql = """
@@ -105,4 +144,54 @@ class DoPickOrderQueryService(
true
}
}
// Add new method to check non-issue lines for records
private fun checkDoPickOrderRecordHasNonIssueLines(recordId: Long): Boolean {
return try {
// First get the record_id from do_pick_order_record
val recordSql = """
SELECT record_id
FROM fpsmsdb.do_pick_order_record dpor
WHERE dpor.id = :recordId
""".trimIndent()
val recordResult = jdbcDao.queryForList(recordSql, mapOf("recordId" to recordId))
val recordIdValue = (recordResult.firstOrNull()?.get("record_id") as? Number)?.toLong()
if (recordIdValue == null) {
return true // If no record_id, assume it's valid
}
// Check do_pick_order_line_record table
val totalLinesSql = """
SELECT COUNT(*) as total_lines
FROM fpsmsdb.do_pick_order_line_record dpolr
WHERE dpolr.record_id = :recordId
AND dpolr.deleted = 0
""".trimIndent()
val totalLinesResult = jdbcDao.queryForList(totalLinesSql, mapOf("recordId" to recordIdValue))
val totalLines = (totalLinesResult.firstOrNull()?.get("total_lines") as? Number)?.toInt() ?: 0
if (totalLines == 0) {
return true
}
val nonIssueLinesSql = """
SELECT COUNT(*) as non_issue_lines
FROM fpsmsdb.do_pick_order_line_record dpolr
WHERE dpolr.record_id = :recordId
AND dpolr.deleted = 0
AND (dpolr.status IS NULL OR dpolr.status != 'issue')
""".trimIndent()
val nonIssueLinesResult = jdbcDao.queryForList(nonIssueLinesSql, mapOf("recordId" to recordIdValue))
val nonIssueLines = (nonIssueLinesResult.firstOrNull()?.get("non_issue_lines") as? Number)?.toInt() ?: 0
nonIssueLines > 0
} catch (e: Exception) {
println("❌ Error checking non-issue lines for record: ${e.message}")
true
}
}
}

+ 1
- 0
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoPickOrderService.kt View File

@@ -56,6 +56,7 @@ open class DoPickOrderService(
private val truckRepository: TruckRepository,
private val doPickOrderLineRepository: DoPickOrderLineRepository,
@Lazy private val deliveryOrderRepository: DeliveryOrderRepository,
private val doPickOrderLineRecordRepository: DoPickOrderLineRecordRepository
) {
open fun findReleasedDoPickOrders(): List<DoPickOrder> {


+ 6
- 1
src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/DoDetailResponse.kt View File

@@ -52,4 +52,9 @@ data class AssignByLaneRequest(
val truckDepartureTime: String?, // 可选:限定出车时间
val truckLanceCode: String ,
val requiredDate: LocalDate? // 必填:车道编号
)
)
data class DoPickOrderSummaryItem(
val truckDepartureTime: java.time.LocalTime?,
val truckLanceCode: String?,
val handledBy: Long?
)

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

@@ -3570,7 +3570,10 @@ ORDER BY
it.deleted == false &&
it.assignTo?.id == userId &&
it.type?.value == "do" &&
(it.status == PickOrderStatus.RELEASED || it.status == PickOrderStatus.PENDING)
(it.status == PickOrderStatus.RELEASED ||
it.status == PickOrderStatus.PENDING ||
it.status == PickOrderStatus.PICKING ||
it.status == PickOrderStatus.ASSIGNED)
}
if (userPickOrders.isEmpty()) {
@@ -3867,6 +3870,8 @@ ORDER BY
mapOf(
"id" to lineId,
"pickOrderLineId" to lineId,
"pickOrderId" to po.id,
"requiredQty" to pol.qty,
"status" to pol.status?.value,
"item" to mapOf(


+ 94
- 46
src/main/java/com/ffii/fpsms/modules/stock/service/SuggestedPickLotService.kt View File

@@ -38,6 +38,7 @@ import com.ffii.fpsms.modules.master.entity.ItemsRepository
import com.ffii.fpsms.modules.pickOrder.enums.PickOrderLineStatus
import com.ffii.fpsms.modules.stock.entity.projection.StockOutLineInfo
import com.ffii.fpsms.modules.stock.entity.StockOutLIneRepository
import com.ffii.fpsms.modules.stock.web.model.StockOutStatus
@Service
open class SuggestedPickLotService(
val suggestedPickLotRepository: SuggestPickLotRepository,
@@ -282,71 +283,118 @@ open class SuggestedPickLotService(
return suggestedPickLotRepository.saveAllAndFlush(request)
}
private fun createStockOutLineForSuggestion(
suggestion: SuggestedPickLot,
pickOrder: PickOrder
): StockOutLine? {
try {
val suggestedLotLine = suggestion.suggestedLotLine
val pickOrderLine = suggestion.pickOrderLine
if (suggestedLotLine == null || pickOrderLine == null) {
println("Cannot create stock out line: missing suggestedLotLine or pickOrderLine")
return null
}
suggestion: SuggestedPickLot,
pickOrder: PickOrder
): StockOutLine? {
try {
val suggestedLotLine = suggestion.suggestedLotLine
val pickOrderLine = suggestion.pickOrderLine
// FIX: Allow creating stock out line even when suggestedLotLine is null (insufficient stock case)
if (pickOrderLine == null) {
println("Cannot create stock out line: missing pickOrderLine")
return null
}
// Get pick order type value (do, job, material, etc.)
val pickOrderTypeValue = pickOrder.type?.value ?: "do"
// If suggestedLotLine is null, create stock out line with inventoryLotLineId = null
if (suggestedLotLine == null) {
println("Creating stock out line with no lot (insufficient stock) for pickOrderLineId: ${pickOrderLine.id}, type: $pickOrderTypeValue")
// Check if stock out line already exists
val existingStockOutLine = stockOutLIneRepository.findByPickOrderLineIdAndInventoryLotLineIdAndDeletedFalse(
pickOrderLine.id!!,
suggestedLotLine.id!!
)
// Check if stock out line already exists for this pick order line with null lot
val existingStockOutLineInfo = stockOutLIneRepository
.findAllByPickOrderLineIdAndDeletedFalse(pickOrderLine.id!!)
.find { it.inventoryLotLineId == null }
if (existingStockOutLine.isNotEmpty()) {
println("Stock out line already exists for pickOrderLineId: ${pickOrderLine.id}, inventoryLotLineId: ${suggestedLotLine.id}")
return existingStockOutLine.first()
if (existingStockOutLineInfo != null) {
println("Stock out line already exists for pickOrderLineId: ${pickOrderLine.id} with no lot")
// Get the actual entity by ID
return stockOutLIneRepository.findById(existingStockOutLineInfo.id!!).orElse(null)
}
// Get or create StockOut
val stockOut = stockOutRepository.findByConsoPickOrderCode(pickOrder.consoCode ?: "")
.orElseGet {
// Create new StockOut if it doesn't exist
val newStockOut = StockOut().apply {
this.consoPickOrderCode = pickOrder.consoCode ?: ""
this.type = pickOrderTypeValue // Use pick order type (do, job, material, etc.)
this.status = StockOutStatus.PENDING.status
}
stockOutRepository.save(newStockOut)
}
// Update pick order line status to PICKING
val updatedPickOrderLine = pickOrderLineRepository.saveAndFlush(
pickOrderLine.apply {
this.status = PickOrderLineStatus.PICKING
}
)
// Get item
val item = itemRepository.findById(updatedPickOrderLine.item!!.id!!).orElseThrow()
// Create stock out line
val item = pickOrderLine.item ?: itemRepository.findById(pickOrderLine.item!!.id!!).orElseThrow()
// Create stock out line with inventoryLotLineId = null
val stockOutLine = StockOutLine().apply {
this.item = item
this.qty = 0.0
this.stockOut = stockOut
this.inventoryLotLine = suggestedLotLine
this.pickOrderLine = updatedPickOrderLine
this.pickOrderLine = pickOrderLine
this.inventoryLotLine = null // No lot available
this.qty = (suggestion.qty ?: BigDecimal.ZERO).toDouble()
this.status = StockOutLineStatus.PENDING.status
this.deleted = false
}
val savedStockOutLine = stockOutLIneRepository.saveAndFlush(stockOutLine)
println(" Created stock out line ID: ${savedStockOutLine.id} for suggestion ID: ${suggestion.id}")
val savedStockOutLine = stockOutLIneRepository.save(stockOutLine)
println("Created stock out line ${savedStockOutLine.id} with no lot for pickOrderLineId: ${pickOrderLine.id}")
return savedStockOutLine
} catch (e: Exception) {
println("❌ Error creating stock out line for suggestion: ${e.message}")
e.printStackTrace()
return null
}
// Original logic for when suggestedLotLine is not null
// Check if stock out line already exists
val existingStockOutLine = stockOutLIneRepository.findByPickOrderLineIdAndInventoryLotLineIdAndDeletedFalse(
pickOrderLine.id!!,
suggestedLotLine.id!!
)
if (existingStockOutLine.isNotEmpty()) {
println("Stock out line already exists for pickOrderLineId: ${pickOrderLine.id}, inventoryLotLineId: ${suggestedLotLine.id}")
return existingStockOutLine.first()
}
// Get or create StockOut
val stockOut = stockOutRepository.findByConsoPickOrderCode(pickOrder.consoCode ?: "")
.orElseGet {
// Create new StockOut if it doesn't exist
val newStockOut = StockOut().apply {
this.consoPickOrderCode = pickOrder.consoCode ?: ""
this.type = pickOrderTypeValue // Use pick order type (do, job, material, etc.)
this.status = StockOutStatus.PENDING.status
}
stockOutRepository.save(newStockOut)
}
// Update pick order line status to PICKING
val updatedPickOrderLine = pickOrderLineRepository.saveAndFlush(
pickOrderLine.apply {
this.status = PickOrderLineStatus.PICKING
}
)
// Get item
val item = itemRepository.findById(updatedPickOrderLine.item!!.id!!).orElseThrow()
// Create stock out line
val stockOutLine = StockOutLine().apply {
this.item = item
this.qty = 0.0
this.stockOut = stockOut
this.inventoryLotLine = suggestedLotLine
this.pickOrderLine = updatedPickOrderLine
this.status = StockOutLineStatus.PENDING.status
}
val savedStockOutLine = stockOutLIneRepository.saveAndFlush(stockOutLine)
println(" Created stock out line ID: ${savedStockOutLine.id} for suggestion ID: ${suggestion.id}")
return savedStockOutLine
} catch (e: Exception) {
println("❌ Error creating stock out line for suggestion: ${e.message}")
e.printStackTrace()
return null
}
}
@Transactional(rollbackFor = [Exception::class])
open fun resuggestPickOrder(pickOrderId: Long): MessageResponse {
try {
@@ -379,7 +427,7 @@ open class SuggestedPickLotService(
// Only resuggest if the pick order has rejected stock out lines
pickOrderToCheck.pickOrderLines.any { pol ->
val stockOutLines = stockOutLIneRepository.findAllByPickOrderLineIdAndDeletedFalse(pol.id!!)
val hasRejectedStockOutLine = stockOutLines.any { it.status == "rejected" }
val hasRejectedStockOutLine = stockOutLines.any { it.status.equals("rejected", ignoreCase = true)}
if (hasRejectedStockOutLine) {
println("Pick Order ${pickOrderToCheck.code} has rejected stock out lines - will resuggest")


+ 9
- 0
src/main/resources/db/changelog/changes/20251106_01_enson/01_altertable_enson.sql View File

@@ -0,0 +1,9 @@
-- liquibase formatted sql
-- changeset enson:altertable_enson

ALTER TABLE `fpsmsdb`.`items`
ADD COLUMN `store_id` VARCHAR(255) After `type`,
ADD COLUMN `MTMSPickRoutingID` INT After `store_id`;

ALTER TABLE `fpsmsdb`.`truck`
ADD COLUMN `districtReference` INT After `LoadingSequence`;

Loading…
Cancel
Save