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(&quot;quantity&quot;);}" 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"/>