You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by as...@apache.org on 2010/04/21 11:36:41 UTC

svn commit: r936228 - in /ofbiz/trunk: applications/order/src/org/ofbiz/order/shoppingcart/ applications/order/webapp/ordermgr/WEB-INF/actions/entry/catalog/ applications/product/data/ specialpurpose/ecommerce/data/ specialpurpose/ecommerce/webapp/ecom...

Author: ashish
Date: Wed Apr 21 09:36:40 2010
New Revision: 936228

URL: http://svn.apache.org/viewvc?rev=936228&view=rev
Log:
Applied patch from jira issue: OFBIZ-3633 - Minimum order quantity.
It will work as follows;
We will set the special type price as 'MINIMUM_ORDER_PRICE' for a Product in ProductPrice entity. On the basis of it we will get the minimum order quantity of the product on the basis of this price and sale price.
Will get the minimum order quantity for product by division. For example we have selling price of product P1 is $10.00 and its MINIMUM_ORDER_PRICE is $100.00 then minimum order quantity for the product will be --> 100/10 ==> 10.

To achieve the above ;
write a getMinimumOrderQuantity() method in ShoppingCart.java which takes the itemBasePrice and productId as in parameter, and call it where we add, update the cart items and change the quantity to minmumOrderQuantity if it is less then minimum.

Thanks Deepak & Rishi for the contribution and others for providing valuable comments / suggestions.

Modified:
    ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCart.java
    ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartHelper.java
    ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/catalog/ProductDetail.groovy
    ofbiz/trunk/applications/product/data/ProductTypeData.xml
    ofbiz/trunk/specialpurpose/ecommerce/data/DemoProduct.xml
    ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/catalog/configproductdetail.ftl
    ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/catalog/productdetail.ftl

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?rev=936228&r1=936227&r2=936228&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCart.java (original)
+++ ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCart.java Wed Apr 21 09:36:40 2010
@@ -22,11 +22,13 @@ import javolution.util.FastList;
 import javolution.util.FastMap;
 import org.ofbiz.base.util.*;
 import org.ofbiz.entity.Delegator;
-import org.ofbiz.entity.Delegator;
 import org.ofbiz.entity.DelegatorFactory;
 import org.ofbiz.entity.GenericEntityException;
 import org.ofbiz.entity.GenericPK;
 import org.ofbiz.entity.GenericValue;
+import org.ofbiz.entity.condition.EntityCondition;
+import org.ofbiz.entity.condition.EntityExpr;
+import org.ofbiz.entity.condition.EntityOperator;
 import org.ofbiz.entity.util.EntityUtil;
 import org.ofbiz.order.finaccount.FinAccountHelper;
 import org.ofbiz.order.order.OrderReadHelper;
@@ -491,6 +493,14 @@ public class ShoppingCart implements Ite
 
             if (sci.equals(productId, reservStart, reservLength, reservPersons, accommodationMapId, accommodationSpotId, features, attributes, prodCatalogId,selectedAmount, configWrapper, itemType, itemGroup, false)) {
                 BigDecimal newQuantity = sci.getQuantity().add(quantity);
+                try {
+                    BigDecimal minQuantity = getMinimumOrderQuantity(delegator,sci.getBasePrice(), productId);
+                    if(newQuantity.compareTo(minQuantity) < 0) {
+                        newQuantity = minQuantity;
+                    }
+                } catch (GenericEntityException e) {
+                    Debug.logError(e, module);
+                }
                 if (sci.getItemType().equals("RENTAL_ORDER_ITEM")) {
                     // check to see if the related fixed asset is available for the new quantity
                     String isAvailable = ShoppingCartItem.checkAvailability(productId, newQuantity, reservStart, reservLength, this);
@@ -528,6 +538,14 @@ public class ShoppingCart implements Ite
                 throw new CartItemModifyException("SupplierProduct not found");
             }
         } else {
+            try {
+                BigDecimal minQuantity = getMinimumOrderQuantity(delegator,null, productId);
+                if(quantity.compareTo(minQuantity) < 0) {
+                    quantity = minQuantity;
+                }
+            } catch (GenericEntityException e) {
+                Debug.logError(e, module);
+            }
             return this.addItem(0, ShoppingCartItem.makeItem(Integer.valueOf(0), productId, selectedAmount, quantity, null,
                     reservStart, reservLength, reservPersons, accommodationMapId, accommodationSpotId, shipBeforeDate, shipAfterDate,
                     features, attributes, prodCatalogId, configWrapper, itemType, itemGroup, dispatcher,
@@ -4922,4 +4940,43 @@ public class ShoppingCart implements Ite
     public void setOrderStatusString(String orderStatusString) {
         this.orderStatusString = orderStatusString;
     }
+    public static BigDecimal getMinimumOrderQuantity (Delegator delegator, BigDecimal itemBasePrice, String itemProductId) 
+    throws GenericEntityException {
+        BigDecimal minQuantity = BigDecimal.ZERO;
+        BigDecimal minimumOrderPrice = BigDecimal.ZERO; 
+        
+        List<EntityExpr> exprs = FastList.newInstance();
+        exprs.add(EntityCondition.makeCondition("productId", EntityOperator.EQUALS, itemProductId));
+        exprs.add(EntityCondition.makeCondition("productPriceTypeId", EntityOperator.EQUALS, "MINIMUM_ORDER_PRICE"));
+        
+        List<GenericValue> minimumOrderPriceList =  delegator.findList("ProductPrice", EntityCondition.makeCondition(exprs, EntityOperator.AND), null, null, null, false);
+        if(minimumOrderPriceList != null) {
+            minimumOrderPriceList = EntityUtil.filterByDate(minimumOrderPriceList);
+        }
+        if (itemBasePrice == null) {
+            List<GenericValue> productPriceList = EntityUtil.filterByDate(delegator.findList("ProductPrice", EntityCondition.makeCondition("productId", itemProductId), null, null, null, false));
+            Iterator it = productPriceList.iterator();
+            Map productPriceMap = FastMap.newInstance();
+            while (it.hasNext()) {
+                GenericValue productPrice = (GenericValue) it.next();
+                productPriceMap.put(productPrice.getString("productPriceTypeId"), productPrice.getBigDecimal("price"));
+            }
+            if (UtilValidate.isNotEmpty(productPriceMap.get("SPECIAL_PROMO_PRICE"))) {
+                itemBasePrice= (BigDecimal) productPriceMap.get("SPECIAL_PROMO_PRICE");
+            } else if (UtilValidate.isNotEmpty(productPriceMap.get("PROMO_PRICE"))) {
+                itemBasePrice= (BigDecimal) productPriceMap.get("PROMO_PRICE");
+            } else if (UtilValidate.isNotEmpty(productPriceMap.get("DEFAULT_PRICE"))) {
+                itemBasePrice= (BigDecimal) productPriceMap.get("DEFAULT_PRICE");
+            } else if (UtilValidate.isNotEmpty(productPriceMap.get("LIST_PRICE"))) {
+                itemBasePrice= (BigDecimal) productPriceMap.get("LIST_PRICE");
+            }
+        }
+        if(UtilValidate.isNotEmpty(minimumOrderPriceList)) {
+            minimumOrderPrice = EntityUtil.getFirst(minimumOrderPriceList).getBigDecimal("price");
+        }
+        if(minimumOrderPrice.compareTo(itemBasePrice) > 0) {
+            minQuantity = minimumOrderPrice.divide(itemBasePrice, 0, BigDecimal.ROUND_UP);
+        }
+        return minQuantity;
+    }
 }

Modified: ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartHelper.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartHelper.java?rev=936228&r1=936227&r2=936228&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartHelper.java (original)
+++ ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartHelper.java Wed Apr 21 09:36:40 2010
@@ -776,6 +776,10 @@ public class ShoppingCartHelper {
                                             }
                                         }
                                     } else {
+                                        BigDecimal minQuantity = ShoppingCart.getMinimumOrderQuantity(delegator, item.getBasePrice(), item.getProductId());
+                                        if(quantity.compareTo(minQuantity) < 0) {
+                                            quantity = minQuantity;
+                                        }
                                         item.setQuantity(quantity, dispatcher, this.cart, true, false);
                                         cart.setItemShipGroupQty(item, quantity, 0);
                                     }

Modified: ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/catalog/ProductDetail.groovy
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/catalog/ProductDetail.groovy?rev=936228&r1=936227&r2=936228&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/catalog/ProductDetail.groovy (original)
+++ ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/catalog/ProductDetail.groovy Wed Apr 21 09:36:40 2010
@@ -38,6 +38,7 @@ import org.ofbiz.product.catalog.*;
 import org.ofbiz.product.store.*;
 import org.ofbiz.webapp.stats.VisitHandler;
 import org.ofbiz.order.shoppingcart.ShoppingCartEvents;
+import org.ofbiz.order.shoppingcart.ShoppingCart;
 
 String buildNext(Map map, List order, String current, String prefix, Map featureTypes) {
     def ct = 0;
@@ -363,6 +364,7 @@ if (product) {
                     // make a list of variant sku with requireAmount
                     variantsRes = dispatcher.runSync("getAssociatedProducts", [productId : productId, type : "PRODUCT_VARIANT", checkViewAllow : true, prodCatalogId : currentCatalogId]);
                     variants = variantsRes.assocProducts;
+                    variantPriceList = [];
                     if (variants) {
                         amt = new StringBuffer();
                         amt.append("function checkAmtReq(sku) { ");
@@ -384,6 +386,30 @@ if (product) {
                             if (cart.isSalesOrder()) {
                                 // sales order: run the "calculateProductPrice" service
                                 variantPriceMap = dispatcher.runSync("calculateProductPrice", priceContext);
+                                BigDecimal calculatedPrice = (BigDecimal)variantPriceMap.get("price");
+                                //Get the minimum quantity for varients if MINIMUM_ORDER_PRICE is set for varients.
+                                variantPriceMap.put("minimumQuantity", ShoppingCart.getMinimumOrderQuantity(delegator, calculatedPrice, variant.get("productId")));
+                                Iterator treeMapIter = variantTree.entrySet().iterator();
+                                while (treeMapIter.hasNext()) {
+                                    Map.Entry entry = treeMapIter.next();
+                                    if (entry.getValue() instanceof  Map) {
+                                        Iterator entryIter = entry.getValue().entrySet().iterator();
+                                        while (entryIter.hasNext()) {
+                                            Map.Entry innerentry = entryIter.next();
+                                            if (variant.get("productId").equals(innerentry.getValue().get(0))) {
+                                                variantPriceMap.put("variantName", innerentry.getKey());
+                                                variantPriceMap.put("secondVariantName", entry.getKey());
+                                                break;
+                                            }
+                                        }
+                                    } else if (UtilValidate.isNotEmpty(entry.getValue())) { 
+                                        if (variant.get("productId").equals(entry.getValue().get(0))) {
+                                            variantPriceMap.put("variantName", entry.getKey());
+                                            break;
+                                        }
+                                    }
+                                }
+                                variantPriceList.add(variantPriceMap);
                             } else {
                                 variantPriceMap = dispatcher.runSync("calculatePurchasePrice", priceContext);
                             }
@@ -395,6 +421,7 @@ if (product) {
                         amt.append(" } ");
                         variantPriceJS.append(" } ");
                     }
+                    context.variantPriceList = variantPriceList;
                     jsBuf.append(amt.toString());
                     jsBuf.append(variantPriceJS.toString());
                     jsBuf.append("</script>");
@@ -403,7 +430,9 @@ if (product) {
                 }
             }
         }
-    }
+    } else {
+        context.minimumQuantity= ShoppingCart.getMinimumOrderQuantity(delegator, priceMap.price, productId);
+    } 
 
     //get last inventory count from product facility for the product
     facilities = delegator.findList("ProductFacility", EntityCondition.makeCondition([productId : product.productId]), null, null, null, false);

Modified: ofbiz/trunk/applications/product/data/ProductTypeData.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/data/ProductTypeData.xml?rev=936228&r1=936227&r2=936228&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/data/ProductTypeData.xml (original)
+++ ofbiz/trunk/applications/product/data/ProductTypeData.xml Wed Apr 21 09:36:40 2010
@@ -425,6 +425,7 @@ under the License.
     <ProductPriceType description="Wholesale Price" productPriceTypeId="WHOLESALE_PRICE"/>
     <ProductPriceType description="Special Promo Price" productPriceTypeId="SPECIAL_PROMO_PRICE"/>
     <ProductPriceType description="Box Price" productPriceTypeId="BOX_PRICE"/>
+    <ProductPriceType description="Minimum Order Price" productPriceTypeId="MINIMUM_ORDER_PRICE"/>
 
     <ProductPricePurpose description="Purchase/Initial" productPricePurposeId="PURCHASE"/>
     <ProductPricePurpose description="Recurring Charge" productPricePurposeId="RECURRING_CHARGE"/>

Modified: ofbiz/trunk/specialpurpose/ecommerce/data/DemoProduct.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ecommerce/data/DemoProduct.xml?rev=936228&r1=936227&r2=936228&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/ecommerce/data/DemoProduct.xml (original)
+++ ofbiz/trunk/specialpurpose/ecommerce/data/DemoProduct.xml Wed Apr 21 09:36:40 2010
@@ -329,6 +329,7 @@ under the License.
     <ProductPrice productId="WG-5569" productPricePurposeId="PURCHASE" productPriceTypeId="SPECIAL_PROMO_PRICE" currencyUomId="USD" productStoreGroupId="_NA_" fromDate="2001-05-13 12:00:00.0" price="41.99" createdDate="2001-05-13 12:00:00.0" createdByUserLogin="admin" lastModifiedDate="2001-05-13 12:00:00.0" lastModifiedByUserLogin="admin"/>
     <ProductPrice productId="WG-5569" productPricePurposeId="PURCHASE" productPriceTypeId="DEFAULT_PRICE" currencyUomId="USD" productStoreGroupId="_NA_" fromDate="2001-05-13 12:00:00.0" price="59.99" createdDate="2001-05-13 12:00:00.0" createdByUserLogin="admin" lastModifiedDate="2001-05-13 12:00:00.0" lastModifiedByUserLogin="admin"/>
     <ProductPrice productId="WG-5569" productPricePurposeId="PURCHASE" productPriceTypeId="LIST_PRICE" currencyUomId="USD" productStoreGroupId="_NA_" fromDate="2001-05-13 12:00:00.0" price="60.0" createdDate="2001-05-13 12:00:00.0" createdByUserLogin="admin" lastModifiedDate="2001-05-13 12:00:00.0" lastModifiedByUserLogin="admin"/>
+    <ProductPrice productId="WG-5569" productPricePurposeId="PURCHASE" productPriceTypeId="MINIMUM_ORDER_PRICE" currencyUomId="USD" productStoreGroupId="_NA_" fromDate="2001-05-13 12:00:00.0" price="100.0" createdDate="2001-05-13 12:00:00.0" createdByUserLogin="admin" lastModifiedDate="2001-05-13 12:00:00.0" lastModifiedByUserLogin="admin"/>
     <ProductPrice productId="WG-9943" productPricePurposeId="PURCHASE" productPriceTypeId="DEFAULT_PRICE" currencyUomId="USD" productStoreGroupId="_NA_" fromDate="2001-05-13 12:00:00.0" price="549.99" createdDate="2001-05-13 12:00:00.0" createdByUserLogin="admin" lastModifiedDate="2001-05-13 12:00:00.0" lastModifiedByUserLogin="admin"/>
     <ProductPrice productId="WG-9943" productPricePurposeId="PURCHASE" productPriceTypeId="LIST_PRICE" currencyUomId="USD" productStoreGroupId="_NA_" fromDate="2001-05-13 12:00:00.0" price="550.0" createdDate="2001-05-13 12:00:00.0" createdByUserLogin="admin" lastModifiedDate="2001-05-13 12:00:00.0" lastModifiedByUserLogin="admin"/>
     <ProductPrice productId="WG-9943" productPricePurposeId="PURCHASE" productPriceTypeId="COMPETITIVE_PRICE" currencyUomId="USD" productStoreGroupId="_NA_" fromDate="2001-05-13 12:00:00.0" price="922.0" createdDate="2001-05-13 12:00:00.0" createdByUserLogin="admin" lastModifiedDate="2001-05-13 12:00:00.0" lastModifiedByUserLogin="admin"/>

Modified: ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/catalog/configproductdetail.ftl
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/catalog/configproductdetail.ftl?rev=936228&r1=936227&r2=936228&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/catalog/configproductdetail.ftl (original)
+++ ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/catalog/configproductdetail.ftl Wed Apr 21 09:36:40 2010
@@ -357,6 +357,9 @@ function getConfigDetails(event) {
             <#else>
               <a href="javascript:addItem()" class="buttontext"><span style="white-space: nowrap;">${uiLabelMap.OrderAddToCart}</span></a>&nbsp;
               <input type="text" size="5" name="quantity" value="1" />
+                <#if minimumQuantity?exists &&  minimumQuantity &gt; 0 >
+                  Minimum order quantity is ${minimumQuantity}.
+               </#if>
             </#if>
           </#if>
           <#if requestParameters.category_id?exists>

Modified: ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/catalog/productdetail.ftl
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/catalog/productdetail.ftl?rev=936228&r1=936227&r2=936228&view=diff
==============================================================================
--- ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/catalog/productdetail.ftl (original)
+++ ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/catalog/productdetail.ftl Wed Apr 21 09:36:40 2010
@@ -566,6 +566,18 @@ ${virtualJavaScript?if_exists}
               </#if>
           </#if>
         </#if>
+        <#if variantPriceList?exists>
+          <#list variantPriceList as vpricing>
+            <#assign variantName = vpricing.get("variantName")?if_exists>
+            <#assign secondVariantName = vpricing.get("secondVariantName")?if_exists>
+            <#assign minimumQuantity = vpricing.get("minimumQuantity")>
+            <#if minimumQuantity &gt; 0>
+              <div>minimum order quantity for ${secondVariantName!} ${variantName!} is ${minimumQuantity!}.</div>
+            </#if>
+          </#list>
+        <#elseif minimumQuantity?exists && minimumQuantity?has_content && minimumQuantity &gt; 0>
+           <div>minimum order quantity for ${productContentWrapper.get("PRODUCT_NAME")?if_exists} is ${minimumQuantity!}.</div>
+        </#if>
         </fieldset>
       </form>
     </div>