Sfoglia il codice sorgente

replenishment setup

production
kelvin.yau 1 settimana fa
parent
commit
f74dc566ee
5 ha cambiato i file con 153 aggiunte e 0 eliminazioni
  1. +2
    -0
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRecordRepository.kt
  2. +2
    -0
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRepository.kt
  3. +59
    -0
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt
  4. +2
    -0
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/DoDetailResponse.kt
  5. +88
    -0
      src/main/resources/db/changelog/changes/20260611_KelvinY/01_create_do_replenishment.sql

+ 2
- 0
src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRecordRepository.kt Vedi File

@@ -16,6 +16,8 @@ import java.time.LocalDate
@Repository
interface DoPickOrderRecordRepository : JpaRepository<DoPickOrderRecord, Long> {
fun findByPickOrderId(pickOrderId: Long): List<DoPickOrderRecord>

fun findByDoOrderIdAndDeletedFalse(doOrderId: Long): List<DoPickOrderRecord>
fun findByTicketNoStartingWith(ticketPrefix: String): List<DoPickOrderRecord>

@Query("""


+ 2
- 0
src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DoPickOrderRepository.kt Vedi File

@@ -21,6 +21,8 @@ interface DoPickOrderRepository : JpaRepository<DoPickOrder, Long> {
): List<DoPickOrder>
fun findByPickOrderId(pickOrderId: Long): List<DoPickOrder>

fun findByDoOrderIdAndDeletedFalse(doOrderId: Long): List<DoPickOrder>

fun findByTicketStatusIn(statuses: List<DoPickOrderStatus>): List<DoPickOrder>
// 在 DoPickOrderRepository 中添加这个方法
fun findByHandledByAndTicketStatusIn(handledBy: Long, status: List<DoPickOrderStatus>): List<DoPickOrder>


+ 59
- 0
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt Vedi File

@@ -473,8 +473,66 @@ open class DeliveryOrderService(
}
}

/**
* Picker display name from [DeliveryOrderPickOrder.handlerName] (workbench source of truth).
* Linked via [pick_order.doId] or [do_pick_order_line.do_order_id]; falls back to [User.name]
* from [DeliveryOrderPickOrder.handledBy] when [handlerName] was not persisted.
*/
private fun resolveHandlerNameForDeliveryOrder(doId: Long): String? {
val sql = """
SELECT DISTINCT TRIM(handler_name) AS handler_name
FROM (
SELECT COALESCE(
NULLIF(TRIM(dop.handlerName), ''),
NULLIF(TRIM(u.name), '')
) AS handler_name
FROM fpsmsdb.delivery_order_pick_order dop
INNER JOIN fpsmsdb.pick_order po
ON po.deliveryOrderPickOrderId = dop.id AND po.deleted = 0
LEFT JOIN fpsmsdb.user u
ON u.id = dop.handledBy AND u.deleted = 0
WHERE dop.deleted = 0
AND po.doId = :doId

UNION

SELECT COALESCE(
NULLIF(TRIM(dop.handlerName), ''),
NULLIF(TRIM(u.name), '')
) AS handler_name
FROM fpsmsdb.delivery_order_pick_order dop
INNER JOIN fpsmsdb.pick_order po
ON po.deliveryOrderPickOrderId = dop.id AND po.deleted = 0
INNER JOIN fpsmsdb.do_pick_order_line dpol
ON dpol.pick_order_id = po.id AND dpol.deleted = 0
LEFT JOIN fpsmsdb.user u
ON u.id = dop.handledBy AND u.deleted = 0
WHERE dop.deleted = 0
AND dpol.do_order_id = :doId
) resolved
WHERE handler_name IS NOT NULL AND TRIM(handler_name) <> ''
ORDER BY handler_name
""".trimIndent()

val names = jdbcDao.queryForList(sql, mapOf("doId" to doId))
.mapNotNull { row ->
val key = row.keys.find { it.equals("handler_name", true) } ?: return@mapNotNull null
row[key]?.toString()?.trim()?.takeIf { it.isNotEmpty() }
}
.distinct()
.sorted()

return names.joinToString(",").ifBlank { null }
}

open fun getDetailedDo(id: Long): DoDetailResponse? {
val deliveryOrder = deliveryOrderRepository.findByIdAndDeletedIsFalse(id) ?: return null
val handlerName = try {
resolveHandlerNameForDeliveryOrder(id)
} catch (ex: Exception) {
log.warn("Failed to resolve handler name for delivery order {}: {}", id, ex.message)
null
}

val itemIds = deliveryOrder.deliveryOrderLines.mapNotNull { it.item?.id }.distinct()
val stockQtyByItemId = itemIds.associateWith { itemId ->
@@ -493,6 +551,7 @@ open class DeliveryOrderService(
completeDate = deliveryOrder.completeDate,
status = deliveryOrder.status?.value,
isExtra = deliveryOrder.isExtra,
handlerName = handlerName,
deliveryOrderLines = deliveryOrder.deliveryOrderLines.map { line ->
val itemId = line.item?.id
val stockQty = itemId?.let { stockQtyByItemId[it] } ?: BigDecimal.ZERO


+ 2
- 0
src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/DoDetailResponse.kt Vedi File

@@ -20,6 +20,8 @@ data class DoDetailResponse(
val status: String?,
/** 加單 DO(M18 加單專用同步) */
val isExtra: Boolean = false,
/** 揀貨員名稱(來源:delivery_order_pick_order.handlerName) */
val handlerName: String? = null,
val deliveryOrderLines: List<DoDetailLineResponse>
)



+ 88
- 0
src/main/resources/db/changelog/changes/20260611_KelvinY/01_create_do_replenishment.sql Vedi File

@@ -0,0 +1,88 @@
-- liquibase formatted sql
-- changeset KelvinY:20260611_01_create_do_replenishment
-- preconditions onFail:MARK_RAN
-- precondition-sql-check expectedResult:0 SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = 'do_replenishment'

CREATE TABLE IF NOT EXISTS `do_replenishment`
(
`id` BIGINT NOT NULL AUTO_INCREMENT,
`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`createdBy` VARCHAR(30) NULL DEFAULT NULL,
`version` INT NOT NULL DEFAULT '0',
`modified` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`modifiedBy` VARCHAR(30) NULL DEFAULT NULL,
`deleted` TINYINT(1) NOT NULL DEFAULT '0',
`code` VARCHAR(100) NOT NULL,
`deliveryDate` DATE NOT NULL,
`sourceDoId` BIGINT NOT NULL,
`sourceDoCode` VARCHAR(100) NULL DEFAULT NULL,
`sourceDoLineId` BIGINT NOT NULL,
`sourceM18DataLogId` BIGINT NOT NULL,
`sourceM18Id` BIGINT NOT NULL,
`itemId` BIGINT NOT NULL,
`itemNo` VARCHAR(100) NULL DEFAULT NULL,
`itemName` VARCHAR(255) NULL DEFAULT NULL,
`replenishQty` DECIMAL(14, 2) NOT NULL,
`uomId` BIGINT NULL DEFAULT NULL,
`shopId` BIGINT NULL DEFAULT NULL,
`shopCode` VARCHAR(50) NULL DEFAULT NULL,
`shopName` VARCHAR(255) NULL DEFAULT NULL,
`truckLaneCode` VARCHAR(100) NULL DEFAULT NULL,
`targetDoId` BIGINT NULL DEFAULT NULL,
`targetDoCode` VARCHAR(100) NULL DEFAULT NULL,
`pickOrderLineId` BIGINT NULL DEFAULT NULL,
`status` VARCHAR(20) NOT NULL DEFAULT 'pending',
CONSTRAINT pk_do_replenishment PRIMARY KEY (`id`)
);

SET @idx_dr_code := (
SELECT COUNT(*) FROM information_schema.statistics
WHERE table_schema = DATABASE() AND table_name = 'do_replenishment' AND index_name = 'uk_dr_code'
);
SET @sql_dr_code := IF(
@idx_dr_code = 0,
'CREATE UNIQUE INDEX uk_dr_code ON `do_replenishment` (`code`)',
'SELECT 1'
);
PREPARE stmt_dr_code FROM @sql_dr_code;
EXECUTE stmt_dr_code;
DEALLOCATE PREPARE stmt_dr_code;

SET @idx_dr_status_date := (
SELECT COUNT(*) FROM information_schema.statistics
WHERE table_schema = DATABASE() AND table_name = 'do_replenishment' AND index_name = 'idx_dr_status_delivery_date'
);
SET @sql_dr_sd := IF(
@idx_dr_status_date = 0,
'CREATE INDEX idx_dr_status_delivery_date ON `do_replenishment` (`status`, `deliveryDate`)',
'SELECT 1'
);
PREPARE stmt_dr_sd FROM @sql_dr_sd;
EXECUTE stmt_dr_sd;
DEALLOCATE PREPARE stmt_dr_sd;

SET @idx_dr_lane_shop := (
SELECT COUNT(*) FROM information_schema.statistics
WHERE table_schema = DATABASE() AND table_name = 'do_replenishment' AND index_name = 'idx_dr_lane_shop_status'
);
SET @sql_dr_ls := IF(
@idx_dr_lane_shop = 0,
'CREATE INDEX idx_dr_lane_shop_status ON `do_replenishment` (`truckLaneCode`, `shopId`, `status`)',
'SELECT 1'
);
PREPARE stmt_dr_ls FROM @sql_dr_ls;
EXECUTE stmt_dr_ls;
DEALLOCATE PREPARE stmt_dr_ls;

SET @idx_dr_source_line := (
SELECT COUNT(*) FROM information_schema.statistics
WHERE table_schema = DATABASE() AND table_name = 'do_replenishment' AND index_name = 'idx_dr_source_line'
);
SET @sql_dr_sl := IF(
@idx_dr_source_line = 0,
'CREATE INDEX idx_dr_source_line ON `do_replenishment` (`sourceDoId`, `sourceDoLineId`)',
'SELECT 1'
);
PREPARE stmt_dr_sl FROM @sql_dr_sl;
EXECUTE stmt_dr_sl;
DEALLOCATE PREPARE stmt_dr_sl;

Caricamento…
Annulla
Salva