|
|
@@ -401,6 +401,7 @@ open class ProductionScheduleService( |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
val approver = SecurityUtils.getUser().getOrNull() // Get approver once |
|
|
val approver = SecurityUtils.getUser().getOrNull() // Get approver once |
|
|
|
|
|
var jobOrderCount = 0 |
|
|
|
|
|
|
|
|
for (d in data) { |
|
|
for (d in data) { |
|
|
// 2. Safely cast the ID (Int) and convert it to Long for repository lookup |
|
|
// 2. Safely cast the ID (Int) and convert it to Long for repository lookup |
|
|
@@ -448,25 +449,27 @@ open class ProductionScheduleService( |
|
|
logger.info("[releaseProdSchedule] prodScheduleLine.needNoOfJobOrder:" + prodScheduleLine.needNoOfJobOrder) |
|
|
logger.info("[releaseProdSchedule] prodScheduleLine.needNoOfJobOrder:" + prodScheduleLine.needNoOfJobOrder) |
|
|
//repeat(prodScheduleLine.needNoOfJobOrder) { |
|
|
//repeat(prodScheduleLine.needNoOfJobOrder) { |
|
|
// 6. Create Job Order |
|
|
// 6. Create Job Order |
|
|
val joRequest = CreateJobOrderRequest( |
|
|
|
|
|
bomId = bom.id, // bom is guaranteed non-null here |
|
|
|
|
|
reqQty = bom.outputQty?.multiply(BigDecimal.valueOf(prodScheduleLine.batchNeed.toLong())), |
|
|
|
|
|
approverId = approver?.id, |
|
|
|
|
|
|
|
|
|
|
|
// CRUCIAL FIX: Use the line ID, not the parent schedule ID |
|
|
|
|
|
prodScheduleLineId = prodScheduleLine.id!! |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
val joRequest = CreateJobOrderRequest( |
|
|
|
|
|
bomId = bom.id, // bom is guaranteed non-null here |
|
|
|
|
|
reqQty = bom.outputQty?.multiply(BigDecimal.valueOf(prodScheduleLine.batchNeed.toLong())), |
|
|
|
|
|
approverId = approver?.id, |
|
|
|
|
|
|
|
|
// Assuming createJobOrder returns the created Job Order (jo) |
|
|
|
|
|
val jo = jobOrderService.createJobOrder(joRequest) |
|
|
|
|
|
|
|
|
|
|
|
val createdJobOrderId = jo.id |
|
|
|
|
|
?: throw IllegalStateException("Job Order creation failed: returned object ID is null.") |
|
|
|
|
|
|
|
|
// CRUCIAL FIX: Use the line ID, not the parent schedule ID |
|
|
|
|
|
prodScheduleLineId = prodScheduleLine.id!! |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
// Assuming createJobOrder returns the created Job Order (jo) |
|
|
|
|
|
val jo = jobOrderService.createJobOrder(joRequest) |
|
|
|
|
|
|
|
|
|
|
|
val createdJobOrderId = jo.id |
|
|
|
|
|
?: throw IllegalStateException("Job Order creation failed: returned object ID is null.") |
|
|
|
|
|
|
|
|
|
|
|
// 7. Create related job order data |
|
|
|
|
|
jobOrderBomMaterialService.createJobOrderBomMaterialsByJoId(createdJobOrderId) |
|
|
|
|
|
jobOrderProcessService.createJobOrderProcessesByJoId(createdJobOrderId) |
|
|
|
|
|
productProcessService.createProductProcessByJobOrderId(createdJobOrderId, prodScheduleLine.itemPriority.toInt()) |
|
|
|
|
|
|
|
|
// 7. Create related job order data |
|
|
|
|
|
jobOrderBomMaterialService.createJobOrderBomMaterialsByJoId(createdJobOrderId) |
|
|
|
|
|
jobOrderProcessService.createJobOrderProcessesByJoId(createdJobOrderId) |
|
|
|
|
|
productProcessService.createProductProcessByJobOrderId(createdJobOrderId, prodScheduleLine.itemPriority.toInt()) |
|
|
|
|
|
|
|
|
jobOrderCount++ |
|
|
//} |
|
|
//} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@@ -477,7 +480,11 @@ open class ProductionScheduleService( |
|
|
|
|
|
|
|
|
return MessageResponse( |
|
|
return MessageResponse( |
|
|
id = request.id.toLong(), |
|
|
id = request.id.toLong(), |
|
|
message = "Successfully created Job Orders for all production schedule lines (Parent ID: ${request.id}).", |
|
|
|
|
|
|
|
|
//message = "Successfully created Job Orders for all production schedule lines (Parent ID: ${request.id}).", |
|
|
|
|
|
message = if (jobOrderCount == 0) |
|
|
|
|
|
"沒有建立新工單(可能因為成品已有生產中的工單)." |
|
|
|
|
|
else |
|
|
|
|
|
"成功建立 $jobOrderCount 張工單!", |
|
|
name = "", |
|
|
name = "", |
|
|
code = "", |
|
|
code = "", |
|
|
type = "", |
|
|
type = "", |
|
|
@@ -1438,8 +1445,8 @@ open class ProductionScheduleService( |
|
|
val sheet = workbook.createSheet(safeSheetName) |
|
|
val sheet = workbook.createSheet(safeSheetName) |
|
|
|
|
|
|
|
|
val headers = listOf( |
|
|
val headers = listOf( |
|
|
"Item Code", "Item Name", "Avg Qty Last Month", "Stock Qty", "Days Left", |
|
|
|
|
|
"Output Qty", "Batch Need", "Priority" |
|
|
|
|
|
|
|
|
"物料編號", "物料名稱", "每日平均出貨量", "出貨前預計存貨量", "可用日", |
|
|
|
|
|
"每批數量", "生產量(批)", "優先度" |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
// Header row |
|
|
// Header row |
|
|
@@ -1498,10 +1505,10 @@ open class ProductionScheduleService( |
|
|
val matSheet = workbook.createSheet("Material Summary") |
|
|
val matSheet = workbook.createSheet("Material Summary") |
|
|
|
|
|
|
|
|
val matHeaders = listOf( |
|
|
val matHeaders = listOf( |
|
|
"Mat Code", "Mat Name", "Required Qty", "Total Qty Need", |
|
|
|
|
|
"UoM", "Purchase Qty Need", "Purchase Unit", |
|
|
|
|
|
"Purchased Qty", "On Hand Qty", "Unavailable Qty", |
|
|
|
|
|
"Related Item Code", "Related Item Name" |
|
|
|
|
|
|
|
|
"物料編號", "物料名稱", "欠缺需量", "總用量", |
|
|
|
|
|
"單位", "數量(採購單位)", "採購單位", |
|
|
|
|
|
"已採購數量", "庫存數", "庫存單位", |
|
|
|
|
|
"相關成品編號", "相關成品名稱" |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
val matHeaderRow = matSheet.createRow(0) |
|
|
val matHeaderRow = matSheet.createRow(0) |
|
|
@@ -1532,7 +1539,7 @@ open class ProductionScheduleService( |
|
|
rowData["purchaseUnit"]?.toString() ?: "", |
|
|
rowData["purchaseUnit"]?.toString() ?: "", |
|
|
purchased, |
|
|
purchased, |
|
|
onHand, |
|
|
onHand, |
|
|
asDouble(rowData["unavailableQty"]), |
|
|
|
|
|
|
|
|
rowData["stockUnit"]?.toString() ?: "", |
|
|
rowData["itemCode"]?.toString() ?: "", |
|
|
rowData["itemCode"]?.toString() ?: "", |
|
|
rowData["itemName"]?.toString() ?: "" |
|
|
rowData["itemName"]?.toString() ?: "" |
|
|
) |
|
|
) |
|
|
@@ -1755,6 +1762,7 @@ open class ProductionScheduleService( |
|
|
) as purchaseUnit, |
|
|
) as purchaseUnit, |
|
|
min(ps.produceAt) as toProdcueFrom, |
|
|
min(ps.produceAt) as toProdcueFrom, |
|
|
max(ps.produceAt) as toProdcueAt, |
|
|
max(ps.produceAt) as toProdcueAt, |
|
|
|
|
|
ucs.udfudesc as stockUnit, |
|
|
psl.* |
|
|
psl.* |
|
|
|
|
|
|
|
|
from production_schedule_line psl |
|
|
from production_schedule_line psl |
|
|
@@ -1764,6 +1772,8 @@ open class ProductionScheduleService( |
|
|
left join bom_material bm on bom.id = bm.bomId |
|
|
left join bom_material bm on bom.id = bm.bomId |
|
|
left join items itm on bm.itemId = itm.id |
|
|
left join items itm on bm.itemId = itm.id |
|
|
left join inventory iv on itm.id = iv.itemId |
|
|
left join inventory iv on itm.id = iv.itemId |
|
|
|
|
|
left join item_uom ius on items.id = ius.itemId and ius.stockUnit = 1 |
|
|
|
|
|
left join uom_conversion ucs on ius.uomId = ucs.id |
|
|
|
|
|
|
|
|
where ps.produceAt >= :fromDate |
|
|
where ps.produceAt >= :fromDate |
|
|
and ps.id = (select id from production_schedule where produceAt = ps.produceAt order by id desc limit 1) |
|
|
and ps.id = (select id from production_schedule where produceAt = ps.produceAt order by id desc limit 1) |
|
|
@@ -1810,7 +1820,7 @@ open class ProductionScheduleService( |
|
|
JOIN bom_material bm ON bom.id = bm.bomId |
|
|
JOIN bom_material bm ON bom.id = bm.bomId |
|
|
JOIN items itm ON bm.itemId = itm.id |
|
|
JOIN items itm ON bm.itemId = itm.id |
|
|
JOIN item_uom itum ON itm.id = itum.itemId and itum.purchaseUnit = 1 |
|
|
JOIN item_uom itum ON itm.id = itum.itemId and itum.purchaseUnit = 1 |
|
|
join uom_conversion uomP on item.uomId = uomP.id |
|
|
|
|
|
|
|
|
join uom_conversion uomP on itum.uomId = uomP.id |
|
|
JOIN item_uom itsm ON itm.id = itsm.itemId and itsm.stockUnit = 1 |
|
|
JOIN item_uom itsm ON itm.id = itsm.itemId and itsm.stockUnit = 1 |
|
|
LEFT JOIN inventory iv ON itm.id = iv.itemId |
|
|
LEFT JOIN inventory iv ON itm.id = iv.itemId |
|
|
WHERE DATE(ps.produceAt) >= DATE_ADD(:fromDate, INTERVAL 1 DAY) |
|
|
WHERE DATE(ps.produceAt) >= DATE_ADD(:fromDate, INTERVAL 1 DAY) |
|
|
|