瀏覽代碼

DO 放單 relate created need write in username

production
CANCERYS\kw093 1 周之前
父節點
當前提交
d5b88deb09
共有 2 個文件被更改,包括 142 次插入66 次删除
  1. +24
    -1
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoReleaseCoordinatorService.kt
  2. +118
    -65
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoWorkbenchReleaseService.kt

+ 24
- 1
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoReleaseCoordinatorService.kt 查看文件

@@ -28,6 +28,8 @@ import com.ffii.fpsms.modules.deliveryOrder.web.models.AssignByDoPickOrderIdRequ
import com.ffii.fpsms.modules.user.entity.UserRepository import com.ffii.fpsms.modules.user.entity.UserRepository
import com.ffii.fpsms.modules.pickOrder.entity.PickOrderRepository import com.ffii.fpsms.modules.pickOrder.entity.PickOrderRepository
import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderRecordRepository import com.ffii.fpsms.modules.deliveryOrder.entity.DoPickOrderRecordRepository
import org.springframework.security.core.context.SecurityContext
import org.springframework.security.core.context.SecurityContextHolder
import com.ffii.fpsms.modules.pickOrder.enums.PickOrderStatus import com.ffii.fpsms.modules.pickOrder.enums.PickOrderStatus
import jakarta.persistence.OptimisticLockException import jakarta.persistence.OptimisticLockException
import org.hibernate.StaleObjectStateException import org.hibernate.StaleObjectStateException
@@ -491,6 +493,7 @@ class DoReleaseCoordinatorService(
return ids return ids
} }
} }
/** FP-MTMS Version Checklist | Functions Ref. No. 77 | v1.0.0 | 2026-09-08 */
fun startBatchReleaseAsync(ids: List<Long>, userId: Long): MessageResponse { fun startBatchReleaseAsync(ids: List<Long>, userId: Long): MessageResponse {
if (ids.isEmpty()) { if (ids.isEmpty()) {
return MessageResponse( return MessageResponse(
@@ -502,10 +505,13 @@ class DoReleaseCoordinatorService(
val jobId = UUID.randomUUID().toString() val jobId = UUID.randomUUID().toString()
val status = BatchReleaseJobStatus(jobId = jobId, total = ids.size) val status = BatchReleaseJobStatus(jobId = jobId, total = ids.size)
jobs[jobId] = status jobs[jobId] = status
val workerSecurityContext = copySecurityContextForWorker()


executor.submit { executor.submit {
batchReleaseConcurrencyGate.acquireUninterruptibly()
try { try {
SecurityContextHolder.setContext(workerSecurityContext)
batchReleaseConcurrencyGate.acquireUninterruptibly()
try {
try { try {
println("Starting batch release for ${ids.size} orders (job $jobId)") println("Starting batch release for ${ids.size} orders (job $jobId)")
val sortedIds = getOrderedDeliveryOrderIds(ids) val sortedIds = getOrderedDeliveryOrderIds(ids)
@@ -643,6 +649,9 @@ class DoReleaseCoordinatorService(
} finally { } finally {
batchReleaseConcurrencyGate.release() batchReleaseConcurrencyGate.release()
} }
} finally {
SecurityContextHolder.clearContext()
}
} }


return MessageResponse( return MessageResponse(
@@ -851,6 +860,7 @@ class DoReleaseCoordinatorService(
) )
} }


/** FP-MTMS Version Checklist | Functions Ref. No. 77 | v1.0.0 | 2026-09-08 */
fun startBatchReleaseAsyncSingle(doId: Long, userId: Long): MessageResponse { fun startBatchReleaseAsyncSingle(doId: Long, userId: Long): MessageResponse {
val deliveryOrder = deliveryOrderRepository.findByIdAndDeletedIsFalse(doId) val deliveryOrder = deliveryOrderRepository.findByIdAndDeletedIsFalse(doId)
?: return MessageResponse( ?: return MessageResponse(
@@ -858,8 +868,11 @@ class DoReleaseCoordinatorService(
message = "Delivery Order not found", errorPosition = null, entity = null message = "Delivery Order not found", errorPosition = null, entity = null
) )
val workerSecurityContext = copySecurityContextForWorker()

executor.submit { executor.submit {
try { try {
SecurityContextHolder.setContext(workerSecurityContext)
println("📦 Starting single release for DO $doId") println("📦 Starting single release for DO $doId")
// 调用 releaseDeliveryOrderWithoutTicket 创建 pick order // 调用 releaseDeliveryOrderWithoutTicket 创建 pick order
@@ -958,6 +971,8 @@ class DoReleaseCoordinatorService(
} catch (e: Exception) { } catch (e: Exception) {
println("❌ Single release exception: ${e.message}") println("❌ Single release exception: ${e.message}")
e.printStackTrace() e.printStackTrace()
} finally {
SecurityContextHolder.clearContext()
} }
} }
@@ -968,6 +983,14 @@ class DoReleaseCoordinatorService(
) )
} }
/** FP-MTMS Version Checklist | Functions Ref. No. 77 | v1.0.0 | 2026-09-08 */
private fun copySecurityContextForWorker(): SecurityContext {
val parent = SecurityContextHolder.getContext()
val copy = SecurityContextHolder.createEmptyContext()
copy.authentication = parent.authentication
return copy
}

private fun updateSingleTicketNumbers() { private fun updateSingleTicketNumbers() {
try { try {
// 1. 查找所有 TEMP- 开头的 single release type 订单 // 1. 查找所有 TEMP- 开头的 single release type 订单


+ 118
- 65
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DoWorkbenchReleaseService.kt 查看文件

@@ -9,6 +9,9 @@ import com.ffii.fpsms.modules.deliveryOrder.web.models.WorkbenchMergeTicketCandi
import com.ffii.fpsms.modules.master.web.models.MessageResponse import com.ffii.fpsms.modules.master.web.models.MessageResponse
import com.ffii.fpsms.modules.stock.service.StockOutLineWorkbenchService import com.ffii.fpsms.modules.stock.service.StockOutLineWorkbenchService
import com.ffii.fpsms.modules.stock.service.SuggestedPickLotWorkbenchService import com.ffii.fpsms.modules.stock.service.SuggestedPickLotWorkbenchService
import com.ffii.fpsms.modules.user.entity.UserRepository
import org.springframework.security.core.context.SecurityContext
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional import org.springframework.transaction.annotation.Transactional
import java.time.Instant import java.time.Instant
@@ -95,6 +98,7 @@ open class DoWorkbenchReleaseService(
private val suggestedPickLotWorkbenchService: SuggestedPickLotWorkbenchService, private val suggestedPickLotWorkbenchService: SuggestedPickLotWorkbenchService,
private val stockOutLineWorkbenchService: StockOutLineWorkbenchService, private val stockOutLineWorkbenchService: StockOutLineWorkbenchService,
private val doFloorSupplierSettingsService: DoFloorSupplierSettingsService, private val doFloorSupplierSettingsService: DoFloorSupplierSettingsService,
private val userRepository: UserRepository,
) { ) {
private val poolSize = Runtime.getRuntime().availableProcessors() private val poolSize = Runtime.getRuntime().availableProcessors()
private val executor = Executors.newFixedThreadPool(kotlin.math.min(poolSize, 4)) private val executor = Executors.newFixedThreadPool(kotlin.math.min(poolSize, 4))
@@ -142,6 +146,7 @@ open class DoWorkbenchReleaseService(
open fun startBatchReleaseAsyncSingleV2(ids: List<Long>, userId: Long): MessageResponse = open fun startBatchReleaseAsyncSingleV2(ids: List<Long>, userId: Long): MessageResponse =
startBatchReleaseAsyncInternal(ids, userId, useV2 = true, dopReleaseType = "single") startBatchReleaseAsyncInternal(ids, userId, useV2 = true, dopReleaseType = "single")


/** FP-MTMS Version Checklist | Functions Ref. No. 78 | v1.0.0 | 2026-09-08 */
private fun startBatchReleaseAsyncInternal( private fun startBatchReleaseAsyncInternal(
ids: List<Long>, ids: List<Long>,
userId: Long, userId: Long,
@@ -164,75 +169,83 @@ open class DoWorkbenchReleaseService(
val jobId = UUID.randomUUID().toString() val jobId = UUID.randomUUID().toString()
val status = WorkbenchBatchReleaseJobStatus(jobId = jobId, total = ids.size) val status = WorkbenchBatchReleaseJobStatus(jobId = jobId, total = ids.size)
jobs[jobId] = status jobs[jobId] = status
val actor = resolveReleaseActor(userId)
// Capture auth before worker thread: BaseEntity @PrePersist needs SecurityContext for pick_order / lines.
val workerSecurityContext = copySecurityContextForWorker()


executor.submit { executor.submit {
batchReleaseConcurrencyGate.acquireUninterruptibly()
try { try {
val orderedIds = getOrderedDeliveryOrderIds(ids)
val successResults = mutableListOf<ReleaseDoResult>()
SecurityContextHolder.setContext(workerSecurityContext)
batchReleaseConcurrencyGate.acquireUninterruptibly()
try {
val orderedIds = getOrderedDeliveryOrderIds(ids)
val successResults = mutableListOf<ReleaseDoResult>()


orderedIds.forEach { deliveryOrderId ->
try {
val statusRows = jdbcDao.queryForList(
"""
SELECT status
FROM fpsmsdb.delivery_order
WHERE id = :id AND deleted = 0
""".trimIndent(),
mapOf("id" to deliveryOrderId)
)
val currentStatus = statusRows.firstOrNull()?.get("status")?.toString()?.lowercase()
if (currentStatus == DeliveryOrderStatus.COMPLETED.value || currentStatus == DeliveryOrderStatus.RECEIVING.value) {
return@forEach
}
orderedIds.forEach { deliveryOrderId ->
try {
val statusRows = jdbcDao.queryForList(
"""
SELECT status
FROM fpsmsdb.delivery_order
WHERE id = :id AND deleted = 0
""".trimIndent(),
mapOf("id" to deliveryOrderId)
)
val currentStatus = statusRows.firstOrNull()?.get("status")?.toString()?.lowercase()
if (currentStatus == DeliveryOrderStatus.COMPLETED.value || currentStatus == DeliveryOrderStatus.RECEIVING.value) {
return@forEach
}


val released = releaseDeliveryOrderWorkbenchWithRetries(deliveryOrderId, userId, useV2)
val released = releaseDeliveryOrderWorkbenchWithRetries(deliveryOrderId, userId, useV2)


if (released != null) {
successResults += released
status.success.incrementAndGet()
} else {
if (released != null) {
successResults += released
status.success.incrementAndGet()
} else {
synchronized(status.failed) {
status.failed.add(deliveryOrderId to "Release returned null")
}
}
} catch (e: Exception) {
synchronized(status.failed) { synchronized(status.failed) {
status.failed.add(deliveryOrderId to "Release returned null")
status.failed.add(deliveryOrderId to (e.message ?: "Unknown error"))
} }
} }
} catch (e: Exception) {
synchronized(status.failed) {
status.failed.add(deliveryOrderId to (e.message ?: "Unknown error"))
}
} }
}

try {
createAndLinkDeliveryOrderPickOrders(successResults, dopReleaseType, mergeExtraIntoLaneTicket)
} catch (e: Exception) {
// header-link failure shouldn't crash job; status.failed already includes per-DO failures
println("❌ workbench createAndLinkDeliveryOrderPickOrders failed: ${e.message}")
}


val replenishmentPickOrderIds = runWorkbenchReplenishmentRelease(successResults)
try {
createAndLinkDeliveryOrderPickOrders(successResults, dopReleaseType, mergeExtraIntoLaneTicket, actor)
} catch (e: Exception) {
// header-link failure shouldn't crash job; status.failed already includes per-DO failures
println("❌ workbench createAndLinkDeliveryOrderPickOrders failed: ${e.message}")
}


if (!useV2) {
val pickOrdersForDownstream = (successResults.map { it.pickOrderId } + replenishmentPickOrderIds).toSet()
pickOrdersForDownstream.forEach { pickOrderId ->
try {
suggestedPickLotWorkbenchService.rebuildNoHoldSuggestionsForPickOrder(pickOrderId)
stockOutLineWorkbenchService.ensureStockOutLinesForPickOrderNoHold(pickOrderId, userId)
} catch (e: Exception) {
val deliveryOrderId = successResults.firstOrNull { it.pickOrderId == pickOrderId }?.deliveryOrderId
?: 0L
synchronized(status.failed) {
status.failed.add(
deliveryOrderId to ("Downstream workbench step failed for pick order $pickOrderId: ${e.message}")
)
val replenishmentPickOrderIds = runWorkbenchReplenishmentRelease(successResults)

if (!useV2) {
val pickOrdersForDownstream = (successResults.map { it.pickOrderId } + replenishmentPickOrderIds).toSet()
pickOrdersForDownstream.forEach { pickOrderId ->
try {
suggestedPickLotWorkbenchService.rebuildNoHoldSuggestionsForPickOrder(pickOrderId)
stockOutLineWorkbenchService.ensureStockOutLinesForPickOrderNoHold(pickOrderId, userId)
} catch (e: Exception) {
val deliveryOrderId = successResults.firstOrNull { it.pickOrderId == pickOrderId }?.deliveryOrderId
?: 0L
synchronized(status.failed) {
status.failed.add(
deliveryOrderId to ("Downstream workbench step failed for pick order $pickOrderId: ${e.message}")
)
}
} }
} }
} }
} finally {
status.running = false
status.finishedAt = Instant.now().toEpochMilli()
batchReleaseConcurrencyGate.release()
} }
} finally { } finally {
status.running = false
status.finishedAt = Instant.now().toEpochMilli()
batchReleaseConcurrencyGate.release()
SecurityContextHolder.clearContext()
} }
} }


@@ -318,6 +331,7 @@ open class DoWorkbenchReleaseService(
) )
} }


val actor = resolveReleaseActor(userId)
val orderedIds = getOrderedDeliveryOrderIds(ids) val orderedIds = getOrderedDeliveryOrderIds(ids)
val successResults = mutableListOf<ReleaseDoResult>() val successResults = mutableListOf<ReleaseDoResult>()
val failed = mutableListOf<Pair<Long, String>>() val failed = mutableListOf<Pair<Long, String>>()
@@ -350,7 +364,7 @@ open class DoWorkbenchReleaseService(
} }
} }


val createdHeaders = createAndLinkDeliveryOrderPickOrders(successResults, "batch", mergeExtraIntoLaneTicket)
val createdHeaders = createAndLinkDeliveryOrderPickOrders(successResults, "batch", mergeExtraIntoLaneTicket, actor)
val replenishmentPickOrderIds = runWorkbenchReplenishmentRelease(successResults) val replenishmentPickOrderIds = runWorkbenchReplenishmentRelease(successResults)
if (!useV2) { if (!useV2) {
val pickOrdersForDownstream = (successResults.map { it.pickOrderId } + replenishmentPickOrderIds).toSet() val pickOrdersForDownstream = (successResults.map { it.pickOrderId } + replenishmentPickOrderIds).toSet()
@@ -504,6 +518,37 @@ open class DoWorkbenchReleaseService(
} }
} }


/**
* FP-MTMS Version Checklist | Functions Ref. No. 78 | v1.0.0 | 2026-09-08
* Username for ticket createdBy/modifiedBy. Capture on the request thread, then copy onto the worker.
*/
private fun resolveReleaseActor(userId: Long): String {
val fromSecurity = SecurityContextHolder.getContext().authentication?.name
?.trim()
?.takeIf { it.isNotEmpty() && !it.equals("anonymousUser", ignoreCase = true) }
?.take(30)
if (fromSecurity != null) return fromSecurity
if (userId > 0L) {
val fromUser = userRepository.findById(userId).orElse(null)?.username
?.trim()
?.takeIf { it.isNotEmpty() }
?.take(30)
if (fromUser != null) return fromUser
}
return "system"
}

/**
* FP-MTMS Version Checklist | Functions Ref. No. 78 | v1.0.0 | 2026-09-08
* Copy auth for the worker thread so BaseEntity @PrePersist matches JO / consumable pick-order creation.
*/
private fun copySecurityContextForWorker(): SecurityContext {
val parent = SecurityContextHolder.getContext()
val copy = SecurityContextHolder.createEmptyContext()
copy.authentication = parent.authentication
return copy
}

private fun resolveTicketFloorSegment(storeId: String?, isDefaultTruckLane: Boolean): String = private fun resolveTicketFloorSegment(storeId: String?, isDefaultTruckLane: Boolean): String =
if (isDefaultTruckLane) { if (isDefaultTruckLane) {
WORKBENCH_TICKET_FLOOR_SEGMENT_DEFAULT_TRUCK WORKBENCH_TICKET_FLOOR_SEGMENT_DEFAULT_TRUCK
@@ -837,7 +882,7 @@ open class DoWorkbenchReleaseService(
} }
} }


private fun setRelationshipIdSelf(headerId: Long) {
private fun setRelationshipIdSelf(headerId: Long, actor: String) {
jdbcDao.executeUpdate( jdbcDao.executeUpdate(
""" """
UPDATE fpsmsdb.delivery_order_pick_order UPDATE fpsmsdb.delivery_order_pick_order
@@ -849,7 +894,7 @@ open class DoWorkbenchReleaseService(
mapOf( mapOf(
"headerId" to headerId, "headerId" to headerId,
"modified" to LocalDateTime.now(), "modified" to LocalDateTime.now(),
"modifiedBy" to "system",
"modifiedBy" to actor,
), ),
) )
} }
@@ -914,10 +959,11 @@ open class DoWorkbenchReleaseService(
isSingleRelease: Boolean, isSingleRelease: Boolean,
requiredDate: LocalDate, requiredDate: LocalDate,
ticketFloorSegment: String, ticketFloorSegment: String,
actor: String,
): Long? { ): Long? {
val ticketNo = nextDeliveryOrderPickOrderMergeTicketNo(requiredDate, ticketFloorSegment) val ticketNo = nextDeliveryOrderPickOrderMergeTicketNo(requiredDate, ticketFloorSegment)
val releaseType = WorkbenchReleaseTypeSupport.mergeTicketReleaseType(isSingleRelease) val releaseType = WorkbenchReleaseTypeSupport.mergeTicketReleaseType(isSingleRelease)
return insertNewDeliveryOrderPickOrderHeader(first, storeId, releaseType, ticketNo)
return insertNewDeliveryOrderPickOrderHeader(first, storeId, releaseType, ticketNo, actor)
} }


private fun linkPickOrdersToHeader(headerId: Long, group: List<ReleaseDoResult>) { private fun linkPickOrdersToHeader(headerId: Long, group: List<ReleaseDoResult>) {
@@ -941,6 +987,7 @@ open class DoWorkbenchReleaseService(
storeId: String?, storeId: String?,
releaseTypeCol: String, releaseTypeCol: String,
ticketNo: String, ticketNo: String,
actor: String,
): Long? { ): Long? {
val now = LocalDateTime.now() val now = LocalDateTime.now()
jdbcDao.executeUpdate( jdbcDao.executeUpdate(
@@ -970,9 +1017,9 @@ open class DoWorkbenchReleaseService(
"ticketNo" to ticketNo, "ticketNo" to ticketNo,
"releaseType" to releaseTypeCol, "releaseType" to releaseTypeCol,
"created" to now, "created" to now,
"createdBy" to "system",
"createdBy" to actor,
"modified" to now, "modified" to now,
"modifiedBy" to "system",
"modifiedBy" to actor,
) )
) )
return jdbcDao.queryForList( return jdbcDao.queryForList(
@@ -984,7 +1031,7 @@ open class DoWorkbenchReleaseService(
LIMIT 1 LIMIT 1
""".trimIndent(), """.trimIndent(),
mapOf("ticketNo" to ticketNo) mapOf("ticketNo" to ticketNo)
).firstOrNull()?.get("id")?.let { (it as Number).toLong() }?.also { setRelationshipIdSelf(it) }
).firstOrNull()?.get("id")?.let { (it as Number).toLong() }?.also { setRelationshipIdSelf(it, actor) }
} }


/** /**
@@ -997,6 +1044,7 @@ open class DoWorkbenchReleaseService(
isSingleRelease: Boolean, isSingleRelease: Boolean,
requiredDate: LocalDate, requiredDate: LocalDate,
ticketFloorSegment: String, ticketFloorSegment: String,
actor: String,
): Int { ): Int {
val activeMerge = findActiveMergeTicket(first, storeId, isSingleRelease) val activeMerge = findActiveMergeTicket(first, storeId, isSingleRelease)
if (activeMerge != null) { if (activeMerge != null) {
@@ -1010,14 +1058,14 @@ open class DoWorkbenchReleaseService(
val sourceToRetire = plainBatch ?: legacyUpgraded val sourceToRetire = plainBatch ?: legacyUpgraded


if (sourceToRetire != null) { if (sourceToRetire != null) {
val mergeHeaderId = createNewMergeHeader(first, storeId, isSingleRelease, requiredDate, ticketFloorSegment)
val mergeHeaderId = createNewMergeHeader(first, storeId, isSingleRelease, requiredDate, ticketFloorSegment, actor)
?: return 0 ?: return 0
retireSourceTicketIntoMergeHeader(sourceToRetire.id, mergeHeaderId) retireSourceTicketIntoMergeHeader(sourceToRetire.id, mergeHeaderId)
linkPickOrdersToHeader(mergeHeaderId, group) linkPickOrdersToHeader(mergeHeaderId, group)
return 1 return 1
} }


val mergeHeaderId = createNewMergeHeader(first, storeId, isSingleRelease, requiredDate, ticketFloorSegment)
val mergeHeaderId = createNewMergeHeader(first, storeId, isSingleRelease, requiredDate, ticketFloorSegment, actor)
?: return 0 ?: return 0
linkPickOrdersToHeader(mergeHeaderId, group) linkPickOrdersToHeader(mergeHeaderId, group)
return 1 return 1
@@ -1033,6 +1081,7 @@ open class DoWorkbenchReleaseService(
results: List<ReleaseDoResult>, results: List<ReleaseDoResult>,
dopReleaseType: String = "batch", dopReleaseType: String = "batch",
mergeExtraIntoLaneTicket: Boolean = true, mergeExtraIntoLaneTicket: Boolean = true,
actor: String,
): Int { ): Int {
if (results.isEmpty()) return 0 if (results.isEmpty()) return 0


@@ -1064,6 +1113,7 @@ open class DoWorkbenchReleaseService(
isSingleRelease, isSingleRelease,
requiredDate, requiredDate,
ticketFloorSegment, ticketFloorSegment,
actor,
) )
} }


@@ -1079,6 +1129,7 @@ open class DoWorkbenchReleaseService(
storeId, storeId,
WorkbenchReleaseTypeSupport.LEGACY_IS_EXTRA, WorkbenchReleaseTypeSupport.LEGACY_IS_EXTRA,
ticketNo, ticketNo,
actor,
) ?: return 0 ) ?: return 0
linkPickOrdersToHeader(headerId, group) linkPickOrdersToHeader(headerId, group)
return 1 return 1
@@ -1104,7 +1155,7 @@ open class DoWorkbenchReleaseService(
} else { } else {
nextDeliveryOrderPickOrderBatchTicketNo(requiredDate, ticketFloorSegment) nextDeliveryOrderPickOrderBatchTicketNo(requiredDate, ticketFloorSegment)
} }
val headerId = insertNewDeliveryOrderPickOrderHeader(first, storeId, releaseTypeCol, ticketNo)
val headerId = insertNewDeliveryOrderPickOrderHeader(first, storeId, releaseTypeCol, ticketNo, actor)
?: return 0 ?: return 0
linkPickOrdersToHeader(headerId, group) linkPickOrdersToHeader(headerId, group)
return 1 return 1
@@ -1206,6 +1257,7 @@ open class DoWorkbenchReleaseService(
isSingleRelease = isSingleRelease, isSingleRelease = isSingleRelease,
requiredDate = requiredDate, requiredDate = requiredDate,
ticketFloorSegment = ticketFloorSegment, ticketFloorSegment = ticketFloorSegment,
actor = resolveReleaseActor(0L),
) ?: return mergeTicketsError("CREATE_FAILED", "Failed to create TI-M merge ticket") ) ?: return mergeTicketsError("CREATE_FAILED", "Failed to create TI-M merge ticket")
} }


@@ -1473,6 +1525,7 @@ open class DoWorkbenchReleaseService(
isSingleRelease: Boolean, isSingleRelease: Boolean,
requiredDate: LocalDate, requiredDate: LocalDate,
ticketFloorSegment: String, ticketFloorSegment: String,
actor: String,
): Long? { ): Long? {
val ticketNo = nextDeliveryOrderPickOrderMergeTicketNo(requiredDate, ticketFloorSegment) val ticketNo = nextDeliveryOrderPickOrderMergeTicketNo(requiredDate, ticketFloorSegment)
val releaseType = WorkbenchReleaseTypeSupport.mergeTicketReleaseType(isSingleRelease) val releaseType = WorkbenchReleaseTypeSupport.mergeTicketReleaseType(isSingleRelease)
@@ -1504,9 +1557,9 @@ open class DoWorkbenchReleaseService(
"ticketNo" to ticketNo, "ticketNo" to ticketNo,
"releaseType" to releaseType, "releaseType" to releaseType,
"created" to now, "created" to now,
"createdBy" to "system",
"createdBy" to actor,
"modified" to now, "modified" to now,
"modifiedBy" to "system",
"modifiedBy" to actor,
), ),
) )
return jdbcDao.queryForList( return jdbcDao.queryForList(
@@ -1515,6 +1568,6 @@ open class DoWorkbenchReleaseService(
WHERE ticketNo = :ticketNo ORDER BY id DESC LIMIT 1 WHERE ticketNo = :ticketNo ORDER BY id DESC LIMIT 1
""".trimIndent(), """.trimIndent(),
mapOf("ticketNo" to ticketNo), mapOf("ticketNo" to ticketNo),
).firstOrNull()?.get("id")?.let { (it as Number).toLong() }?.also { setRelationshipIdSelf(it) }
).firstOrNull()?.get("id")?.let { (it as Number).toLong() }?.also { setRelationshipIdSelf(it, actor) }
} }
} }

Loading…
取消
儲存