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 <[email protected]>
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="[email protected]" fromAddress="[email protected]"/>
+ <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"/>