You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by si...@apache.org on 2007/02/27 20:51:53 UTC

svn commit: r512373 - in /ofbiz/trunk/applications: order/config/ order/src/org/ofbiz/order/shoppingcart/ order/webapp/ordermgr/WEB-INF/actions/entry/ product/data/

Author: sichen
Date: Tue Feb 27 11:51:52 2007
New Revision: 512373

URL: http://svn.apache.org/viewvc?view=rev&rev=512373
Log:
Implementing logic to handle automatic creation of drop ship groups during checkout
    - If a product is set to always drop ship (Product.requirementMethodEnumId == 'PRODRQM_DS').
    - If a product is set to drop ship when inventory is low (Product.requirementMethodEnumId == 'PRODRQM_DSATP'). In this case, item quantities > ATP will be drop shipped.
    - Items are reassigned to ship groups based on supplier.
    - Ship groups are created if necessary.
    - Suppliers are determined using by ProductSupplier.canDropShip == Y, and ProductSupplier.supplierPrefOrderId - main suppliers are used in preference to alternate suppliers.
    - Changing Enumeration.enumId PRODRQM_DSQOH to PRODRQM_DSATP in ProductTypeData.xml.

Modified:
    ofbiz/trunk/applications/order/config/OrderErrorUiLabels.properties
    ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/CheckOutEvents.java
    ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCart.java
    ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartItem.java
    ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/checkoutoptions.bsh
    ofbiz/trunk/applications/product/data/ProductTypeData.xml

Modified: ofbiz/trunk/applications/order/config/OrderErrorUiLabels.properties
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/config/OrderErrorUiLabels.properties?view=diff&rev=512373&r1=512372&r2=512373
==============================================================================
--- ofbiz/trunk/applications/order/config/OrderErrorUiLabels.properties (original)
+++ ofbiz/trunk/applications/order/config/OrderErrorUiLabels.properties Tue Feb 27 11:51:52 2007
@@ -172,6 +172,7 @@
 OrderProblemGettingItemShipAfterDateFor=Problem getting itemShipAfterDate for ${productId}
 OrderProblemGettingItemShipBeforeDateFor=Problem getting itemShipBeforeDate for ${productId}
 OrderProblemGettingOrderItemRecords=Problem getting OrderItem records
+OrderProblemGettingProductStoreRecords=Problem getting ProductStore records
 OrderProblemGettingTheRecordIterator=Problem getting the Record Iterator
 OrderProblemOccurredInTaxService=Problem occurred in tax service
 OrderProblemSendingEmail=Problem sending email
@@ -207,6 +208,7 @@
 OrderReturnTotalCannotLessThanZero=Return total [${returnTotalAmount}] can not less than zero.
 OrderReturnQuantityCannotExceedTheOrderedQuantity=Return quantity [ ${parameters.returnQuantity} ] cannot exceed the ordered quantity [ ${orderItem.quantity} ]. 
 OrderRunServiceGetSuppliersForProductError=Run service [getSuppliersForProduct] error :
+OrderRunServiceGetInventoryAvailableByFacilityError=Run service [getInventoryAvailableByFacility] error :
 OrderSecurityErrorToRunForAnotherParty=Security Error : to run ${parentMethodName} for another party you must have the PARTYMGR_${permissionAction} or PARTYMGR_ADMIN permission
 OrderSecurityErrorToRunAutoUpdateQuotePrice=Security Error : to run autoUpdateQuotePrice you must have the ORDERMGR_CREATE or ORDERMGR_ADMIN permission
 OrderSecurityErrorToRunCheckCreateOrderRequirementCommitment=Security Error: to run createOrderRequirementCommitment you must have ORDERMGR_CREATE or ORDERMGR_ADMIN permission

Modified: ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/CheckOutEvents.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/CheckOutEvents.java?view=diff&rev=512373&r1=512372&r2=512373
==============================================================================
--- ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/CheckOutEvents.java (original)
+++ ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/CheckOutEvents.java Tue Feb 27 11:51:52 2007
@@ -630,6 +630,15 @@
             }
         }
 
+        // Reassign items requiring drop-shipping to new or existing drop-ship groups
+        if ("init".equals(mode) || "default".equals(mode)) {
+            try {
+                cart.createDropShipGroups(dispatcher);
+            } catch (CartItemModifyException e) {
+                Debug.logError(e, module);
+            }
+        }
+        
         // set the customer info
         if (mode != null && mode.equals("default")) {
             cart.setDefaultCheckoutOptions(dispatcher);

Modified: ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCart.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCart.java?view=diff&rev=512373&r1=512372&r2=512373
==============================================================================
--- ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCart.java (original)
+++ ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCart.java Tue Feb 27 11:51:52 2007
@@ -21,18 +21,7 @@
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 import javolution.util.FastList;
 import javolution.util.FastMap;
@@ -3612,6 +3601,164 @@
         return result;
     }
 
+    public Map getShipGroupsBySupplier(String supplierPartyId) {
+        Map shipGroups = new TreeMap();
+        for (int i = 0; i < this.shipInfo.size(); i++) {
+            CartShipInfo csi = (CartShipInfo) shipInfo.get(i);
+            if ((csi.supplierPartyId == null && supplierPartyId == null) ||
+                (UtilValidate.isNotEmpty(csi.supplierPartyId) && csi.supplierPartyId.equals(supplierPartyId))) {
+                shipGroups.put(new Integer(i), csi);
+            }
+        }
+        return shipGroups;
+    }
+
+    /**
+     * Examine each item of each ship group and create new ship groups if the item should be drop shipped
+     * @param dispatcher
+     * @throws CartItemModifyException
+     */
+    public void createDropShipGroups(LocalDispatcher dispatcher) throws CartItemModifyException {
+
+        // Retrieve the facilityId from the cart's productStoreId because ShoppingCart.setFacilityId() doesn't seem to be used anywhere
+        String facilityId = null;
+        if (UtilValidate.isNotEmpty(this.getProductStoreId())) {
+            try {
+                GenericValue productStore = delegator.findByPrimaryKeyCache("ProductStore", UtilMisc.toMap("productStoreId", this.getProductStoreId()));
+                facilityId = productStore.getString("inventoryFacilityId");
+            } catch (Exception e) {
+                Debug.logError(UtilProperties.getMessage(resource_error,"OrderProblemGettingProductStoreRecords", locale) + e.getMessage(), module);
+                return;
+            }
+        }
+        
+        List shipGroups = getShipGroups();
+        if (shipGroups == null) return;
+
+        // Intermediate structure supplierPartyId -> { ShoppingCartItem = { originalShipGroupIndex = dropShipQuantity } } to collect drop-shippable items
+        Map dropShipItems = new HashMap();
+        
+        for (int shipGroupIndex = 0; shipGroupIndex < shipGroups.size(); shipGroupIndex++) {
+            
+            CartShipInfo shipInfo = (CartShipInfo) shipGroups.get(shipGroupIndex);
+            
+            // Ignore ship groups that are already drop shipped
+            String shipGroupSupplierPartyId = shipInfo.getSupplierPartyId();
+            if (UtilValidate.isNotEmpty(shipGroupSupplierPartyId)) continue;
+
+            // Ignore empty ship groups
+            Set shipItems = shipInfo.getShipItems();
+            if (UtilValidate.isEmpty(shipItems)) continue;
+
+            Iterator siit = shipItems.iterator();
+            while (siit.hasNext()) {
+                
+                ShoppingCartItem cartItem = (ShoppingCartItem) siit.next();
+
+                double itemQuantity = cartItem.getQuantity();
+                double dropShipQuantity = 0;
+
+                GenericValue product = cartItem.getProduct();
+                String productId = product.getString("productId");
+                String requirementMethodEnumId = product.getString("requirementMethodEnumId");
+
+                if ("PRODRQM_DS".equals(requirementMethodEnumId)) {
+                    
+                    // Drop ship the full quantity if the product is marked drop-ship only
+                    dropShipQuantity = itemQuantity;
+                    
+                } else if ("PRODRQM_DSATP".equals(requirementMethodEnumId)) {
+                    
+                    // Drop ship the quantity not available in inventory if the product is marked drop-ship on low inventory
+                    try {
+
+                        // Get ATP for the product
+                        Map getProductInventoryAvailableResult = dispatcher.runSync("getInventoryAvailableByFacility", UtilMisc.toMap("productId", productId, "facilityId", facilityId));
+                        double availableToPromise = ((Double) getProductInventoryAvailableResult.get("availableToPromiseTotal")).doubleValue();
+
+                        if (itemQuantity <= availableToPromise) {
+                            dropShipQuantity = 0;
+                        } else {
+                            dropShipQuantity = itemQuantity - availableToPromise;
+                        }
+
+                    } catch (Exception e) {
+                        Debug.logWarning(UtilProperties.getMessage(resource_error,"OrderRunServiceGetInventoryAvailableByFacilityError", locale) + e.getMessage(), module);
+                    }
+                } else {
+                    
+                    // Don't drop ship anything if the product isn't so marked
+                    dropShipQuantity = 0;
+                }
+
+                if (dropShipQuantity <= 0) continue;
+                
+                // Find a supplier for the product
+                String supplierPartyId = null;
+                try {
+                    Map getSuppliersForProductResult = dispatcher.runSync("getSuppliersForProduct", UtilMisc.toMap("productId", productId, "quantity", new Double(dropShipQuantity), "canDropShip", "Y", "currencyUomId", getCurrency()));
+                    List supplierProducts = (List) getSuppliersForProductResult.get("supplierProducts");
+                    
+                    // Order suppliers by supplierPrefOrderId so that preferred suppliers are used first
+                    supplierProducts = EntityUtil.orderBy(supplierProducts, UtilMisc.toList("supplierPrefOrderId"));
+                    GenericValue supplierProduct = EntityUtil.getFirst(supplierProducts);
+                    if (! UtilValidate.isEmpty(supplierProduct)) {
+                        supplierPartyId = supplierProduct.getString("partyId");
+                    }
+                } catch (Exception e) {
+                    Debug.logWarning(UtilProperties.getMessage(resource_error,"OrderRunServiceGetSuppliersForProductError", locale) + e.getMessage(), module);
+                }
+                
+                // Leave the items untouched if we couldn't find a supplier
+                if (UtilValidate.isEmpty(supplierPartyId)) continue;
+                
+                if (! dropShipItems.containsKey(supplierPartyId)) dropShipItems.put(supplierPartyId, new HashMap());
+                Map supplierCartItems = (Map) dropShipItems.get(supplierPartyId);
+
+                if (! supplierCartItems.containsKey(cartItem)) supplierCartItems.put(cartItem, new HashMap());
+                Map cartItemGroupQuantities = (Map) supplierCartItems.get(cartItem);
+
+                cartItemGroupQuantities.put(new Integer(shipGroupIndex), new Double(dropShipQuantity));
+            }
+        }
+
+        // Reassign the drop-shippable item quantities to new or existing drop-ship groups
+        Iterator dsit = dropShipItems.keySet().iterator();
+        while (dsit.hasNext()) {
+            String supplierPartyId = (String) dsit.next();
+
+            CartShipInfo shipInfo = null;
+            int newShipGroupIndex = -1 ;
+            
+            // Attempt to get the first ship group for the supplierPartyId
+            TreeMap supplierShipGroups = (TreeMap) this.getShipGroupsBySupplier(supplierPartyId);
+            if (! UtilValidate.isEmpty(supplierShipGroups)) {
+                newShipGroupIndex = ((Integer) supplierShipGroups.firstKey()).intValue();
+                shipInfo = (CartShipInfo) supplierShipGroups.get(supplierShipGroups.firstKey());
+            }
+            if (newShipGroupIndex == -1) {
+                newShipGroupIndex = addShipInfo();
+                shipInfo = (CartShipInfo) this.shipInfo.get(newShipGroupIndex);
+            }
+            shipInfo.supplierPartyId = supplierPartyId;
+
+            Map supplierCartItems = (Map) dropShipItems.get(supplierPartyId);
+            Iterator itit = supplierCartItems.keySet().iterator();
+            while (itit.hasNext()) {
+
+                ShoppingCartItem cartItem = (ShoppingCartItem) itit.next();
+                Map cartItemGroupQuantities = (Map) supplierCartItems.get(cartItem);
+                Iterator cigit = cartItemGroupQuantities.keySet().iterator();
+                while (cigit.hasNext()) {
+
+                    Integer previousShipGroupIndex = (Integer) cigit.next();
+                    double dropShipQuantity = ((Double) cartItemGroupQuantities.get(previousShipGroupIndex)).doubleValue();
+                    positionItemToGroup(cartItem, dropShipQuantity, previousShipGroupIndex.intValue(), newShipGroupIndex, true);
+                }
+            }
+        }
+    }
+    
     static class BasePriceOrderComparator implements Comparator, Serializable {
         private boolean ascending = false;
 

Modified: ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartItem.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartItem.java?view=diff&rev=512373&r1=512372&r2=512373
==============================================================================
--- ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartItem.java (original)
+++ ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartItem.java Tue Feb 27 11:51:52 2007
@@ -928,6 +928,11 @@
         // set the item ship group
         if (resetShipGroup) {
             cart.clearItemShipInfo(this);
+
+            /*
+
+            // Deprecated in favour of ShoppingCart.createDropShipGroups(), called during checkout
+
             int shipGroupIndex = -1;
             if ("PURCHASE_ORDER".equals(cart.getOrderType())) {
                 shipGroupIndex = 0;
@@ -963,7 +968,6 @@
                         Debug.logWarning("Error calling getSuppliersForProduct service, result is: " + supplierProductsResult, module);
                     }
                 }
-                // TODO: implement auto drop-ship on low qoh
 
                 if (shipGroupIndex == -1) {
                     List shipGroups = cart.getShipGroups();
@@ -981,6 +985,8 @@
                 }
             }
             cart.setItemShipGroupQty(this, quantity, shipGroupIndex);
+            */
+            cart.setItemShipGroupQty(this, quantity, 0);
         }
     }
 

Modified: ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/checkoutoptions.bsh
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/checkoutoptions.bsh?view=diff&rev=512373&r1=512372&r2=512373
==============================================================================
--- ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/checkoutoptions.bsh (original)
+++ ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/checkoutoptions.bsh Tue Feb 27 11:51:52 2007
@@ -38,6 +38,11 @@
     context.put("carrierShipmentMethodList", shippingEstWpr.getShippingMethods());
 }
 
+// Reassign items requiring drop-shipping to new or existing drop-ship groups
+if (shoppingCart != null) {
+    shoppingCart.createDropShipGroups(dispatcher);
+}
+
 profiledefs = delegator.findByPrimaryKey("PartyProfileDefault", UtilMisc.toMap("partyId", userLogin.getString("partyId"), "productStoreId", productStoreId));
 context.put("profiledefs", profiledefs);
 

Modified: ofbiz/trunk/applications/product/data/ProductTypeData.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/data/ProductTypeData.xml?view=diff&rev=512373&r1=512372&r2=512373
==============================================================================
--- ofbiz/trunk/applications/product/data/ProductTypeData.xml (original)
+++ ofbiz/trunk/applications/product/data/ProductTypeData.xml Tue Feb 27 11:51:52 2007
@@ -412,7 +412,7 @@
     <!-- PRODRQM_DS: a drop ship group is created to trigger automatic creation of a purchase order (drop shipment) every time a sales order is created-->
     <Enumeration description="Drop-ship only" enumCode="DROPS" enumId="PRODRQM_DS" sequenceId="06" enumTypeId="PROD_REQ_METHOD"/>
     <!-- PRODRQM_DSQOH: auto drop ship on low quantity on hand -->
-    <Enumeration description="Auto drop-ship on low quantity" enumCode="DROPS_QOH" enumId="PRODRQM_DSQOH" sequenceId="07" enumTypeId="PROD_REQ_METHOD"/>
+    <Enumeration description="Auto drop-ship on low quantity" enumCode="DROPS_ATP" enumId="PRODRQM_DSATP" sequenceId="07" enumTypeId="PROD_REQ_METHOD"/>
 
     <!-- inventory item status -->
     <StatusType description="Inventory Item" hasTable="N" parentTypeId="" statusTypeId="INVENTORY_ITEM_STTS"/>