svn commit: r882618 - in /ofbiz/trunk/applications: order/webapp/ordermgr/WEB-INF/actions/entry/catalog/ order/webapp/ordermgr/entry/catalog/ product/servicedef/ product/src/org/ofbiz/product/product/

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r882618 - in /ofbiz/trunk/applications: order/webapp/ordermgr/WEB-INF/actions/entry/catalog/ order/webapp/ordermgr/entry/catalog/ product/servicedef/ product/src/org/ofbiz/product/product/

ashish-18
Author: ashish
Date: Fri Nov 20 15:54:39 2009
New Revision: 882618

URL: http://svn.apache.org/viewvc?rev=882618&view=rev
Log:
Applied patch from jira issue OFBIZ-3077 - Error for productStoreId when click on productId link from showcart of purchase order.

Steps regenerate error:
1) Hit url: https://localhost:8443/ordermgr/control/orderentry
2) Select purchase order with supplier
3) Add product for order
4) Click on the productId from showcart page

it will generate error as following
org.ofbiz.widget.screen.ScreenRenderException: Error rendering screen component://order/widget/ordermgr/OrderEntryCatalogScreens.xml#productdetail: java.lang.NullPointerException: Cannot get property 'productStoreId' on null object (Cannot get property 'productStoreId' on null object)

Notes from Mridul:
As Joe has already stated that we need to do few adjustments in the code based on presence of productStoreId. I would vote for:

   1. Showing all reviews.
   2. Skipping surveys.

The third section, which is the most important one and needs productStoreId is getProductVariantTree service invoked in ProductDetail.groovy (line 232). getProductVariantTree service needs productStoreId to get available inventory. In case of PO's we don't need to check for available inventory at all. Now for being able to use the same code to display product detail page in case of a PO, we will need to make modifications to getProductVariantTree service too, which can be done in two ways:

   1. Add a boolean IN attribute checkInventory to service definition, if its true check the available inventory and if false do not.
   2. A check on productStoreId in the implementation can serve our purpose too.

I like #1 more as it won't eliminate importance of productStoreId in case of a sales order. Looking forward to suggestions from community to handle this situation.

Thanks Amit for the contribution. Mridul Thanks a lot for providing useful notes for the implementation.
Guys, I appreciate your coordination on this!

Modified:
    ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/catalog/ProductDetail.groovy
    ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/catalog/ProductSummary.groovy
    ofbiz/trunk/applications/order/webapp/ordermgr/entry/catalog/productdetail.ftl
    ofbiz/trunk/applications/product/servicedef/services_view.xml
    ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductServices.java

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=882618&r1=882617&r2=882618&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 Fri Nov 20 15:54:39 2009
@@ -137,11 +137,15 @@
         }
     }
 
-    // get the product store
-    productStore = ProductStoreWorker.getProductStore(request);
-    productStoreId = productStore.productStoreId;
-    context.productStoreId = productStoreId;
-
+    // get the product store for only Sales Order not for Purchase Order.
+    productStore = null;
+    productStoreId = null;
+    cart = ShoppingCartEvents.getCartObject(request);
+    if (cart.isSalesOrder()) {
+        productStore = ProductStoreWorker.getProductStore(request);
+        productStoreId = productStore.productStoreId;
+        context.productStoreId = productStoreId;
+    }
     // get a defined survey
     productSurvey = ProductStoreWorker.getProductSurveys(delegator, productStoreId, productId, "CART_ADD");
     if (productSurvey) {
@@ -176,8 +180,13 @@
         context.priceMap = priceMap;
     }
 
-    // get the product review(s)
-    reviewByAnd = [statusId : "PRR_APPROVED", productStoreId : productStoreId];
+    // get the product review(s)
+    // get all product review in case of Purchase Order.
+    reviewByAnd = [:];
+    reviewByAnd.statusId = "PRR_APPROVED";
+    if (cart.isSalesOrder()) {
+        reviewByAnd.productStoreId = productStoreId;
+    }
     reviews = product.getRelatedCache("ProductReview", reviewByAnd, ["-postedDateTime"]);
     context.productReviews = reviews;
     // get the average rating
@@ -190,18 +199,20 @@
     }
 
     // get the days to ship
-
-    facilityId = productStore.inventoryFacilityId;
-    /*
-    productFacility = delegator.findByPrimaryKeyCache("ProductFacility", [productId : productId, facilityId : facilityId);
-    context.daysToShip = productFacility?.daysToShip
-    */
-
-    resultOutput = dispatcher.runSync("getInventoryAvailableByFacility", [productId : productId, facilityId : facilityId, useCache : false]);
-    totalAvailableToPromise = resultOutput.availableToPromiseTotal;
-    if (totalAvailableToPromise) {
-        productFacility = delegator.findByPrimaryKeyCache("ProductFacility", [productId : productId, facilityId : facilityId]);
+    // if order is purchase then don't calculate available inventory for product.
+    if (cart.isSalesOrder()) {
+        facilityId = productStore.inventoryFacilityId;
+        /*
+        productFacility = delegator.findByPrimaryKeyCache("ProductFacility", [productId : productId, facilityId : facilityId);
         context.daysToShip = productFacility?.daysToShip
+        */
+
+        resultOutput = dispatcher.runSync("getInventoryAvailableByFacility", [productId : productId, facilityId : facilityId, useCache : false]);
+        totalAvailableToPromise = resultOutput.availableToPromiseTotal;
+        if (totalAvailableToPromise) {
+            productFacility = delegator.findByPrimaryKeyCache("ProductFacility", [productId : productId, facilityId : facilityId]);
+            context.daysToShip = productFacility?.daysToShip
+        }
     } else {
        supplierProducts = delegator.findByAndCache("SupplierProduct", [productId : productId], ["-availableFromDate"]);
        supplierProduct = EntityUtil.getFirst(supplierProducts);
@@ -229,7 +240,12 @@
             featureMap = dispatcher.runSync("getProductFeatureSet", [productId : productId]);
             featureSet = featureMap.featureSet;
             if (featureSet) {
-                variantTreeMap = dispatcher.runSync("getProductVariantTree", [productId : productId, featureOrder : featureSet, productStoreId : productStoreId]);
+                //if order is purchase then don't calculate available inventory for product.
+                if (cart.isPurchaseOrder()) {
+                    variantTreeMap = dispatcher.runSync("getProductVariantTree", [productId : productId, featureOrder : featureSet, checkInventory: false]);
+                } else {
+                    variantTreeMap = dispatcher.runSync("getProductVariantTree", [productId : productId, featureOrder : featureSet, productStoreId : productStoreId]);
+                }
                 variantTree = variantTreeMap.variantTree;
                 imageMap = variantTreeMap.variantSample;
                 virtualVariant = variantTreeMap.virtualVariant;
@@ -349,21 +365,27 @@
                         variantPriceJS = new StringBuffer();
                         variantPriceJS.append("function getVariantPrice(sku) { ");
                         // Format to apply the currency code to the variant price in the javascript
-                        localeString = productStore.defaultLocaleString;
-                        if (localeString) {
-                            locale = UtilMisc.parseLocale(localeString);
+                        if (productStore) {
+                            localeString = productStore.defaultLocaleString;
+                            if (localeString) {
+                                locale = UtilMisc.parseLocale(localeString);
+                            }
                         }
                         numberFormat = NumberFormat.getCurrencyInstance(locale);
                         variants.each { variantAssoc ->
                             variant = variantAssoc.getRelatedOne("AssocProduct");
                             // Get the price for each variant. Reuse the priceContext already setup for virtual product above and replace the product
+                            priceContext.product = variant;
                             if (cart.isSalesOrder()) {
                                 // sales order: run the "calculateProductPrice" service
-                                priceContext.product = variant;
+                                variantPriceMap = dispatcher.runSync("calculateProductPrice", priceContext);
+                            } else {
                                 variantPriceMap = dispatcher.runSync("calculateProductPrice", priceContext);
                             }
                             amt.append(" if (sku == \"" + variant.productId + "\") return \"" + (variant.requireAmount ?: "N") + "\"; ");
-                            variantPriceJS.append("  if (sku == \"" + variant.productId + "\") return \"" + numberFormat.format(variantPriceMap.basePrice) + "\"; ");
+                            if (variantPriceMap) {
+                                variantPriceJS.append("  if (sku == \"" + variant.productId + "\") return \"" + numberFormat.format(variantPriceMap.basePrice) + "\"; ");
+                            }
                         }
                         amt.append(" } ");
                         variantPriceJS.append(" } ");

Modified: ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/catalog/ProductSummary.groovy
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/catalog/ProductSummary.groovy?rev=882618&r1=882617&r2=882618&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/catalog/ProductSummary.groovy (original)
+++ ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/catalog/ProductSummary.groovy Fri Nov 20 15:54:39 2009
@@ -40,12 +40,18 @@
 
 webSiteId = CatalogWorker.getWebSiteId(request);
 catalogId = CatalogWorker.getCurrentCatalogId(request);
-productStore = ProductStoreWorker.getProductStore(request);
-facilityId = productStore.inventoryFacilityId;
-productStoreId = productStore.productStoreId;
+cart = ShoppingCartEvents.getCartObject(request);
+productStore = null;
+productStoreId = null;
+facilityId = null;
+if (cart.isSalesOrder()) {
+    productStore = ProductStoreWorker.getProductStore(request);
+    productStoreId = productStore.productStoreId;
+    context.productStoreId = productStoreId;
+    facilityId = productStore.inventoryFacilityId;
+}
 autoUserLogin = session.getAttribute("autoUserLogin");
 userLogin = session.getAttribute("userLogin");
-cart = ShoppingCartEvents.getCartObject(request);
 
 context.remove("daysToShip");
 context.remove("averageRating");
@@ -57,12 +63,15 @@
     product = delegator.findByPrimaryKeyCache("Product", [productId : productId]);
 }
 if (product) {
-    resultOutput = dispatcher.runSync("getInventoryAvailableByFacility", [productId : product.productId, facilityId : facilityId, useCache : true]);
-    totalAvailableToPromise = resultOutput.availableToPromiseTotal;
-    if (totalAvailableToPromise && totalAvailableToPromise.doubleValue() > 0) {
-        productFacility = delegator.findByPrimaryKeyCache("ProductFacility", [productId : product.productId, facilityId : facilityId]);
-        if (productFacility?.daysToShip != null) {
-            context.daysToShip = productFacility.daysToShip;
+    //if order is purchase then don't calculate available inventory for product.
+    if (cart.isSalesOrder()) {
+        resultOutput = dispatcher.runSync("getInventoryAvailableByFacility", [productId : product.productId, facilityId : facilityId, useCache : true]);
+        totalAvailableToPromise = resultOutput.availableToPromiseTotal;
+        if (totalAvailableToPromise && totalAvailableToPromise.doubleValue() > 0) {
+            productFacility = delegator.findByPrimaryKeyCache("ProductFacility", [productId : product.productId, facilityId : facilityId]);
+            if (productFacility?.daysToShip != null) {
+                context.daysToShip = productFacility.daysToShip;
+            }
         }
     } else {
        supplierProducts = delegator.findByAndCache("SupplierProduct", [productId : product.productId], ["-availableFromDate"]);
@@ -140,7 +149,6 @@
 sizeProductFeatureAndAppls = delegator.findByAnd("ProductFeatureAndAppl", [productId : productId, productFeatureTypeId : "SIZE"], ["sequenceNum", "defaultSequenceNum"]);
 
 context.product = product;
-context.productStoreId = productStoreId;
 context.categoryId = categoryId;
 context.productReviews = reviews;
 context.sizeProductFeatureAndAppls = sizeProductFeatureAndAppls;

Modified: ofbiz/trunk/applications/order/webapp/ordermgr/entry/catalog/productdetail.ftl
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/webapp/ordermgr/entry/catalog/productdetail.ftl?rev=882618&r1=882617&r2=882618&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/webapp/ordermgr/entry/catalog/productdetail.ftl (original)
+++ ofbiz/trunk/applications/order/webapp/ordermgr/entry/catalog/productdetail.ftl Fri Nov 20 15:54:39 2009
@@ -470,14 +470,16 @@
         <#else>
           <input type="hidden" name="product_id" value="${product.productId}"/>
           <input type="hidden" name="add_product_id" value="${product.productId}"/>
-          <#assign isStoreInventoryNotAvailable = !(Static["org.ofbiz.product.store.ProductStoreWorker"].isStoreInventoryAvailable(request, product, 1.0?double))>
-          <#assign isStoreInventoryRequired = Static["org.ofbiz.product.store.ProductStoreWorker"].isStoreInventoryRequired(request, product)>
-          <#if isStoreInventoryNotAvailable>
-            <#if isStoreInventoryRequired>
-              <div><b>${uiLabelMap.ProductItemOutOfStock}.</b></div>
-              <#assign inStock = false>
-            <#else>
-              <div><b>${product.inventoryMessage?if_exists}</b></div>
+          <#if productStoreId?exists>
+            <#assign isStoreInventoryNotAvailable = !(Static["org.ofbiz.product.store.ProductStoreWorker"].isStoreInventoryAvailable(request, product, 1.0?double))>
+            <#assign isStoreInventoryRequired = Static["org.ofbiz.product.store.ProductStoreWorker"].isStoreInventoryRequired(request, product)>
+            <#if isStoreInventoryNotAvailable>
+              <#if isStoreInventoryRequired>
+                <div><b>${uiLabelMap.ProductItemOutOfStock}.</b></div>
+                <#assign inStock = false>
+              <#else>
+                <div><b>${product.inventoryMessage?if_exists}</b></div>
+              </#if>
             </#if>
           </#if>
         </#if>
@@ -526,7 +528,7 @@
         <form name="addToShoppingList" method="post" action="<@ofbizUrl>addItemToShoppingList<#if requestAttributes._CURRENT_VIEW_?exists>/${requestAttributes._CURRENT_VIEW_}</#if></@ofbizUrl>">
           <input type="hidden" name="productId" value="${product.productId}"/>
           <input type="hidden" name="product_id" value="${product.productId}"/>
-          <input type="hidden" name="productStoreId" value="${productStoreId}"/>
+          <input type="hidden" name="productStoreId" value="${productStoreId?if_exists}"/>
           <input type="hidden" name="reservStart" value= ""/>
           <select name="shoppingListId">
             <#if shoppingLists?has_content>

Modified: ofbiz/trunk/applications/product/servicedef/services_view.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/servicedef/services_view.xml?rev=882618&r1=882617&r2=882618&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/servicedef/services_view.xml (original)
+++ ofbiz/trunk/applications/product/servicedef/services_view.xml Fri Nov 20 15:54:39 2009
@@ -50,7 +50,8 @@
         <description>Gets a tree of product variants based on a virtual product and a list of features.</description>
         <attribute name="productId" type="String" mode="IN"/>
         <attribute name="featureOrder" type="java.util.Collection" mode="IN"/>
-        <attribute name="productStoreId" type="String" mode="IN"/>
+        <attribute name="productStoreId" type="String" mode="IN" optional="true"/>
+        <attribute name="checkInventory" type="Boolean" mode="IN" default-value="true" optional="true"/>
         <attribute name="variantTree" type="java.util.Map" mode="OUT" optional="true"/>
         <attribute name="variantSample" type="java.util.Map" mode="OUT" optional="true"/>
         <attribute name="virtualVariant" type="java.util.List" mode="OUT" optional="true"/>

Modified: ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductServices.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductServices.java?rev=882618&r1=882617&r2=882618&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductServices.java (original)
+++ ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductServices.java Fri Nov 20 15:54:39 2009
@@ -187,6 +187,7 @@
     public static Map<String, Object> prodMakeFeatureTree(DispatchContext dctx, Map<String, ? extends Object> context) {
         // * String productId      -- Parent (virtual) product ID
         // * List featureOrder     -- Order of features
+        // * Boolean checkInventory-- To calculate available inventory.
         // * String productStoreId -- Product Store ID for Inventory
         String productStoreId = (String) context.get("productStoreId");
         Locale locale = (Locale) context.get("locale");
@@ -251,11 +252,19 @@
             }
 
             // next check inventory for each item: if inventory is not required or is available
+            Boolean checkInventory = (Boolean) context.get("checkInventory");
             try {
-                Map<String, Object> invReqResult = dispatcher.runSync("isStoreInventoryAvailableOrNotRequired", UtilMisc.<String, Object>toMap("productStoreId", productStoreId, "productId", productIdTo, "quantity", BigDecimal.ONE));
-                if (ServiceUtil.isError(invReqResult)) {
-                    return ServiceUtil.returnError("Error calling the isStoreInventoryRequired when building the variant product tree.", null, null, invReqResult);
-                } else if ("Y".equals((String) invReqResult.get("availableOrNotRequired"))) {
+                if (checkInventory) {
+                    Map<String, Object> invReqResult = dispatcher.runSync("isStoreInventoryAvailableOrNotRequired", UtilMisc.<String, Object>toMap("productStoreId", productStoreId, "productId", productIdTo, "quantity", BigDecimal.ONE));
+                    if (ServiceUtil.isError(invReqResult)) {
+                        return ServiceUtil.returnError("Error calling the isStoreInventoryRequired when building the variant product tree.", null, null, invReqResult);
+                    } else if ("Y".equals((String) invReqResult.get("availableOrNotRequired"))) {
+                        items.add(productIdTo);
+                        if (productTo.getString("isVirtual") != null && productTo.getString("isVirtual").equals("Y")) {
+                            virtualVariant.add(productIdTo);
+                        }
+                    }
+                } else {
                     items.add(productIdTo);
                     if (productTo.getString("isVirtual") != null && productTo.getString("isVirtual").equals("Y")) {
                         virtualVariant.add(productIdTo);