You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by nm...@apache.org on 2020/05/19 15:09:57 UTC

[ofbiz-framework] branch trunk updated: Improved: Convert ProductionRunServices.xml file from mini-lang to groovy DSL (OFBIZ-11395)

This is an automated email from the ASF dual-hosted git repository.

nmalin 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 b134c6b  Improved: Convert ProductionRunServices.xml file from mini-lang to groovy DSL (OFBIZ-11395)
b134c6b is described below

commit b134c6b72fff1d625b0e5c2b88a2933378353596
Author: Nicolas Malin <ni...@nereide.fr>
AuthorDate: Tue May 19 17:09:34 2020 +0200

    Improved: Convert ProductionRunServices.xml file from mini-lang to groovy DSL
    (OFBIZ-11395)
    
    Thanks to Yashwant Dhakad for this patch
---
 .../jobshopmgt/ProductionRunServices.groovy        | 397 +++++++++++++++++
 .../minilang/jobshopmgt/ProductionRunServices.xml  | 495 ---------------------
 .../servicedef/services_production_run.xml         |  20 +-
 3 files changed, 407 insertions(+), 505 deletions(-)

diff --git a/applications/manufacturing/groovyScripts/jobshopmgt/ProductionRunServices.groovy b/applications/manufacturing/groovyScripts/jobshopmgt/ProductionRunServices.groovy
new file mode 100644
index 0000000..30690ce
--- /dev/null
+++ b/applications/manufacturing/groovyScripts/jobshopmgt/ProductionRunServices.groovy
@@ -0,0 +1,397 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+import org.apache.ofbiz.base.util.UtilDateTime
+import org.apache.ofbiz.base.util.UtilProperties
+import org.apache.ofbiz.entity.GenericValue
+import org.apache.ofbiz.service.ServiceUtil
+
+/**
+ * Assign the selected party to the production run or task.
+ */
+def createProductionRunPartyAssign() {
+    parameters.statusId = "PRTYASGN_ASSIGNED"
+    if (!parameters.workEffortId) {
+        parameters.workEffortId = parameters.productionRunId
+    }
+
+    Map serviceResult = run service: "assignPartyToWorkEffort", with: parameters
+    if (ServiceUtil.isError(serviceResult)) {
+        return serviceResult
+    }
+    return [successMessage: null, productionRunId: parameters.workEffortId]
+}
+
+/**
+ *Associate the production run to another production run
+ */
+def createProductionRunAssoc() {
+    Map serviceContext = [workEffortAssocTypeId: "WORK_EFF_PRECEDENCY"]
+    if ("WF_PREDECESSOR" == parameters.workFlowSequenceTypeId) {
+        serviceContext.workEffortIdFrom = parameters.productionRunIdTo
+        serviceContext.workEffortIdTo = parameters.productionRunId
+    } else if ("WF_SUCCESSOR" == parameters.workFlowSequenceTypeId) {
+        serviceContext.workEffortIdFrom = parameters.productionRunId
+        serviceContext.workEffortIdTo = parameters.productionRunIdTo
+    }
+
+    Map serviceResult = run service: "createWorkEffortAssoc", with: serviceContext
+    if (ServiceUtil.isError(serviceResult)) {
+        return serviceResult
+    }
+    return success()
+}
+
+/**
+ *Issues the Inventory for a Production Run Task
+ */
+def issueProductionRunTask() {
+    GenericValue workEffort = from("WorkEffort").where(parameters).queryOne()
+    parameters.failIfItemsAreNotAvailable = parameters.failIfItemsAreNotAvailable ?: "Y"
+    parameters.failIfItemsAreNotOnHand = parameters.failIfItemsAreNotOnHand ?: "Y"
+    if (workEffort && "PRUN_CANCELLED" != workEffort.currentStatusId) {
+        from("WorkEffortGoodStandard")
+                .where(workEffortId: workEffort.workEffortId,
+                        statusId: "WEGS_CREATED",
+                        workEffortGoodStdTypeId: "PRUNT_PROD_NEEDED")
+                .filterByDate()
+                .queryList()
+                .each { component ->
+                    if (component.productId) {
+                        Map callSvcMap = component.getAllFields()
+                        BigDecimal totalIssuance = 0.0
+                        from("WorkEffortAndInventoryAssign")
+                                .where(workEffortId: workEffort.workEffortId,
+                                        productId: component.productId)
+                                .queryList()
+                                .each { issuance ->
+                                    if (issuance.quantity) {
+                                        totalIssuance += issuance.quantity
+                                    }
+                                }
+                        if (totalIssuance != 0) {
+                            callSvcMap.quantity = component.estimatedQuantity - totalIssuance
+                        }
+                        callSvcMap.reserveOrderEnumId = parameters.reserveOrderEnumId
+                        callSvcMap.description = "BOM Part"
+                        callSvcMap.failIfItemsAreNotAvailable = parameters.failIfItemsAreNotAvailable
+                        callSvcMap.failIfItemsAreNotOnHand = parameters.failIfItemsAreNotOnHand
+
+                        Map serviceResult = run service: "issueProductionRunTaskComponent", with: callSvcMap
+                        if (ServiceUtil.isError(serviceResult)) {
+                            return serviceResult
+                        }
+                    }
+                    logInfo("Issued inventory for workEffortId ${workEffort.workEffortId}")
+                }
+    }
+    return success()
+}
+
+/**
+ *Issues the Inventory for a Production Run Task Component
+ */
+def issueProductionRunTaskComponent() {
+    GenericValue workEffort = from("WorkEffort").where("workEffortId", parameters.workEffortId).queryOne()
+    GenericValue productionRun = from("WorkEffort").where("workEffortId", workEffort.workEffortParentId).queryOne()
+    if (['PRUN_CANCELLED', 'PRUN_CLOSED'].contains(productionRun.currentStatusId)) {
+        return error(UtilProperties.getMessage('ManufacturingUiLabels',
+                'ManufacturingAddProdCompInCompCanStatusError', locale))
+    }
+    String productId = parameters.productId
+    GenericValue workEffortGoodStandard = null
+    BigDecimal estimatedQuantity = parameters.quantity ?: 0.0
+    if (parameters.fromDate) {
+        workEffortGoodStandard = from("WorkEffortGoodStandard")
+                .where("workEffortId", parameters.workEffortId,
+                        "productId", parameters.productId,
+                        "fromDate", parameters.fromDate,
+                        "workEffortGoodStdTypeId", "PRUNT_PROD_NEEDED")
+                .queryOne()
+        productId = workEffortGoodStandard.productId
+        if (!parameters.quantity) {
+            estimatedQuantity = workEffortGoodStandard.estimatedQuantity
+        }
+
+        if (!productId) {
+            Map serviceResult = run service: "createWorkEffortGoodStandard", with: [workEffortId: parameters.workEffortId,
+                                                                                    productId: parameters.productId,
+                                                                                    workEffortGoodStdTypeId: "PRUNT_PROD_NEEDED",
+                                                                                    fromDate: parameters.fromDate,
+                                                                                    estimatedQuantity: estimatedQuantity,
+                                                                                    statusId: "WEGS_CREATED"]
+            if (ServiceUtil.isError(serviceResult)) {
+                return serviceResult
+            }
+            // if the task is in completed status we want to make WEIA for the added product as well
+            if ("PRUN_COMPLETED" == workEffort.currentStatusId) {
+                productId = parameters.productId
+            }
+        }
+
+    // kind of like the inventory reservation routine, find InventoryItems to issue from,
+    // but instead of doing the reservation just create an issuance and an inventory item detail for the change
+    if (productId) {
+        String orderBy = "+datetimeReceived"
+        nowTimestamp = UtilDateTime.nowTimestamp()
+
+            // before we do the find, put together the orderBy list based on which reserveOrderEnumId is specified
+            switch (parameters.reserveOrderEnumId) {
+                case "INVRO_FIFO_EXP":
+                    orderBy = "+expireDate"
+                    break
+                case "INVRO_LIFO_EXP":
+                    orderBy = "-expireDate"
+                    break
+                case "INVRO_LIFO_REC":
+                    orderBy = "-datetimeReceived"
+                    break
+                default:
+                    parameters.reserveOrderEnumId = "INVRO_FIFO_REC"
+                    break
+            }
+            Map lookupFieldMap = [productId: productId,
+                                  facilityId: workEffort.facilityId]
+            if (parameters.lotId) {
+                parameters.failIfItemsAreNotAvailable = "Y"
+                lookupFieldMap.lotId = parameters.lotId
+            }
+            if (parameters.locationSeqId) {
+                lookupFieldMap.locationSeqId = parameters.locationSeqId
+            }
+            List inventoryItemList = from("InventoryItem")
+                    .where(lookupFieldMap)
+                    .orderBy(orderBy)
+                    .queryList()
+
+            if (parameters.locationSeqId && parameters.secondaryLocationSeqId) {
+                lookupFieldMap.locationSeqId = parameters.locationSeqId
+                inventoryItemList << from("InventoryItem")
+                        .where(lookupFieldMap)
+                        .orderBy(orderBy)
+                        .queryList()
+            }
+
+            GenericValue lastNonSerInventoryItem = null
+            parameters.quantityNotIssued = estimatedQuantity
+            parameters.useReservedItems = "N"
+
+            inventoryItemList.each { inventoryItem ->
+                issueProductionRunTaskComponentInline(parameters, inventoryItem, lastNonSerInventoryItem)
+            }
+
+            if (parameters.failIfItemsAreNotAvailable != "Y" && parameters.quantityNotIssued != 0) {
+                parameters.useReservedItems = "Y"
+                inventoryItemList.each { inventoryItem ->
+                    if (parameters.quantityNotIssued > 0) {
+                        inventoryItem.refresh()
+                        issueProductionRunTaskComponentInline(parameters, inventoryItem, lastNonSerInventoryItem)
+                    }
+                }
+            }
+            // if quantityNotIssued is not 0, then pull it from the last non-serialized inventory item found, in the quantityNotIssued field
+            if (parameters.quantityNotIssued != 0) {
+                if (parameters.failIfItemsAreNotAvailable == "Y" || !parameters.failIfItemsAreNotOnHand) {
+                    GenericValue product
+                    if (productId) {
+                        product = from("Product").where(productId: productId).cache().queryOne()
+                    }
+                    Map paramMap = [productId: productId,
+                                    internalName: product ? product.internalName : '',
+                                    parameters: parameters]
+                    return ServiceUtil.returnError((UtilProperties.getMessage('ManufacturingUiLabels',
+                            'ManufacturingMaterialsNotAvailable', paramMap, parameters.locale)))
+                }
+                if (lastNonSerInventoryItem) {
+                    Map serviceResult = run service: "assignInventoryToWorkEffort", with: [workEffortId: parameters.workEffortId,
+                                                                                           inventoryItemId: lastNonSerInventoryItem.inventoryItemId,
+                                                                                           quantity: parameters.quantityNotIssued]
+                    if (ServiceUtil.isError(serviceResult)) {
+                        return serviceResult
+                    }
+
+                    // subtract from quantityNotIssued from the availableToPromise and quantityOnHand of existing inventory item
+                    // instead of updating InventoryItem, add an InventoryItemDetail
+                    serviceResult = run service: "createInventoryItemDetail", with: [inventoryItemId: lastNonSerInventoryItem.inventoryItemId,
+                                                                                     workEffortId: parameters.workEffortId,
+                                                                                     availableToPromiseDiff: -parameters.quantityNotIssued,
+                                                                                     quantityOnHandDiff: -parameters.quantityNotIssued,
+                                                                                     reasonEnumId: parameters.reasonEnumId,
+                                                                                     description: parameters.description]
+                    if (ServiceUtil.isError(serviceResult)) {
+                        return error(ServiceUtil.getErrorMessage(serviceResult))
+                    }
+                    serviceResult = run service: "balanceInventoryItems", with: [inventoryItemId: lastNonSerInventoryItem.inventoryItemId]
+                    if (ServiceUtil.isError(serviceResult)) {
+                        return error(ServiceUtil.getErrorMessage(serviceResult))
+                    }
+                } else {
+                    // no non-ser inv item, create a non-ser InventoryItem with availableToPromise = -quantityNotIssued
+                    Map serviceResult = run service: "createInventoryItem", with: [productId: productId,
+                                                                                   facilityId: workEffort.facilityId,
+                                                                                   inventoryItemTypeId: "NON_SERIAL_INV_ITEM"]
+                    if (ServiceUtil.isError(serviceResult)) {
+                        return serviceResult
+                    }
+                    String inventoryItemId = serviceResult.inventoryItemId
+                    serviceResult = run service: "assignInventoryToWorkEffort", with: [workEffortId: workEffort.workEffortId,
+                                                                                       inventoryItemId: inventoryItemId,
+                                                                                       quantity: parameters.quantityNotIssued]
+                    if (ServiceUtil.isError(serviceResult)) {
+                        return serviceResult
+                    }
+
+                    // also create a detail record with the quantities
+                    serviceResult = run service: "createInventoryItemDetail",
+                            with: [workEffortId: workEffort.workEffortId,
+                                   inventoryItemId: inventoryItemId,
+                                   availableToPromiseDiff: -parameters.quantityNotIssued,
+                                   quantityOnHandDiff: -parameters.quantityNotIssued,
+                                   reasonEnumId: parameters.reasonEnumId,
+                                   description: parameters.description]
+                    if (ServiceUtil.isError(serviceResult)) {
+                        return serviceResult
+                    }
+                    parameters.quantityNotIssued = 0.0
+                }
+            }
+            if (workEffortGoodStandard) {
+                BigDecimal totalIssuance = 0.0
+                from("WorkEffortAndInventoryAssign")
+                        .where("workEffortId", workEffortGoodStandard.workEffortId,
+                                "productId", workEffortGoodStandard.productId)
+                        .queryList()
+                        .each { issuance ->
+                            totalIssuance += issuance.quantity
+                        }
+                if (workEffortGoodStandard.estimatedQuantity <= totalIssuance) {
+                    workEffortGoodStandard.statusId = "WEGS_COMPLETED"
+                    workEffortGoodStandard.store()
+                }
+            }
+        }
+    }
+    return success()
+}
+
+
+/**
+ *Does a issuance for one InventoryItem, meant to be called in-line
+ */
+def issueProductionRunTaskComponentInline(Map parameters,
+                                          GenericValue inventoryItem,
+                                          GenericValue lastNonSerInventoryItem) {
+
+    if (parameters.quantityNotIssued > 0) {
+        if ("SERIALIZED_INV_ITEM" == inventoryItem.inventoryItemTypeId &&
+                "INV_AVAILABLE" == inventoryItem.statusId) {
+            inventoryItem.statusId = "INV_DELIVERED"
+            inventoryItem.store()
+            Map serviceResult = run service: "assignInventoryToWorkEffort", with: [workEffortId: parameters.workEffortId,
+                                                                                   inventoryItemId: parameters.inventoryItemId,
+                                                                                   quantity: 1]
+            if (ServiceUtil.isError(serviceResult)) {
+                return serviceResult
+            }
+            parameters.quantityNotIssued = parameters.quantityNotIssued - 1
+        }
+        if ((!inventoryItem.statusId || "INV_AVAILABLE" == inventoryItem.statusId) &&
+                "NON_SERIAL_INV_ITEM" == inventoryItem.inventoryItemTypeId) {
+            BigDecimal inventoryItemQuantity = "Y" != parameters.useReservedItems ?
+                    inventoryItem.availableToPromiseTotal:
+                    inventoryItem.quantityOnHandTotal
+
+            // reduce atp on inventoryItem if availableToPromise greater than 0, if not the code at the end of this method will handle it
+            if (inventoryItemQuantity && inventoryItemQuantity > 0) {
+                parameters.deductAmount = parameters.quantityNotIssued > inventoryItemQuantity ?
+                        inventoryItemQuantity:
+                        parameters.quantityNotIssued
+                Map serviceResult = run service: "assignInventoryToWorkEffort", with: [workEffortId: parameters.workEffortId,
+                                                                                   inventoryItemId: inventoryItem.inventoryItemId,
+                                                                                   quantity: parameters.deductAmount]
+                if (ServiceUtil.isError(serviceResult)) {
+                    return serviceResult
+                }
+
+                serviceResult = run service: "createInventoryItemDetail", with: [inventoryItemId: inventoryItem.inventoryItemId,
+                                                                                 workEffortId: parameters.workEffortId,
+                                                                                 availableToPromiseDiff: -parameters.deductAmount,
+                                                                                 quantityOnHandDiff: -parameters.deductAmount,
+                                                                                 reasonEnumId: parameters.reasonEnumId,
+                                                                                 description: parameters.description]
+                if (ServiceUtil.isError(serviceResult)) {
+                    return serviceResult
+                }
+                parameters.quantityNotIssued -= parameters.deductAmount
+                serviceResult = run service: "balanceInventoryItems", with: [inventoryItemId: inventoryItem.inventoryItemId]
+                if (ServiceUtil.isError(serviceResult)) {
+                    return serviceResult
+                }
+                lastNonSerInventoryItem = inventoryItem
+            }
+        }
+    }
+    return success()
+}
+
+/**
+ *Issue one InventoryItem to a WorkEffort
+ */
+def issueInventoryItemToWorkEffort() {
+    GenericValue inventoryItem = parameters.inventoryItem
+    BigDecimal quantityIssued = 0.0
+    if ("SERIALIZED_INV_ITEM" == inventoryItem.inventoryItemTypeId && inventoryItem.statusId) {
+        inventoryItem.statusId = "INV_DELIVERED"
+        inventoryItem.store()
+        quantityIssued = 1
+        Map serviceResult = run service: "assignInventoryToWorkEffort", with: [workEffortId: parameters.workEffortId,
+                                                                               inventoryItemId: inventoryItem.inventoryItemId,
+                                                                               quantity: quantityIssued]
+        if (ServiceUtil.isError(serviceResult)) {
+            return serviceResult
+        }
+    }
+    if ("NON_SERIAL_INV_ITEM" == inventoryItem.inventoryItemTypeId &&
+            inventoryItem.availableToPromiseTotal &&
+            inventoryItem.availableToPromiseTotal > 0) {
+
+        quantityIssued = !parameters.quantity || parameters.quantity > inventoryItem.availableToPromiseTotal ?
+                parameters.quantity:
+                inventoryItem.availableToPromiseTotal
+        Map serviceResult = run service: "assignInventoryToWorkEffort", with: [workEffortId: parameters.workEffortId,
+                                                                               inventoryItemId: inventoryItem.inventoryItemId,
+                                                                               quantity: quantityIssued]
+        if (ServiceUtil.isError(serviceResult)) {
+            return serviceResult
+        }
+
+        serviceResult = run service: "createInventoryItemDetail", with: [inventoryItemId: inventoryItem.inventoryItemId,
+                                                                         workEffortId: parameters.workEffortId,
+                                                                         availableToPromiseDiff: - quantityIssued,
+                                                                         quantityOnHandDiff: - quantityIssued,
+                                                                         reasonEnumId: parameters.reasonEnumId,
+                                                                         description: parameters.description]
+        if (ServiceUtil.isError(serviceResult)) {
+            return serviceResult
+        }
+        parameters.quantityNotIssued -= parameters.deductAmount
+    }
+    return [successMessage: null, finishedProductId: inventoryItem.productId, quantityIssued: quantityIssued]
+}
\ No newline at end of file
diff --git a/applications/manufacturing/minilang/jobshopmgt/ProductionRunServices.xml b/applications/manufacturing/minilang/jobshopmgt/ProductionRunServices.xml
deleted file mode 100644
index c98d188..0000000
--- a/applications/manufacturing/minilang/jobshopmgt/ProductionRunServices.xml
+++ /dev/null
@@ -1,495 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements.  See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership.  The ASF licenses this file
-to you under the Apache License, Version 2.0 (the
-"License"); you may not use this file except in compliance
-with the License.  You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied.  See the License for the
-specific language governing permissions and limitations
-under the License.
--->
-
-<simple-methods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-        xmlns="http://ofbiz.apache.org/Simple-Method" xsi:schemaLocation="http://ofbiz.apache.org/Simple-Method http://ofbiz.apache.org/dtds/simple-methods.xsd">
-    
-    
-    <simple-method method-name="createProductionRunPartyAssign" 
-        short-description="Assign the selected party to the production run or task">
-        
-        <set field="parameters.statusId" value="PRTYASGN_ASSIGNED"/>
-        
-        <if-empty field="parameters.workEffortId">
-            <set field="parameters.workEffortId" from-field="parameters.productionRunId"/>
-        </if-empty>
-        
-        <field-to-result field="parameters.productionRunId" result-name="productionRunId" />
-        <call-simple-method method-name="assignPartyToWorkEffort"
-            xml-resource="component://workeffort/minilang/workeffort/WorkEffortSimpleServices.xml" />
-        
-    </simple-method>
-    <simple-method method-name="createProductionRunAssoc" short-description="Associate the production run to another production run">
-        
-        <if-compare field="parameters.workFlowSequenceTypeId" operator="equals" value="WF_PREDECESSOR">
-            <set field="ctx.workEffortIdFrom" from-field="parameters.productionRunIdTo"/>
-            <set field="ctx.workEffortIdTo" from-field="parameters.productionRunId"/>
-        </if-compare>
-        <if-compare field="parameters.workFlowSequenceTypeId" operator="equals" value="WF_SUCCESSOR">
-            <set field="ctx.workEffortIdFrom" from-field="parameters.productionRunId"/>
-            <set field="ctx.workEffortIdTo" from-field="parameters.productionRunIdTo"/>
-        </if-compare>
-        
-        <set field="ctx.workEffortAssocTypeId" value="WORK_EFF_PRECEDENCY"/>
-        <call-service service-name="createWorkEffortAssoc" in-map-name="ctx"/>
-    </simple-method>
-    
-    <!-- Warehouse -->
-    <simple-method method-name="issueProductionRunTask" short-description="Issues the Inventory for a Production Run Task" login-required="false">
-        <entity-one entity-name="WorkEffort" value-field="workEffort"/>
-        <if-empty field="parameters.failIfItemsAreNotAvailable">
-            <set field="parameters.failIfItemsAreNotAvailable" value="Y"/>
-        </if-empty>
-        <if-empty field="parameters.failIfItemsAreNotOnHand">
-            <set field="parameters.failIfItemsAreNotOnHand" value="Y"/>
-        </if-empty>
-        <if-not-empty field="workEffort">
-            <if-compare value="PRUN_CANCELLED" operator="not-equals" field="workEffort.currentStatusId">
-                <set from-field="parameters.workEffortId" field="lookupComponentsMap.workEffortId"/>
-                <set value="WEGS_CREATED" field="lookupComponentsMap.statusId"/>
-                <set field="lookupComponentsMap.workEffortGoodStdTypeId" value="PRUNT_PROD_NEEDED"/>
-
-                <find-by-and entity-name="WorkEffortGoodStandard" list="components" map="lookupComponentsMap"/>
-                <filter-list-by-date list="components"/>
-                <!-- now go through each work effort good standard and call a service to issue the inventory -->
-                <iterate list="components" entry="component">
-                    <if-not-empty field="component.productId">
-                        <clear-field field="callSvcMap"/>
-                        <set-service-fields service-name="issueProductionRunTaskComponent" map="component" to-map="callSvcMap"/>
-                        <set from-field="reserveOrderEnumId" field="callSvcMap.reserveOrderEnumId"/>
-                        <!-- calculate quantity needed if the produced run quantity is produced partially -->
-                        <entity-and entity-name="WorkEffortAndInventoryAssign" list="issuances">
-                            <field-map field-name="workEffortId" from-field="workEffort.workEffortId"/>
-                            <field-map field-name="productId" from-field="component.productId"/>
-                        </entity-and>
-                        <set field="totalIssuance" value="0.00" type="BigDecimal"/>
-                        <iterate list="issuances" entry="issuance">
-                            <calculate field="totalIssuance">
-                                <calcop operator="add">
-                                    <calcop operator="get" field="issuance.quantity"/>
-                                    <calcop operator="get" field="totalIssuance"/>
-                                </calcop>
-                            </calculate>
-                        </iterate>
-                        
-                        <if-compare field="totalIssuance" operator="not-equals" value="0.00">
-                            <set field="callSvcMap.quantity" value="0.00" type="BigDecimal"/>
-                            <calculate field="callSvcMap.quantity">
-                                <calcop operator="subtract" field="component.estimatedQuantity">
-                                    <calcop operator="get" field="totalIssuance"/>
-                                </calcop>
-                            </calculate>
-                        </if-compare>
-                        <set field="callSvcMap.description" value="BOM Part"/>
-                        <set field="callSvcMap.failIfItemsAreNotAvailable" from-field="parameters.failIfItemsAreNotAvailable"/>
-                        <set field="callSvcMap.failIfItemsAreNotOnHand" from-field="parameters.failIfItemsAreNotOnHand"/>
-                        <call-service service-name="issueProductionRunTaskComponent" in-map-name="callSvcMap"/>
-                    </if-not-empty>
-                </iterate>
-                <log level="info" message="Issued inventory for workEffortId ${workEffort.workEffortId}."/>
-            </if-compare>
-        </if-not-empty>
-    </simple-method>
-    <simple-method method-name="issueProductionRunTaskComponent" short-description="Issues the Inventory for a Production Run Task Component" login-required="false">
-
-        <!-- NOTE: the inventory will be issued from the WorkEffort.facilityId -->
-        <entity-one entity-name="WorkEffort" value-field="workEffort"/>
-        <entity-one entity-name="WorkEffort" value-field="productionRun">
-            <field-map field-name="workEffortId" from-field="workEffort.workEffortParentId"/>
-        </entity-one>
-        <if>
-            <condition>
-                <or>
-                    <if-compare field="productionRun.currentStatusId" operator="equals" value="PRUN_CANCELLED"/>
-                    <if-compare field="productionRun.currentStatusId" operator="equals" value="PRUN_CLOSED"/>
-                </or>
-            </condition>
-            <then>
-                <add-error>
-                    <fail-property property="ManufacturingAddProdCompInCompCanStatusError" resource="ManufacturingUiLabels"/>
-                </add-error>
-            </then>
-        </if>
-        <check-errors/>
-
-        <if-empty field="parameters.fromDate">
-            <set field="productId" from-field="parameters.productId"/>
-            <set from-field="parameters.quantity" field="estimatedQuantity" default-value="0.0" type="BigDecimal"/>
-        <else>
-            <entity-one entity-name="WorkEffortGoodStandard" value-field="workEffortGoodStandard" auto-field-map="false">
-                <field-map field-name="workEffortId" from-field="parameters.workEffortId"/>
-                <field-map field-name="productId" from-field="parameters.productId"/>
-                <field-map field-name="fromDate" from-field="parameters.fromDate"/>
-                <field-map field-name="workEffortGoodStdTypeId" value="PRUNT_PROD_NEEDED"/>
-            </entity-one>
-            <set from-field="workEffortGoodStandard.productId" field="productId"/>
-            <if-empty field="parameters.quantity">
-                <set from-field="workEffortGoodStandard.estimatedQuantity" field="estimatedQuantity"/>
-            <else>
-                <set from-field="parameters.quantity" field="estimatedQuantity" default-value="0.0" type="BigDecimal"/>
-            </else>
-            </if-empty>
-            <!-- If no product found in the workEffortGoodStandard then create the entry in workEffortGoodStandard-->
-            <if-empty field="productId">
-                <set field="createWorkEffortGoodStdMap.workEffortId" from-field="parameters.workEffortId" />
-                <set field="createWorkEffortGoodStdMap.productId" from-field="parameters.productId"/>
-                <set field="createWorkEffortGoodStdMap.workEffortGoodStdTypeId" value="PRUNT_PROD_NEEDED"/>
-                <set field="createWorkEffortGoodStdMap.fromDate" from-field="parameters.fromDate" />
-                <set field="createWorkEffortGoodStdMap.estimatedQuantity" from-field="parameters.quantity"/>
-                <set field="createWorkEffortGoodStdMap.statusId" value="WEGS_CREATED"/>
-                <call-service service-name="createWorkEffortGoodStandard" in-map-name="createWorkEffortGoodStdMap"/>
-                <!-- if the task is in completed status we want to make WEIA for the added product as well -->
-                <if-compare value="workEffort.currentStatusId" operator="equals" field="PRUN_COMPLETED">
-                    <set field="productId" from-field="parameters.productId"/>
-                </if-compare>
-            </if-empty>
-        </else>
-        </if-empty>
-
-        <!-- kind of like the inventory reservation routine, find InventoryItems to issue from, but instead of doing the reservation just create an issuance and an inventory item detail for the change -->
-        <if-not-empty field="productId">
-            <now-timestamp field="nowTimestamp"/>
-
-            <!-- before we do the find, put together the orderBy list based on which reserveOrderEnumId is specified -->
-            <if-compare value="INVRO_FIFO_EXP" operator="equals" field="parameters.reserveOrderEnumId">
-                <set value="+expireDate" field="orderByString"/>
-            <else>
-                <if-compare value="INVRO_LIFO_EXP" operator="equals" field="parameters.reserveOrderEnumId">
-                    <set value="-expireDate" field="orderByString"/>
-                <else>
-                    <if-compare value="INVRO_LIFO_REC" operator="equals" field="parameters.reserveOrderEnumId">
-                        <set value="-datetimeReceived" field="orderByString"/>
-                    <else>
-                        <!-- the default reserveOrderEnumId is INVRO_FIFO_REC, ie FIFO based on date received -->
-                        <set value="+datetimeReceived" field="orderByString"/>
-                        <set value="INVRO_FIFO_REC" field="parameters.reserveOrderEnumId"/>
-                    </else>
-                    </if-compare>
-                </else>
-                </if-compare>
-            </else>
-            </if-compare>
-            <field-to-list field="orderByString" list="orderByList"/>
-            <set from-field="productId" field="lookupFieldMap.productId"/>
-            <set from-field="workEffort.facilityId" field="lookupFieldMap.facilityId"/>
-            
-            <!-- if lotId is passed, failIfItemsAreNotAvailable is set to automatically set to "Y" -->
-            <if-not-empty field="parameters.lotId">
-                <set field="parameters.failIfItemsAreNotAvailable" value="Y"/>
-                <set field="lookupFieldMap.lotId" from-field="parameters.lotId"/>
-            </if-not-empty>
-            
-            <!-- if locationSeqId is passed, then only the inventory items in the location are considered -->
-            <if-not-empty field="parameters.locationSeqId">
-                <set from-field="parameters.locationSeqId" field="lookupFieldMap.locationSeqId"/>
-            </if-not-empty>
-            <find-by-and entity-name="InventoryItem" map="lookupFieldMap" list="primaryInventoryItemList" order-by-list="orderByList"/>
-            <set from-field="primaryInventoryItemList" field="inventoryItemList"/>
-            <!-- if secondaryLocationSeqId is also passed, then also the inventory items in the secondary location are considered, after the ones in the main location -->
-            <if-not-empty field="parameters.locationSeqId">
-                <if-not-empty field="parameters.secondaryLocationSeqId">
-                    <set from-field="parameters.secondaryLocationSeqId" field="lookupFieldMap.locationSeqId"/>
-                    <find-by-and entity-name="InventoryItem" map="lookupFieldMap" list="secondaryInventoryItemList" order-by-list="orderByList"/>
-                    <list-to-list list="secondaryInventoryItemList" to-list="inventoryItemList"/>
-                </if-not-empty>
-            </if-not-empty>
-
-            <set from-field="estimatedQuantity" field="parameters.quantityNotIssued"/>
-
-            <set field="parameters.useReservedItems" value="N"/>
-            <iterate list="inventoryItemList" entry="inventoryItem">
-                <!-- this is a little trick to get the InventoryItem value object without doing a query, possible since all fields on InventoryItem are also on InventoryItemAndLocation with the same names -->
-                <call-simple-method method-name="issueProductionRunTaskComponentInline"/>
-            </iterate>
-
-            <if>
-                <condition>
-                    <and>
-                        <if-compare field="parameters.failIfItemsAreNotAvailable" operator="not-equals" value="Y" type="String"/>
-                        <if-compare field="parameters.quantityNotIssued" operator="greater" value="0" type="BigDecimal"/>
-                    </and>
-                </condition>
-                <then>
-                    <set field="parameters.useReservedItems" value="Y"/>
-                    <iterate list="inventoryItemList" entry="inventoryItem">
-                        <if-compare field="parameters.quantityNotIssued" operator="greater" value="0" type="BigDecimal">
-                            <refresh-value value-field="inventoryItem"/>
-                            <!-- this is a little trick to get the InventoryItem value object without doing a query, possible since all fields on InventoryItem are also on InventoryItemAndLocation with the same names -->
-                            <call-simple-method method-name="issueProductionRunTaskComponentInline"/>
-                        </if-compare>
-                    </iterate>
-                </then>
-            </if>
-
-            <!-- if quantityNotIssued is not 0, then pull it from the last non-serialized inventory item found, in the quantityNotIssued field -->
-            <if-compare field="parameters.quantityNotIssued" operator="not-equals" value="0" type="BigDecimal">
-                <if>
-                    <condition>
-                        <or>
-                            <if-compare field="parameters.failIfItemsAreNotAvailable" operator="equals" value="Y" type="String"/>
-                            <if-empty field="parameters.failIfItemsAreNotOnHand"/>
-                        </or>
-                    </condition>
-                    <then>
-                        <add-error>
-                            <fail-property resource="ManufacturingUiLabels" property="ManufacturingMaterialsNotAvailable"/>
-                        </add-error>
-                    </then>
-                </if>
-                <check-errors/>
-                <if-not-empty field="lastNonSerInventoryItem">
-                    <!-- create ItemIssuance record -->
-                    <set from-field="parameters.workEffortId" field="issuanceCreateMap.workEffortId"/>
-                    <set from-field="lastNonSerInventoryItem.inventoryItemId" field="issuanceCreateMap.inventoryItemId"/>
-                    <set from-field="parameters.quantityNotIssued" field="issuanceCreateMap.quantity"/>
-                    <call-service service-name="assignInventoryToWorkEffort" in-map-name="issuanceCreateMap">
-                    </call-service>
-
-                    <!-- subtract from quantityNotIssued from the availableToPromise and quantityOnHand of existing inventory item -->
-                    <!-- instead of updating InventoryItem, add an InventoryItemDetail -->
-                    <set from-field="lastNonSerInventoryItem.inventoryItemId" field="createDetailMap.inventoryItemId"/>
-                    <set from-field="parameters.workEffortId" field="createDetailMap.workEffortId"/>
-                    <calculate field="createDetailMap.availableToPromiseDiff">
-                        <calcop operator="negative" field="parameters.quantityNotIssued"/>
-                    </calculate>
-                    <calculate field="createDetailMap.quantityOnHandDiff">
-                        <calcop operator="negative" field="parameters.quantityNotIssued"/>
-                    </calculate>
-                    <set field="createDetailMap.reasonEnumId" from-field="parameters.reasonEnumId"/>
-                    <set field="createDetailMap.description" from-field="parameters.description"/>
-                    <call-service service-name="createInventoryItemDetail" in-map-name="createDetailMap"/>
-                    <clear-field field="createDetailMap"/>
-                    <set field="balanceInventoryItemsInMap.inventoryItemId" from-field="lastNonSerInventoryItem.inventoryItemId"/>
-                    <call-service service-name="balanceInventoryItems" in-map-name="balanceInventoryItemsInMap"/>
-                <else>
-                    <!-- no non-ser inv item, create a non-ser InventoryItem with availableToPromise = -quantityNotIssued -->
-                    <clear-field field="createInvItemInMap"/>
-                    <clear-field field="createInvItemOutMap"/>
-                    <set field="createInvItemInMap.productId" from-field="productId"/>
-                    <set field="createInvItemInMap.facilityId" from-field="workEffort.facilityId"/>
-                    <set field="createInvItemInMap.inventoryItemTypeId" value="NON_SERIAL_INV_ITEM"/>
-                    <call-service service-name="createInventoryItem" in-map-name="createInvItemInMap">
-                        <result-to-field result-name="inventoryItemId" field="createInvItemOutMap.inventoryItemId"/>
-                    </call-service>
-
-                    <!-- create ItemIssuance record -->
-                    <set field="issuanceCreateMap.workEffortId" from-field="parameters.workEffortId"/>
-                    <set field="issuanceCreateMap.inventoryItemId" from-field="createInvItemOutMap.inventoryItemId"/>
-                    <set field="issuanceCreateMap.quantity" from-field="parameters.quantityNotIssued"/>
-                    <call-service service-name="assignInventoryToWorkEffort" in-map-name="issuanceCreateMap">
-                    </call-service>
-
-                    <!-- also create a detail record with the quantities -->
-                    <set field="createDetailMap.inventoryItemId" from-field="createInvItemOutMap.inventoryItemId"/>
-                    <set field="createDetailMap.workEffortId" from-field="parameters.workEffortId"/>
-                    <calculate field="createDetailMap.availableToPromiseDiff">
-                        <calcop operator="negative" field="parameters.quantityNotIssued"/>
-                    </calculate>
-                    <calculate field="createDetailMap.quantityOnHandDiff">
-                        <calcop operator="negative" field="parameters.quantityNotIssued"/>
-                    </calculate>
-                    <set field="createDetailMap.reasonEnumId" from-field="parameters.reasonEnumId"/>
-                    <set field="createDetailMap.description" from-field="parameters.description"/>
-                    <call-service service-name="createInventoryItemDetail" in-map-name="createDetailMap"/>
-                    <clear-field field="createDetailMap"/>
-                </else>
-                </if-not-empty>
-                <calculate field="parameters.quantityNotIssued" ><number value="0"/></calculate>
-            </if-compare>
-            <if-not-empty field="workEffortGoodStandard">
-                <entity-and entity-name="WorkEffortAndInventoryAssign" list="issuances">
-                    <field-map field-name="workEffortId" from-field="workEffortGoodStandard.workEffortId"/>
-                    <field-map field-name="productId" from-field="workEffortGoodStandard.productId"/>
-                </entity-and>
-                <iterate list="issuances" entry="issuance">
-                    <calculate field="totalIssuance">
-                        <calcop operator="add">
-                            <calcop operator="get" field="issuance.quantity"/>
-                            <calcop operator="get" field="totalIssuance"/>
-                        </calcop>
-                    </calculate>
-                </iterate>
-                <if-compare-field field="workEffortGoodStandard.estimatedQuantity" to-field="totalIssuance" operator="less-equals" type="BigDecimal">
-                    <set value="WEGS_COMPLETED" field="workEffortGoodStandard.statusId"/>
-                    <store-value value-field="workEffortGoodStandard"/>
-                </if-compare-field>
-            </if-not-empty>
-        </if-not-empty>
-    </simple-method>
-    <simple-method method-name="issueProductionRunTaskComponentInline" short-description="Does a issuance for one InventoryItem, meant to be called in-line">
-        <!-- only do something with this inventoryItem if there is more inventory to issue -->
-        <if-compare field="parameters.quantityNotIssued" operator="greater" value="0" type="BigDecimal">
-            <if-compare value="SERIALIZED_INV_ITEM" operator="equals" field="inventoryItem.inventoryItemTypeId">
-                <if-compare value="INV_AVAILABLE" operator="equals" field="inventoryItem.statusId">
-                    <!-- change status on inventoryItem -->
-                    <set value="INV_DELIVERED" field="inventoryItem.statusId"/>
-                    <store-value value-field="inventoryItem"/>
-
-                    <!-- create ItemIssuance record -->
-                    <set from-field="parameters.workEffortId" field="issuanceCreateMap.workEffortId"/>
-                    <set from-field="inventoryItem.inventoryItemId" field="issuanceCreateMap.inventoryItemId"/>
-                    <calculate field="issuanceCreateMap.quantity" ><number value="1"/></calculate>
-                    <call-service service-name="assignInventoryToWorkEffort" in-map-name="issuanceCreateMap"/>
-                    <clear-field field="issuanceCreateMap"/>
-
-                    <calculate field="parameters.quantityNotIssued">
-                        <calcop operator="subtract" field="parameters.quantityNotIssued"><number value="1.0"/></calcop>
-                    </calculate>
-                </if-compare>
-            </if-compare>
-            <if>
-                <condition>
-                    <and>
-                        <or>
-                            <if-empty field="inventoryItem.statusId"/>
-                            <if-compare field="inventoryItem.statusId" operator="equals" value="INV_AVAILABLE"/>
-                        </or>
-                        <if-compare field="inventoryItem.inventoryItemTypeId" operator="equals" value="NON_SERIAL_INV_ITEM"/>
-                    </and>
-                </condition>
-                <then>
-                    <if-compare field="parameters.useReservedItems" operator="equals" value="Y">
-                        <set field="inventoryItemQuantity" from-field="inventoryItem.quantityOnHandTotal"/>
-                    <else>
-                        <set field="inventoryItemQuantity" from-field="inventoryItem.availableToPromiseTotal"/>
-                    </else>
-                    </if-compare>
-
-                    <if-not-empty field="inventoryItemQuantity">
-                        <!-- reduce atp on inventoryItem if availableToPromise greater than 0, if not the code at the end of this method will handle it -->
-                        <if-compare field="inventoryItemQuantity" operator="greater" value="0" type="BigDecimal">
-                            <if-compare-field field="parameters.quantityNotIssued" to-field="inventoryItemQuantity" operator="greater" type="BigDecimal">
-                                <set from-field="inventoryItemQuantity" field="parameters.deductAmount"/>
-                            <else>
-                                <set from-field="parameters.quantityNotIssued" field="parameters.deductAmount"/>
-                            </else>
-                            </if-compare-field>
-
-                            <!-- create WorkEffortInventoryAssign record -->
-                            <set from-field="parameters.workEffortId" field="issuanceCreateMap.workEffortId"/>
-                            <set from-field="inventoryItem.inventoryItemId" field="issuanceCreateMap.inventoryItemId"/>
-                            <set from-field="parameters.deductAmount" field="issuanceCreateMap.quantity"/>
-                            <call-service service-name="assignInventoryToWorkEffort" in-map-name="issuanceCreateMap">
-                            </call-service>
-
-                            <!-- instead of updating InventoryItem, add an InventoryItemDetail -->
-                            <set from-field="inventoryItem.inventoryItemId" field="createDetailMap.inventoryItemId"/>
-                            <set from-field="parameters.workEffortId" field="createDetailMap.workEffortId"/>
-                            <!-- update availableToPromiseDiff AND quantityOnHandDiff since this is an issuance -->
-                            <calculate field="createDetailMap.availableToPromiseDiff">
-                                <calcop operator="negative" field="parameters.deductAmount"/>
-                            </calculate>
-                            <calculate field="createDetailMap.quantityOnHandDiff">
-                                <calcop operator="negative" field="parameters.deductAmount"/>
-                            </calculate>
-                            <set field="createDetailMap.reasonEnumId" from-field="parameters.reasonEnumId"/>
-                            <set field="createDetailMap.description" from-field="parameters.description"/>
-                            <call-service service-name="createInventoryItemDetail" in-map-name="createDetailMap"/>
-                            <clear-field field="createDetailMap"/>
-
-                            <calculate field="parameters.quantityNotIssued" >
-                                <calcop operator="subtract" field="parameters.quantityNotIssued">
-                                    <calcop operator="get" field="parameters.deductAmount"/>
-                                </calcop>
-                            </calculate>
-                            <set field="balanceInventoryItemsInMap.inventoryItemId" from-field="inventoryItem.inventoryItemId"/>
-                            <call-service service-name="balanceInventoryItems" in-map-name="balanceInventoryItemsInMap"/>
-
-                            <clear-field field="issuanceCreateMap"/>
-                        </if-compare>
-                    </if-not-empty>
-
-                    <!-- keep track of the last non-serialized inventory item for use if inventory is not sufficient for amount already issued -->
-                    <!-- use env variable named lastNonSerInventoryItem -->
-                    <set from-field="inventoryItem" field="lastNonSerInventoryItem"/>
-                </then>
-            </if>
-        </if-compare>
-    </simple-method>
-
-    <simple-method method-name="issueInventoryItemToWorkEffort" short-description="Issue one InventoryItem to a WorkEffort">
-        <set field="inventoryItem" from-field="parameters.inventoryItem"/>
-        <field-to-result field="inventoryItem.productId" result-name="finishedProductId"/>
-        <if-compare value="SERIALIZED_INV_ITEM" operator="equals" field="inventoryItem.inventoryItemTypeId">
-            <if-compare value="INV_AVAILABLE" operator="equals" field="inventoryItem.statusId">
-                <!-- change status on inventoryItem -->
-                <set field="inventoryItem.statusId" value="INV_DELIVERED"/>
-                <call-service service-name="updateInventoryItem" in-map-name="updateContext"/>
-
-                <!-- create ItemIssuance record -->
-                <set field="issuanceCreateMap.workEffortId" from-field="parameters.workEffortId"/>
-                <set field="issuanceCreateMap.inventoryItemId" from-field="inventoryItem.inventoryItemId"/>
-                <calculate field="issuanceCreateMap.quantity" ><number value="1"/></calculate>
-                <call-service service-name="assignInventoryToWorkEffort" in-map-name="issuanceCreateMap"/>
-                <field-to-result field="issuanceCreateMap.quantity" result-name="quantityIssued"/>
-            </if-compare>
-        </if-compare>
-        <if>
-            <condition>
-                <and>
-                    <if-compare field="inventoryItem.inventoryItemTypeId" operator="equals" value="NON_SERIAL_INV_ITEM"/>
-                    <not><if-empty field="inventoryItem.availableToPromiseTotal"/></not>
-                    <if-compare field="inventoryItem.availableToPromiseTotal" operator="greater" value="0" type="BigDecimal"/>
-                </and>
-            </condition>
-            <then>
-                <if>
-                    <condition>
-                        <or>
-                            <if-empty field="parameters.quantity"/>
-                            <if-compare-field field="parameters.quantity" to-field="inventoryItem.availableToPromiseTotal" operator="greater" type="BigDecimal"/>
-                        </or>
-                    </condition>
-                    <then>
-                        <set from-field="inventoryItem.availableToPromiseTotal" field="deductAmount"/>
-                    </then>
-                    <else>
-                        <set from-field="parameters.quantity" field="deductAmount"/>
-                    </else>
-                </if>
-                <!-- create WorkEffortInventoryAssign record -->
-                <set from-field="parameters.workEffortId" field="issuanceCreateMap.workEffortId"/>
-                <set from-field="inventoryItem.inventoryItemId" field="issuanceCreateMap.inventoryItemId"/>
-                <set from-field="deductAmount" field="issuanceCreateMap.quantity"/>
-                <call-service service-name="assignInventoryToWorkEffort" in-map-name="issuanceCreateMap">
-                </call-service>
-
-                <!-- instead of updating InventoryItem, add an InventoryItemDetail -->
-                <set from-field="inventoryItem.inventoryItemId" field="createDetailMap.inventoryItemId"/>
-                <set from-field="parameters.workEffortId" field="createDetailMap.workEffortId"/>
-                <!-- update availableToPromiseDiff AND quantityOnHandDiff since this is an issuance -->
-                <calculate field="createDetailMap.availableToPromiseDiff">
-                    <calcop operator="negative" field="deductAmount"/>
-                </calculate>
-                <calculate field="createDetailMap.quantityOnHandDiff">
-                    <calcop operator="negative" field="deductAmount"/>
-                </calculate>
-                <call-service service-name="createInventoryItemDetail" in-map-name="createDetailMap"/>
-                <field-to-result field="deductAmount" result-name="quantityIssued"/>
-            </then>
-            <else>
-                <calculate field="deductAmount"><number value="0"/></calculate>
-                <field-to-result field="deductAmount" result-name="quantityIssued"/>
-            </else>
-        </if>
-    </simple-method>
-
-</simple-methods>
-
diff --git a/applications/manufacturing/servicedef/services_production_run.xml b/applications/manufacturing/servicedef/services_production_run.xml
index 3526091..b4d8c3b 100644
--- a/applications/manufacturing/servicedef/services_production_run.xml
+++ b/applications/manufacturing/servicedef/services_production_run.xml
@@ -38,8 +38,8 @@ under the License.
         <attribute name="productionRunId" type="String" mode="OUT" optional="false"/>
         <attribute name="estimatedCompletionDate" type="java.sql.Timestamp" mode="OUT" optional="true"/>
     </service>
-    <service name="createProductionRunPartyAssign" engine="simple"
-        location="component://manufacturing/minilang/jobshopmgt/ProductionRunServices.xml" invoke="createProductionRunPartyAssign" auth="false">
+    <service name="createProductionRunPartyAssign" engine="groovy"
+             location="component://manufacturing/groovyScripts/jobshopmgt/ProductionRunServices.groovy" invoke="createProductionRunPartyAssign" auth="false">
         <description>
             Associate a party to the production run
         </description>
@@ -50,8 +50,8 @@ under the License.
         <attribute name="fromDate" type="java.sql.Timestamp" mode="INOUT" optional="true"/>
         <attribute name="thruDate" type="Timestamp" mode="IN" optional="true"/>
     </service>
-    <service name="createProductionRunAssoc" engine="simple"
-                location="component://manufacturing/minilang/jobshopmgt/ProductionRunServices.xml" invoke="createProductionRunAssoc" auth="false">
+    <service name="createProductionRunAssoc" engine="groovy"
+             location="component://manufacturing/groovyScripts/jobshopmgt/ProductionRunServices.groovy" invoke="createProductionRunAssoc" auth="false">
         <description>
             Associate the production run to another production run
         </description>
@@ -193,8 +193,8 @@ under the License.
         <attribute name="productionRunId" type="String" mode="IN" optional="false"/>
         <attribute name="productId" type="String" mode="IN" optional="false"/>
     </service>
-    <service name="issueProductionRunTask" engine="simple"
-                location="component://manufacturing/minilang/jobshopmgt/ProductionRunServices.xml" invoke="issueProductionRunTask" auth="false">
+    <service name="issueProductionRunTask" engine="groovy"
+             location="component://manufacturing/groovyScripts/jobshopmgt/ProductionRunServices.groovy" invoke="issueProductionRunTask" auth="false">
         <description>
             Issues the Inventory for a Production Run Task.
             Note that this skips the normal inventory reservation process.
@@ -204,8 +204,8 @@ under the License.
         <attribute name="failIfItemsAreNotAvailable" type="String" mode="IN" optional="true"/>
         <attribute name="failIfItemsAreNotOnHand" type="String" mode="IN" optional="true"/>
     </service>
-    <service name="issueProductionRunTaskComponent" engine="simple"
-                location="component://manufacturing/minilang/jobshopmgt/ProductionRunServices.xml" invoke="issueProductionRunTaskComponent" auth="false">
+    <service name="issueProductionRunTaskComponent" engine="groovy"
+             location="component://manufacturing/groovyScripts/jobshopmgt/ProductionRunServices.groovy" invoke="issueProductionRunTaskComponent" auth="false">
         <description>
             Issues the Inventory for a Production Run Task Component. For more info see the issueProductionRunTask service.
             If fromDate is passed, then the WorkEffortGoodStandard record with pk composed of (workEffortId|productId|fromDate)
@@ -231,8 +231,8 @@ under the License.
         <attribute name="reasonEnumId" type="String" mode="IN" optional="true"/>
         <attribute name="description" type="String" mode="IN" optional="true"/>
     </service>
-    <service name="issueInventoryItemToWorkEffort" engine="simple"
-                location="component://manufacturing/minilang/jobshopmgt/ProductionRunServices.xml" invoke="issueInventoryItemToWorkEffort" auth="false">
+    <service name="issueInventoryItemToWorkEffort" engine="groovy"
+             location="component://manufacturing/groovyScripts/jobshopmgt/ProductionRunServices.groovy" invoke="issueInventoryItemToWorkEffort" auth="false">
         <description>
             Issue one InventoryItem (or part of it) to a WorkEffort.
             Note that this skips the normal inventory reservation process.