Selaa lähdekoodia

update

master
CANCERYS\kw093 2 päivää sitten
vanhempi
commit
a4ff32c62c
7 muutettua tiedostoa jossa 98 lisäystä ja 22 poistoa
  1. +12
    -8
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt
  2. +1
    -0
      src/main/java/com/ffii/fpsms/modules/master/entity/ProcessRepository.kt
  3. +17
    -0
      src/main/java/com/ffii/fpsms/modules/master/web/ProcessController.kt
  4. +3
    -1
      src/main/java/com/ffii/fpsms/modules/stock/entity/StockTakeRecord.kt
  5. +53
    -13
      src/main/java/com/ffii/fpsms/modules/stock/service/StockTakeRecordService.kt
  6. +4
    -0
      src/main/java/com/ffii/fpsms/modules/stock/web/model/StockTakeRecordReponse.kt
  7. +8
    -0
      src/main/resources/db/changelog/changes/20260325_01_Enson/01_alter_stock_take.sql

+ 12
- 8
src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderService.kt Näytä tiedosto

@@ -751,13 +751,15 @@ open class DeliveryOrderService(
}
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
.filter { it.deleted != true } // 只跳过 deleted=true(deleted 为空时也当作未删)
.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,
@@ -1443,7 +1445,9 @@ open class DeliveryOrderService(
deliveryOrderRepository.save(deliveryOrder)

// 创建 pick order
val pols = deliveryOrder.deliveryOrderLines.map {
val pols = deliveryOrder.deliveryOrderLines
.filter { it.deleted != true } // 只跳过 deleted=true(deleted 为空时也当作未删)
.map {
SavePickOrderLineRequest(
itemId = it.item?.id,
qty = it.qty ?: BigDecimal.ZERO,


+ 1
- 0
src/main/java/com/ffii/fpsms/modules/master/entity/ProcessRepository.kt Näytä tiedosto

@@ -8,4 +8,5 @@ import java.util.*
interface ProcessRepository: AbstractRepository<Process, Long> {
fun findByCodeAndDeletedIsFalse(code: String): Process?
fun findByNameAndDeletedIsFalse(name: String): Process?
fun findAllByDeletedFalse(): List<Process>
}

+ 17
- 0
src/main/java/com/ffii/fpsms/modules/master/web/ProcessController.kt Näytä tiedosto

@@ -0,0 +1,17 @@
package com.ffii.fpsms.modules.master.web

import com.ffii.fpsms.modules.master.entity.Process
import com.ffii.fpsms.modules.master.entity.ProcessRepository
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/Process")
class ProcessController(
private val processRepository: ProcessRepository,
) {
/** All non-deleted master processes (for dropdowns, e.g. distinct codes on the client). */
@GetMapping
fun allProcesses(): List<Process> = processRepository.findAllByDeletedFalse()
}

+ 3
- 1
src/main/java/com/ffii/fpsms/modules/stock/entity/StockTakeRecord.kt Näytä tiedosto

@@ -77,7 +77,9 @@ open class StockTakeRecord : BaseEntity<Long>() {
@Column(name = "stockTakeEndTime")
open var stockTakeEndTime: LocalDateTime? = null

@Column(name = "approverTime")
open var approverTime: LocalDateTime? = null
@Column(name = "date", nullable = false)
open var date: LocalDate? = null


+ 53
- 13
src/main/java/com/ffii/fpsms/modules/stock/service/StockTakeRecordService.kt Näytä tiedosto

@@ -366,6 +366,8 @@ class StockTakeRecordService(
stockTakeSection = stockTakeRecord?.stockTakeSection ?: warehouse?.stockTakeSection,
stockTakeSectionDescription = warehouse?.stockTakeSectionDescription,
stockTakerName = stockTakeRecord?.stockTakerName,
stockTakeEndTime = stockTakeRecord?.stockTakeEndTime,
approverTime = stockTakeRecord?.approverTime,
)
}
@@ -380,16 +382,14 @@ class StockTakeRecordService(
}
}

// Pending / Approved 只看「審核是否完成」,不要用 stockTakeRecord.status == "completed":
// picker 在 inQty==outQty 時也會寫 status=completed,會被誤判成已審核而只出現在 Approved 分頁。
val approvalFilteredResults = when (approvalView?.lowercase()) {
"approved" -> filteredResults.filter { response ->
response.stockTakeRecordStatus == "completed" ||
response.approverQty != null ||
response.finalQty != null
response.approverQty != null || response.finalQty != null
}
"pending" -> filteredResults.filter { response ->
!(response.stockTakeRecordStatus == "completed" ||
response.approverQty != null ||
response.finalQty != null)
response.approverQty == null && response.finalQty == null
}
else -> filteredResults
}
@@ -683,6 +683,11 @@ class StockTakeRecordService(
approverBadQty = stockTakeRecord?.approverBadQty,
finalQty = stockTakeLine?.finalQty,
bookQty = stockTakeRecord?.bookQty,
stockTakeSection = stockTakeRecord?.stockTakeSection ?: warehouse?.stockTakeSection,
stockTakeSectionDescription = warehouse?.stockTakeSectionDescription,
stockTakerName = stockTakeRecord?.stockTakerName,
stockTakeEndTime = stockTakeRecord?.stockTakeEndTime,
approverTime = stockTakeRecord?.approverTime,
)
}

@@ -1099,14 +1104,18 @@ return RecordsRes(paginatedResult, filteredResults.size)
this.approverBadQty = finalBadQty
this.varianceQty = varianceQty
this.status = "completed"
this.approverTime = java.time.LocalDateTime.now()
// stockTakeEndTime 目前只在 saveStockTakeRecord「第二次盤點」時寫入;只做第一次盤點時會一直是 null。
// 審核通過時若仍為空,補上時間,讓列表「審核/完成時間」有值(不覆寫已有第二次盤點結束時間)。
if (this.stockTakeEndTime == null) {
this.stockTakeEndTime = java.time.LocalDateTime.now()
}
}

val savedRecord = stockTakeRecordRepository.save(stockTakeRecord)

// ------- 取当前库存行 / 库存信息 -------
val inventoryLotLine = inventoryLotLineRepository.findByIdAndDeletedIsFalse(
stockTakeRecord.inventoryLotId ?: throw IllegalArgumentException("Inventory lot ID not found")
) ?: throw IllegalArgumentException("Inventory lot line not found")
// stockTakeRecord.inventoryLotId 是 inventory_lot 主鍵,不是 inventory_lot_line 主鍵;必須用倉庫+批次定位庫存行
val inventoryLotLine = resolveInventoryLotLineForStockTakeRecord(savedRecord)

val inventoryLot = inventoryLotRepository.findByIdAndDeletedFalse(
inventoryLotLine.inventoryLot?.id ?: throw IllegalArgumentException("Inventory lot ID not found")
@@ -1209,6 +1218,10 @@ open fun batchSaveApproverStockTakeRecords(
this.approverBadQty = badQty
this.varianceQty = varianceQty
this.status = "completed"
this.approverTime = java.time.LocalDateTime.now()
if (this.stockTakeEndTime == null) {
this.stockTakeEndTime = java.time.LocalDateTime.now()
}
}
stockTakeRecordRepository.save(record)
@@ -1321,6 +1334,10 @@ open fun batchSaveApproverStockTakeRecordsAll(
this.approverBadQty = badQty
this.varianceQty = varianceQty
this.status = "completed"
this.approverTime = java.time.LocalDateTime.now()
if (this.stockTakeEndTime == null) {
this.stockTakeEndTime = java.time.LocalDateTime.now()
}
}

stockTakeRecordRepository.save(record)
@@ -1362,6 +1379,26 @@ open fun batchSaveApproverStockTakeRecordsAll(
)
}

/**
* stockTakeRecord 上存的是 inventory_lot.id(批次),不是 inventory_lot_line.id;用倉庫 + 批次找唯一庫存行。
*/
private fun resolveInventoryLotLineForStockTakeRecord(record: StockTakeRecord): InventoryLotLine {
val warehouseId = record.warehouse?.id
?: throw IllegalArgumentException("Warehouse not found on stock take record")
val lotId = record.inventoryLotId ?: record.lotId
?: throw IllegalArgumentException("Inventory lot ID not found on stock take record")
val lines = inventoryLotLineRepository.findAllByWarehouseIdInAndInventoryLotIdInAndDeletedIsFalse(
listOf(warehouseId),
listOf(lotId)
)
if (lines.isEmpty()) {
throw IllegalArgumentException(
"Inventory lot line not found for warehouseId=$warehouseId inventoryLotId=$lotId"
)
}
return lines.maxByOrNull { it.id ?: 0L }!!
}

/**
* 根据 variance 调整库存并创建 Stock Ledger。
* 当 variance != 0 时:创建 StockTakeLine,并根据 variance 正负创建 StockIn/StockOut 及 Ledger。
@@ -1375,9 +1412,7 @@ private fun applyVarianceAdjustment(
) {
if (varianceQty == BigDecimal.ZERO) return

val inventoryLotLine = inventoryLotLineRepository.findByIdAndDeletedIsFalse(
stockTakeRecord.inventoryLotId ?: throw IllegalArgumentException("Inventory lot ID not found")
) ?: throw IllegalArgumentException("Inventory lot line not found")
val inventoryLotLine = resolveInventoryLotLineForStockTakeRecord(stockTakeRecord)

val inventoryLot = inventoryLotRepository.findByIdAndDeletedFalse(
inventoryLotLine.inventoryLot?.id ?: throw IllegalArgumentException("Inventory lot ID not found")
@@ -1625,6 +1660,11 @@ open fun getInventoryLotDetailsByStockTakeSectionNotMatch(
approverBadQty = stockTakeRecord.approverBadQty,
finalQty = stockTakeLine?.finalQty,
bookQty = stockTakeRecord.bookQty,
stockTakeSection = stockTakeRecord.stockTakeSection ?: warehouse?.stockTakeSection,
stockTakeSectionDescription = warehouse?.stockTakeSectionDescription,
stockTakerName = stockTakeRecord.stockTakerName,
stockTakeEndTime = stockTakeRecord.stockTakeEndTime,
approverTime = stockTakeRecord.approverTime,
)
}


+ 4
- 0
src/main/java/com/ffii/fpsms/modules/stock/web/model/StockTakeRecordReponse.kt Näytä tiedosto

@@ -64,6 +64,10 @@ data class InventoryLotDetailResponse(
val stockTakeSection: String? = null,
val stockTakeSectionDescription: String? = null,
val stockTakerName: String? = null,
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
val stockTakeEndTime: LocalDateTime? = null,
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
val approverTime: LocalDateTime? = null,
)
data class InventoryLotLineListRequest(
val warehouseCode: String


+ 8
- 0
src/main/resources/db/changelog/changes/20260325_01_Enson/01_alter_stock_take.sql Näytä tiedosto

@@ -0,0 +1,8 @@
-- liquibase formatted sql
-- changeset Enson:alter_stock_take_approver_time

ALTER TABLE `fpsmsdb`.`stocktakerecord`
ADD COLUMN `approverTime` DATETIME NULL AFTER `stockTakeEndTime`;




Ladataan…
Peruuta
Tallenna