You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by ad...@apache.org on 2008/12/05 16:35:12 UTC
svn commit: r723764 - in /ofbiz/trunk/applications/product:
entitydef/entitymodel.xml
script/org/ofbiz/product/inventory/InventoryReserveServices.xml
script/org/ofbiz/product/inventory/InventoryServices.xml
Author: adrianc
Date: Fri Dec 5 07:35:12 2008
New Revision: 723764
URL: http://svn.apache.org/viewvc?rev=723764&view=rev
Log:
BalanceInventoryItems performance improvement. Inventory receipts or returns in an installation that has thousands of backorders was running unacceptably slow. This commit fixes that.
Modified:
ofbiz/trunk/applications/product/entitydef/entitymodel.xml
ofbiz/trunk/applications/product/script/org/ofbiz/product/inventory/InventoryReserveServices.xml
ofbiz/trunk/applications/product/script/org/ofbiz/product/inventory/InventoryServices.xml
Modified: ofbiz/trunk/applications/product/entitydef/entitymodel.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/entitydef/entitymodel.xml?rev=723764&r1=723763&r2=723764&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/entitydef/entitymodel.xml (original)
+++ ofbiz/trunk/applications/product/entitydef/entitymodel.xml Fri Dec 5 07:35:12 2008
@@ -1606,6 +1606,29 @@
<!-- org.ofbiz.product.inventory -->
<!-- ========================================================= -->
+ <view-entity entity-name="BalanceInventoryItemsView"
+ package-name="org.ofbiz.product.inventory"
+ title="Balance Inventory Items View Entity">
+ <member-entity entity-alias="INV" entity-name="InventoryItem"/>
+ <member-entity entity-alias="RES" entity-name="OrderItemShipGrpInvRes"/>
+ <alias entity-alias="INV" name="inventoryItemId"/>
+ <alias entity-alias="INV" name="productId"/>
+ <alias entity-alias="INV" name="facilityId"/>
+ <alias entity-alias="INV" name="inventoryItemTypeId"/>
+ <alias entity-alias="INV" name="availableToPromiseTotal"/>
+ <alias entity-alias="INV" name="quantityOnHandTotal"/>
+ <alias entity-alias="RES" name="orderId"/>
+ <alias entity-alias="RES" name="shipGroupSeqId"/>
+ <alias entity-alias="RES" name="orderItemSeqId"/>
+ <alias entity-alias="RES" name="quantity"/>
+ <alias entity-alias="RES" name="quantityNotAvailable"/>
+ <alias entity-alias="RES" name="reserveOrderEnumId"/>
+ <alias entity-alias="RES" name="reservedDatetime"/>
+ <alias entity-alias="RES" name="sequenceId"/>
+ <view-link entity-alias="INV" rel-entity-alias="RES">
+ <key-map field-name="inventoryItemId"/>
+ </view-link>
+ </view-entity>
<entity entity-name="InventoryItem"
package-name="org.ofbiz.product.inventory"
title="Inventory Item Entity">
Modified: ofbiz/trunk/applications/product/script/org/ofbiz/product/inventory/InventoryReserveServices.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/script/org/ofbiz/product/inventory/InventoryReserveServices.xml?rev=723764&r1=723763&r2=723764&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/script/org/ofbiz/product/inventory/InventoryReserveServices.xml (original)
+++ ofbiz/trunk/applications/product/script/org/ofbiz/product/inventory/InventoryReserveServices.xml Fri Dec 5 07:35:12 2008
@@ -92,7 +92,7 @@
<order-by field-name="${orderByString}"/>
</entity-condition>
<iterate entry-name="inventoryItemAndLocation" list-name="inventoryItemAndLocations">
- <if-compare field="inventoryItemAndLocation.locationTypeEnumId" operator="equals" value="FLT_PICKLOC">
+ <if-compare field="parameters.quantityNotReserved" operator="greater" value="0" type="Double">
<!-- 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 -->
<make-value entity-name="InventoryItem" map-name="inventoryItemAndLocation" value-name="inventoryItem"/>
<call-simple-method method-name="reserveForInventoryItemInline"/>
@@ -112,7 +112,7 @@
<order-by field-name="${orderByString}"/>
</entity-condition>
<iterate entry-name="inventoryItemAndLocation" list-name="inventoryItemAndLocations">
- <if-compare field="inventoryItemAndLocation.locationTypeEnumId" operator="equals" value="FLT_BULK">
+ <if-compare field="parameters.quantityNotReserved" operator="greater" value="0" type="Double">
<!-- 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 -->
<make-value entity-name="InventoryItem" map-name="inventoryItemAndLocation" value-name="inventoryItem"/>
<call-simple-method method-name="reserveForInventoryItemInline"/>
@@ -133,9 +133,17 @@
<order-by field-name="${orderByString}"/>
</entity-condition>
<iterate entry-name="inventoryItem" list-name="inventoryItems">
- <if-empty field="inventoryItem.locationSeqId">
- <call-simple-method method-name="reserveForInventoryItemInline"/>
- </if-empty>
+ <if>
+ <condition>
+ <and>
+ <if-compare field="parameters.quantityNotReserved" operator="greater" value="0" type="Double"/>
+ <if-empty field="inventoryItem.locationSeqId"/>
+ </and>
+ </condition>
+ <then>
+ <call-simple-method method-name="reserveForInventoryItemInline"/>
+ </then>
+ </if>
</iterate>
</if-compare>
@@ -370,25 +378,6 @@
<simple-method method-name="reserveForInventoryItemInline" short-description="Does a reservation for one InventoryItem, meant to be called in-line">
<!-- only do something with this inventoryItem if there is more inventory to reserve -->
<if-compare field="parameters.quantityNotReserved" operator="greater" value="0" type="Double">
- <!-- get the promiseDatetime -->
- <get-related-one value-name="inventoryItem" relation-name="ProductFacility" to-value-name="productFacility"/>
- <set field="daysToShip" from-field="productFacility.daysToShip"/>
- <if-empty field="daysToShip">
- <!-- if the product does not have its own days to ship, use Facility.defaultDaysToShip, if not then use 30 days as a USA industry default -->
- <if-not-empty field="facility.defaultDaysToShip">
- <set field="daysToShip" from-field="facility.defaultDaysToShip" type="Long"/>
- <else>
- <set field="daysToShip" value="30" type="Long"/>
- </else>
- </if-not-empty>
- </if-empty>
- <call-bsh><![CDATA[
- java.sql.Timestamp orderDate = orderHeader.getTimestamp("orderDate");
- java.util.Calendar cal = java.util.Calendar.getInstance();
- cal.setTimeInMillis(orderDate.getTime());
- cal.add(java.util.Calendar.DAY_OF_YEAR, daysToShip.intValue());
- return org.ofbiz.base.util.UtilMisc.toMap("promisedDatetime", new java.sql.Timestamp(cal.getTimeInMillis()));
- ]]></call-bsh>
<if-compare value="SERIALIZED_INV_ITEM" operator="equals" field="inventoryItem.inventoryItemTypeId">
<if-compare value="INV_AVAILABLE" operator="equals" field="inventoryItem.statusId">
@@ -397,6 +386,7 @@
<store-value value-name="inventoryItem"/>
<!-- store OrderItemShipGrpInvRes record -->
+ <call-simple-method method-name="getPromisedDateTime"/>
<set from-field="parameters.orderId" field="reserveOisgirMap.orderId"/>
<set from-field="parameters.orderItemSeqId" field="reserveOisgirMap.orderItemSeqId"/>
<set from-field="parameters.shipGroupSeqId" field="reserveOisgirMap.shipGroupSeqId"/>
@@ -445,6 +435,7 @@
<clear-field field-name="createDetailMap"/>
<!-- create OrderItemShipGrpInvRes record -->
+ <call-simple-method method-name="getPromisedDateTime"/>
<set from-field="parameters.orderId" field="reserveOisgirMap.orderId"/>
<set from-field="parameters.orderItemSeqId" field="reserveOisgirMap.orderItemSeqId"/>
<set from-field="parameters.shipGroupSeqId" field="reserveOisgirMap.shipGroupSeqId"/>
@@ -472,6 +463,26 @@
</if-compare>
</if-compare>
</simple-method>
+
+ <simple-method method-name="getPromisedDateTime" short-description="Get Inventory Promised Date/Time">
+ <!-- get the promiseDatetime -->
+ <get-related-one value-name="inventoryItem" relation-name="ProductFacility" to-value-name="productFacility"/>
+ <set field="daysToShip" from-field="productFacility.daysToShip"/>
+ <if-empty field="daysToShip">
+ <!-- if the product does not have its own days to ship, use Facility.defaultDaysToShip, if not then use 30 days as a USA industry default -->
+ <set field="daysToShip" from-field="facility.defaultDaysToShip" type="Long"/>
+ </if-empty>
+ <if-empty field="daysToShip">
+ <set field="daysToShip" value="30" type="Long"/>
+ </if-empty>
+ <call-bsh><![CDATA[
+ java.sql.Timestamp orderDate = orderHeader.getTimestamp("orderDate");
+ java.util.Calendar cal = java.util.Calendar.getInstance();
+ cal.setTimeInMillis(orderDate.getTime());
+ cal.add(java.util.Calendar.DAY_OF_YEAR, daysToShip.intValue());
+ return org.ofbiz.base.util.UtilMisc.toMap("promisedDatetime", new java.sql.Timestamp(cal.getTimeInMillis()));
+ ]]></call-bsh>
+ </simple-method>
<simple-method method-name="reserveOrderItemInventory" short-description="Reserve Order Item Inventory">
<entity-one entity-name="OrderItemShipGrpInvRes" value-name="checkOisgirEntity"/>
Modified: ofbiz/trunk/applications/product/script/org/ofbiz/product/inventory/InventoryServices.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/script/org/ofbiz/product/inventory/InventoryServices.xml?rev=723764&r1=723763&r2=723764&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/script/org/ofbiz/product/inventory/InventoryServices.xml (original)
+++ ofbiz/trunk/applications/product/script/org/ofbiz/product/inventory/InventoryServices.xml Fri Dec 5 07:35:12 2008
@@ -709,26 +709,28 @@
<entity-one entity-name="InventoryItem" value-name="inventoryItem"/>
<!-- find all items which have a negative ATP -->
- <entity-condition entity-name="InventoryItem" list-name="inventoryItems">
- <condition-list combine="and">
- <condition-expr field-name="productId" operator="equals" env-name="inventoryItem.productId"/>
- <condition-expr field-name="facilityId" operator="equals" env-name="inventoryItem.facilityId"/>
- <condition-expr field-name="inventoryItemTypeId" operator="equals" value="NON_SERIAL_INV_ITEM"/>
- <condition-list combine="or">
- <condition-expr field-name="availableToPromiseTotal" operator="equals" env-name="nullField"/>
- <condition-expr field-name="availableToPromiseTotal" operator="equals" value=""/>
- <condition-expr field-name="availableToPromiseTotal" operator="less" value="0"/>
+ <entity-condition entity-name="BalanceInventoryItemsView" list-name="inventoryItems">
+ <condition-list combine="or">
+ <condition-list combine="and">
+ <condition-expr field-name="productId" operator="equals" env-name="inventoryItem.productId"/>
+ <condition-expr field-name="facilityId" operator="equals" env-name="inventoryItem.facilityId"/>
+ <condition-expr field-name="inventoryItemTypeId" operator="equals" value="NON_SERIAL_INV_ITEM"/>
+ <condition-list combine="or">
+ <condition-expr field-name="availableToPromiseTotal" operator="equals" env-name="nullField"/>
+ <condition-expr field-name="availableToPromiseTotal" operator="equals" value=""/>
+ <condition-expr field-name="availableToPromiseTotal" operator="less" value="0"/>
+ </condition-list>
</condition-list>
- <!-- Exclude the current item from the selection, because it will be added to the list anyway -->
- <condition-expr field-name="inventoryItemId" operator="not-equals" env-name="inventoryItem.inventoryItemId"/>
+ <!-- the current item is added to the list, even if its atp is greater than zero, because there could be
+ negative reservations (backorders) on it, if the atp has been increased by an inventory variance -->
+ <condition-expr field-name="inventoryItemId" operator="equals" env-name="inventoryItem.inventoryItemId"/>
</condition-list>
- <!-- TODO: order the list of inventory items in a useful way, since operations occur below based on the first item -->
+ <order-by field-name="reservedDatetime"/>
+ <order-by field-name="sequenceId"/>
</entity-condition>
- <!-- the current item is added to the list, even if its atp is greater than zero, because there could be
- negative reservations (backorders) on it, if the atp has been increased by an inventory variance -->
- <field-to-list field-name="inventoryItem" list-name="inventoryItems"/>
<!-- find their current reservations -->
+ <set field="reserveQtyAccum" value="0" type="Double"/>
<iterate list-name="inventoryItems" entry-name="item">
<!-- If quantityOnHandTotal is not equal to availableToPromiseTotal this means that
there are pending reservations on the item that cause availableToPromiseTotal
@@ -737,51 +739,48 @@
for example, if we have a negative quantityOnHandTotal and quantityOnHandTotal equal to
availableToPromiseTotal, then no reservations are present.
-->
- <if-compare-field field="item.quantityOnHandTotal" to-field="item.availableToPromiseTotal" operator="not-equals">
- <get-related value-name="item" relation-name="OrderItemShipGrpInvRes" list-name="relatedRes"/>
- <!--<list-to-list list-name="relatedRes" to-list-name="reservations"/>-->
-
- <iterate list-name="relatedRes" entry-name="oneRelatedRes">
- <entity-condition entity-name="PicklistAndBinAndItem" list-name="picklistItemList">
- <condition-list combine="and">
- <condition-expr field-name="orderId" env-name="oneRelatedRes.orderId"/>
- <condition-expr field-name="shipGroupSeqId" env-name="oneRelatedRes.shipGroupSeqId"/>
- <condition-expr field-name="orderItemSeqId" env-name="oneRelatedRes.orderItemSeqId"/>
- <condition-expr field-name="inventoryItemId" env-name="oneRelatedRes.inventoryItemId"/>
- <condition-expr field-name="statusId" operator="not-equals" value="PICKLIST_CANCELLED"/>
- <condition-expr field-name="statusId" operator="not-equals" value="PICKLIST_PICKED"/>
- </condition-list>
- </entity-condition>
-
- <!-- only cancel/re-reserve when there are no picklists associated; this will prevent
- orders appearing on duplicate pick lists -->
-
- <if-empty field="picklistItemList">
- <log level="info" message="Order [${oneRelatedRes.orderId}] was not found on any picklist for InventoryItem [${oneRelatedRes.inventoryItemId}]"/>
- <if>
- <condition>
- <and>
- <if-compare-field field="parameters.priorityOrderId" to-field="oneRelatedRes.orderId" operator="equals"/>
- <if-compare-field field="parameters.priorityOrderItemSeqId" to-field="oneRelatedRes.orderItemSeqId" operator="equals"/>
- </and>
- </condition>
- <then>
- <field-to-list field-name="oneRelatedRes" list-name="privilegedReservations"/>
- </then>
- <else>
- <field-to-list field-name="oneRelatedRes" list-name="reservations"/>
- </else>
- </if>
- </if-empty>
- </iterate>
- </if-compare-field>
+ <if>
+ <condition>
+ <and>
+ <if-compare-field field="reserveQtyAccum" operator="less" to-field="inventoryItem.quantityOnHandTotal" type="Double"/>
+ <if-compare-field field="item.quantityOnHandTotal" operator="not-equals" to-field="item.availableToPromiseTotal"/>
+ </and>
+ </condition>
+ <then>
+ <entity-condition entity-name="PicklistAndBinAndItem" list-name="picklistItemList">
+ <condition-list combine="and">
+ <condition-expr field-name="orderId" env-name="item.orderId"/>
+ <condition-expr field-name="shipGroupSeqId" env-name="item.shipGroupSeqId"/>
+ <condition-expr field-name="orderItemSeqId" env-name="item.orderItemSeqId"/>
+ <condition-expr field-name="inventoryItemId" env-name="item.inventoryItemId"/>
+ <condition-expr field-name="statusId" operator="not-equals" value="PICKLIST_CANCELLED"/>
+ <condition-expr field-name="statusId" operator="not-equals" value="PICKLIST_PICKED"/>
+ </condition-list>
+ </entity-condition>
+ <!-- only cancel/re-reserve when there are no picklists associated; this will prevent
+ orders appearing on duplicate pick lists -->
+ <if-empty field="picklistItemList">
+ <log level="info" message="Order [${item.orderId}] was not found on any picklist for InventoryItem [${item.inventoryItemId}]"/>
+ <if>
+ <condition>
+ <and>
+ <if-compare-field field="parameters.priorityOrderId" operator="equals" to-field="item.orderId"/>
+ <if-compare-field field="parameters.priorityOrderItemSeqId" operator="equals" to-field="item.orderItemSeqId"/>
+ </and>
+ </condition>
+ <then>
+ <field-to-list field-name="item" list-name="privilegedReservations"/>
+ </then>
+ <else>
+ <field-to-list field-name="item" list-name="reservations"/>
+ </else>
+ </if>
+ <set field="reserveQtyAccum" value="${bsh:reserveQtyAccum + item.getDouble("quantity");}" type="Double"/>
+ </if-empty>
+ </then>
+ </if>
</iterate>
- <!-- sort the list by date -->
- <set field="orderByList[]" value="reservedDatetime"/>
- <set field="orderByList[]" value="sequenceId"/>
- <order-value-list list-name="reservations" order-by-list-name="orderByList"/>
-
<list-to-list list-name="privilegedReservations" to-list-name="allReservations"/>
<list-to-list list-name="reservations" to-list-name="allReservations"/>
@@ -794,11 +793,7 @@
<!-- FIRST, cancel all the reservations -->
<iterate list-name="allReservations" entry-name="oisgir">
- <clear-field field-name="cancelOisgirMap"/>
- <set field="cancelOisgirMap.orderId" from-field="oisgir.orderId"/>
- <set field="cancelOisgirMap.orderItemSeqId" from-field="oisgir.orderItemSeqId"/>
- <set field="cancelOisgirMap.inventoryItemId" from-field="oisgir.inventoryItemId"/>
- <set field="cancelOisgirMap.shipGroupSeqId" from-field="oisgir.shipGroupSeqId"/>
+ <set-service-fields service-name="cancelOrderItemShipGrpInvRes" to-map-name="cancelOisgirMap" map-name="oisgir"/>
<call-service service-name="cancelOrderItemShipGrpInvRes" in-map-name="cancelOisgirMap"/>
</iterate>
@@ -811,23 +806,14 @@
<log level="verbose" message="Adding ${oisgir.orderId} to touchedOrderIdMap"/>
</if-compare>
</if-not-empty>
-
- <!-- require inventory is N because it had to be N to begin with to have a negative ATP -->
- <clear-field field-name="resMap"/>
+ <set-service-fields service-name="reserveProductInventory" to-map-name="resMap" map-name="oisgir"/>
<set field="resMap.productId" from-field="inventoryItem.productId"/>
- <set field="resMap.orderId" from-field="oisgir.orderId"/>
- <set field="resMap.orderItemSeqId" from-field="oisgir.orderItemSeqId"/>
- <set field="resMap.quantity" from-field="oisgir.quantity"/>
- <set field="resMap.reservedDatetime" from-field="oisgir.reservedDatetime"/>
- <set field="resMap.reserveOrderEnumId" from-field="oisgir.reserveOrderEnumId"/>
+ <!-- require inventory is N because it had to be N to begin with to have a negative ATP -->
<set field="resMap.requireInventory" value="N"/>
- <set field="resMap.shipGroupSeqId" from-field="oisgir.shipGroupSeqId"/>
- <set field="resMap.sequenceId" from-field="oisgir.sequenceId"/>
<log level="info" message="Re-reserving product [${resMap.productId}] for order item [${resMap.orderId}:${resMap.orderItemSeqId}] quantity [${resMap.quantity}]; facility [${inventoryItem.facilityId}]"/>
<if-empty field="inventoryItem.facilityId">
<log level="warning" message="In balanceInventoryItems there is no facilityId, so reserving from any facility for order item [${resMap.orderId}:${resMap.orderItemSeqId}]"></log>
<call-service service-name="reserveProductInventory" in-map-name="resMap"/>
-
<else>
<set field="resMap.facilityId" from-field="inventoryItem.facilityId"/>
<call-service service-name="reserveProductInventoryByFacility" in-map-name="resMap"/>