浏览代码

update

master
CANCERYS\kw093 1 个月前
父节点
当前提交
23e1ff5c5f
共有 6 个文件被更改,包括 211 次插入54 次删除
  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 查看文件

@@ -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.LaneBtn
import com.ffii.fpsms.modules.deliveryOrder.web.models.LaneRow 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.StoreLaneSummary
import com.ffii.fpsms.modules.deliveryOrder.web.models.DoPickOrderSummaryItem
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
import java.time.LocalDate import java.time.LocalDate
import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderRecordRepository


@Service @Service
class DoPickOrderQueryService( class DoPickOrderQueryService(
private val doPickOrderRepository: DoPickOrderRepository, private val doPickOrderRepository: DoPickOrderRepository,
private val jdbcDao: JdbcDao
private val jdbcDao: JdbcDao,
private val doPickOrderRecordRepository: DoPickOrderRecordRepository
) { ) {
fun getSummaryByStore(storeId: String, requiredDate: LocalDate?): StoreLaneSummary { fun getSummaryByStore(storeId: String, requiredDate: LocalDate?): StoreLaneSummary {
@@ -25,15 +28,25 @@ class DoPickOrderQueryService(
else -> storeId 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, actualStoreId,
targetDate, targetDate,
listOf(DoPickOrderStatus.pending, DoPickOrderStatus.released, DoPickOrderStatus.completed) 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!!) val hasNonIssueLines = checkDoPickOrderHasNonIssueLines(doPickOrder.id!!)
if (!hasNonIssueLines) { if (!hasNonIssueLines) {
println("🔍 DEBUG: Filtering out DoPickOrder ${doPickOrder.id} - all lines are issues") println("🔍 DEBUG: Filtering out DoPickOrder ${doPickOrder.id} - all lines are issues")
@@ -41,9 +54,34 @@ class DoPickOrderQueryService(
hasNonIssueLines 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) -> .mapValues { (_, list) ->
LaneBtn( LaneBtn(
truckLanceCode = list.first().truckLanceCode ?: "", truckLanceCode = list.first().truckLanceCode ?: "",
@@ -72,6 +110,7 @@ class DoPickOrderQueryService(
return StoreLaneSummary(storeId = storeId, rows = timeGroups) return StoreLaneSummary(storeId = storeId, rows = timeGroups)
} }
private fun checkDoPickOrderHasNonIssueLines(doPickOrderId: Long): Boolean { private fun checkDoPickOrderHasNonIssueLines(doPickOrderId: Long): Boolean {
return try { return try {
val totalLinesSql = """ val totalLinesSql = """
@@ -105,4 +144,54 @@ class DoPickOrderQueryService(
true 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 查看文件

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


+ 6
- 1
src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/DoDetailResponse.kt 查看文件

@@ -52,4 +52,9 @@ data class AssignByLaneRequest(
val truckDepartureTime: String?, // 可选:限定出车时间 val truckDepartureTime: String?, // 可选:限定出车时间
val truckLanceCode: String , val truckLanceCode: String ,
val requiredDate: LocalDate? // 必填:车道编号 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 查看文件

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


+ 94
- 46
src/main/java/com/ffii/fpsms/modules/stock/service/SuggestedPickLotService.kt 查看文件

@@ -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.pickOrder.enums.PickOrderLineStatus
import com.ffii.fpsms.modules.stock.entity.projection.StockOutLineInfo import com.ffii.fpsms.modules.stock.entity.projection.StockOutLineInfo
import com.ffii.fpsms.modules.stock.entity.StockOutLIneRepository import com.ffii.fpsms.modules.stock.entity.StockOutLIneRepository
import com.ffii.fpsms.modules.stock.web.model.StockOutStatus
@Service @Service
open class SuggestedPickLotService( open class SuggestedPickLotService(
val suggestedPickLotRepository: SuggestPickLotRepository, val suggestedPickLotRepository: SuggestPickLotRepository,
@@ -282,71 +283,118 @@ open class SuggestedPickLotService(
return suggestedPickLotRepository.saveAllAndFlush(request) return suggestedPickLotRepository.saveAllAndFlush(request)
} }
private fun createStockOutLineForSuggestion( 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 // Get or create StockOut
val stockOut = stockOutRepository.findByConsoPickOrderCode(pickOrder.consoCode ?: "") val stockOut = stockOutRepository.findByConsoPickOrderCode(pickOrder.consoCode ?: "")
.orElseGet { .orElseGet {
// Create new StockOut if it doesn't exist
val newStockOut = StockOut().apply { val newStockOut = StockOut().apply {
this.consoPickOrderCode = pickOrder.consoCode ?: "" this.consoPickOrderCode = pickOrder.consoCode ?: ""
this.type = pickOrderTypeValue // Use pick order type (do, job, material, etc.)
this.status = StockOutStatus.PENDING.status
} }
stockOutRepository.save(newStockOut) 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 { val stockOutLine = StockOutLine().apply {
this.item = item
this.qty = 0.0
this.stockOut = stockOut 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.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 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]) @Transactional(rollbackFor = [Exception::class])
open fun resuggestPickOrder(pickOrderId: Long): MessageResponse { open fun resuggestPickOrder(pickOrderId: Long): MessageResponse {
try { try {
@@ -379,7 +427,7 @@ open class SuggestedPickLotService(
// Only resuggest if the pick order has rejected stock out lines // Only resuggest if the pick order has rejected stock out lines
pickOrderToCheck.pickOrderLines.any { pol -> pickOrderToCheck.pickOrderLines.any { pol ->
val stockOutLines = stockOutLIneRepository.findAllByPickOrderLineIdAndDeletedFalse(pol.id!!) 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) { if (hasRejectedStockOutLine) {
println("Pick Order ${pickOrderToCheck.code} has rejected stock out lines - will resuggest") 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 查看文件

@@ -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`;

正在加载...
取消
保存