|
|
|
@@ -670,133 +670,269 @@ open class DeliveryOrderService( |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//Delivery Note |
|
|
|
@Throws(IOException::class) |
|
|
|
@Transactional |
|
|
|
open fun exportDeliveryNote(request: ExportDeliveryNoteRequest): Map<String, Any> { |
|
|
|
val DELIVERYNOTE_PDF = "DeliveryNote/DeliveryNotePDF.jrxml" |
|
|
|
val resource = ClassPathResource(DELIVERYNOTE_PDF) |
|
|
|
if (!resource.exists()) { |
|
|
|
throw FileNotFoundException("Report file not fount: $DELIVERYNOTE_PDF") |
|
|
|
} |
|
|
|
val doPickOrder = doPickOrderRepository.findById(request.doPickOrderId).orElseThrow { |
|
|
|
NoSuchElementException("DoPickOrder not found with ID: ${request.doPickOrderId}") |
|
|
|
} |
|
|
|
val pickOrderIds = if (doPickOrder.pickOrderId != null) { |
|
|
|
// Single pick order case |
|
|
|
listOf(doPickOrder.pickOrderId!!) |
|
|
|
} else { |
|
|
|
// Merged pick orders case - get from DoPickOrderLine |
|
|
|
val doPickOrderLines = doPickOrderLineRepository.findByDoPickOrderIdAndDeletedFalse(doPickOrder.id!!) |
|
|
|
val orderIds = doPickOrderLines.mapNotNull { it.pickOrderId }.distinct() |
|
|
|
// Delivery Note |
|
|
|
@Throws(IOException::class) |
|
|
|
@Transactional |
|
|
|
open fun exportDeliveryNote(request: ExportDeliveryNoteRequest): Map<String, Any> { |
|
|
|
|
|
|
|
if (orderIds.isEmpty()) { |
|
|
|
throw IllegalStateException("DoPickOrder ${request.doPickOrderId} has no associated pick orders") |
|
|
|
} |
|
|
|
orderIds |
|
|
|
} |
|
|
|
// INPUT STREAM SETUP |
|
|
|
val DELIVERYNOTE_PDF = "DeliveryNote/DeliveryNotePDF.jrxml" |
|
|
|
val resource = ClassPathResource(DELIVERYNOTE_PDF) |
|
|
|
if (!resource.exists()) { |
|
|
|
throw FileNotFoundException("Report file not found: $DELIVERYNOTE_PDF") |
|
|
|
} |
|
|
|
|
|
|
|
val deliveryOrderIds = if (doPickOrder.doOrderId != null) { |
|
|
|
// Single delivery order case |
|
|
|
listOf(doPickOrder.doOrderId!!) |
|
|
|
} else { |
|
|
|
// Merged delivery orders case - get from DoPickOrderLine |
|
|
|
val doPickOrderLines = doPickOrderLineRepository.findByDoPickOrderIdAndDeletedFalse(doPickOrder.id!!) |
|
|
|
val orderIds = doPickOrderLines.mapNotNull { it.doOrderId }.distinct() |
|
|
|
val inputStream = resource.inputStream |
|
|
|
val deliveryNote = JasperCompileManager.compileReport(inputStream) |
|
|
|
|
|
|
|
if (orderIds.isEmpty()) { |
|
|
|
throw IllegalStateException("DoPickOrder ${request.doPickOrderId} has no associated delivery orders") |
|
|
|
} |
|
|
|
orderIds |
|
|
|
val fields = mutableListOf<MutableMap<String, Any>>() |
|
|
|
val params = mutableMapOf<String, Any>() |
|
|
|
|
|
|
|
// DRAFT & RECORD SEPARATION |
|
|
|
if (request.isDraft) { |
|
|
|
return exportDeliveryNoteFromDraft(request, deliveryNote, fields, params) |
|
|
|
} else { |
|
|
|
return exportDeliveryNoteFromRecord(request, deliveryNote, fields, params) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// DRAFT |
|
|
|
private fun exportDeliveryNoteFromDraft( |
|
|
|
request: ExportDeliveryNoteRequest, |
|
|
|
deliveryNote: net.sf.jasperreports.engine.JasperReport, |
|
|
|
fields: MutableList<MutableMap<String, Any>>, |
|
|
|
params: MutableMap<String, Any> |
|
|
|
): Map<String, Any> { |
|
|
|
val doPickOrder = doPickOrderRepository.findById(request.doPickOrderId).orElseThrow { |
|
|
|
NoSuchElementException("DoPickOrder not found with ID: ${request.doPickOrderId}") |
|
|
|
} |
|
|
|
|
|
|
|
val pickOrderIds = if (doPickOrder.pickOrderId != null) { |
|
|
|
// SINGLE DELIVERY ORDER |
|
|
|
listOf(doPickOrder.pickOrderId!!) |
|
|
|
} else { |
|
|
|
// MERGED DELIVERY ORDERS (DOPICKORDERLINE) |
|
|
|
val doPickOrderLines = doPickOrderLineRepository.findByDoPickOrderIdAndDeletedFalse(doPickOrder.id!!) |
|
|
|
val orderIds = doPickOrderLines.mapNotNull { it.pickOrderId }.distinct() |
|
|
|
|
|
|
|
if (orderIds.isEmpty()) { |
|
|
|
throw IllegalStateException("DoPickOrder ${request.doPickOrderId} has no associated pick orders") |
|
|
|
} |
|
|
|
orderIds |
|
|
|
} |
|
|
|
|
|
|
|
val deliveryNoteInfo = deliveryOrderIds.flatMap { deliveryOrderId -> |
|
|
|
deliveryOrderRepository.findDeliveryOrderInfoById(deliveryOrderId) |
|
|
|
}.toMutableList() |
|
|
|
val deliveryOrderIds = if (doPickOrder.doOrderId != null) { |
|
|
|
// SINGLE DELIVERY ORDER |
|
|
|
listOf(doPickOrder.doOrderId!!) |
|
|
|
} else { |
|
|
|
// MERGED DELIVERY ORDERS (DOPICKORDERLINE) |
|
|
|
val doPickOrderLines = doPickOrderLineRepository.findByDoPickOrderIdAndDeletedFalse(doPickOrder.id!!) |
|
|
|
val orderIds = doPickOrderLines.mapNotNull { it.doOrderId }.distinct() |
|
|
|
|
|
|
|
if (deliveryNoteInfo.isEmpty()) { |
|
|
|
throw NoSuchElementException("Delivery orders not found for IDs: $deliveryOrderIds") |
|
|
|
if (orderIds.isEmpty()) { |
|
|
|
throw IllegalStateException("DoPickOrder ${request.doPickOrderId} has no associated delivery orders") |
|
|
|
} |
|
|
|
orderIds |
|
|
|
} |
|
|
|
|
|
|
|
val pickOrderId = pickOrderIds.first() |
|
|
|
val deliveryNoteInfo = deliveryOrderIds.flatMap { deliveryOrderId -> |
|
|
|
deliveryOrderRepository.findDeliveryOrderInfoById(deliveryOrderId) |
|
|
|
}.toMutableList() |
|
|
|
|
|
|
|
val inputStream = resource.inputStream |
|
|
|
val deliveryNote = JasperCompileManager.compileReport(inputStream) |
|
|
|
if (deliveryNoteInfo.isEmpty()) { |
|
|
|
throw NoSuchElementException("Delivery orders not found for IDs: $deliveryOrderIds") |
|
|
|
} |
|
|
|
|
|
|
|
val fields = mutableListOf<MutableMap<String, Any>>() |
|
|
|
val params = mutableMapOf<String, Any>() |
|
|
|
val pickOrderId = pickOrderIds.first() |
|
|
|
val truckNo = doPickOrder.truckLanceCode ?: "" |
|
|
|
val selectedPickOrder = pickOrderRepository.findById(pickOrderId).orElse(null) |
|
|
|
|
|
|
|
val truckNo = doPickOrder.truckLanceCode ?: "" |
|
|
|
val selectedPickOrder = pickOrderRepository.findById(pickOrderId).orElse(null) |
|
|
|
val allLines = deliveryNoteInfo.flatMap { info -> |
|
|
|
info.deliveryOrderLines.map { line -> line } |
|
|
|
} |
|
|
|
|
|
|
|
val allLines = deliveryNoteInfo.flatMap { info -> |
|
|
|
info.deliveryOrderLines.map { line -> line } |
|
|
|
} |
|
|
|
val sortedLines = allLines.sortedBy { line -> |
|
|
|
line.itemId?.let { itemId -> |
|
|
|
getWarehouseOrderByItemId(itemId) |
|
|
|
} ?: Int.MAX_VALUE |
|
|
|
} |
|
|
|
|
|
|
|
val sortedLines = allLines.sortedBy { line -> |
|
|
|
line.itemId?.let { itemId -> |
|
|
|
getWarehouseOrderByItemId(itemId) |
|
|
|
} ?: Int.MAX_VALUE |
|
|
|
} |
|
|
|
sortedLines.forEach { line -> |
|
|
|
val field = mutableMapOf<String, Any>() |
|
|
|
|
|
|
|
field["sequenceNumber"] = (fields.size + 1).toString() |
|
|
|
field["itemNo"] = line.itemNo |
|
|
|
field["itemName"] = line.itemName ?: "" |
|
|
|
field["uom"] = line.uom ?: "" |
|
|
|
field["qty"] = line.qty.toString() |
|
|
|
field["shortName"] = line.uomShortDesc ?: "" |
|
|
|
|
|
|
|
val route = line.itemId?.let { itemId -> |
|
|
|
getWarehouseCodeByItemId(itemId) |
|
|
|
} ?: "-" |
|
|
|
field["route"] = route |
|
|
|
|
|
|
|
//USE SUGGESTED PICK LOTS |
|
|
|
val lotNo = line.itemId?.let { itemId -> |
|
|
|
pickOrderIds.mapNotNull { pickOrderId -> |
|
|
|
val lots = getLotNumbersForPickOrderByItemId(itemId, pickOrderId) |
|
|
|
lots.ifBlank { null } |
|
|
|
}.distinct().joinToString(", ") |
|
|
|
}?.ifBlank { "沒有庫存" } ?: "沒有庫存" |
|
|
|
field["lotNo"] = lotNo |
|
|
|
fields.add(field) |
|
|
|
} |
|
|
|
|
|
|
|
sortedLines.forEach { line -> |
|
|
|
val field = mutableMapOf<String, Any>() |
|
|
|
params["dnTitle"] = "送貨單(初稿)" |
|
|
|
params["colQty"] = "所需數量" |
|
|
|
params["totalCartonTitle"] = "" |
|
|
|
params["deliveryNoteCodeTitle"] = "" |
|
|
|
params["deliveryNoteCode"] = "" |
|
|
|
|
|
|
|
field["sequenceNumber"] = (fields.size + 1).toString() |
|
|
|
field["itemNo"] = line.itemNo |
|
|
|
field["itemName"] = line.itemName ?: "" |
|
|
|
field["uom"] = line.uom ?: "" |
|
|
|
field["qty"] = line.qty.toString() |
|
|
|
field["shortName"] = line.uomShortDesc ?: "" |
|
|
|
|
|
|
|
val route = line.itemId?.let { itemId -> |
|
|
|
getWarehouseCodeByItemId(itemId) |
|
|
|
} ?: "-" |
|
|
|
field["route"] = route |
|
|
|
|
|
|
|
val lotNo = line.itemId?.let { itemId -> |
|
|
|
pickOrderIds.mapNotNull { pickOrderId -> |
|
|
|
val lots = getLotNumbersForPickOrderByItemId(itemId, pickOrderId) |
|
|
|
lots.ifBlank { null } |
|
|
|
}.distinct().joinToString(", ") |
|
|
|
}?.ifBlank { "沒有庫存" } ?: "沒有庫存" |
|
|
|
field["lotNo"] = lotNo |
|
|
|
fields.add(field) |
|
|
|
params["numOfCarton"] = request.numOfCarton.toString() |
|
|
|
if (params["numOfCarton"] == "0") { |
|
|
|
params["numOfCarton"] = "" |
|
|
|
} |
|
|
|
|
|
|
|
params["shopName"] = doPickOrder.shopName ?: deliveryNoteInfo[0].shopName ?: "" |
|
|
|
params["shopAddress"] = deliveryNoteInfo[0].shopAddress ?: "" |
|
|
|
params["deliveryDate"] = deliveryNoteInfo[0].estimatedArrivalDate?.format(DateTimeFormatter.ISO_LOCAL_DATE) ?: "" |
|
|
|
params["truckNo"] = truckNo |
|
|
|
params["ShopPurchaseOrderNo"] = doPickOrder.deliveryOrderCode ?: deliveryNoteInfo.joinToString(", ") { it.code } |
|
|
|
params["FGPickOrderNo"] = doPickOrder.pickOrderCode ?: selectedPickOrder?.code ?: "" |
|
|
|
|
|
|
|
return mapOf( |
|
|
|
"report" to PdfUtils.fillReport(deliveryNote, fields, params), |
|
|
|
"filename" to deliveryNoteInfo.joinToString("_") { it.code } |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
private fun exportDeliveryNoteFromRecord( |
|
|
|
request: ExportDeliveryNoteRequest, |
|
|
|
deliveryNote: net.sf.jasperreports.engine.JasperReport, |
|
|
|
fields: MutableList<MutableMap<String, Any>>, |
|
|
|
params: MutableMap<String, Any> |
|
|
|
) : Map<String, Any> { |
|
|
|
|
|
|
|
val doPickOrderRecord = doPickOrderRecordRepository.findById(request.doPickOrderId).orElseThrow { |
|
|
|
NoSuchElementException("DoPickOrderRecord not found with ID: ${request.doPickOrderId}") |
|
|
|
} |
|
|
|
|
|
|
|
val doPickOrderLineRecords = doPickOrderLineRecordRepository.findByDoPickOrderIdAndDeletedFalse(request.doPickOrderId) |
|
|
|
|
|
|
|
val pickOrderIds = doPickOrderLineRecords.mapNotNull { it.pickOrderId }.distinct() |
|
|
|
if(pickOrderIds.isEmpty()){ |
|
|
|
throw IllegalStateException("DoPickOrderRecord ${request.doPickOrderId} has no associated pick orders") |
|
|
|
} |
|
|
|
|
|
|
|
val deliveryOrderIds = doPickOrderLineRecords.mapNotNull { it.doOrderId }.distinct() |
|
|
|
if(deliveryOrderIds.isEmpty()){ |
|
|
|
throw IllegalStateException("DoPickOrderRecord ${request.doPickOrderId} has no associated delivery orders") |
|
|
|
} |
|
|
|
|
|
|
|
val deliveryNoteInfo = deliveryOrderIds.flatMap { deliveryOrderId -> |
|
|
|
deliveryOrderRepository.findDeliveryOrderInfoById(deliveryOrderId) |
|
|
|
}.toMutableList() |
|
|
|
|
|
|
|
val pickOrderId = pickOrderIds.first() |
|
|
|
val truckNo = doPickOrderRecord.truckLanceCode ?: "" |
|
|
|
val selectedPickOrder = pickOrderRepository.findById(pickOrderId).orElse(null) |
|
|
|
|
|
|
|
val allLines = deliveryNoteInfo.flatMap { info -> |
|
|
|
info.deliveryOrderLines.map { line -> line } |
|
|
|
} |
|
|
|
|
|
|
|
val pickOrderLines = pickOrderIds.flatMap { pickOrderId -> |
|
|
|
pickOrderLineRepository.findAllByPickOrderId(pickOrderId) |
|
|
|
} |
|
|
|
|
|
|
|
val pickOrderLineIdsByItemId = pickOrderLines |
|
|
|
.groupBy { it.item?.id } |
|
|
|
.mapValues { (_, lines) -> lines.mapNotNull { it.id } } |
|
|
|
|
|
|
|
val allPickOrderLineIds = pickOrderLines.mapNotNull { it.id } |
|
|
|
val stockOutLinesByPickOrderLineId = if (allPickOrderLineIds.isNotEmpty()) { |
|
|
|
allPickOrderLineIds.associateWith { pickOrderLineId -> |
|
|
|
stockOutLineRepository.findAllByPickOrderLineIdAndDeletedFalse(pickOrderLineId) |
|
|
|
} |
|
|
|
} else { |
|
|
|
emptyMap() |
|
|
|
} |
|
|
|
|
|
|
|
val sortedLines = allLines.sortedBy { line -> |
|
|
|
line.itemId?.let { itemId -> |
|
|
|
getWarehouseOrderByItemId(itemId) |
|
|
|
} ?: Int.MAX_VALUE |
|
|
|
} |
|
|
|
|
|
|
|
sortedLines.forEach { line -> |
|
|
|
val field = mutableMapOf<String, Any>() |
|
|
|
|
|
|
|
if (request.isDraft) { |
|
|
|
params["dnTitle"] = "送貨單(初稿)" |
|
|
|
params["colQty"] = "所需數量" |
|
|
|
params["totalCartonTitle"] = "" |
|
|
|
params["deliveryOrderCodeTitle"] = "" |
|
|
|
params["deliveryOrderCode"] = "" |
|
|
|
field["sequenceNumber"] = (fields.size + 1).toString() |
|
|
|
field["itemNo"] = line.itemNo |
|
|
|
field["itemName"] = line.itemName ?: "" |
|
|
|
field["uom"] = line.uom ?: "" |
|
|
|
|
|
|
|
val actualPickQty = if (line.itemId != null) { |
|
|
|
val pickOrderLineIdsForItem = pickOrderLineIdsByItemId[line.itemId] ?: emptyList() |
|
|
|
val totalQty = pickOrderLineIdsForItem.sumOf { pickOrderLineId -> |
|
|
|
val stockOutLines = stockOutLinesByPickOrderLineId[pickOrderLineId] ?: emptyList() |
|
|
|
stockOutLines.sumOf { it.qty } |
|
|
|
} |
|
|
|
totalQty.toString() |
|
|
|
} else { |
|
|
|
params["dnTitle"] = "送貨單" |
|
|
|
params["colQty"] = "已提數量" |
|
|
|
params["totalCartonTitle"] = "總箱數:" |
|
|
|
params["deliveryOrderCodeTitle"] = "送貨單編號:" |
|
|
|
params["deliveryOrderCode"] = "GEN FROM CODE GENERATOR (NEED FIND TIMING)" |
|
|
|
line.qty.toString() |
|
|
|
} |
|
|
|
field["qty"] = actualPickQty |
|
|
|
|
|
|
|
params["numOfCarton"] = request.numOfCarton.toString() |
|
|
|
if (params["numOfCarton"] == "0") { |
|
|
|
params["numOfCarton"] = "" |
|
|
|
} |
|
|
|
field["shortName"] = line.uomShortDesc ?: "" |
|
|
|
|
|
|
|
params["shopName"] = doPickOrder.shopName ?: deliveryNoteInfo[0].shopName ?:"" |
|
|
|
params["shopAddress"] = deliveryNoteInfo[0].shopAddress ?: "" |
|
|
|
params["deliveryDate"] = deliveryNoteInfo[0].estimatedArrivalDate?.format(DateTimeFormatter.ISO_LOCAL_DATE) ?: "" |
|
|
|
params["truckNo"] = truckNo |
|
|
|
params["ShopPurchaseOrderNo"] = doPickOrder.deliveryOrderCode ?: deliveryNoteInfo.joinToString(", ") { it.code } |
|
|
|
params["FGPickOrderNo"] = doPickOrder.pickOrderCode ?: selectedPickOrder?.code ?: "" |
|
|
|
val route = line.itemId?.let { itemId -> |
|
|
|
getWarehouseCodeByItemId(itemId) |
|
|
|
} ?: "-" |
|
|
|
field["route"] = route |
|
|
|
|
|
|
|
//USE STOCK OUT LINE |
|
|
|
val lotNo = line.itemId?.let { itemId -> |
|
|
|
val pickOrderLineIdsForItem = pickOrderLineIdsByItemId[itemId] ?: emptyList() |
|
|
|
val lotNumbers = pickOrderLineIdsForItem.flatMap { pickOrderLineId -> |
|
|
|
val stockOutLines = stockOutLinesByPickOrderLineId[pickOrderLineId] ?: emptyList() |
|
|
|
stockOutLines.mapNotNull { it.lotNo } |
|
|
|
}.distinct().joinToString(", ") |
|
|
|
|
|
|
|
return mapOf( |
|
|
|
"report" to PdfUtils.fillReport(deliveryNote, fields, params), |
|
|
|
"filename" to deliveryNoteInfo.joinToString("_") { it.code } |
|
|
|
) |
|
|
|
lotNumbers.ifBlank { |
|
|
|
"沒有庫存" |
|
|
|
} |
|
|
|
} ?: "沒有庫存" |
|
|
|
|
|
|
|
field["lotNo"] = lotNo |
|
|
|
fields.add(field) |
|
|
|
} |
|
|
|
|
|
|
|
params["dnTitle"] = "送貨單" |
|
|
|
params["colQty"] = "已提數量" |
|
|
|
params["totalCartonTitle"] = "總箱數:" |
|
|
|
params["deliveryNoteCodeTitle"] = "送貨單編號:" |
|
|
|
params["deliveryNoteCode"] = doPickOrderRecord.deliveryNoteCode ?: "" |
|
|
|
|
|
|
|
params["numOfCarton"] = request.numOfCarton.toString() |
|
|
|
if (params["numOfCarton"] == "0") { |
|
|
|
params["numOfCarton"] = "" |
|
|
|
} |
|
|
|
|
|
|
|
params["shopName"] = doPickOrderRecord.shopName ?: deliveryNoteInfo[0].shopName ?: "" |
|
|
|
params["shopAddress"] = deliveryNoteInfo[0].shopAddress ?: "" |
|
|
|
params["deliveryDate"] = deliveryNoteInfo[0].estimatedArrivalDate?.format(DateTimeFormatter.ISO_LOCAL_DATE) ?: "" |
|
|
|
params["truckNo"] = truckNo |
|
|
|
params["ShopPurchaseOrderNo"] = doPickOrderRecord.deliveryOrderCode ?: deliveryNoteInfo.joinToString(", ") { it.code } |
|
|
|
params["FGPickOrderNo"] = doPickOrderRecord.pickOrderCode ?: selectedPickOrder?.code ?: "" |
|
|
|
|
|
|
|
return mapOf( |
|
|
|
"report" to PdfUtils.fillReport(deliveryNote, fields, params), |
|
|
|
"filename" to deliveryNoteInfo.joinToString("_") { it.code } |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
//Print Delivery Note |
|
|
|
@Transactional |
|
|
|
open fun printDeliveryNote(request: PrintDeliveryNoteRequest) { |
|
|
|
@@ -857,7 +993,7 @@ open class DeliveryOrderService( |
|
|
|
|
|
|
|
} |
|
|
|
params["shopPurchaseOrderNo"] = doPickOrder.deliveryOrderCode ?: cartonLabelInfo[0].code |
|
|
|
params["deliveryOrderCode"] = "GEN FROM CODE GENERATOR (NEED FIND TIMING)" |
|
|
|
params["deliveryNoteCode"] = "GEN FROM CODE GENERATOR (NEED FIND TIMING)" |
|
|
|
params["shopAddress"] = cartonLabelInfo[0].shopAddress ?: "" |
|
|
|
params["shopName"] = doPickOrder.shopName ?: cartonLabelInfo[0].shopName ?: "" |
|
|
|
|
|
|
|
|