Skip to content

Commit

Permalink
Improved: Convert OrderServices.xml mini-lang to groovyDSL
Browse files Browse the repository at this point in the history
checkCreateStockRequirementQoh, checkCreateStockRequirementAtp and
checkCreateProductRequirementForFacility (OFBIZ-9984)

Migration of the services and corresponding tests update to ensure
  • Loading branch information
MkLeila committed Oct 4, 2024
1 parent ad84551 commit 0140569
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 236 deletions.
222 changes: 0 additions & 222 deletions applications/order/minilang/order/OrderServices.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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"/>
Expand Down
12 changes: 6 additions & 6 deletions applications/order/servicedef/services_requirement.xml
Original file line number Diff line number Diff line change
Expand Up @@ -129,17 +129,17 @@ 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">
<exclude field-name="issuedDateTime"/>
</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"/>
Expand All @@ -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"/>
Expand Down
Loading

0 comments on commit 0140569

Please sign in to comment.