Parcourir la source

update stock take record

master
CANCERYS\kw093 il y a 3 jours
Parent
révision
f1002169ae
6 fichiers modifiés avec 97 ajouts et 14 suppressions
  1. +3
    -0
      src/main/java/com/ffii/fpsms/modules/stock/entity/StockTakeRecord.kt
  2. +1
    -0
      src/main/java/com/ffii/fpsms/modules/stock/entity/StockTakeRecordRepository.kt
  3. +64
    -14
      src/main/java/com/ffii/fpsms/modules/stock/service/StockTakeRecordService.kt
  4. +6
    -0
      src/main/java/com/ffii/fpsms/modules/stock/web/StockTakeRecordController.kt
  5. +5
    -0
      src/main/resources/db/changelog/changes/20260323_04_Enson/01_alter_stock_take.sql
  6. +18
    -0
      src/main/resources/db/changelog/changes/20260323_04_Enson/02_add_stock_take_round_indexes.sql

+ 3
- 0
src/main/java/com/ffii/fpsms/modules/stock/entity/StockTakeRecord.kt Voir le fichier

@@ -27,6 +27,9 @@ open class StockTakeRecord : BaseEntity<Long>() {
@ManyToOne
@JoinColumn(name = "stockTakeId", nullable = false)
open var stockTake: StockTake? = null

@Column(name = "stockTakeRoundId")
open var stockTakeRoundId: Long? = null
@Column(name = "approverId")
open var approverId: Long? = null


+ 1
- 0
src/main/java/com/ffii/fpsms/modules/stock/entity/StockTakeRecordRepository.kt Voir le fichier

@@ -11,6 +11,7 @@ import java.time.LocalDate
interface StockTakeRecordRepository : AbstractRepository<StockTakeRecord, Long> {
fun findAllByStockTakeIdAndDeletedIsFalse(stockTakeId: Long): List<StockTakeRecord>;
fun findAllByStockTakeIdInAndDeletedIsFalse(stockTakeIds: Collection<Long>): List<StockTakeRecord>;
fun findAllByStockTakeRoundIdAndDeletedIsFalse(stockTakeRoundId: Long): List<StockTakeRecord>;
fun findByIdAndDeletedIsFalse(id: Serializable): StockTakeRecord?;

@Query("""


+ 64
- 14
src/main/java/com/ffii/fpsms/modules/stock/service/StockTakeRecordService.kt Voir le fichier

@@ -230,19 +230,25 @@ class StockTakeRecordService(
println("getApproverInventoryLotDetailsAll called with stockTakeId: $stockTakeId, pageNum: $pageNum, pageSize: $pageSize")

// 3. 如果传了 stockTakeId,就把「同一轮」的所有 stockTake 找出来(stockTakeRoundId,舊資料則 planStart)
val roundStockTakeIds: Set<Long> = if (stockTakeId != null) {
// stockTakeId != null 时,优先用 stocktakerecord.stockTakeRoundId 取整轮记录(更快)
// 如果该轮因为旧数据尚未写入 roundId 导致取不到,再 fallback 到旧逻辑(根据 stock_take 的 planStart / stockTakeRoundId 求 stockTakeId 列表)
val (roundStockTakeIds, roundStockTakeRecords) = if (stockTakeId != null) {
val baseStockTake = stockTakeRepository.findByIdAndDeletedIsFalse(stockTakeId)
?: throw IllegalArgumentException("Stock take not found: $stockTakeId")
resolveRoundStockTakeIds(baseStockTake)
} else {
emptySet()
}

// 4. 如果有 stockTakeId,则预先把这一轮相关的 stockTakeRecord 查出来建 map(避免全表扫描 + N^2)
val roundStockTakeRecords = if (stockTakeId != null && roundStockTakeIds.isNotEmpty()) {
stockTakeRecordRepository.findAllByStockTakeIdInAndDeletedIsFalse(roundStockTakeIds)
val roundId = baseStockTake.stockTakeRoundId ?: baseStockTake.id
val recordsByRound = stockTakeRecordRepository.findAllByStockTakeRoundIdAndDeletedIsFalse(roundId)

if (recordsByRound.isNotEmpty()) {
val ids = recordsByRound.mapNotNull { it.stockTake?.id }.toSet()
ids to recordsByRound
} else {
val ids = resolveRoundStockTakeIds(baseStockTake)
val records = if (ids.isNotEmpty()) stockTakeRecordRepository.findAllByStockTakeIdInAndDeletedIsFalse(ids) else emptyList()
ids to records
}
} else {
emptyList()
emptySet<Long>() to emptyList()
}
val stockTakeRecordsMap = roundStockTakeRecords
.groupBy { Pair(it.lotId ?: 0L, it.warehouse?.id ?: 0L) }
@@ -413,13 +419,19 @@ class StockTakeRecordService(
.maxByOrNull { it.actualStart ?: it.planStart ?: LocalDateTime.MIN }
?: return emptyList()

val roundStockTakeIds = resolveRoundStockTakeIds(latestBaseStockTake)
if (roundStockTakeIds.isEmpty()) return emptyList()

// stockTakeRecord 存在性:用来对齐 details 接口的 `stockTakeRecordId != null`
val roundStockTakeRecords = stockTakeRecordRepository.findAllByStockTakeIdInAndDeletedIsFalse(roundStockTakeIds)
// 优先用 stocktakerecord.stockTakeRoundId 直接取该轮次记录(避免再算 stockTakeId 列表 + in 查询)
val roundId = latestBaseStockTake.stockTakeRoundId ?: latestBaseStockTake.id
var roundStockTakeRecords = stockTakeRecordRepository.findAllByStockTakeRoundIdAndDeletedIsFalse(roundId)
.filter { it.warehouse?.id in warehouseIds }

// 兼容旧数据:如果该轮次 roundId 为空/未补写,则 fallback 到旧逻辑
if (roundStockTakeRecords.isEmpty()) {
val roundStockTakeIds = resolveRoundStockTakeIds(latestBaseStockTake)
if (roundStockTakeIds.isEmpty()) return emptyList()
roundStockTakeRecords = stockTakeRecordRepository.findAllByStockTakeIdInAndDeletedIsFalse(roundStockTakeIds)
.filter { it.warehouse?.id in warehouseIds }
}

val recordKeySet = roundStockTakeRecords.mapNotNull { r ->
val lotId = r.lotId
val whId = r.warehouse?.id
@@ -476,6 +488,40 @@ class StockTakeRecordService(
)
}

/**
* 轻量版:只返回 Approver 最新一轮的基本信息,不做 totalItem/totalLot 重计算。
* 用于前端先拿 stockTakeId,再调用 pending/approved 明细接口。
*/
open fun getLatestApproverStockTakeHeader(): AllPickedStockTakeListReponse? {
val latestBaseStockTake = stockTakeRepository.findAll()
.filter { !it.deleted }
.maxByOrNull { it.actualStart ?: it.planStart ?: LocalDateTime.MIN }
?: return null

val statusValue = latestBaseStockTake.status?.let { st ->
if (st == StockTakeStatus.APPROVING || st == StockTakeStatus.COMPLETED) st.value else ""
} ?: ""

return AllPickedStockTakeListReponse(
id = 1L,
stockTakeSession = "",
lastStockTakeDate = latestBaseStockTake.actualStart?.toLocalDate(),
status = statusValue,
currentStockTakeItemNumber = 0,
totalInventoryLotNumber = 0,
stockTakeId = latestBaseStockTake.id ?: 0,
stockTakeRoundId = latestBaseStockTake.stockTakeRoundId ?: latestBaseStockTake.id,
stockTakerName = null,
approverName = null,
TotalItemNumber = 0,
startTime = latestBaseStockTake.actualStart,
endTime = latestBaseStockTake.actualEnd,
ReStockTakeTrueFalse = false,
planStartDate = latestBaseStockTake.planStart?.toLocalDate(),
stockTakeSectionDescription = null
)
}

open fun getInventoryLotDetailsByWarehouseCode(warehouseCode: String): List<InventoryLotDetailResponse> {
println("getInventoryLotDetailsByWarehouseCode called with code: $warehouseCode")

@@ -690,6 +736,8 @@ return RecordsRes(paginatedResult, filteredResults.size)
val varianceQty = availableQty - request.qty - request.badQty
// 更新字段(第二次盘点)
existingRecord.apply {
// 兼容旧数据:如果之前没写 round id,则补写
this.stockTakeRoundId = this.stockTakeRoundId ?: (stockTake.stockTakeRoundId ?: stockTake.id)
this.pickerSecondStockTakeQty = request.qty
this.pickerSecondBadQty = request.badQty // 更新 badQty
this.status = "pass"
@@ -711,6 +759,7 @@ return RecordsRes(paginatedResult, filteredResults.size)
this.lotId = inventoryLot.id
this.warehouse = warehouse
this.stockTake = stockTake
this.stockTakeRoundId = stockTake.stockTakeRoundId ?: stockTake.id
this.stockTakeSection = warehouse.stockTakeSection
this.inventoryLotId = inventoryLot.id
this.stockTakerId = stockTakerId
@@ -853,6 +902,7 @@ return RecordsRes(paginatedResult, filteredResults.size)
this.lotId = inventoryLot.id
this.warehouse = warehouse
this.stockTake = stockTake
this.stockTakeRoundId = stockTake.stockTakeRoundId ?: stockTake.id
this.stockTakeSection = request.stockTakeSection
this.inventoryLotId = inventoryLot.id
this.stockTakerId = request.stockTakerId


+ 6
- 0
src/main/java/com/ffii/fpsms/modules/stock/web/StockTakeRecordController.kt Voir le fichier

@@ -94,6 +94,12 @@ class StockTakeRecordController(
fun AllApproverStockTakeList(): List<AllPickedStockTakeListReponse> {
return stockOutRecordService.AllApproverStockTakeList()
}
@GetMapping("/LatestApproverStockTakeHeader")
fun latestApproverStockTakeHeader(): ResponseEntity<AllPickedStockTakeListReponse> {
val header = stockOutRecordService.getLatestApproverStockTakeHeader()
?: return ResponseEntity.notFound().build()
return ResponseEntity.ok(header)
}
@GetMapping("/inventoryLotDetailsBySectionNotMatch")
fun getInventoryLotDetailsByStockTakeSectionNotMatch(
@RequestParam stockTakeSection: String,


+ 5
- 0
src/main/resources/db/changelog/changes/20260323_04_Enson/01_alter_stock_take.sql Voir le fichier

@@ -0,0 +1,5 @@
-- liquibase formatted sql
-- changeset Enson:alter_stocktakerecord_stockTakeRoundId

ALTER TABLE `fpsmsdb`.`stocktakerecord`
ADD COLUMN `stockTakeRoundId` INT NULL AFTER `stockTakeId`;

+ 18
- 0
src/main/resources/db/changelog/changes/20260323_04_Enson/02_add_stock_take_round_indexes.sql Voir le fichier

@@ -0,0 +1,18 @@
-- liquibase formatted sql
-- changeset Enson:add_stock_take_round_indexes

-- 1) stocktakerecord:优先按“同一轮次”取记录(避免再用 stockTakeId 列表 + in)
ALTER TABLE `fpsmsdb`.`stocktakerecord`
ADD INDEX `idx_stocktakerecord_round_deleted_wh_lot`
(`stockTakeRoundId`, `deleted`, `warehouseId`, `inventoryLotId`);

-- 2) stock_take_line:给 (stockTakeId, inventoryLotLineId) 的 join / map 提速
ALTER TABLE `fpsmsdb`.`stock_take_line`
ADD INDEX `idx_stocktakeline_stockTakeId_lineId_deleted`
(`stockTakeId`, `inventoryLotLineId`, `deleted`);

-- 3) inventory_lot_line:给 (warehouseId, inventoryLotId) 的库存行筛选提速
ALTER TABLE `fpsmsdb`.`inventory_lot_line`
ADD INDEX `idx_inventorylotline_wh_lot_deleted`
(`warehouseId`, `inventoryLotId`, `deleted`);


Chargement…
Annuler
Enregistrer