浏览代码

update

master
CANCERYS\kw093 2 个月前
父节点
当前提交
2a119d0d23
共有 5 个文件被更改,包括 269 次插入83 次删除
  1. +4
    -1
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrder.kt
  2. +185
    -81
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt
  3. +4
    -1
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/DoDetailResponse.kt
  4. +7
    -0
      src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickOrderLineRepository.kt
  5. +69
    -0
      src/main/resources/db/changelog/changes/20250918_01_enson/01_create_group_enson.sql

+ 4
- 1
src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrder.kt 查看文件

@@ -19,7 +19,8 @@ class DoPickOrder {
@Column(name = "ticket_no", length = 50)
var ticketNo: String? = null
@Column(name = "pick_order_id")
var pickOrderId: Long? = null
@Enumerated(EnumType.STRING)
@Column(name = "ticket_status")
var ticketStatus: DoPickOrderStatus? = null
@@ -72,6 +73,7 @@ class DoPickOrder {
ticketStatus: DoPickOrderStatus,
truckId: Long? = null,
truckDepartureTime: LocalTime? = null,
pickOrderId: Long? = null,
itemId: Long? = null,
shopId: Long? = null,
shopPoSupplierId: Long? = null,
@@ -81,6 +83,7 @@ class DoPickOrder {
) {
this.storeId = storeId
this.ticketNo = ticketNo
this.pickOrderId = pickOrderId
this.ticketStatus = ticketStatus
this.truckId = truckId
this.truckDepartureTime = truckDepartureTime


+ 185
- 81
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt 查看文件

@@ -35,6 +35,18 @@ import com.ffii.fpsms.modules.deliveryOrder.enums.DoPickOrderStatus
import java.time.format.DateTimeFormatter
import com.ffii.fpsms.modules.pickOrder.entity.TruckRepository
import java.time.LocalTime
import com.ffii.fpsms.modules.stock.service.SuggestedPickLotService
import com.ffii.fpsms.modules.stock.entity.InventoryLotLineRepository
import com.ffii.fpsms.modules.stock.entity.StockOutRepository
import com.ffii.fpsms.modules.stock.entity.StockOutLIneRepository
import com.ffii.fpsms.modules.stock.entity.StockOut
import com.ffii.fpsms.modules.stock.entity.StockOutLine
import com.ffii.fpsms.modules.stock.web.model.StockOutStatus
import com.ffii.fpsms.modules.stock.web.model.StockOutLineStatus
import com.ffii.fpsms.modules.stock.web.model.SuggestedPickLotForPolRequest
import com.ffii.fpsms.modules.pickOrder.entity.PickOrderRepository
import com.ffii.fpsms.modules.pickOrder.entity.PickOrderLineRepository

@Service
open class DeliveryOrderService(
private val deliveryOrderRepository: DeliveryOrderRepository,
@@ -46,7 +58,13 @@ open class DeliveryOrderService(
private val userRepository: UserRepository,
private val pickOrderService: PickOrderService,
private val doPickOrderService: DoPickOrderService,
private val truckRepository: TruckRepository
private val truckRepository: TruckRepository,
private val pickOrderRepository: PickOrderRepository,
private val suggestedPickLotService: SuggestedPickLotService,
private val inventoryLotLineRepository: InventoryLotLineRepository,
private val stockOutRepository: StockOutRepository,
private val stockOutLineRepository: StockOutLIneRepository,
private val pickOrderLineRepository: PickOrderLineRepository
) {

open fun findByM18DataLogId(m18DataLogId: Long): DeliveryOrder? {
@@ -302,93 +320,179 @@ open class DeliveryOrderService(
return savedDeliveryOrder
}


@Transactional(rollbackFor = [Exception::class])
open fun releaseDeliveryOrder(request: ReleaseDoRequest): MessageResponse {
println("�� DEBUG: Starting releaseDeliveryOrder for DO ID: ${request.id}, User ID: ${request.userId}")
val deliveryOrder = deliveryOrderRepository.findByIdAndDeletedIsFalse(request.id)
?: throw NoSuchElementException("Delivery Order not found")
println("�� DEBUG: Found delivery order - ID: ${deliveryOrder.id}, Shop: ${deliveryOrder.shop?.code}, Status: ${deliveryOrder.status}")
deliveryOrder.apply {
status = DeliveryOrderStatus.PENDING
}
deliveryOrderRepository.save(deliveryOrder)
open fun releaseDeliveryOrder(request: ReleaseDoRequest): MessageResponse {
println("�� DEBUG: Starting releaseDeliveryOrder for DO ID: ${request.id}, User ID: ${request.userId}")
val deliveryOrder = deliveryOrderRepository.findByIdAndDeletedIsFalse(request.id)
?: throw NoSuchElementException("Delivery Order not found")
println("�� DEBUG: Found delivery order - ID: ${deliveryOrder.id}, Shop: ${deliveryOrder.shop?.code}, Status: ${deliveryOrder.status}")
deliveryOrder.apply {
status = DeliveryOrderStatus.PENDING
}
deliveryOrderRepository.save(deliveryOrder)

val pols = deliveryOrder.deliveryOrderLines.map {
SavePickOrderLineRequest(
itemId = it.item?.id,
qty = it.qty ?: BigDecimal.ZERO,
uomId = it.uom?.id,
val pols = deliveryOrder.deliveryOrderLines.map {
SavePickOrderLineRequest(
itemId = it.item?.id,
qty = it.qty ?: BigDecimal.ZERO,
uomId = it.uom?.id,
)
}
val po = SavePickOrderRequest(
doId = deliveryOrder.id,
type = PickOrderType.DELIVERY_ORDER,
targetDate = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: LocalDate.now(),
pickOrderLine = pols
)
}
val po = SavePickOrderRequest(
doId = deliveryOrder.id,
type = PickOrderType.DELIVERY_ORDER,
targetDate = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: LocalDate.now(),
pickOrderLine = pols
)

val createdPickOrder = pickOrderService.create(po)
println("🔍 DEBUG: Created pick order - ID: ${createdPickOrder.id}")

// ✅ CREATE do_pick_order_record entries
val targetDate = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: LocalDate.now()
val datePrefix = targetDate.format(DateTimeFormatter.ofPattern("ddMMyy"))
println("�� DEBUG: Target date: $targetDate, Date prefix: $datePrefix")
// Get next ticket number for this date
val nextTicketNumber = doPickOrderService.getNextTicketNumber(datePrefix)
println("�� DEBUG: Next ticket number: $nextTicketNumber")
// ✅ Find truck by shop ID with earliest departure time
val truck = deliveryOrder.shop?.id?.let { shopId ->
println("�� DEBUG: Looking for truck with shop ID: $shopId")
val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId)
println("🔍 DEBUG: Found ${trucks.size} trucks for shop $shopId")
trucks.forEach { t ->
println("🔍 DEBUG: Truck ID: ${t.id}, DepartureTime: ${t.departureTime}")

val createdPickOrder = pickOrderService.create(po)
println("🔍 DEBUG: Created pick order - ID: ${createdPickOrder.id}")
val consoCode = pickOrderService.assignConsoCode()
val pickOrderEntity = pickOrderRepository.findById(createdPickOrder.id!!).orElse(null)
if (pickOrderEntity != null) {
pickOrderEntity.consoCode = consoCode
pickOrderEntity.status = com.ffii.fpsms.modules.pickOrder.enums.PickOrderStatus.RELEASED
pickOrderRepository.saveAndFlush(pickOrderEntity)
println("�� DEBUG: Assigned consoCode $consoCode to pick order ${createdPickOrder.id}")
// ✅ Debug: Check pick order lines
println("�� DEBUG: Pick order has ${pickOrderEntity.pickOrderLines?.size ?: 0} pick order lines")
pickOrderEntity.pickOrderLines?.forEach { line ->
println("🔍 DEBUG: Pick order line - Item ID: ${line.item?.id}, Qty: ${line.qty}")
}
val lines = pickOrderLineRepository.findAllByPickOrderId(pickOrderEntity.id!!)
println("🔍 DEBUG: Loaded ${lines.size} pick order lines from DB")
if (lines.isEmpty()) {
println("⚠️ No pick order lines found; suggestions will be empty")
}
// ✅ Create suggested pick lots and hold inventory (like normal release)
println("🔍 DEBUG: About to call suggestionForPickOrderLines for pick order ${pickOrderEntity.id}")
val suggestions = suggestedPickLotService.suggestionForPickOrderLines(
SuggestedPickLotForPolRequest(pickOrderLines = lines)
)
println("🔍 DEBUG: Got ${suggestions.suggestedList.size} suggested pick lots")
if (suggestions.suggestedList.isEmpty()) {
println("⚠️ WARNING: No suggested pick lots generated - this might be due to no inventory available")
}
val saveSuggestedPickLots = suggestedPickLotService.saveAll(suggestions.suggestedList)
println("🔍 DEBUG: Saved ${saveSuggestedPickLots.size} suggested pick lots")
// ✅ Hold inventory quantities
val inventoryLotLines = inventoryLotLineRepository.findAllByIdIn(
saveSuggestedPickLots.mapNotNull { it.suggestedLotLine?.id }
)
saveSuggestedPickLots.forEach { lot ->
if (lot.suggestedLotLine != null && lot.suggestedLotLine?.id != null && lot.suggestedLotLine!!.id!! > 0) {
val lineIndex = inventoryLotLines.indexOf(lot.suggestedLotLine)
if (lineIndex >= 0) {
inventoryLotLines[lineIndex].holdQty =
(inventoryLotLines[lineIndex].holdQty ?: BigDecimal.ZERO).plus(lot.qty ?: BigDecimal.ZERO)
}
}
}
inventoryLotLineRepository.saveAll(inventoryLotLines)
// ✅ Create stock out record and pre-create stock out lines
val stockOut = StockOut().apply {
this.type = "job"
this.consoPickOrderCode = consoCode
this.status = StockOutStatus.PENDING.status
this.handler = request.userId
}
val savedStockOut = stockOutRepository.saveAndFlush(stockOut)
// ✅ Pre-create stock out lines for suggested lots
saveSuggestedPickLots.forEach { lot ->
val polId = lot.pickOrderLine?.id
val illId = lot.suggestedLotLine?.id
if (polId != null && illId != null) {
val existingLines = stockOutLineRepository.findByPickOrderLineIdAndInventoryLotLineIdAndDeletedFalse(polId, illId)
if (existingLines.isEmpty()) {
val pickOrderLine = pickOrderLineRepository.findById(polId).orElse(null)
val inventoryLotLine = inventoryLotLineRepository.findById(illId).orElse(null)
if (pickOrderLine != null && inventoryLotLine != null) {
val line = StockOutLine().apply {
this.stockOut = savedStockOut
this.pickOrderLine = pickOrderLine
this.inventoryLotLine = inventoryLotLine
this.item = pickOrderLine.item
this.status = StockOutLineStatus.PENDING.status
this.qty = 0.0
}
stockOutLineRepository.save(line)
}
}
}
}
}
val selectedTruck = trucks.minByOrNull { it.departureTime ?: LocalTime.MAX }
println("🔍 DEBUG: Selected truck: ID=${selectedTruck?.id}, DepartureTime=${selectedTruck?.departureTime}")
selectedTruck
}
println("🔍 DEBUG: Processing ${deliveryOrder.deliveryOrderLines.size} delivery order lines")
deliveryOrder.deliveryOrderLines.forEach { line ->
val storeId = if (deliveryOrder.shop?.code == "P06B") "2/F" else "4/F"
println("�� DEBUG: Processing line - Item ID: ${line.item?.id}, Store ID: $storeId")

// ✅ CREATE do_pick_order_record entries
val targetDate = deliveryOrder.estimatedArrivalDate?.toLocalDate() ?: LocalDate.now()
val datePrefix = targetDate.format(DateTimeFormatter.ofPattern("ddMMyy"))
val doPickOrder = DoPickOrder(
storeId = storeId,
ticketNo = nextTicketNumber,
ticketStatus = DoPickOrderStatus.pending,
truckId = truck?.id,
truckDepartureTime = truck?.departureTime,
itemId = line.item?.id,
shopId = deliveryOrder.shop?.id,
shopPoSupplierId = deliveryOrder.shop?.id,
handledBy = request.userId
)
println("�� DEBUG: Target date: $targetDate, Date prefix: $datePrefix")
println("�� DEBUG: Creating DoPickOrder - Store: $storeId, Ticket: $nextTicketNumber, Truck: ${truck?.id}")
// Get next ticket number for this date
val nextTicketNumber = doPickOrderService.getNextTicketNumber(datePrefix)
println("🔍 DEBUG: Next ticket number: $nextTicketNumber")
val savedDoPickOrder = doPickOrderService.save(doPickOrder)
println("🔍 DEBUG: Saved DoPickOrder - ID: ${savedDoPickOrder.id}")
// ✅ Find truck by shop ID with earliest departure time
val truck = deliveryOrder.shop?.id?.let { shopId ->
println("�� DEBUG: Looking for truck with shop ID: $shopId")
val trucks = truckRepository.findByShopIdAndDeletedFalse(shopId)
println("🔍 DEBUG: Found ${trucks.size} trucks for shop $shopId")
trucks.forEach { t ->
println("🔍 DEBUG: Truck ID: ${t.id}, DepartureTime: ${t.departureTime}")
}
val selectedTruck = trucks.minByOrNull { it.departureTime ?: LocalTime.MAX }
println("🔍 DEBUG: Selected truck: ID=${selectedTruck?.id}, DepartureTime=${selectedTruck?.departureTime}")
selectedTruck
}
println("🔍 DEBUG: Processing ${deliveryOrder.deliveryOrderLines.size} delivery order lines")
deliveryOrder.deliveryOrderLines.forEach { line ->
val storeId = if (deliveryOrder.shop?.code == "P06B") "2/F" else "4/F"
println("�� DEBUG: Processing line - Item ID: ${line.item?.id}, Store ID: $storeId")
val doPickOrder = DoPickOrder(
storeId = storeId,
ticketNo = nextTicketNumber,
ticketStatus = DoPickOrderStatus.pending,
truckId = truck?.id,
pickOrderId = createdPickOrder.id,
truckDepartureTime = truck?.departureTime,
itemId = line.item?.id,
shopId = deliveryOrder.shop?.id,
shopPoSupplierId = deliveryOrder.shop?.id,
handledBy = request.userId
)
println("�� DEBUG: Creating DoPickOrder - Store: $storeId, Ticket: $nextTicketNumber, Truck: ${truck?.id}")
val savedDoPickOrder = doPickOrderService.save(doPickOrder)
println("🔍 DEBUG: Saved DoPickOrder - ID: ${savedDoPickOrder.id}")
}

return MessageResponse(
id = deliveryOrder.id,
code = deliveryOrder.code,
name = deliveryOrder.shop?.name,
type = null,
message = null,
errorPosition = null,
entity = mapOf("status" to deliveryOrder.status?.value)
)
}

return MessageResponse(
id = deliveryOrder.id,
code = deliveryOrder.code,
name = deliveryOrder.shop?.name,
type = null,
message = null,
errorPosition = null,
entity = mapOf("status" to deliveryOrder.status?.value)
)
}
}

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

@@ -1,15 +1,18 @@
package com.ffii.fpsms.modules.deliveryOrder.web.models

import java.time.LocalDateTime
import com.fasterxml.jackson.annotation.JsonFormat
data class DoDetailResponse(
val id: Long,
val code: String,
val supplierCode: String?,
val shopCode: String?,
val currencyCode: String?,
@JsonFormat(pattern = "yyyy-MM-dd")
val orderDate: LocalDateTime?,
@JsonFormat(pattern = "yyyy-MM-dd")
val estimatedArrivalDate: LocalDateTime?,
@JsonFormat(pattern = "yyyy-MM-dd")
val completeDate: LocalDateTime?,
val status: String?,
val deliveryOrderLines: List<DoDetailLineResponse>


+ 7
- 0
src/main/java/com/ffii/fpsms/modules/pickOrder/entity/PickOrderLineRepository.kt 查看文件

@@ -14,4 +14,11 @@ interface PickOrderLineRepository : AbstractRepository<PickOrderLine, Long> {
AND pol.pickOrder.deleted = false
""")
fun findAllPickOrdersByItemId(@Param("itemId") itemId: Long): List<PickOrder>


@Query("""
SELECT pol FROM PickOrderLine pol
WHERE pol.pickOrder.id = :pickOrderId AND pol.deleted = false
""")
fun findAllByPickOrderId(@Param("pickOrderId") pickOrderId: Long): List<PickOrderLine>
}

+ 69
- 0
src/main/resources/db/changelog/changes/20250918_01_enson/01_create_group_enson.sql 查看文件

@@ -0,0 +1,69 @@
--liquibase formatted sql

--changeset enson:update

CREATE TABLE `do_pick_order` (
`id` int NOT NULL AUTO_INCREMENT,
`store_id` varchar(10) NOT NULL,
`ticket_no` varchar(50) NOT NULL,
`ticket_status` enum('pending','completed') DEFAULT 'pending',
`pick_order_id` int NOT NULL,
`truck_id` int NOT NULL,
`truck_departure_time` TIME NOT NULL,
`item_id` int NOT NULL,
`shop_id` int DEFAULT NULL,
`shop_po_supplier_id` int NOT NULL,
`handled_by` int NOT NULL,
`created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`createdBy` varchar(30) DEFAULT NULL,
`version` int NOT NULL DEFAULT '0',
`modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`modifiedBy` varchar(30) DEFAULT NULL,
`deleted` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `IDX_DO_PICK_ORDER_PICK_ORDER` (`pick_order_id`),
KEY `IDX_DO_PICK_ORDER_TRUCK` (`truck_id`),
KEY `IDX_DO_PICK_ORDER_ITEM` (`item_id`),
KEY `IDX_DO_PICK_ORDER_SHOP` (`shop_id`),
KEY `IDX_DO_PICK_ORDER_SHOP_SUPP` (`shop_po_supplier_id`),
KEY `IDX_DO_PICK_ORDER_HANDLED_BY` (`handled_by`),
CONSTRAINT `FK_DO_PICK_ORDER_ON_PICK_ORDER` FOREIGN KEY (`pick_order_id`) REFERENCES `pick_order` (`id`),
CONSTRAINT `FK_DO_PICK_ORDER_ON_HANDLED_BY` FOREIGN KEY (`handled_by`) REFERENCES `user` (`id`),
CONSTRAINT `FK_DO_PICK_ORDER_ON_ITEM` FOREIGN KEY (`item_id`) REFERENCES `items` (`id`),
CONSTRAINT `FK_DO_PICK_ORDER_ON_SHOP` FOREIGN KEY (`shop_id`) REFERENCES `shop` (`id`),
CONSTRAINT `FK_DO_PICK_ORDER_ON_SHOP_PO_SUPPLIER` FOREIGN KEY (`shop_po_supplier_id`) REFERENCES `shop` (`id`),
CONSTRAINT `FK_DO_PICK_ORDER_ON_TRUCK` FOREIGN KEY (`truck_id`) REFERENCES `Truck` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

CREATE TABLE `do_pick_order_record` (
`id` int NOT NULL AUTO_INCREMENT,
`store_id` varchar(10) NOT NULL,
`ticket_no` varchar(50) NOT NULL,
`ticket_status` enum('pending','completed') DEFAULT 'pending',
`pick_order_id` int NOT NULL,
`truck_id` int NOT NULL,
`truck_departure_time` TIME NOT NULL,
`item_id` int NOT NULL,
`shop_id` int DEFAULT NULL,
`shop_po_supplier_id` int NOT NULL,
`handled_by` int NOT NULL,
`created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`createdBy` varchar(30) DEFAULT NULL,
`version` int NOT NULL DEFAULT '0',
`modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`modifiedBy` varchar(30) DEFAULT NULL,
`deleted` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `IDX_DO_PICK_ORDER_REC_PICK_ORDER` (`pick_order_id`),
KEY `IDX_DO_PICK_ORDER_REC_TRUCK` (`truck_id`),
KEY `IDX_DO_PICK_ORDER_REC_ITEM` (`item_id`),
KEY `IDX_DO_PICK_ORDER_REC_SHOP` (`shop_id`),
KEY `IDX_DO_PICK_ORDER_REC_SHOP_SUPP` (`shop_po_supplier_id`),
KEY `IDX_DO_PICK_ORDER_REC_HANDLED_BY` (`handled_by`),
CONSTRAINT `FK_DO_PICK_ORDER_REC_ON_PICK_ORDER` FOREIGN KEY (`pick_order_id`) REFERENCES `pick_order` (`id`),
CONSTRAINT `FK_DO_PICK_ORDER_REC_ON_HANDLED_BY` FOREIGN KEY (`handled_by`) REFERENCES `user` (`id`),
CONSTRAINT `FK_DO_PICK_ORDER_REC_ON_ITEM` FOREIGN KEY (`item_id`) REFERENCES `items` (`id`),
CONSTRAINT `FK_DO_PICK_ORDER_REC_ON_SHOP` FOREIGN KEY (`shop_id`) REFERENCES `shop` (`id`),
CONSTRAINT `FK_DO_PICK_ORDER_REC_ON_SHOP_PO_SUPPLIER` FOREIGN KEY (`shop_po_supplier_id`) REFERENCES `shop` (`id`),
CONSTRAINT `FK_DO_PICK_ORDER_REC_ON_TRUCK` FOREIGN KEY (`truck_id`) REFERENCES `Truck` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

正在加载...
取消
保存