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

mleila 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 014056918f Improved: Convert OrderServices.xml mini-lang to groovyDSL 
checkCreateStockRequirementQoh, checkCreateStockRequirementAtp and 
checkCreateProductRequirementForFacility (OFBIZ-9984)
014056918f is described below

commit 014056918f000d0d58b3fb48df99bca9042130b9
Author: MLeila <mle...@apache.org>
AuthorDate: Fri Oct 4 16:19:50 2024 +0200

    Improved: Convert OrderServices.xml mini-lang to groovyDSL
    checkCreateStockRequirementQoh, checkCreateStockRequirementAtp and
    checkCreateProductRequirementForFacility (OFBIZ-9984)
    
    Migration of the services and corresponding tests update to ensure
---
 .../order/minilang/order/OrderServices.xml         | 222 ---------------------
 .../order/servicedef/services_requirement.xml      |  12 +-
 .../order/OrderRequirementServicesScript.groovy    | 174 +++++++++++++++-
 .../order/order/test/OrderRequirementTests.groovy  |   9 +-
 applications/order/testdef/data/OrderTestData.xml  |  12 +-
 5 files changed, 193 insertions(+), 236 deletions(-)

diff --git a/applications/order/minilang/order/OrderServices.xml 
b/applications/order/minilang/order/OrderServices.xml
index f24b297dc9..1147b39bce 100644
--- a/applications/order/minilang/order/OrderServices.xml
+++ b/applications/order/minilang/order/OrderServices.xml
@@ -21,228 +21,6 @@ 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";>
 
-    <!-- order requirement methods -->
-    <simple-method method-name="getProductFacilityAndQuantities" 
short-description="finds ProductFacility and QOH, ATP inventory for an 
inventoryItem">
-        <!-- Get the ProductFacility for the minimum stock level -->
-        <entity-one entity-name="ProductFacility" 
value-field="productFacility">
-            <field-map field-name="productId" 
from-field="inventoryItem.productId"/>
-            <field-map field-name="facilityId" 
from-field="inventoryItem.facilityId"/>
-        </entity-one>
-
-        <!-- Get the product's total quantityOnHand in the facility -->
-        <set from-field="inventoryItem.productId" field="inputMap.productId"/>
-        <set from-field="inventoryItem.facilityId" 
field="inputMap.facilityId"/>
-        <call-service service-name="getInventoryAvailableByFacility" 
in-map-name="inputMap">
-           <result-to-field result-name="quantityOnHandTotal" 
field="quantityOnHandTotal"/>
-           <result-to-field result-name="availableToPromiseTotal" 
field="availableToPromiseTotal"/>
-        </call-service>
-        <clear-field field="inputMap"/>
-    </simple-method>
-
-    <simple-method method-name="getProductRequirementMethod" 
short-description="finds the requirement method for the product">
-        <if-not-empty field="parameters.orderId">
-            <entity-one entity-name="OrderHeader" auto-field-map="true" 
value-field="order"/>
-        </if-not-empty>
-        <entity-one entity-name="Product" auto-field-map="true" 
value-field="product"/>
-        <set from-field="product.requirementMethodEnumId" 
field="requirementMethodId"/>
-        <if-empty field="requirementMethodId">
-            <set field="isMarketingPkg" value="${groovy: 
org.apache.ofbiz.entity.util.EntityTypeUtil.hasParentType(delegator, 
'ProductType', 'productTypeId', product.productTypeId, 'parentTypeId', 
'MARKETING_PKG')}" type="Boolean"/>
-            <if>
-                <condition>
-                    <and>
-                        <if-compare field="isMarketingPkg" operator="equals" 
value="false" type="Boolean"/>
-                        <if-compare field="product.productTypeId" 
operator="not-equals" value="DIGITAL_GOOD"/>
-                        <not><if-empty field="order"/></not>
-                    </and>
-                </condition>
-                <then>
-                    <entity-one entity-name="ProductStore" 
value-field="productStore">
-                        <field-map field-name="productStoreId" 
from-field="order.productStoreId"/>
-                    </entity-one>
-                    <set from-field="productStore.requirementMethodEnumId" 
field="requirementMethodId"/>
-                </then>
-            </if>
-        </if-empty>
-    </simple-method>
-
-    <simple-method method-name="checkCreateStockRequirementQoh" 
short-description="Create a Requirement if QOH goes under the minimum stock 
level">
-        <check-permission permission="ORDERMGR" action="_CREATE">
-            <fail-property resource="OrderErrorUiLabels" 
property="OrderSecurityErrorToRunCheckCreateStockRequirement"/>
-        </check-permission>
-        <check-errors/>
-
-        <!-- If the service is triggered by the updateItemIssuance service, 
get the ItemIssuance by the passed itemIssuanceId -->
-        <if-not-empty field="parameters.itemIssuanceId">
-            <entity-one entity-name="ItemIssuance" auto-field-map="true" 
value-field="itemIssuance"/>
-            <entity-one entity-name="InventoryItem" 
value-field="inventoryItem">
-                <field-map field-name="inventoryItemId" 
from-field="itemIssuance.inventoryItemId"/>
-            </entity-one>
-        <else>
-            <entity-one entity-name="InventoryItem" auto-field-map="true" 
value-field="inventoryItem"/>
-        </else>
-        </if-not-empty>
-
-        <set from-field="inventoryItem.productId" 
field="parameters.productId"/>
-        <call-simple-method method-name="getProductRequirementMethod"/>
-
-        <if-compare field="requirementMethodId" operator="equals" 
value="PRODRQM_STOCK">
-            <!-- get QOH, ATP quantities and find ProductFacility which has 
the minimum stock -->
-            <call-simple-method method-name="getProductFacilityAndQuantities"/>
-
-            <if-not-empty field="productFacility.minimumStock">
-                <!-- No requirements are created if we are already under stock 
-->
-                <if-compare-field field="quantityOnHandTotal" 
to-field="productFacility.minimumStock" operator="greater-equals" 
type="BigDecimal">
-                    <calculate field="newQuantityOnHand">
-                        <calcop operator="subtract" 
field="quantityOnHandTotal">
-                            <calcop operator="get" 
field="parameters.quantity"/>
-                        </calcop>
-                    </calculate>
-                    <!-- If this new issuance will cause the 
quantityOnHandTotal to go below the minimumStock, create a new requirement -->
-                    <if-compare-field field="newQuantityOnHand" 
to-field="productFacility.minimumStock" operator="less" type="BigDecimal">
-                        <set from-field="inventoryItem.productId" 
field="inputMap.productId"/>
-                        <set from-field="productFacility.facilityId" 
field="inputMap.facilityId"/>
-                        <if-not-empty field="productFacility.reorderQuantity">
-                            <set from-field="productFacility.reorderQuantity" 
field="inputMap.quantity"/>
-                        <else>
-                            <set from-field="parameters.quantity" 
field="inputMap.quantity"/>
-                        </else>
-                        </if-not-empty>
-                        <set value="PRODUCT_REQUIREMENT" 
field="inputMap.requirementTypeId"/>
-                        <call-service service-name="createRequirement" 
in-map-name="inputMap">
-                            <result-to-field result-name="requirementId" 
field="parameters.requirementId"/>
-                        </call-service>
-                        <field-to-result field="parameters.requirementId" 
result-name="requirementId"/>
-                    </if-compare-field>
-                </if-compare-field>
-            </if-not-empty>
-        </if-compare>
-    </simple-method>
-
-    <simple-method method-name="checkCreateStockRequirementAtp" 
short-description="Create a Requirement if ATP goes under the minimum stock 
level">
-        <check-permission permission="ORDERMGR" action="_CREATE">
-            <fail-property resource="OrderErrorUiLabels" 
property="OrderSecurityErrorToRunCheckCreateStockRequirement"/>
-        </check-permission>
-        <check-errors/>
-
-        <!-- assumes that inventoryItemId is one of the parameters and get the 
inventory item of the reservation -->
-        <entity-one entity-name="InventoryItem" value-field="inventoryItem" 
auto-field-map="true"/>
-
-        <!-- find the requirement method for this product -->
-        <set from-field="inventoryItem.productId" 
field="parameters.productId"/>
-        <call-simple-method method-name="getProductRequirementMethod"/>
-
-        <if-compare field="requirementMethodId" operator="equals" 
value="PRODRQM_STOCK_ATP">
-            <!-- get QOH, ATP quantities and find ProductFacility which has 
the minimum stock -->
-            <call-simple-method method-name="getProductFacilityAndQuantities"/>
-
-            <if-not-empty field="productFacility.minimumStock">
-                <!-- No requirements are created if we are not under stock -->
-                <!-- this service is supposed to be called after inventory is 
reserved, so inventory should have been updated already -->
-                <if-compare-field field="availableToPromiseTotal" 
to-field="productFacility.minimumStock" operator="less" type="BigDecimal">
-                    <calculate field="oldAvailableToPromise">
-                        <calcop operator="add" field="availableToPromiseTotal">
-                            <calcop operator="get" 
field="parameters.quantity"/>
-                        </calcop>
-                    </calculate>
-                    <!-- If before this reservation the 
availableToPromiseTotal was over minimumStock, create a new requirement -->
-                    <if-compare-field field="oldAvailableToPromise" 
to-field="productFacility.minimumStock" operator="greater-equals" 
type="BigDecimal">
-                        <set from-field="inventoryItem.productId" 
field="inputMap.productId"/>
-                        <set from-field="productFacility.facilityId" 
field="inputMap.facilityId"/>
-                        <if-not-empty field="productFacility.reorderQuantity">
-                            <set from-field="productFacility.reorderQuantity" 
field="inputMap.quantity"/>
-                        <else>
-                            <set from-field="parameters.quantity" 
field="inputMap.quantity"/>
-                        </else>
-                        </if-not-empty>
-                        <set value="PRODUCT_REQUIREMENT" 
field="inputMap.requirementTypeId"/>
-                        <call-service service-name="createRequirement" 
in-map-name="inputMap">
-                            <result-to-field result-name="requirementId" 
field="parameters.requirementId"/>
-                        </call-service>
-                        <field-to-result field="parameters.requirementId" 
result-name="requirementId"/>
-                    </if-compare-field>
-                </if-compare-field>
-            </if-not-empty>
-        </if-compare>
-    </simple-method>
-
-    <simple-method method-name="checkCreateProductRequirementForFacility" 
short-description="Create Requirements for all the products in a facility with 
QOH under the minimum stock level">
-        <check-permission permission="ORDERMGR" action="_CREATE">
-            <fail-property resource="OrderErrorUiLabels" 
property="OrderSecurityErrorToRunCheckCreateStockRequirement"/>
-        </check-permission>
-        <check-errors/>
-
-        <entity-and entity-name="ProductFacility" list="products">
-            <field-map field-name="facilityId" 
from-field="parameters.facilityId"/>
-        </entity-and>
-
-        <iterate list="products" entry="productFacility">
-            <set from-field="productFacility.productId" 
field="parameters.productId"/>
-            <clear-field field="requirementMethodId"/>
-            <call-simple-method method-name="getProductRequirementMethod"/>
-            <if-empty field="requirementMethodId">
-                <set field="requirementMethodId" 
from-field="parameters.defaultRequirementMethodId"/>
-            </if-empty>
-            <if>
-                <condition>
-                    <or>
-                        <if-compare field="requirementMethodId" 
operator="equals" value="PRODRQM_STOCK"/>
-                        <if-compare field="requirementMethodId" 
operator="equals" value="PRODRQM_STOCK_ATP"/>
-                    </or>
-                </condition>
-                <then>
-
-                    <!-- get QOH, ATP and find ProductFacility which has the 
minimum stock -->
-
-                    <if-not-empty field="productFacility.minimumStock">
-                        <!-- Get the product's total quantityOnHand in the 
facility -->
-                        <clear-field field="inputMap"/>
-                        <set from-field="productFacility.productId" 
field="inputMap.productId"/>
-                        <set from-field="productFacility.facilityId" 
field="inputMap.facilityId"/>
-                        <call-service 
service-name="getInventoryAvailableByFacility" in-map-name="inputMap">
-                           <result-to-field result-name="quantityOnHandTotal" 
field="quantityOnHandTotal"/>
-                           <result-to-field 
result-name="availableToPromiseTotal" field="availableToPromiseTotal"/>
-                        </call-service>
-
-                        <if-compare field="requirementMethodId" 
operator="equals" value="PRODRQM_STOCK">
-                            <set from-field="quantityOnHandTotal" 
field="currentQuantity"/>
-                        <else>
-                            <set from-field="availableToPromiseTotal" 
field="currentQuantity"/>
-                        </else>
-                        </if-compare>
-
-                        <!-- No requirements are created if we are already 
under stock -->
-                        <if-compare-field field="currentQuantity" 
to-field="productFacility.minimumStock" operator="less" type="BigDecimal">
-                            <clear-field field="inputMap"/>
-                            <set from-field="productFacility.productId" 
field="inputMap.productId"/>
-                            <if-not-empty 
field="productFacility.reorderQuantity">
-                                <set 
from-field="productFacility.reorderQuantity" field="inputMap.quantity" 
type="BigDecimal"/>
-                            <else>
-                                <set value="0" field="inputMap.quantity" 
type="BigDecimal"/>
-                            </else>
-                            </if-not-empty>
-
-                            <calculate field="quantityShortfall">
-                                <calcop operator="subtract" 
field="productFacility.minimumStock">
-                                    <calcop operator="get" 
field="currentQuantity"/>
-                                </calcop>
-                            </calculate>
-                            <if-compare-field field="inputMap.quantity" 
to-field="quantityShortfall" operator="less" type="BigDecimal">
-                                <set from-field="quantityShortfall" 
field="inputMap.quantity" type="BigDecimal"/>
-                            </if-compare-field>
-
-                            <set value="PRODUCT_REQUIREMENT" 
field="inputMap.requirementTypeId"/>
-                            <set from-field="parameters.facilityId" 
field="inputMap.facilityId"/>
-                            <call-service service-name="createRequirement" 
in-map-name="inputMap">
-                                <result-to-field result-name="requirementId" 
field="requirementId"/>
-                            </call-service>
-                            <log level="info" message="Requirement creted with 
id [${requirementId}] for product with id [${productFacility.productId}]."/>
-                        </if-compare-field>
-                    </if-not-empty>
-                </then>
-            </if>
-        </iterate>
-    </simple-method>
-
     <simple-method method-name="orderSequence_enforced" 
short-description="Enforced Sequence (no gaps, per organization)">
         <log level="info" message="In getNextOrderId sequence enum Enforced"/> 
         <set field="partyAcctgPreference" 
from-field="parameters.partyAcctgPreference"/>
diff --git a/applications/order/servicedef/services_requirement.xml 
b/applications/order/servicedef/services_requirement.xml
index 58a100c5a9..e5706842d5 100644
--- a/applications/order/servicedef/services_requirement.xml
+++ b/applications/order/servicedef/services_requirement.xml
@@ -129,8 +129,8 @@ under the License.
         <attribute name="quantity" type="BigDecimal" mode="IN" 
optional="true"/>
         <attribute name="requirementId" type="String" mode="OUT" 
optional="true"/>
     </service>
-    <service name="checkCreateStockRequirementQoh" engine="simple" auth="true" 
default-entity-name="ItemIssuance"
-            location="component://order/minilang/order/OrderServices.xml" 
invoke="checkCreateStockRequirementQoh">
+    <service name="checkCreateStockRequirementQoh" engine="groovy" auth="true" 
default-entity-name="ItemIssuance"
+            
location="component://order/src/main/groovy/org/apache/ofbiz/order/order/OrderRequirementServicesScript.groovy"
 invoke="checkCreateStockRequirementQoh">
         <description>Create a Product Requirement based on QOH 
inventory</description>
         <auto-attributes include="pk" mode="IN" optional="true"/>
         <auto-attributes include="nonpk" mode="IN" optional="true">
@@ -138,8 +138,8 @@ under the License.
         </auto-attributes>
         <attribute name="requirementId" type="String" mode="OUT" 
optional="true"/>
     </service>
-    <service name="checkCreateStockRequirementAtp" engine="simple" auth="true"
-            location="component://order/minilang/order/OrderServices.xml" 
invoke="checkCreateStockRequirementAtp">
+    <service name="checkCreateStockRequirementAtp" engine="groovy" auth="true"
+            
location="component://order/src/main/groovy/org/apache/ofbiz/order/order/OrderRequirementServicesScript.groovy"
 invoke="checkCreateStockRequirementAtp">
         <description>Create a Product Requirement based on ATP 
inventory</description>
         <attribute name="orderId" type="String" mode="IN" optional="false"/>
         <attribute name="shipGroupSeqId" type="String" mode="IN" 
optional="false"/>
@@ -150,8 +150,8 @@ under the License.
         <attribute name="requirementId" type="String" mode="OUT" 
optional="true"/>
     </service>
 
-    <service name="checkCreateProductRequirementForFacility" engine="simple" 
auth="true"
-            location="component://order/minilang/order/OrderServices.xml" 
invoke="checkCreateProductRequirementForFacility">
+    <service name="checkCreateProductRequirementForFacility" engine="groovy" 
auth="true"
+            
location="component://order/src/main/groovy/org/apache/ofbiz/order/order/OrderRequirementServicesScript.groovy"
 invoke="checkCreateProductRequirementForFacility">
         <description>Create Requirements for all the products in a facility 
with QOH under the minimum stock level</description>
         <attribute name="facilityId" type="String" mode="IN" optional="false"/>
         <attribute name="defaultRequirementMethodId" type="String" mode="IN" 
optional="true"/>
diff --git 
a/applications/order/src/main/groovy/org/apache/ofbiz/order/order/OrderRequirementServicesScript.groovy
 
b/applications/order/src/main/groovy/org/apache/ofbiz/order/order/OrderRequirementServicesScript.groovy
index 3a74c55ff6..c546595706 100644
--- 
a/applications/order/src/main/groovy/org/apache/ofbiz/order/order/OrderRequirementServicesScript.groovy
+++ 
b/applications/order/src/main/groovy/org/apache/ofbiz/order/order/OrderRequirementServicesScript.groovy
@@ -18,7 +18,11 @@
 */
 package org.apache.ofbiz.order.order
 
+import org.apache.ofbiz.base.util.Debug
+import org.apache.ofbiz.base.util.UtilProperties
 import org.apache.ofbiz.entity.GenericValue
+import org.apache.ofbiz.entity.util.EntityTypeUtil
+import org.apache.ofbiz.service.ServiceUtil
 
 /*
  * Create OrderRequirementCommitment and Requirement for items with automatic 
requirement upon ordering
@@ -29,18 +33,18 @@ Map checkCreateOrderRequirement() {
     if (order.orderTypeId == 'SALES_ORDER' && reqMap.requirementMethodId == 
'PRODRQM_AUTO') {
         createRequirementAndCommitment()
     }
-    success()
+    return success()
 }
 
-Map getProductRequirementMethod() {
+Map getProductRequirementMethod(String productId) {
     GenericValue order = from('OrderHeader').where(parameters).queryOne()
-    GenericValue product = from('Product').where(parameters).queryOne()
-    String requirementMethodId = product ? product.requirementMethodId : ''
+    GenericValue product = from('Product').where(productId: 
productId).queryOne()
+    String requirementMethodId = product ? product.requirementMethodEnumId : ''
     if (!requirementMethodId && product) {
         boolean isMarketingPkg = EntityTypeUtil.hasParentType(delegator, 
'ProductType', 'productTypeId',
                                                               
product.productTypeId, 'parentTypeId', 'MARKETING_PKG')
         if (!isMarketingPkg && product.productTypeId != 'DIGITAL_GOOD' && 
order) {
-            productStore = from('ProductStore').where(productStoreId: 
order.productStoreId).queryOne()
+            GenericValue productStore = 
from('ProductStore').where(productStoreId: order.productStoreId).queryOne()
             requirementMethodId = productStore ? 
productStore.requirementMethodEnumId : ''
         }
     }
@@ -69,3 +73,163 @@ Map createRequirementAndCommitment() {
     return returnMap
 }
 
+/*
+Stock Requirement
+*/
+
+Map checkCreateStockRequirementQoh() {
+    checkCreateStockRequirement('PRODRQM_STOCK')
+}
+
+Map checkCreateStockRequirementAtp() {
+    checkCreateStockRequirement('PRODRQM_STOCK_ATP')
+}
+
+Map checkCreateStockRequirement(String methodId) {
+    if (!(security.hasEntityPermission("ORDERMGR", "_CREATE", 
parameters.userLogin))) {
+        return error(UtilProperties.getMessage("OrderErrorUiLabels", 
"OrderSecurityErrorToRunCheckCreateStockRequirement", parameters.locale))
+    }
+    Map resultMap = success()
+
+    String requirementMethodId
+    String productId
+    String facilityId
+    GenericValue inventoryItem
+    BigDecimal quantity = parameters.quantity?:0
+
+    // If the service is triggered by the updateItemIssuance service, get the 
ItemIssuance by the passed itemIssuanceId
+    Map inventoryItemAndRequirementMethodId = getStockRequirementMethod()
+    requirementMethodId = 
inventoryItemAndRequirementMethodId.requirementMethodId
+    inventoryItem = inventoryItemAndRequirementMethodId.inventoryItem
+    if (inventoryItem) {
+        productId = inventoryItem.productId
+        facilityId = inventoryItem.facilityId
+    }
+
+    if (requirementMethodId && methodId == requirementMethodId && 
inventoryItem) {
+        Map result = getProductFacilityAndQuantities(productId, facilityId)
+        boolean createRequirement = false
+        if (result.productFacility) {
+            GenericValue productFacility = result.productFacility
+            BigDecimal currentQuantity = 0
+            BigDecimal minimumStock = 
productFacility.getBigDecimal('minimumStock')
+            switch (methodId) {
+                case 'PRODRQM_STOCK': //qoh
+                    //No requirements are created if we are already under stock
+                    BigDecimal quantityOnHandTotal = result.quantityOnHandTotal
+                    if (minimumStock && quantityOnHandTotal >= minimumStock) {
+                        BigDecimal newQuantityOnHand = 
quantityOnHandTotal.subtract(quantity)
+                        /*If this new issuance will cause the 
quantityOnHandTotal to go below the minimumStock,
+                        create a new requirement */
+                        if (newQuantityOnHand < productFacility.minimumStock) {
+                            currentQuantity = quantityOnHandTotal
+                            createRequirement = true
+                        }
+                    }
+                    break
+                case 'PRODRQM_STOCK_ATP': // atp
+                    /* No requirements are created if we are not under stock
+                    this service is supposed to be called after inventory is 
reserved,
+                    so inventory should have been updated already */
+                    BigDecimal availableToPromiseTotal = 
result.availableToPromiseTotal
+                    if (minimumStock && availableToPromiseTotal < 
minimumStock) {
+                        BigDecimal oldAvailableToPromiseTotal = 
availableToPromiseTotal.add(quantity)
+                        /* If before this reservation the 
availableToPromiseTotal was over minimumStock,
+                        create a new requirement*/
+                        if (oldAvailableToPromiseTotal >= minimumStock) {
+                            currentQuantity = availableToPromiseTotal
+                            createRequirement = true
+                        }
+                    }
+                    break
+            }
+            if (createRequirement) {
+                BigDecimal reqQuantity = productFacility.reorderQuantity 
?:(quantity?:0)
+                Map inputMap = [
+                        productId        : productId,
+                        facilityId       : facilityId,
+                        quantity         : reqQuantity,
+                        requirementTypeId: 'PRODUCT_REQUIREMENT'
+                ]
+                result = run service: 'createRequirement', with: inputMap
+                if (ServiceUtil.isError(result)) {
+                    return result
+                }
+                resultMap.requirementId = result.requirementId
+            }
+        }
+    }
+    return resultMap
+}
+
+
+Map checkCreateProductRequirementForFacility() {
+    if (!(security.hasEntityPermission("ORDERMGR", "_CREATE", 
parameters.userLogin))) {
+        return error(UtilProperties.getMessage("OrderErrorUiLabels", 
"OrderSecurityErrorToRunCheckCreateStockRequirement", parameters.locale))
+    }
+    Map resultMap = success()
+
+    List<GenericValue> products = from('ProductFacility').where([facilityId: 
parameters.facilityId]).queryList()
+    for (GenericValue productFacility : products) {
+        String requirementMethodId = 
getProductRequirementMethod(productFacility.productId).requirementMethodId
+        if (!requirementMethodId) requirementMethodId = 
parameters.defaultRequirementMethodId
+        if (requirementMethodId) {
+            Map result = 
getProductFacilityAndQuantities(productFacility.productId, 
productFacility.facilityId)
+            boolean createRequirement = false
+            BigDecimal currentQuantity = 'PRODRQM_STOCK' == 
requirementMethodId?result.quantityOnHandTotal: result.availableToPromiseTotal
+            BigDecimal minimumStock = 
productFacility.getBigDecimal('minimumStock')
+            if (minimumStock && currentQuantity < minimumStock) {
+                BigDecimal reqQuantity = productFacility.reorderQuantity ?:0
+                BigDecimal quantityShortfall = 
minimumStock.subtract(currentQuantity)
+                if (reqQuantity < quantityShortfall) {
+                    reqQuantity = quantityShortfall
+                }
+                Map inputMap = [productId        : productFacility.productId,
+                                facilityId       : productFacility.facilityId,
+                                quantity         : reqQuantity,
+                                requirementTypeId: 'PRODUCT_REQUIREMENT'
+                    ]
+                result = run service: 'createRequirement', with: inputMap
+                if (ServiceUtil.isError(result)) {
+                    return result
+                }
+                Debug.logInfo("Requirement creted with id 
[${result.requirementId}] for product with id [${productFacility.productId}]", 
'OrderRequirementServiceScript')
+            }
+        }
+    }
+    return resultMap
+}
+
+private Map getStockRequirementMethod() {
+    GenericValue inventoryItem = null
+    if (parameters.itemIssuanceId) {
+         GenericValue itemIssuance = from('ItemIssuance')
+            .where([itemIssuanceId: parameters.itemIssuanceId])
+            .queryOne()
+        inventoryItem = itemIssuance? 
itemIssuance.getRelatedOne('InventoryItem', true): null
+    } else {
+        inventoryItem = from('InventoryItem').where(parameters).queryOne()
+    }
+    if (!inventoryItem) return [requirementMethodId: null, inventoryItem: null]
+    String requirementMethodId = 
getProductRequirementMethod(inventoryItem.productId).requirementMethodId
+    return [requirementMethodId: requirementMethodId, inventoryItem: 
inventoryItem]
+}
+
+private Map getProductFacilityAndQuantities(String productId, String 
facilityId) {
+    // Get the ProductFacility for the minimum stock level
+    GenericValue productFacility = from('ProductFacility')
+            .where([productId : productId,
+                    facilityId: facilityId])
+            .queryOne()
+    // Get the product's total quantityOnHand in the facility
+    Map resultMap = run service: 'getInventoryAvailableByFacility', with: [
+            *         : parameters,
+            productId : productId,
+            facilityId: facilityId
+    ]
+    if (ServiceUtil.isError(resultMap)) {
+        return resultMap
+    }
+    resultMap.productFacility = productFacility
+    return resultMap
+}
diff --git 
a/applications/order/src/main/groovy/org/apache/ofbiz/order/order/test/OrderRequirementTests.groovy
 
b/applications/order/src/main/groovy/org/apache/ofbiz/order/order/test/OrderRequirementTests.groovy
index 1c3c8d7e2e..e359ba0165 100644
--- 
a/applications/order/src/main/groovy/org/apache/ofbiz/order/order/test/OrderRequirementTests.groovy
+++ 
b/applications/order/src/main/groovy/org/apache/ofbiz/order/order/test/OrderRequirementTests.groovy
@@ -30,7 +30,7 @@ class OrderRequirementTests extends OFBizTestCase {
     void testCheckCreateProductRequirementForFacility() {
         Map serviceCtx = [
             facilityId: 'WebStoreWarehouse',
-            orderItemSeqId: '00001',
+            defaultRequirementMethodId: 'PRODRQM_STOCK',
             userLogin: userLogin
         ]
         Map serviceResult = 
dispatcher.runSync('checkCreateProductRequirementForFacility', serviceCtx)
@@ -40,6 +40,9 @@ class OrderRequirementTests extends OFBizTestCase {
         Map serviceCtx = [
             orderId: 'TEST_DEMO10090',
             orderItemSeqId: '00001',
+            shipGroupSeqId: '00001',
+            itemIssuanceId: '9006',
+            quantity: '300',
             userLogin: userLogin
         ]
         Map serviceResult = 
dispatcher.runSync('checkCreateStockRequirementQoh', serviceCtx)
@@ -47,9 +50,11 @@ class OrderRequirementTests extends OFBizTestCase {
     }
     void testCheckCreateStockRequirementAtp() {
         Map serviceCtx = [
-            orderId: 'TEST_DEMO10090',
+            orderId: 'TEST_DEMO10091',
             orderItemSeqId: '00001',
             shipGroupSeqId: '00001',
+            inventoryItemId: '9028',
+            quantity: '20',
             userLogin: userLogin
         ]
         Map serviceResult = 
dispatcher.runSync('checkCreateStockRequirementAtp', serviceCtx)
diff --git a/applications/order/testdef/data/OrderTestData.xml 
b/applications/order/testdef/data/OrderTestData.xml
index 8fe8bb4035..518c13dc01 100644
--- a/applications/order/testdef/data/OrderTestData.xml
+++ b/applications/order/testdef/data/OrderTestData.xml
@@ -26,13 +26,20 @@ under the License.
     <ProductCategory productCategoryId="CATALOG1_BEST_SELL" 
productCategoryTypeId="BEST_SELL_CATEGORY" categoryName="Demo Best Selling"/>
     <ProdCatalogCategory prodCatalogId="DemoCatalog" 
productCategoryId="CATALOG1_BEST_SELL" fromDate="2010-01-01 12:00:00.0" 
sequenceNum="1" prodCatalogCategoryTypeId="PCCT_BEST_SELL"/>
 
-    <ProductStore productStoreId="9000" storeName="OFBiz Ebay Store1-AU" 
companyName="Apache Ofbiz" title="Test OFBiz store1"/>
+    <ProductStore productStoreId="9000" storeName="OFBiz Ebay Store1-AU" 
companyName="Apache Ofbiz" title="Test OFBiz store1" 
requirementMethodEnumId="PRODRQM_STOCK"/>
     <ProductStoreEmailSetting productStoreId="9000" 
emailType="PRDS_ODR_CONFIRM" 
bodyScreenLocation="component://ecommerce/widget/EmailOrderScreens.xml#OrderConfirmNotice"
 
xslfoAttachScreenLocation="component://ecommerce/widget/EmailOrderScreens.xml#OrderConfirmNoticePdf"
 subject="OFBiz Demo - Order Confirmation #${orderId}" 
bccAddress="ofbizt...@example.com" fromAddress="ofbizt...@example.com"/>
 
+    <ProductStore productStoreId="9000ATP" storeName="OFBiz Ebay Store2-AU" 
companyName="Apache Ofbiz" title="Test OFBiz store2 atp" 
requirementMethodEnumId="PRODRQM_STOCK_ATP"/>
+    <Facility facilityId="WebStoreWarehouseAtp" facilityTypeId="WAREHOUSE" 
facilityName="Web Store Warehouse ATP" 
defaultInventoryItemTypeId="NON_SERIAL_INV_ITEM"/>
+    <ProductFacility productId="GZ-2644" facilityId="WebStoreWarehouseAtp" 
minimumStock="10" reorderQuantity="20" daysToShip="15"/>
+
     <!--Demo data for a sales order -->
     <OrderHeader orderId="TEST_DEMO10090" orderTypeId="SALES_ORDER" 
salesChannelEnumId="WEB_SALES_CHANNEL" orderDate="2008-04-23 16:49:27.392" 
entryDate="2008-04-23 16:49:27.392" priority="2" visitId="10002" 
statusId="ORDER_APPROVED" currencyUom="USD" productStoreId="9000" 
remainingSubTotal="38.40" grandTotal="50.85"  invoicePerShipment="Y" 
webSiteId="WebStore"/>
     <OrderItem orderId="TEST_DEMO10090" orderItemSeqId="00001" 
orderItemTypeId="PRODUCT_ORDER_ITEM" productId="GZ-2644" 
prodCatalogId="DemoCatalog" isPromo="N" quantity="2.0" selectedAmount="0.0" 
unitPrice="38.4" unitListPrice="48.0" isModifiedPrice="N" 
itemDescription="Round Gizmo" statusId="ITEM_APPROVED"/>
 
+    <OrderHeader orderId="TEST_DEMO10091" orderTypeId="SALES_ORDER" 
salesChannelEnumId="WEB_SALES_CHANNEL" orderDate="2008-04-23 16:49:27.392" 
entryDate="2008-04-23 16:49:27.392" priority="2" visitId="10002" 
statusId="ORDER_APPROVED" currencyUom="USD" productStoreId="9000ATP" 
remainingSubTotal="38.40" grandTotal="50.85"  invoicePerShipment="Y" 
webSiteId="WebStore"/>
+    <OrderItem orderId="TEST_DEMO10091" orderItemSeqId="00001" 
orderItemTypeId="PRODUCT_ORDER_ITEM" productId="GZ-2644" 
prodCatalogId="DemoCatalog" isPromo="N" quantity="2.0" selectedAmount="0.0" 
unitPrice="38.4" unitListPrice="48.0" isModifiedPrice="N" 
itemDescription="Round Gizmo" statusId="ITEM_APPROVED"/>
+
     <Party partyId="TestDemoCustomer" partyTypeId="PERSON" 
statusId="PARTY_ENABLED"/>
     <Person partyId="TestDemoCustomer" firstName="Test" lastName="Customer"/>
     <PartyRole partyId="TestDemoCustomer" roleTypeId="CUSTOMER"/>
@@ -54,6 +61,9 @@ under the License.
     <OrderRole orderId="TEST_DEMO10090" partyId="TestDemoCustomer" 
roleTypeId="SHIP_TO_CUSTOMER"/>
     <OrderContactMech orderId="TEST_DEMO10090" 
contactMechPurposeTypeId="ORDER_EMAIL" contactMechId="TestContactMech"/>
     <WorkEffort workEffortId="9000" workEffortTypeId="PROJECT" 
currentStatusId="_NA_" lastStatusUpdate="2007-12-14 15:07:52.901" 
scopeEnumId="WES_PRIVATE" workEffortName="Demo Project1 Cust1" 
revisionNumber="1"/>
+    <ItemIssuance itemIssuanceId="9006" orderId="TEST_DEMO10090" 
orderItemSeqId="00001" shipGroupSeqId="00001" inventoryItemId="9001" 
quantity="2.000000"/>
+    <InventoryItem facilityId="WebStoreWarehouseAtp" inventoryItemId="9028" 
inventoryItemTypeId="NON_SERIAL_INV_ITEM" productId="GZ-2644" 
ownerPartyId="Company" currencyUomId="USD" unitCost="2.5"/>
+    <InventoryItemDetail inventoryItemId="9028" 
inventoryItemDetailSeqId="0001" effectiveDate="2001-05-13 12:00:00.0" 
availableToPromiseDiff="5" quantityOnHandDiff="5" accountingQuantityDiff="5"/>
     <Requirement requirementId="1000" 
requirementTypeId="CUSTOMER_REQUIREMENT"/>
     <ReturnHeader returnId="1009" statusId="RETURN_RECEIVED" 
returnHeaderTypeId="CUSTOMER_RETURN"/>
     <ReturnItem returnId="1009" returnItemSeqId="00001" 
returnReasonId="RTN_NOT_WANT" returnTypeId="RTN_REFUND" 
returnItemTypeId="RET_FPROD_ITEM" returnQuantity="1.000000"/>


Reply via email to