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"/>


Reply via email to