|
|
|
@@ -32,6 +32,13 @@ import com.ffii.fpsms.modules.stock.web.model.StockOutLineStatus |
|
|
|
import com.ffii.fpsms.modules.stock.web.model.StockOutStatus |
|
|
|
import com.ffii.fpsms.modules.pickOrder.enums.PickOrderLineStatus |
|
|
|
import com.ffii.fpsms.modules.pickOrder.enums.PickOrderStatus |
|
|
|
import com.ffii.fpsms.modules.pickOrder.web.models.* |
|
|
|
import com.ffii.fpsms.modules.common.SecurityUtils |
|
|
|
import com.ffii.fpsms.modules.stock.entity.StockOut |
|
|
|
import com.ffii.fpsms.modules.pickOrder.entity.PickOrderLine |
|
|
|
import com.ffii.fpsms.modules.master.entity.ItemsRepository |
|
|
|
import com.ffii.fpsms.modules.common.CodeGenerator |
|
|
|
import com.ffii.fpsms.modules.pickOrder.web.models.SubmitIssueRequest |
|
|
|
@Service |
|
|
|
open class PickExecutionIssueService( |
|
|
|
private val pickExecutionIssueRepository: PickExecutionIssueRepository, |
|
|
|
@@ -45,7 +52,8 @@ open class PickExecutionIssueService( |
|
|
|
private val pickOrderLineRepository: PickOrderLineRepository, |
|
|
|
private val doPickOrderService: DoPickOrderService, |
|
|
|
private val joPickOrderRepository: JoPickOrderRepository, |
|
|
|
private val joPickOrderRecordRepository: JoPickOrderRecordRepository |
|
|
|
private val joPickOrderRecordRepository: JoPickOrderRecordRepository, |
|
|
|
private val itemsRepository: ItemsRepository |
|
|
|
|
|
|
|
) { |
|
|
|
|
|
|
|
@@ -792,4 +800,567 @@ open fun createBatchReleaseIssue( |
|
|
|
return 0 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
open fun getMissItemList(issueCategory: String = "lot_issue"): List<PickExecutionIssue> { |
|
|
|
val category = try { |
|
|
|
IssueCategory.valueOf(issueCategory) |
|
|
|
} catch (e: Exception) { |
|
|
|
IssueCategory.lot_issue |
|
|
|
} |
|
|
|
return pickExecutionIssueRepository.findMissItemList(category).filter { it.handleStatus != HandleStatus.completed } |
|
|
|
} |
|
|
|
|
|
|
|
open fun getBadItemList(issueCategory: String = "lot_issue"): List<PickExecutionIssue> { |
|
|
|
val category = try { |
|
|
|
IssueCategory.valueOf(issueCategory) |
|
|
|
} catch (e: Exception) { |
|
|
|
IssueCategory.lot_issue |
|
|
|
} |
|
|
|
return pickExecutionIssueRepository.findBadItemListByCategory(category).filter { it.handleStatus != HandleStatus.completed } |
|
|
|
} |
|
|
|
open fun getBadItemOnlyList(): List<PickExecutionIssue> { |
|
|
|
return pickExecutionIssueRepository.findBadItemOnlyList(IssueCategory.lot_issue) |
|
|
|
} |
|
|
|
|
|
|
|
open fun getExpiryItemList(): List<ExpiryItemResponse> { |
|
|
|
val today = LocalDate.now() |
|
|
|
val lotLines = inventoryLotLineRepository.findExpiredItems(today) |
|
|
|
|
|
|
|
return lotLines.map { lotLine -> |
|
|
|
val lot = lotLine.inventoryLot |
|
|
|
val item = lot?.item // Get item from inventoryLot |
|
|
|
ExpiryItemResponse( |
|
|
|
id = lotLine.id ?: 0L, |
|
|
|
itemId = item?.id ?: 0L, |
|
|
|
itemCode = item?.code ?: "", |
|
|
|
itemDescription = item?.name, |
|
|
|
lotId = lot?.id ?: 0L, |
|
|
|
lotNo = lot?.lotNo, |
|
|
|
storeLocation = lotLine.warehouse?.code, // Construct from warehouse |
|
|
|
expiryDate = lot?.expiryDate, |
|
|
|
remainingQty = (lotLine.inQty ?: BigDecimal.ZERO).subtract(lotLine.outQty ?: BigDecimal.ZERO) |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@Transactional(rollbackFor = [Exception::class]) |
|
|
|
open fun submitMissItem(request: SubmitIssueRequest): MessageResponse { |
|
|
|
try { |
|
|
|
val issue = pickExecutionIssueRepository.findById(request.issueId).orElse(null) |
|
|
|
?: return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Error", |
|
|
|
code = "NOT_FOUND", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Issue not found", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
|
|
|
|
if (issue.missQty <= BigDecimal.ZERO || issue.deleted) { |
|
|
|
return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Error", |
|
|
|
code = "INVALID", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Invalid issue or no miss quantity", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
val handler = request.handler ?: SecurityUtils.getUser().orElse(null)?.id ?: 0L |
|
|
|
val stockOut = createIssueStockOutHeader("MISS_ITEM", issue.issueRemark, handler) |
|
|
|
|
|
|
|
val pickOrderLine = issue.pickOrderLineId?.let { |
|
|
|
pickOrderLineRepository.findById(it).orElse(null) |
|
|
|
} |
|
|
|
|
|
|
|
val lotLine = issue.lotId?.let { |
|
|
|
inventoryLotLineRepository.findById(it).orElse(null) |
|
|
|
} |
|
|
|
|
|
|
|
val item = itemsRepository.findById(issue.itemId).orElse(null) |
|
|
|
?: return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Error", |
|
|
|
code = "ITEM_NOT_FOUND", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Item not found", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
|
|
|
|
val stockOutLine = StockOutLine().apply { |
|
|
|
this.stockOut = stockOut |
|
|
|
this.inventoryLotLine = lotLine |
|
|
|
this.item = item |
|
|
|
this.qty = issue.missQty.toDouble() |
|
|
|
this.status = StockOutLineStatus.PENDING.status |
|
|
|
this.pickOrderLine = pickOrderLine |
|
|
|
} |
|
|
|
stockOutLineRepository.save(stockOutLine) |
|
|
|
|
|
|
|
if (issue.lotId != null) { |
|
|
|
updateLotLineAfterIssue(issue.lotId, issue.missQty) |
|
|
|
} |
|
|
|
|
|
|
|
markIssueHandled(issue, handler) |
|
|
|
|
|
|
|
return MessageResponse( |
|
|
|
id = stockOut.id, |
|
|
|
name = "Success", |
|
|
|
code = "SUCCESS", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Successfully submitted miss item", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} catch (e: Exception) { |
|
|
|
return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Error", |
|
|
|
code = "ERROR", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Failed to submit miss item: ${e.message}", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@Transactional(rollbackFor = [Exception::class]) |
|
|
|
open fun submitBadItem(request: SubmitIssueRequest): MessageResponse { |
|
|
|
try { |
|
|
|
val issue = pickExecutionIssueRepository.findById(request.issueId).orElse(null) |
|
|
|
?: return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Error", |
|
|
|
code = "NOT_FOUND", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Issue not found", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
|
|
|
|
if (issue.badItemQty <= BigDecimal.ZERO || issue.deleted) { |
|
|
|
return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Error", |
|
|
|
code = "INVALID", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Invalid issue or no bad item quantity", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
val handler = request.handler ?: SecurityUtils.getUser().orElse(null)?.id ?: 0L |
|
|
|
val stockOut = createIssueStockOutHeader("BAD_ITEM", issue.issueRemark, handler) |
|
|
|
|
|
|
|
val pickOrderLine = issue.pickOrderLineId?.let { |
|
|
|
pickOrderLineRepository.findById(it).orElse(null) |
|
|
|
} |
|
|
|
|
|
|
|
val lotLine = issue.lotId?.let { |
|
|
|
inventoryLotLineRepository.findById(it).orElse(null) |
|
|
|
} |
|
|
|
|
|
|
|
val item = itemsRepository.findById(issue.itemId).orElse(null) |
|
|
|
?: return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Error", |
|
|
|
code = "ITEM_NOT_FOUND", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Item not found", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
|
|
|
|
val stockOutLine = StockOutLine().apply { |
|
|
|
this.stockOut = stockOut |
|
|
|
this.inventoryLotLine = lotLine |
|
|
|
this.item = item |
|
|
|
this.qty = issue.badItemQty.toDouble() |
|
|
|
this.status = StockOutLineStatus.PENDING.status |
|
|
|
this.pickOrderLine = pickOrderLine |
|
|
|
} |
|
|
|
stockOutLineRepository.save(stockOutLine) |
|
|
|
|
|
|
|
if (issue.lotId != null) { |
|
|
|
updateLotLineAfterIssue(issue.lotId, issue.badItemQty) |
|
|
|
} |
|
|
|
|
|
|
|
markIssueHandled(issue, handler) |
|
|
|
|
|
|
|
return MessageResponse( |
|
|
|
id = stockOut.id, |
|
|
|
name = "Success", |
|
|
|
code = "SUCCESS", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Successfully submitted bad item", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} catch (e: Exception) { |
|
|
|
return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Error", |
|
|
|
code = "ERROR", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Failed to submit bad item: ${e.message}", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@Transactional(rollbackFor = [Exception::class]) |
|
|
|
open fun submitExpiryItem(request: SubmitExpiryRequest): MessageResponse { |
|
|
|
try { |
|
|
|
val lotLine = inventoryLotLineRepository.findById(request.lotLineId).orElse(null) |
|
|
|
?: return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Error", |
|
|
|
code = "NOT_FOUND", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Lot line not found", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
|
|
|
|
val lot = lotLine.inventoryLot |
|
|
|
val today = LocalDate.now() |
|
|
|
|
|
|
|
if (lot?.expiryDate == null || !lot.expiryDate!!.isBefore(today)) { |
|
|
|
return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Error", |
|
|
|
code = "NOT_EXPIRED", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Item is not expired", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
val inQty = lotLine.inQty ?: BigDecimal.ZERO |
|
|
|
val outQty = lotLine.outQty ?: BigDecimal.ZERO |
|
|
|
val remainingQty = inQty.subtract(outQty) |
|
|
|
|
|
|
|
if (remainingQty <= BigDecimal.ZERO) { |
|
|
|
return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Error", |
|
|
|
code = "NO_REMAINING", |
|
|
|
type = "stock_issue", |
|
|
|
message = "No remaining quantity", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
val handler = request.handler ?: SecurityUtils.getUser().orElse(null)?.id ?: 0L |
|
|
|
val stockOut = createIssueStockOutHeader("EXPIRY_ITEM", "Expired item removal", handler) |
|
|
|
|
|
|
|
val item = lot.item |
|
|
|
?: return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Error", |
|
|
|
code = "ITEM_NOT_FOUND", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Item not found", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
|
|
|
|
val stockOutLine = StockOutLine().apply { |
|
|
|
this.stockOut = stockOut |
|
|
|
this.inventoryLotLine = lotLine |
|
|
|
this.item = item |
|
|
|
this.qty = remainingQty.toDouble() |
|
|
|
this.status = StockOutLineStatus.PENDING.status |
|
|
|
} |
|
|
|
stockOutLineRepository.save(stockOutLine) |
|
|
|
|
|
|
|
updateLotLineAfterIssue(lotLine.id ?: 0L, remainingQty) |
|
|
|
|
|
|
|
return MessageResponse( |
|
|
|
id = stockOut.id, |
|
|
|
name = "Success", |
|
|
|
code = "SUCCESS", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Successfully submitted expiry item", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} catch (e: Exception) { |
|
|
|
return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Error", |
|
|
|
code = "ERROR", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Failed to submit expiry item: ${e.message}", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Fix batchSubmitMissItem method (around line 835): |
|
|
|
@Transactional(rollbackFor = [Exception::class]) |
|
|
|
open fun batchSubmitMissItem(request: BatchSubmitIssueRequest): MessageResponse { |
|
|
|
try { |
|
|
|
val issues = pickExecutionIssueRepository.findAllById(request.issueIds) |
|
|
|
.filter { it.missQty > BigDecimal.ZERO && !it.deleted } |
|
|
|
|
|
|
|
if (issues.isEmpty()) { |
|
|
|
return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Error", |
|
|
|
code = "EMPTY", |
|
|
|
type = "stock_issue", |
|
|
|
message = "No valid issues to submit", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
val handler = request.handler ?: SecurityUtils.getUser().orElse(null)?.id ?: 0L |
|
|
|
|
|
|
|
// Create single StockOut header for all submissions |
|
|
|
val stockOut = createIssueStockOutHeader("MISS_ITEM", "Batch miss item submission", handler) |
|
|
|
|
|
|
|
issues.forEach { issue -> |
|
|
|
|
|
|
|
// Get pickOrderLine if available |
|
|
|
val pickOrderLine = issue.pickOrderLineId?.let { |
|
|
|
pickOrderLineRepository.findById(it).orElse(null) |
|
|
|
} |
|
|
|
|
|
|
|
// Get inventoryLotLine |
|
|
|
val lotLine = issue.lotId?.let { |
|
|
|
inventoryLotLineRepository.findById(it).orElse(null) |
|
|
|
} |
|
|
|
|
|
|
|
// Get item from issue (it has itemId) |
|
|
|
val item = itemsRepository.findById(issue.itemId).orElse(null) |
|
|
|
|
|
|
|
|
|
|
|
// Create StockOutLine |
|
|
|
val stockOutLine = StockOutLine().apply { |
|
|
|
this.stockOut = stockOut |
|
|
|
this.inventoryLotLine = lotLine |
|
|
|
this.item = item |
|
|
|
this.qty = issue.missQty.toDouble() |
|
|
|
this.status = StockOutLineStatus.PENDING.status |
|
|
|
this.pickOrderLine = pickOrderLine |
|
|
|
} |
|
|
|
stockOutLineRepository.save(stockOutLine) |
|
|
|
|
|
|
|
// Update InventoryLotLine |
|
|
|
if (issue.lotId != null) { |
|
|
|
updateLotLineAfterIssue(issue.lotId, issue.missQty) |
|
|
|
} |
|
|
|
|
|
|
|
// Mark issue as handled |
|
|
|
markIssueHandled(issue, handler) |
|
|
|
} |
|
|
|
|
|
|
|
return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Success", |
|
|
|
code = "SUCCESS", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Successfully submitted ${issues.size} miss item(s)", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} catch (e: Exception) { |
|
|
|
return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Error", |
|
|
|
code = "ERROR", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Failed to submit miss items: ${e.message}", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Fix batchSubmitBadItem method (around line 890) - same pattern: |
|
|
|
@Transactional(rollbackFor = [Exception::class]) |
|
|
|
open fun batchSubmitBadItem(request: BatchSubmitIssueRequest): MessageResponse { |
|
|
|
try { |
|
|
|
val issues = pickExecutionIssueRepository.findAllById(request.issueIds) |
|
|
|
.filter { it.badItemQty > BigDecimal.ZERO && !it.deleted } |
|
|
|
|
|
|
|
if (issues.isEmpty()) { |
|
|
|
return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Error", |
|
|
|
code = "EMPTY", |
|
|
|
type = "stock_issue", |
|
|
|
message = "No valid issues to submit", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
val handler = request.handler ?: SecurityUtils.getUser().orElse(null)?.id ?: 0L |
|
|
|
|
|
|
|
// Create single StockOut header for all submissions |
|
|
|
val stockOut = createIssueStockOutHeader("BAD_ITEM", "Batch bad item submission", handler) |
|
|
|
|
|
|
|
issues.forEach { issue -> |
|
|
|
|
|
|
|
// Get pickOrderLine if available |
|
|
|
val pickOrderLine = issue.pickOrderLineId?.let { |
|
|
|
pickOrderLineRepository.findById(it).orElse(null) |
|
|
|
} |
|
|
|
|
|
|
|
// Get inventoryLotLine |
|
|
|
val lotLine = issue.lotId?.let { |
|
|
|
inventoryLotLineRepository.findById(it).orElse(null) |
|
|
|
} |
|
|
|
|
|
|
|
// Get item from issue |
|
|
|
val item = itemsRepository.findById(issue.itemId).orElse(null) |
|
|
|
|
|
|
|
|
|
|
|
// Create StockOutLine |
|
|
|
val stockOutLine = StockOutLine().apply { |
|
|
|
this.stockOut = stockOut |
|
|
|
this.inventoryLotLine = lotLine |
|
|
|
this.item = item |
|
|
|
this.qty = issue.badItemQty.toDouble() |
|
|
|
this.status = StockOutLineStatus.PENDING.status |
|
|
|
this.pickOrderLine = pickOrderLine |
|
|
|
} |
|
|
|
stockOutLineRepository.save(stockOutLine) |
|
|
|
|
|
|
|
// Update InventoryLotLine |
|
|
|
if (issue.lotId != null) { |
|
|
|
updateLotLineAfterIssue(issue.lotId, issue.badItemQty) |
|
|
|
} |
|
|
|
|
|
|
|
// Mark issue as handled |
|
|
|
markIssueHandled(issue, handler) |
|
|
|
} |
|
|
|
|
|
|
|
return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Success", |
|
|
|
code = "SUCCESS", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Successfully submitted ${issues.size} bad item(s)", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} catch (e: Exception) { |
|
|
|
return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Error", |
|
|
|
code = "ERROR", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Failed to submit bad items: ${e.message}", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Fix batchSubmitExpiryItem method (around line 945): |
|
|
|
@Transactional(rollbackFor = [Exception::class]) |
|
|
|
open fun batchSubmitExpiryItem(request: BatchSubmitExpiryRequest): MessageResponse { |
|
|
|
try { |
|
|
|
val lotLines = inventoryLotLineRepository.findAllById(request.lotLineIds) |
|
|
|
.filter { |
|
|
|
val lot = it.inventoryLot |
|
|
|
val today = LocalDate.now() |
|
|
|
lot?.expiryDate != null && lot.expiryDate!!.isBefore(today) && |
|
|
|
(it.inQty ?: BigDecimal.ZERO) != (it.outQty ?: BigDecimal.ZERO) |
|
|
|
} |
|
|
|
|
|
|
|
if (lotLines.isEmpty()) { |
|
|
|
return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Error", |
|
|
|
code = "EMPTY", |
|
|
|
type = "stock_issue", |
|
|
|
message = "No valid expiry items to submit", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
val handler = request.handler ?: SecurityUtils.getUser().orElse(null)?.id ?: 0L |
|
|
|
|
|
|
|
// Create single StockOut header for all submissions |
|
|
|
val stockOut = createIssueStockOutHeader("EXPIRY_ITEM", "Batch expiry item removal", handler) |
|
|
|
|
|
|
|
lotLines.forEach { lotLine -> |
|
|
|
val remainingQty = (lotLine.inQty ?: BigDecimal.ZERO).subtract(lotLine.outQty ?: BigDecimal.ZERO) |
|
|
|
|
|
|
|
// Get item from inventoryLot |
|
|
|
val item = lotLine.inventoryLot?.item |
|
|
|
|
|
|
|
// Create StockOutLine |
|
|
|
val stockOutLine = StockOutLine().apply { |
|
|
|
this.stockOut = stockOut |
|
|
|
this.inventoryLotLine = lotLine |
|
|
|
this.item = item |
|
|
|
this.qty = remainingQty.toDouble() |
|
|
|
this.status = StockOutLineStatus.PENDING.status |
|
|
|
} |
|
|
|
stockOutLineRepository.save(stockOutLine) |
|
|
|
|
|
|
|
// Update InventoryLotLine |
|
|
|
updateLotLineAfterIssue(lotLine.id ?: 0L, remainingQty) |
|
|
|
} |
|
|
|
|
|
|
|
return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Success", |
|
|
|
code = "SUCCESS", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Successfully submitted ${lotLines.size} expiry item(s)", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} catch (e: Exception) { |
|
|
|
return MessageResponse( |
|
|
|
id = null, |
|
|
|
name = "Error", |
|
|
|
code = "ERROR", |
|
|
|
type = "stock_issue", |
|
|
|
message = "Failed to submit expiry items: ${e.message}", |
|
|
|
errorPosition = null |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private fun markIssueHandled(issue: PickExecutionIssue, handler: Long?) { |
|
|
|
pickExecutionIssueRepository.updateHandleStatus( |
|
|
|
issueId = issue.id ?: 0L, |
|
|
|
handleStatus = HandleStatus.completed, |
|
|
|
handleDate = LocalDate.now(), |
|
|
|
handledBy = handler |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
private fun createIssueStockOutHeader(type: String, remarks: String?, handler: Long?): StockOut { |
|
|
|
val prefix = "ISSUE" |
|
|
|
val midfix = CodeGenerator.DEFAULT_MIDFIX |
|
|
|
val latestCode = stockOutRepository.findAll().mapNotNull { it.consoPickOrderCode } |
|
|
|
.filter { it.startsWith("$prefix-$midfix") } |
|
|
|
.maxOrNull() |
|
|
|
val consoCode = CodeGenerator.generateNo(prefix = prefix, midfix = midfix, latestCode = latestCode) |
|
|
|
|
|
|
|
val stockOut = StockOut().apply { |
|
|
|
this.type = type |
|
|
|
this.consoPickOrderCode = consoCode |
|
|
|
this.status = StockOutStatus.PENDING.status |
|
|
|
this.handler = handler |
|
|
|
this.remarks = remarks |
|
|
|
} |
|
|
|
return stockOutRepository.save(stockOut) |
|
|
|
} |
|
|
|
|
|
|
|
private fun updateLotLineAfterIssue(lotLineId: Long, qty: BigDecimal) { |
|
|
|
val lotLine = inventoryLotLineRepository.findById(lotLineId).orElse(null) |
|
|
|
if (lotLine != null) { |
|
|
|
val currentOutQty = lotLine.outQty ?: BigDecimal.ZERO |
|
|
|
val newOutQty = currentOutQty.add(qty) |
|
|
|
lotLine.outQty = newOutQty |
|
|
|
|
|
|
|
// If outQty != inQty, set status to AVAILABLE |
|
|
|
val inQty = lotLine.inQty ?: BigDecimal.ZERO |
|
|
|
if (newOutQty != inQty) { |
|
|
|
lotLine.status = InventoryLotLineStatus.AVAILABLE |
|
|
|
} |
|
|
|
|
|
|
|
lotLine.modified = LocalDateTime.now() |
|
|
|
lotLine.modifiedBy = "system" |
|
|
|
inventoryLotLineRepository.save(lotLine) |
|
|
|
} |
|
|
|
} |
|
|
|
} |