Author: sichen
Date: Mon Mar 5 15:57:17 2007
New Revision: 514929
URL: http://svn.apache.org/viewvc?view=rev&rev=514929
Log:
OFBIZ-774: balance inventory supports serialized inventory
- Extend balanceInventoryItems service to take serialized inventory into account
- If serialized inventory is received and non-serialized inventoryItems exist
with negative or empty values, the service will attempt to apply the serialized
inventory to the first inventoryItem found
- ATP and QOH of the non-serialized will be increased by the serialized quantity
- statusId of the serialized item will be set to INV_PROMISED
- If OrderItemShipGrpInvRes values exist related to the non-serialized item,
the service will reduce the quantity of the first found by the serialized
quantity and create a new OrderItemShipGrpInvRes for the serialized quantity
based on the non-serialized reservation
TODO: Define 'first' in relation to the lists of non-serialized inventoryItems
and OrderItemShipGrpInvRes values - is there a business rule that governs this?
Modified:
ofbiz/trunk/applications/product/script/org/ofbiz/product/inventory/InventoryServices.xml
ofbiz/trunk/applications/product/script/org/ofbiz/shipment/receipt/ShipmentReceiptServices.xml
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?view=diff&rev=514929&r1=514928&r2=514929
==============================================================================
---
ofbiz/trunk/applications/product/script/org/ofbiz/product/inventory/InventoryServices.xml
(original)
+++
ofbiz/trunk/applications/product/script/org/ofbiz/product/inventory/InventoryServices.xml
Mon Mar 5 15:57:17 2007
@@ -488,60 +488,60 @@
<make-value entity-name="InventoryItem" value-name="lookupPKMap"/>
<set-pk-fields value-name="lookupPKMap" map-name="parameters"/>
<find-by-primary-key entity-name="InventoryItem"
map-name="lookupPKMap" value-name="inventoryItem"/>
- <if-compare field-name="inventoryItemTypeId" map-name="inventoryItem"
operator="equals" value="NON_SERIAL_INV_ITEM">
- <!-- now find all items related by product/facility -->
- <set from-field="inventoryItem.facilityId"
field="lookupMap.facilityId"/>
- <set from-field="inventoryItem.productId"
field="lookupMap.productId"/>
- <set value="NON_SERIAL_INV_ITEM"
field="lookupMap.inventoryItemTypeId"/>
- <find-by-and entity-name="InventoryItem" map-name="lookupMap"
list-name="inventoryItems"/>
- <!-- find all items which have a negative ATP; find their current
reservations -->
+ <!-- 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"/>
+ </condition-list>
+ </condition-list>
+ <!-- TODO: order the list of inventory items in a useful way,
since operations occur below based on the first item -->
+ </entity-condition>
+
+ <if-compare field-name="inventoryItemTypeId" map-name="inventoryItem"
operator="equals" value="NON_SERIAL_INV_ITEM">
+ <!-- find their current reservations -->
<iterate list-name="inventoryItems" entry-name="item">
- <if>
- <condition>
- <or>
- <if-empty field-name="availableToPromiseTotal"/>
- <if-compare field-name="availableToPromiseTotal"
map-name="item" operator="less" value="0" type="Double"/>
- </or>
- </condition>
- <then>
- <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-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-name="picklistItemList">
- <log level="always" message="Order
#${oneRelatedRes.orderId} was not found on any picklist for this item
[${oneRelatedRes.inventoryItemId}]"/>
- <if>
- <condition>
- <and>
- <if-compare-field
field-name="parameters.priorityOrderId" operator="equals"
to-field-name="oneRelatedRes.orderId"/>
- <if-compare-field
field-name="parameters.priorityOrderItemSeqId" operator="equals"
to-field-name="oneRelatedRes.orderItemSeqId"/>
- </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>
- </then>
- </if>
+ <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-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-name="picklistItemList">
+ <log level="always" message="Order
#${oneRelatedRes.orderId} was not found on any picklist for this item
[${oneRelatedRes.inventoryItemId}]"/>
+ <if>
+ <condition>
+ <and>
+ <if-compare-field
field-name="parameters.priorityOrderId" operator="equals"
to-field-name="oneRelatedRes.orderId"/>
+ <if-compare-field
field-name="parameters.priorityOrderItemSeqId" operator="equals"
to-field-name="oneRelatedRes.orderItemSeqId"/>
+ </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>
</iterate>
<!-- sort the list by date -->
@@ -574,6 +574,70 @@
<call-service service-name="reserveProductInventory"
in-map-name="resMap"/>
<clear-field field-name="resMap"/>
</iterate>
+
+ <else>
+ <if-compare field-name="inventoryItemTypeId"
map-name="inventoryItem" operator="equals" value="SERIALIZED_INV_ITEM">
+ <now-timestamp-to-env env-name="nowTimestamp"/>
+
+ <!-- Get the first non-serialized inventory item with a
negative ATP -->
+ <first-from-list entry-name="nonSerInvItem"
list-name="inventoryItems"/>
+ <if-not-empty field-name="nonSerInvItem">
+
+ <!-- Change the serialized inventoryItem's status to
promised -->
+ <set field="inventoryItem.statusId"
value="INV_PROMISED"/>
+ <store-value value-name="inventoryItem"
do-cache-clear="true"/>
+ <check-errors/>
+
+ <!-- Update the first negative non-serialized
inventoryItem's ATP and QOH values -->
+ <calculate
field-name="nonSerInvItem.availableToPromiseTotal" type="Double">
+ <calcop operator="add"
field-name="nonSerInvItem.availableToPromiseTotal">
+ <calcop operator="get"
field-name="inventoryItem.availableToPromiseTotal"/>
+ </calcop>
+ </calculate>
+ <calculate
field-name="nonSerInvItem.quantityOnHandTotal" type="Double">
+ <calcop operator="add"
field-name="nonSerInvItem.quantityOnHandTotal">
+ <calcop operator="get"
field-name="inventoryItem.quantityOnHandTotal"/>
+ </calcop>
+ </calculate>
+ <store-value value-name="nonSerInvItem"/>
+ <check-errors/>
+
+ <get-related value-name="nonSerInvItem"
relation-name="OrderItemShipGrpInvRes" list-name="nonSerInvRes"/>
+ <!-- TODO: Order the list of reservations -->
+ <first-from-list entry-name="inventoryReservation"
list-name="nonSerInvRes"/>
+ <if-not-empty field-name="inventoryReservation">
+
+ <!-- Make a new reservation for the serialized
unit quantity for the order -->
+ <make-value value-name="newReservation"
entity-name="OrderItemShipGrpInvRes" map-name="inventoryReservation"/>
+ <set
from-field="inventoryItem.availableToPromiseTotal"
field="newReservation.quantity"/>
+ <set from-field="inventoryItem.inventoryItemId"
field="newReservation.inventoryItemId"/>
+ <create-value value-name="newReservation"/>
+ <check-errors/>
+
+ <!-- Reduce the previous reservation by 1 unit -->
+ <calculate
field-name="inventoryReservation.quantity" type="Double">
+ <calcop operator="subtract"
field-name="inventoryReservation.quantity">
+ <calcop operator="get"
field-name="inventoryItem.availableToPromiseTotal"/>
+ </calcop>
+ </calculate>
+
+ <!-- If the previous reservation quantity is now
zero then cancel it, otherwise store it -->
+ <if-compare
field-name="inventoryReservation.quantity" value="0" operator="less-equals"
type="Double">
+ <set from-field="inventoryReservation.orderId"
field="cancelOisgirMap.orderId"/>
+ <set
from-field="inventoryReservation.orderItemSeqId"
field="cancelOisgirMap.orderItemSeqId"/>
+ <set
from-field="inventoryReservation.inventoryItemId"
field="cancelOisgirMap.inventoryItemId"/>
+ <set
from-field="inventoryReservation.shipGroupSeqId"
field="cancelOisgirMap.shipGroupSeqId"/>
+ <call-service
service-name="cancelOrderItemShipGrpInvRes" in-map-name="cancelOisgirMap"/>
+ <check-errors/>
+ <else>
+ <store-value
value-name="inventoryReservation"/>
+ </else>
+ </if-compare>
+ <check-errors/>
+ </if-not-empty>
+ </if-not-empty>
+ </if-compare>
+ </else>
</if-compare>
</simple-method>
Modified:
ofbiz/trunk/applications/product/script/org/ofbiz/shipment/receipt/ShipmentReceiptServices.xml
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/script/org/ofbiz/shipment/receipt/ShipmentReceiptServices.xml?view=diff&rev=514929&r1=514928&r2=514929
==============================================================================
---
ofbiz/trunk/applications/product/script/org/ofbiz/shipment/receipt/ShipmentReceiptServices.xml
(original)
+++
ofbiz/trunk/applications/product/script/org/ofbiz/shipment/receipt/ShipmentReceiptServices.xml
Mon Mar 5 15:57:17 2007
@@ -107,11 +107,18 @@
<!-- update serialized items to AVAILABLE (only if this is not a
return), which then triggers other SECA chains -->
<if-compare value="SERIALIZED_INV_ITEM" operator="equals"
field-name="parameters.inventoryItemTypeId">
<if-compare value="INV_RETURNED" operator="not-equals"
field-name="parameters.statusId">
- <clear-field field-name="serviceInMap"/>
- <set field="serviceInMap.inventoryItemId"
from-field="parameters.inventoryItemId"/>
- <set field="serviceInMap.statusId" value="INV_AVAILABLE"/>
<!-- XXX set to returned instead -->
- <call-service service-name="updateInventoryItem"
in-map-name="serviceInMap"/>
- <check-errors/>
+ <!-- Retrieve the new inventoryItem -->
+ <set field="inventoryItemLookup.inventoryItemId"
from-field="parameters.inventoryItemId"/>
+ <find-by-primary-key entity-name="InventoryItem"
map-name="inventoryItemLookup" value-name="inventoryItem"/>
+
+ <!-- Don't reset the status if it's already set to
INV_PROMISED downstream -->
+ <if-compare value="INV_PROMISED" operator="not-equals"
field-name="inventoryItem.statusId">
+ <clear-field field-name="serviceInMap"/>
+ <set field="serviceInMap.inventoryItemId"
from-field="parameters.inventoryItemId"/>
+ <set field="serviceInMap.statusId"
value="INV_AVAILABLE"/> <!-- XXX set to returned instead -->
+ <call-service service-name="updateInventoryItem"
in-map-name="serviceInMap"/>
+ <check-errors/>
+ </if-compare>
</if-compare>
</if-compare>
<set value="Received ${parameters.quantityAccepted} of
${parameters.productId} in inventory item ${parameters.inventoryItemId}"
field="successMessageList[]"/>