This is an automated email from the ASF dual-hosted git repository.
mridulpathak pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git
The following commit(s) were added to refs/heads/trunk by this push:
new 5c44d5ed17 Fixed: Five regressions in the minilang-to-Groovy
conversion of ProductionRunServicesScript.groovy (OFBIZ-13618)
5c44d5ed17 is described below
commit 5c44d5ed179759b533a0d08a6872394b6ab7fa5a
Author: Mridul Pathak <[email protected]>
AuthorDate: Sun Sep 27 14:00:20 2026 +0530
Fixed: Five regressions in the minilang-to-Groovy conversion of
ProductionRunServicesScript.groovy (OFBIZ-13618)
- createProductionRunPartyAssign() echoed back the internally-defaulted
workEffortId instead of the original productionRunId, corrupting the OUT
parameter when the two differ.
- issueProductionRunTaskComponent() dereferenced the WorkEffort and its
parent production run without null-checking either lookup, throwing an NPE
instead of a clean service error for a missing task or orphaned parent.
- issueProductionRunTaskComponentInline()'s physical-integrity guard netted
the caller's own reservation by quantityNotAvailable, making it stricter than
the capacity the calling pool-stock loop had already sized issuance to, which
could wrongly abort a whole multi-item issuance instead of issuing what fits.
- issueInventoryItemToWorkEffort() capped issuance at quantityOnHandTotal
instead of availableToPromiseTotal, letting it issue inventory already promised
to other tasks.
- handleManualIssuanceOverride() discarded the result of its inline
issuance call, reporting success even when the inline call actually failed.
---
.../jobshopmgt/ProductionRunServicesScript.groovy | 25 ++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)
diff --git
a/applications/manufacturing/src/main/groovy/org/apache/ofbiz/manufacturing/jobshopmgt/ProductionRunServicesScript.groovy
b/applications/manufacturing/src/main/groovy/org/apache/ofbiz/manufacturing/jobshopmgt/ProductionRunServicesScript.groovy
index 9fb99c703b..e8748fdcb1 100644
---
a/applications/manufacturing/src/main/groovy/org/apache/ofbiz/manufacturing/jobshopmgt/ProductionRunServicesScript.groovy
+++
b/applications/manufacturing/src/main/groovy/org/apache/ofbiz/manufacturing/jobshopmgt/ProductionRunServicesScript.groovy
@@ -34,7 +34,7 @@ Map createProductionRunPartyAssign() {
if (ServiceUtil.isError(serviceResult)) {
return serviceResult
}
- return [successMessage: null, productionRunId: parameters.workEffortId]
+ return [successMessage: null, productionRunId: parameters.productionRunId]
}
/**
@@ -174,6 +174,9 @@ Map issueProductionRunTask() {
*/
Map issueProductionRunTaskComponent() {
GenericValue workEffort = from('WorkEffort').where(workEffortId:
parameters.workEffortId).queryOne()
+ if (!workEffort) {
+ return ServiceUtil.returnError("Cannot find the production run task
with id: ${parameters.workEffortId}")
+ }
// POLICY GATE: Early enforcement
String facilityId = parameters.facilityId ?: workEffort?.facilityId
@@ -184,6 +187,9 @@ Map issueProductionRunTaskComponent() {
}
GenericValue productionRun = from('WorkEffort').where(workEffortId:
workEffort.workEffortParentId).queryOne()
+ if (!productionRun) {
+ return ServiceUtil.returnError("Cannot find the production run with
id: ${workEffort.workEffortParentId}")
+ }
require(!(['PRUN_CANCELLED',
'PRUN_CLOSED'].contains(productionRun.currentStatusId)),
label('ManufacturingUiLabels',
'ManufacturingAddProdCompInCompCanStatusError'))
String productId = parameters.productId
@@ -517,7 +523,11 @@ Map issueProductionRunTaskComponentInline(Map parameters,
GenericValue facility = task ? from('Facility').where(facilityId:
task.facilityId).queryOne() : null
String allowReallocation = facility?.allowInventoryReallocation ?:
'N'
- BigDecimal effectiveAvailable =
(inventoryItem.getBigDecimal('availableToPromiseTotal') ?: BigDecimal.ZERO) +
ourPhysicalResQty
+ // Use the un-netted reservation quantity here, matching the
capacity formula the caller
+ // (issueProductionRunTaskComponent's pool-stock loop) already
used to size quantityNotIssued;
+ // netting by quantityNotAvailable here would make this guard
stricter than the caller's own
+ // sizing and could wrongly abort the whole multi-item issuance
instead of issuing what fits.
+ BigDecimal effectiveAvailable =
(inventoryItem.getBigDecimal('availableToPromiseTotal') ?: BigDecimal.ZERO) +
ourResQty
BigDecimal inventoryItemQuantity
// POLICY GATE: Traditional (Strict) vs Fluid (Reallocation)
@@ -677,9 +687,9 @@ Map issueInventoryItemToWorkEffort() {
}
if (inventoryItem.inventoryItemTypeId == 'NON_SERIAL_INV_ITEM') {
- BigDecimal qoh = inventoryItem.getBigDecimal('quantityOnHandTotal') ?:
0.0
- if (qoh > 0) {
- quantityIssued = (parameters.quantity == null ||
parameters.quantity > qoh) ? qoh : parameters.quantity
+ BigDecimal atp =
inventoryItem.getBigDecimal('availableToPromiseTotal') ?: 0.0
+ if (atp > 0) {
+ quantityIssued = (parameters.quantity == null ||
parameters.quantity > atp) ? atp : parameters.quantity
Map serviceResult = run service: 'assignInventoryToWorkEffort',
with: [workEffortId: workEffortId,
inventoryItemId: inventoryItem.inventoryItemId,
@@ -817,7 +827,10 @@ Map handleManualIssuanceOverride(Map parameters) {
BigDecimal amountToIssue = parameters.quantityNotIssued
Map issueParams = [*:parameters, inventoryItemId:
inventoryItem.inventoryItemId,
quantityNotIssued: amountToIssue,
failIfItemsAreNotAvailable: 'N']
- issueProductionRunTaskComponentInline(issueParams, inventoryItem, null)
+ Map inlineResult = issueProductionRunTaskComponentInline(issueParams,
inventoryItem, null)
+ if (ServiceUtil.isError(inlineResult)) {
+ return inlineResult
+ }
List impactedTasks = [] // reconcileGlobalReservationsInternal already
called via issueProductionRunTaskComponentInline