Ver a proveniência

remove bar from round card lsit

lot expiry after create round before appove
tonigh lot will expiry can not do expiry handle ,block while stock taking relate
stockTakeUpdate
CANCERYS\kw093 há 2 semanas
ascendente
cometimento
8b4802eb31
7 ficheiros alterados com 242 adições e 16 eliminações
  1. +4
    -1
      src/main/java/com/ffii/fpsms/modules/common/scheduler/service/SchedulerService.kt
  2. +65
    -6
      src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt
  3. +5
    -1
      src/main/java/com/ffii/fpsms/modules/pickOrder/web/models/SubmitIssueRequest.kt
  4. +24
    -0
      src/main/java/com/ffii/fpsms/modules/stock/entity/InventoryLotLineRepository.kt
  5. +2
    -0
      src/main/java/com/ffii/fpsms/modules/stock/entity/StockTakeRecordRepository.kt
  6. +16
    -1
      src/main/java/com/ffii/fpsms/modules/stock/service/InventoryLotLineService.kt
  7. +126
    -7
      src/main/java/com/ffii/fpsms/modules/stock/service/StockTakeRecordService.kt

+ 4
- 1
src/main/java/com/ffii/fpsms/modules/common/scheduler/service/SchedulerService.kt Ver ficheiro

@@ -582,7 +582,10 @@ open class SchedulerService(
open fun markExpiredInventoryLotLinesAsUnavailable() { open fun markExpiredInventoryLotLinesAsUnavailable() {
try { try {
val updatedRows = inventoryLotLineService.markExpiredLotLinesAsUnavailable() val updatedRows = inventoryLotLineService.markExpiredLotLinesAsUnavailable()
logger.info("Scheduler - Inventory lot expiry update done, rows updated=$updatedRows")
logger.info(
"Scheduler - Inventory lot expiry update done, rows updated=$updatedRows " +
"(also soft-deletes open stock-take records for those lots)"
)
} catch (e: Exception) { } catch (e: Exception) {
logger.error("Scheduler - Inventory lot expiry update failed: ${e.message}", e) logger.error("Scheduler - Inventory lot expiry update failed: ${e.message}", e)
} }


+ 65
- 6
src/main/java/com/ffii/fpsms/modules/pickOrder/service/PickExecutionIssueService.kt Ver ficheiro

@@ -52,6 +52,7 @@ import com.ffii.fpsms.modules.stock.entity.SuggestPickLotRepository
import org.springframework.beans.factory.annotation.Value import org.springframework.beans.factory.annotation.Value
import com.ffii.fpsms.modules.stock.web.model.BatchStockOutRequest import com.ffii.fpsms.modules.stock.web.model.BatchStockOutRequest
import com.ffii.fpsms.modules.stock.web.model.BatchStockOutLineRequest import com.ffii.fpsms.modules.stock.web.model.BatchStockOutLineRequest
import com.ffii.fpsms.modules.stock.entity.StockTakeRecordRepository
@Service @Service
open class PickExecutionIssueService( open class PickExecutionIssueService(
private val pickExecutionIssueRepository: PickExecutionIssueRepository, private val pickExecutionIssueRepository: PickExecutionIssueRepository,
@@ -72,7 +73,8 @@ open class PickExecutionIssueService(
private val stockLedgerRepository: StockLedgerRepository, private val stockLedgerRepository: StockLedgerRepository,
private val deliveryOrderRepository: DeliveryOrderRepository, private val deliveryOrderRepository: DeliveryOrderRepository,
private val suggestedPickLotRepository: SuggestPickLotRepository, private val suggestedPickLotRepository: SuggestPickLotRepository,
private val doPickOrderRepository: DoPickOrderRepository
private val doPickOrderRepository: DoPickOrderRepository,
private val stockTakeRecordRepository: StockTakeRecordRepository,


) { ) {
// 配置属性:是否在批次拒绝时自动重新建议批次(默认为 false,不自动重新建议) // 配置属性:是否在批次拒绝时自动重新建议批次(默认为 false,不自动重新建议)
@@ -1833,11 +1835,30 @@ open fun getExpiryItemList(
itemName = normalizedItemName, itemName = normalizedItemName,
lotNo = normalizedLotNo, lotNo = normalizedLotNo,
) )

val openStockTakePairs = openStockTakeLotWarehousePairs(
lotLines.mapNotNull { it.inventoryLot?.id }
)
return lotLines.map { lotLine -> return lotLines.map { lotLine ->
val lot = lotLine.inventoryLot val lot = lotLine.inventoryLot
val item = lot?.item // Get item from inventoryLot val item = lot?.item // Get item from inventoryLot
val expiry = lot?.expiryDate val expiry = lot?.expiryDate
val dueOrPast = expiry != null && !expiry.isAfter(today)
val expiresToday = expiry != null && expiry.isEqual(today)
val lotId = lot?.id
val warehouseId = lotLine.warehouse?.id
val stockTakeBlocked = expiresToday &&
lotId != null &&
warehouseId != null &&
(lotId to warehouseId) in openStockTakePairs
val canHandle = dueOrPast && !stockTakeBlocked
val blockKey = when {
canHandle -> null
expiry == null || expiry.isAfter(today) -> "FUTURE"
stockTakeBlocked -> "STOCK_TAKE_OPEN"
else -> null
}
ExpiryItemResponse( ExpiryItemResponse(
id = lotLine.id ?: 0L, id = lotLine.id ?: 0L,
itemId = item?.id ?: 0L, itemId = item?.id ?: 0L,
@@ -1849,11 +1870,36 @@ open fun getExpiryItemList(
expiryDate = expiry, expiryDate = expiry,
remainingQty = (lotLine.inQty ?: BigDecimal.ZERO).subtract(lotLine.outQty ?: BigDecimal.ZERO), remainingQty = (lotLine.inQty ?: BigDecimal.ZERO).subtract(lotLine.outQty ?: BigDecimal.ZERO),
uomDesc = lotLine.stockUom?.uom?.udfudesc, uomDesc = lotLine.stockUom?.uom?.udfudesc,
canHandle = expiry != null && !expiry.isAfter(today),
canHandle = canHandle,
canHandleBlockKey = blockKey,
) )
} }
} }


/** Open-round stock take records keyed by (inventoryLotId, warehouseId). */
private fun openStockTakeLotWarehousePairs(lotIds: Collection<Long>): Set<Pair<Long, Long>> {
val ids = lotIds.filter { it > 0L }.distinct()
if (ids.isEmpty()) return emptySet()
return stockTakeRecordRepository.findAllByLotIdInAndDeletedIsFalse(ids)
.mapNotNull { rec ->
val header = rec.stockTake ?: return@mapNotNull null
if (header.deleted || header.status?.isOpen() != true) return@mapNotNull null
val lotId = rec.lotId ?: return@mapNotNull null
val warehouseId = rec.warehouse?.id ?: return@mapNotNull null
lotId to warehouseId
}
.toSet()
}

/** 今日到期且仍在 open 盤點中 → 不可過期處置(已過期仍可處置)。 */
private fun isExpiresTodayBlockedByOpenStockTake(lotLine: InventoryLotLine, today: LocalDate = LocalDate.now()): Boolean {
val expiry = lotLine.inventoryLot?.expiryDate ?: return false
if (!expiry.isEqual(today)) return false
val lotId = lotLine.inventoryLot?.id ?: return false
val warehouseId = lotLine.warehouse?.id ?: return false
return (lotId to warehouseId) in openStockTakeLotWarehousePairs(listOf(lotId))
}

@Transactional(rollbackFor = [Exception::class]) @Transactional(rollbackFor = [Exception::class])
open fun submitMissItem(request: SubmitIssueRequest): MessageResponse { open fun submitMissItem(request: SubmitIssueRequest): MessageResponse {
try { try {
@@ -2030,6 +2076,17 @@ open fun submitExpiryItem(request: SubmitExpiryRequest): MessageResponse {
errorPosition = null errorPosition = null
) )
} }

if (isExpiresTodayBlockedByOpenStockTake(lotLine, today)) {
return MessageResponse(
id = null,
name = "Error",
code = "STOCK_TAKE_OPEN",
type = "stock_issue",
message = "Expires today and is in an open stock take; cannot dispose until stock take finishes or the lot leaves the round",
errorPosition = null
)
}
val inQty = lotLine.inQty ?: BigDecimal.ZERO val inQty = lotLine.inQty ?: BigDecimal.ZERO
val outQty = lotLine.outQty ?: BigDecimal.ZERO val outQty = lotLine.outQty ?: BigDecimal.ZERO
@@ -2214,19 +2271,21 @@ open fun batchSubmitBadItem(request: BatchSubmitIssueRequest): MessageResponse {
@Transactional(rollbackFor = [Exception::class]) @Transactional(rollbackFor = [Exception::class])
open fun batchSubmitExpiryItem(request: BatchSubmitExpiryRequest): MessageResponse { open fun batchSubmitExpiryItem(request: BatchSubmitExpiryRequest): MessageResponse {
try { try {
val today = LocalDate.now()
val lotLines = inventoryLotLineRepository.findAllById(request.lotLineIds) val lotLines = inventoryLotLineRepository.findAllById(request.lotLineIds)
.filter { .filter {
val lot = it.inventoryLot val lot = it.inventoryLot
val today = LocalDate.now()
lot?.expiryDate != null && lot?.expiryDate != null &&
lot.expiryDate!!.let { !it.isAfter(today) } &&
(it.inQty ?: BigDecimal.ZERO) > (it.outQty ?: BigDecimal.ZERO)
lot.expiryDate!!.let { d -> !d.isAfter(today) } &&
(it.inQty ?: BigDecimal.ZERO) > (it.outQty ?: BigDecimal.ZERO) &&
!isExpiresTodayBlockedByOpenStockTake(it, today)
} }


if (lotLines.isEmpty()) { if (lotLines.isEmpty()) {
return MessageResponse( return MessageResponse(
id = null, name = "Error", code = "EMPTY", type = "stock_issue", id = null, name = "Error", code = "EMPTY", type = "stock_issue",
message = "No valid expiry items to submit", errorPosition = null
message = "No valid expiry items to submit (today-expiry lots in open stock take are blocked)",
errorPosition = null
) )
} }




+ 5
- 1
src/main/java/com/ffii/fpsms/modules/pickOrder/web/models/SubmitIssueRequest.kt Ver ficheiro

@@ -32,8 +32,12 @@ data class ExpiryItemResponse(
val expiryDate: LocalDate?, val expiryDate: LocalDate?,
val remainingQty: BigDecimal, val remainingQty: BigDecimal,
val uomDesc: String?, val uomDesc: String?,
/** True when expiryDate is today or earlier. */
/** True when expiryDate is today or earlier, and not blocked by open stock take (today-expiry). */
val canHandle: Boolean, val canHandle: Boolean,
/**
* When [canHandle] is false: `FUTURE` (not yet due) or `STOCK_TAKE_OPEN` (expires today but in open stock take).
*/
val canHandleBlockKey: String? = null,
) )
data class LotIssueDetailRequest( data class LotIssueDetailRequest(
val lotId: Long, val lotId: Long,


+ 24
- 0
src/main/java/com/ffii/fpsms/modules/stock/entity/InventoryLotLineRepository.kt Ver ficheiro

@@ -287,6 +287,30 @@ WHERE ill.id = :id
@Param("storeIds") storeIds: List<String> @Param("storeIds") storeIds: List<String>
): List<InventoryLotLine> ): List<InventoryLotLine>


/**
* Lot lines that the daily expiry job will mark unavailable
* ([InventoryLot.expiryDate] &lt; today and status not yet unavailable).
*/
@EntityGraph(
type = EntityGraph.EntityGraphType.FETCH,
attributePaths = ["inventoryLot", "warehouse"]
)
@Query(
"""
SELECT ill FROM InventoryLotLine ill
JOIN ill.inventoryLot il
WHERE ill.deleted = false
AND il.deleted = false
AND il.expiryDate IS NOT NULL
AND il.expiryDate < :today
AND (ill.status IS NULL OR ill.status <> :unavailable)
"""
)
fun findExpiredLotLinesNotYetUnavailable(
@Param("today") today: LocalDate,
@Param("unavailable") unavailable: InventoryLotLineStatus,
): List<InventoryLotLine>

@Modifying @Modifying
@Transactional @Transactional
@Query( @Query(


+ 2
- 0
src/main/java/com/ffii/fpsms/modules/stock/entity/StockTakeRecordRepository.kt Ver ficheiro

@@ -19,6 +19,8 @@ interface StockTakeRecordRepository : AbstractRepository<StockTakeRecord, Long>
warehouseIds: Collection<Long> warehouseIds: Collection<Long>
): List<StockTakeRecord> ): List<StockTakeRecord>


fun findAllByLotIdInAndDeletedIsFalse(lotIds: Collection<Long>): List<StockTakeRecord>

@Query( @Query(
""" """


+ 16
- 1
src/main/java/com/ffii/fpsms/modules/stock/service/InventoryLotLineService.kt Ver ficheiro

@@ -64,10 +64,25 @@ open class InventoryLotLineService(
@Lazy @Lazy
private val jobOrderService: JobOrderService, private val jobOrderService: JobOrderService,
private val stockTakeLocationGuard: StockTakeLocationGuard, private val stockTakeLocationGuard: StockTakeLocationGuard,
@Lazy
private val stockTakeRecordService: StockTakeRecordService,
) { ) {
/**
* Daily job: mark expired lot lines UNAVAILABLE, then drop matching open stock-take
* placeholders so picker/approver and section status no longer see those lots.
*/
@Transactional @Transactional
open fun markExpiredLotLinesAsUnavailable(): Int { open fun markExpiredLotLinesAsUnavailable(): Int {
return inventoryLotLineRepository.markExpiredLotLinesAsUnavailable()
val today = LocalDate.now()
val candidates = inventoryLotLineRepository.findExpiredLotLinesNotYetUnavailable(
today,
InventoryLotLineStatus.UNAVAILABLE,
)
val updatedRows = inventoryLotLineRepository.markExpiredLotLinesAsUnavailable()
if (candidates.isNotEmpty()) {
stockTakeRecordService.softDeleteOpenStockTakeRecordsForExpiredLotLines(candidates)
}
return updatedRows
} }


open fun findById(id: Long): Optional<InventoryLotLine> { open fun findById(id: Long): Optional<InventoryLotLine> {


+ 126
- 7
src/main/java/com/ffii/fpsms/modules/stock/service/StockTakeRecordService.kt Ver ficheiro

@@ -496,8 +496,17 @@ open class StockTakeRecordService(
return@forEach return@forEach
} }


// 修復:曾用整輪代表 id 升錯單頭時,本區明細已全 completed 卻仍停在 approving
val status = if (latestStockTake != null) { val status = if (latestStockTake != null) {
latestStockTake.status?.value ?: "pending"
val headerId = latestStockTake.id
if (headerId != null && latestStockTake.status == StockTakeStatus.APPROVING) {
checkAndUpdateStockTakeStatus(headerId, stockTakeSection)
stockTakeRepository.findByIdAndDeletedIsFalse(headerId)?.status?.value
?: latestStockTake.status?.value
?: "pending"
} else {
latestStockTake.status?.value ?: "pending"
}
} else { } else {
"no_cycle" "no_cycle"
} }
@@ -1186,6 +1195,61 @@ open class StockTakeRecordService(
.sorted() .sorted()
} }


/**
* 排程將過期 lot line 標成 UNAVAILABLE 後呼叫:對仍 open 的盤點輪次,
* soft-delete 對應且尚未 completed 的 [StockTakeRecord]/[StockTakeLine],
* 再重算受影響區域單頭狀態。
*/
@Transactional
open fun softDeleteOpenStockTakeRecordsForExpiredLotLines(lotLines: List<InventoryLotLine>): Int {
if (lotLines.isEmpty()) return 0
val pairs = lotLines.mapNotNull { ill ->
val lotId = ill.inventoryLot?.id ?: return@mapNotNull null
val warehouseId = ill.warehouse?.id ?: return@mapNotNull null
lotId to warehouseId
}.toSet()
if (pairs.isEmpty()) return 0

val lotIds = pairs.map { it.first }.distinct()
val toRemove = stockTakeRecordRepository.findAllByLotIdInAndDeletedIsFalse(lotIds).filter { rec ->
val lotId = rec.lotId ?: return@filter false
val warehouseId = rec.warehouse?.id ?: return@filter false
if ((lotId to warehouseId) !in pairs) return@filter false
if (rec.status.equals("completed", ignoreCase = true)) return@filter false
val header = rec.stockTake ?: return@filter false
!header.deleted && header.status?.isOpen() == true
}
if (toRemove.isEmpty()) return 0

val recordIds = toRemove.mapNotNull { it.id }
toRemove.forEach { it.deleted = true }
stockTakeRecordRepository.saveAll(toRemove)

if (recordIds.isNotEmpty()) {
val lines = stockTakeLineRepository.findAllByStockTakeRecord_IdInAndDeletedIsFalse(recordIds)
lines.forEach { it.deleted = true }
if (lines.isNotEmpty()) {
stockTakeLineRepository.saveAll(lines)
}
}

val headersToRefresh = toRemove.mapNotNull { rec ->
val stId = rec.stockTake?.id ?: return@mapNotNull null
val section = rec.stockTakeSection?.trim()?.takeIf { it.isNotBlank() } ?: return@mapNotNull null
stId to section
}.distinct()
headersToRefresh.forEach { (stId, section) ->
checkAndUpdateStockTakeStatus(stId, section)
}

logger.info(
"softDeleteOpenStockTakeRecordsForExpiredLotLines: removed {} record(s), refreshed {} section header(s)",
toRemove.size,
headersToRefresh.size,
)
return toRemove.size
}

open fun listStockTakeRoundCards(yearMonth: String?): StockTakeRoundCardsRes { open fun listStockTakeRoundCards(yearMonth: String?): StockTakeRoundCardsRes {
val all = stockTakeRepository.findAll().filter { !it.deleted } val all = stockTakeRepository.findAll().filter { !it.deleted }
if (all.isEmpty()) { if (all.isEmpty()) {
@@ -1843,6 +1907,13 @@ open class StockTakeRecordService(
this.stockTakerName = user?.name this.stockTakerName = user?.name
this.stockTakeEndTime = java.time.LocalDateTime.now() this.stockTakeEndTime = java.time.LocalDateTime.now()
this.varianceQty = varianceQty this.varianceQty = varianceQty
// 防舊資料:重新盤點後不得沿用先前核准結果
this.approverId = null
this.approverName = null
this.approverStockTakeQty = null
this.approverBadQty = null
this.approverTime = null
this.lastSelect = null
} }
existingRecord existingRecord
} }
@@ -2098,10 +2169,14 @@ open class StockTakeRecordService(


/** /**
* FP-MTMS Version Checklist | Functions Ref. No. 70 | v1.0.0 | 2026-08-31 * FP-MTMS Version Checklist | Functions Ref. No. 70 | v1.0.0 | 2026-08-31
*
* 依 [stockTakeSection] 在同一輪次內解析「該區域」單頭再升狀態。
* 不可直接信任傳入的 stockTakeId:Overall 審核會傳整輪代表 id,若寫錯單頭會造成
* 本區已全數 completed 卻仍停在 approving(狀態寫到別區)。
*/ */
open fun checkAndUpdateStockTakeStatus(stockTakeId: Long, stockTakeSection: String): Map<String, Any> { open fun checkAndUpdateStockTakeStatus(stockTakeId: Long, stockTakeSection: String): Map<String, Any> {
try { try {
val stockTake = stockTakeRepository.findByIdAndDeletedIsFalse(stockTakeId)
val stockTakeHint = stockTakeRepository.findByIdAndDeletedIsFalse(stockTakeId)
?: return mapOf("success" to false, "message" to "Stock take not found") ?: return mapOf("success" to false, "message" to "Stock take not found")


// 1. 获取该 section 下的所有 warehouse // 1. 获取该 section 下的所有 warehouse
@@ -2112,7 +2187,21 @@ open class StockTakeRecordService(


val warehouseIds = warehouses.mapNotNull { it.id }.toSet() val warehouseIds = warehouses.mapNotNull { it.id }.toSet()


val roundId = stockTake.stockTakeRoundId ?: stockTake.id
val roundId = stockTakeHint.stockTakeRoundId ?: stockTakeHint.id
?: return mapOf("success" to false, "message" to "Stock take id is null")

val sectionHeaders = stockTakeRepository.findAllByStockTakeRoundIdAndDeletedIsFalse(roundId)
.filter { !it.deleted && it.stockTakeSection == stockTakeSection }
val stockTake = sectionHeaders.maxWithOrNull(
compareBy<StockTake> { it.actualStart ?: it.planStart ?: LocalDateTime.MIN }
.thenBy { it.id ?: 0L }
) ?: stockTakeHint.takeIf { it.stockTakeSection == stockTakeSection }
?: return mapOf(
"success" to false,
"message" to "Stock take header not found for section $stockTakeSection in round $roundId"
)

val sectionHeaderId = stockTake.id
?: return mapOf("success" to false, "message" to "Stock take id is null") ?: return mapOf("success" to false, "message" to "Stock take id is null")


var stockTakeRecords = stockTakeRecordRepository.findAllByStockTakeRoundIdAndDeletedIsFalse(roundId) var stockTakeRecords = stockTakeRecordRepository.findAllByStockTakeRoundIdAndDeletedIsFalse(roundId)
@@ -2126,7 +2215,7 @@ open class StockTakeRecordService(
stockTakeRecords = stockTakeRecordRepository.findAll() stockTakeRecords = stockTakeRecordRepository.findAll()
.filter { .filter {
!it.deleted && !it.deleted &&
it.stockTake?.id == stockTakeId &&
it.stockTake?.id == sectionHeaderId &&
it.warehouse?.id in warehouseIds && it.warehouse?.id in warehouseIds &&
it.stockTakeSection == stockTakeSection it.stockTakeSection == stockTakeSection
} }
@@ -2144,7 +2233,10 @@ open class StockTakeRecordService(
stockTake.planEnd = now stockTake.planEnd = now
stockTake.actualEnd = now stockTake.actualEnd = now
stockTakeRepository.save(stockTake) stockTakeRepository.save(stockTake)
println("Stock take $stockTakeId status updated to COMPLETED - all records are completed")
println(
"Stock take $sectionHeaderId (section=$stockTakeSection, hintId=$stockTakeId) " +
"status updated to COMPLETED - all records are completed"
)
return mapOf( return mapOf(
"success" to true, "success" to true,
"message" to "Stock take status updated to COMPLETED", "message" to "Stock take status updated to COMPLETED",
@@ -2155,7 +2247,10 @@ open class StockTakeRecordService(
stockTake.actualEnd = now stockTake.actualEnd = now
stockTakeRepository.save(stockTake) stockTakeRepository.save(stockTake)


println("Stock take $stockTakeId status updated to APPROVING - all records are pass")
println(
"Stock take $sectionHeaderId (section=$stockTakeSection, hintId=$stockTakeId) " +
"status updated to APPROVING - all records are pass"
)
return mapOf( return mapOf(
"success" to true, "success" to true,
"message" to "Stock take status updated to APPROVING", "message" to "Stock take status updated to APPROVING",
@@ -2272,7 +2367,9 @@ open class StockTakeRecordService(
} }
val stockTakeSection = savedRecord.stockTakeSection val stockTakeSection = savedRecord.stockTakeSection
if (stockTakeSection != null) { if (stockTakeSection != null) {
checkAndUpdateStockTakeStatus(stockTakeId, stockTakeSection)
// 用明細所屬區域單頭 id(Overall 審核傳入的可能是整輪代表 id)
val statusHeaderId = savedRecord.stockTake?.id ?: stockTakeId
checkAndUpdateStockTakeStatus(statusHeaderId, stockTakeSection)
} }


return savedRecord return savedRecord
@@ -3248,8 +3345,30 @@ open fun updateStockTakeRecordStatusToNotMatch(stockTakeRecordId: Long): StockTa
stockTakeRecord.apply { stockTakeRecord.apply {
this.status = "notMatch" this.status = "notMatch"
// 重新盤點後必須再審核;清掉舊核准欄位,避免 UI 仍顯示在 Approved、單頭卻升不了 completed
this.approverId = null
this.approverName = null
this.approverStockTakeQty = null
this.approverBadQty = null
this.approverTime = null
this.lastSelect = null
this.pickerSecondStockTakeQty = null
this.pickerSecondBadQty = null
this.stockTakeEndTime = null
} }
val saved = stockTakeRecordRepository.save(stockTakeRecord) val saved = stockTakeRecordRepository.save(stockTakeRecord)

saved.id?.let { rid ->
stockTakeLineRepository.findByStockTakeRecord_IdAndDeletedIsFalse(rid)?.let { line ->
line.apply {
this.finalQty = null
this.status = StockTakeLineStatus.PENDING
this.completeDate = null
}
stockTakeLineRepository.save(line)
}
}

val stockTake = saved.stockTake val stockTake = saved.stockTake
if (stockTake != null && !stockTake.deleted) { if (stockTake != null && !stockTake.deleted) {
stockTake.status = StockTakeStatus.STOCKTAKING stockTake.status = StockTakeStatus.STOCKTAKING


Carregando…
Cancelar
Guardar