svn commit: r613216 - in /ofbiz/trunk/applications: ecommerce/webapp/ecommerce/shoppinglist/ manufacturing/src/org/ofbiz/manufacturing/jobshopmgt/ order/data/ order/entitydef/ order/script/org/ofbiz/order/quote/ order/script/org/ofbiz/order/request/ or...

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

svn commit: r613216 - in /ofbiz/trunk/applications: ecommerce/webapp/ecommerce/shoppinglist/ manufacturing/src/org/ofbiz/manufacturing/jobshopmgt/ order/data/ order/entitydef/ order/script/org/ofbiz/order/quote/ order/script/org/ofbiz/order/request/ or...

bibryam
Author: bibryam
Date: Fri Jan 18 09:47:01 2008
New Revision: 613216

URL: http://svn.apache.org/viewvc?rev=613216&view=rev
Log:
Applied my (modified) patch from JIRA Issue # OFBIZ-1453 "store/load possibility for AGGREGATED product configurations".

Modified:
    ofbiz/trunk/applications/ecommerce/webapp/ecommerce/shoppinglist/editShoppingList.ftl
    ofbiz/trunk/applications/manufacturing/src/org/ofbiz/manufacturing/jobshopmgt/ProductionRunServices.java
    ofbiz/trunk/applications/order/data/OrderTypeData.xml
    ofbiz/trunk/applications/order/entitydef/entitymodel.xml
    ofbiz/trunk/applications/order/script/org/ofbiz/order/quote/QuoteServices.xml
    ofbiz/trunk/applications/order/script/org/ofbiz/order/request/CustRequestServices.xml
    ofbiz/trunk/applications/order/servicedef/services_shoppinglist.xml
    ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/CartEventListener.java
    ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/CheckOutHelper.java
    ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCart.java
    ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartEvents.java
    ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartHelper.java
    ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartItem.java
    ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartServices.java
    ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppinglist/ShoppingListEvents.java
    ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppinglist/ShoppingListServices.java
    ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/catalog/prepareconfigform.bsh
    ofbiz/trunk/applications/order/webapp/ordermgr/entry/catalog/configproductdetail.ftl
    ofbiz/trunk/applications/order/widget/ordermgr/OrderEntryForms.xml
    ofbiz/trunk/applications/product/data/ProductTypeData.xml
    ofbiz/trunk/applications/product/entitydef/entitymodel.xml
    ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigWorker.java
    ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigWrapper.java
    ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductWorker.java

Modified: ofbiz/trunk/applications/ecommerce/webapp/ecommerce/shoppinglist/editShoppingList.ftl
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/ecommerce/webapp/ecommerce/shoppinglist/editShoppingList.ftl?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/ecommerce/webapp/ecommerce/shoppinglist/editShoppingList.ftl (original)
+++ ofbiz/trunk/applications/ecommerce/webapp/ecommerce/shoppinglist/editShoppingList.ftl Fri Jan 18 09:47:01 2008
@@ -446,7 +446,7 @@
                           <a href="javascript:document.listreplform_${shoppingListItem.shoppingListItemSeqId}.action='<@ofbizUrl>${addToCartAction}</@ofbizUrl>';document.listreplform_${shoppingListItem.shoppingListItemSeqId}.submit();" class="buttontext">[${uiLabelMap.CommonAdd}&nbsp;${shoppingListItem.quantity?string}&nbsp;${uiLabelMap.EcommerceVariationToCart}]</a>
                         </form>
                       <#else>
-                        <a href="<@ofbizUrl>additem<#if requestAttributes._CURRENT_VIEW_?exists>/${requestAttributes._CURRENT_VIEW_}</#if>?shoppingListId=${shoppingListItem.shoppingListId}&shoppingListItemSeqId=${shoppingListItem.shoppingListItemSeqId}&quantity=${shoppingListItem.quantity}&reservStart=${shoppingListItem.reservStart?if_exists}&reservPersons=${shoppingListItem.reservPersons?if_exists}&reservLength=${shoppingListItem.reservLength?if_exists}&add_product_id=${shoppingListItem.productId}</@ofbizUrl>" class="buttontext">[${uiLabelMap.CommonAdd}&nbsp;${shoppingListItem.quantity?string}&nbsp;${uiLabelMap.EcommerceToCart}]</a>
+                        <a href="<@ofbizUrl>additem<#if requestAttributes._CURRENT_VIEW_?exists>/${requestAttributes._CURRENT_VIEW_}</#if>?shoppingListId=${shoppingListItem.shoppingListId}&shoppingListItemSeqId=${shoppingListItem.shoppingListItemSeqId}&quantity=${shoppingListItem.quantity}&reservStart=${shoppingListItem.reservStart?if_exists}&reservPersons=${shoppingListItem.reservPersons?if_exists}&reservLength=${shoppingListItem.reservLength?if_exists}&configId=${shoppingListItem.configId?if_exists}&add_product_id=${shoppingListItem.productId}</@ofbizUrl>" class="buttontext">[${uiLabelMap.CommonAdd}&nbsp;${shoppingListItem.quantity?string}&nbsp;${uiLabelMap.EcommerceToCart}]</a>
                       </#if>
                     </td>
                   </tr>

Modified: ofbiz/trunk/applications/manufacturing/src/org/ofbiz/manufacturing/jobshopmgt/ProductionRunServices.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/manufacturing/src/org/ofbiz/manufacturing/jobshopmgt/ProductionRunServices.java?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/manufacturing/src/org/ofbiz/manufacturing/jobshopmgt/ProductionRunServices.java (original)
+++ ofbiz/trunk/applications/manufacturing/src/org/ofbiz/manufacturing/jobshopmgt/ProductionRunServices.java Fri Jan 18 09:47:01 2008
@@ -48,6 +48,7 @@
 import org.ofbiz.manufacturing.techdata.TechDataServices;
 import org.ofbiz.product.config.ProductConfigWrapper;
 import org.ofbiz.product.config.ProductConfigWrapper.ConfigOption;
+import org.ofbiz.product.product.ProductWorker;
 import org.ofbiz.service.DispatchContext;
 import org.ofbiz.service.GenericServiceException;
 import org.ofbiz.service.LocalDispatcher;
@@ -2030,9 +2031,16 @@
         if (quantity == null) {
             quantity = new Double(1);
         }
+        String instanceProductId = null;
+        try {
+            instanceProductId = ProductWorker.getAggregatedInstanceId(delegator, config.getProduct().getString("productId"), config.getConfigId());
+        } catch (Exception e) {
+            return ServiceUtil.returnError(e.getMessage());
+        }
+
         Map serviceContext = new HashMap();
         serviceContext.clear();
-        serviceContext.put("productId", config.getProduct().getString("productId"));
+        serviceContext.put("productId", instanceProductId);
         serviceContext.put("pRQuantity", quantity);
         serviceContext.put("startDate", UtilDateTime.nowTimestamp());
         serviceContext.put("facilityId", facilityId);

Modified: ofbiz/trunk/applications/order/data/OrderTypeData.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/data/OrderTypeData.xml?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/data/OrderTypeData.xml (original)
+++ ofbiz/trunk/applications/order/data/OrderTypeData.xml Fri Jan 18 09:47:01 2008
@@ -263,7 +263,7 @@
     <ReturnItemTypeMap returnHeaderTypeId="CUSTOMER_RETURN" returnItemMapKey="FINISHED_GOOD" returnItemTypeId="RET_FPROD_ITEM"/>
     <ReturnItemTypeMap returnHeaderTypeId="CUSTOMER_RETURN" returnItemMapKey="MARKETING_PKG_AUTO" returnItemTypeId="RET_FPROD_ITEM"/>
     <ReturnItemTypeMap returnHeaderTypeId="CUSTOMER_RETURN" returnItemMapKey="MARKETING_PKG_PICK" returnItemTypeId="RET_FPROD_ITEM"/>
-    <ReturnItemTypeMap returnHeaderTypeId="CUSTOMER_RETURN" returnItemMapKey="AGGREGATED" returnItemTypeId="RET_FPROD_ITEM"/>
+    <ReturnItemTypeMap returnHeaderTypeId="CUSTOMER_RETURN" returnItemMapKey="AGGREGATED_CONF" returnItemTypeId="RET_FPROD_ITEM"/>
     <ReturnItemTypeMap returnHeaderTypeId="CUSTOMER_RETURN" returnItemMapKey="DIGITAL_GOOD" returnItemTypeId="RET_DPROD_ITEM"/>
     <ReturnItemTypeMap returnHeaderTypeId="CUSTOMER_RETURN" returnItemMapKey="FINDIG_GOOD" returnItemTypeId="RET_FDPROD_ITEM"/>
     <ReturnItemTypeMap returnHeaderTypeId="CUSTOMER_RETURN" returnItemMapKey="PROMOTION_ADJUSTMENT" returnItemTypeId="RET_PROMOTION_ADJ"/>

Modified: ofbiz/trunk/applications/order/entitydef/entitymodel.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/entitydef/entitymodel.xml?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/entitydef/entitymodel.xml (original)
+++ ofbiz/trunk/applications/order/entitydef/entitymodel.xml Fri Jan 18 09:47:01 2008
@@ -1345,6 +1345,7 @@
       <field name="reservStart" type="date-time"></field>
       <field name="reservLength" type="floating-point"></field>
       <field name="reservPersons" type="floating-point"></field>            
+      <field name="configId" type="id"></field>
       <field name="estimatedDeliveryDate" type="date-time"></field>
       <field name="comments" type="comment"></field>
       <field name="isPromo" type="indicator"></field>
@@ -1672,6 +1673,7 @@
       <field name="reservStart" type="date-time"></field>
       <field name="reservLength" type="floating-point"></field>
       <field name="reservPersons" type="floating-point"></field>      
+      <field name="configId" type="id"></field>
       <field name="description" type="description"></field>
       <field name="story" type="very-long"></field>
       <prim-key field="custRequestId"/>
@@ -2493,6 +2495,7 @@
       <field name="unitPrice" type="currency-amount"></field>
       <field name="reserv2ndPPPerc" type="floating-point"/>
       <field name="reservNthPPPerc" type="floating-point"/>
+      <field name="configId" type="id"></field>
       <field name="totalWithAdjustments" type="currency-amount"></field>
       <field name="wasReserved" type="indicator"></field>
       <prim-key field="visitId"/>
@@ -2592,6 +2595,7 @@
       <field name="reservLength" type="floating-point"></field>
       <field name="reservPersons" type="floating-point"></field>
       <field name="quantityPurchased" type="floating-point"></field>
+      <field name="configId" type="id"></field>
       <prim-key field="shoppingListId"/>
       <prim-key field="shoppingListItemSeqId"/>
       <relation type="one" fk-name="SHLIST_ITEM_LIST" rel-entity-name="ShoppingList">

Modified: ofbiz/trunk/applications/order/script/org/ofbiz/order/quote/QuoteServices.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/script/org/ofbiz/order/quote/QuoteServices.xml?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/script/org/ofbiz/order/quote/QuoteServices.xml (original)
+++ ofbiz/trunk/applications/order/script/org/ofbiz/order/quote/QuoteServices.xml Fri Jan 18 09:47:01 2008
@@ -696,6 +696,11 @@
             <if-compare field-name="isPromo" value="true" operator="equals" type="Boolean">
                 <set value="Y" field="createQuoteItemInMap.isPromo"/>
             </if-compare>
+            <call-object-method obj-field-name="item" method-name="getConfigWrapper" ret-field-name="configWrapper"/>
+            <if-not-empty field-name="configWrapper">
+                <call-object-method obj-field-name="configWrapper" method-name="getConfigId" ret-field-name="configId"/>
+                <set from-field="configId" field="createQuoteItemInMap.configId"/>
+            </if-not-empty>
             <if>
                 <condition>
                     <or>
@@ -810,6 +815,7 @@
             <set field="createQuoteItemInMap.reservStart" from-field="custRequestItem.reservStart"/>
             <set field="createQuoteItemInMap.reservLength" from-field="custRequestItem.reservLength"/>
             <set field="createQuoteItemInMap.reservPersons" from-field="custRequestItem.reservPersons"/>          
+            <set field="createQuoteItemInMap.configId" from-field="custRequestItem.configId"/>
             <call-service service-name="createQuoteItem" in-map-name="createQuoteItemInMap"/>
         </iterate>
         <!-- roles -->

Modified: ofbiz/trunk/applications/order/script/org/ofbiz/order/request/CustRequestServices.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/script/org/ofbiz/order/request/CustRequestServices.xml?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/script/org/ofbiz/order/request/CustRequestServices.xml (original)
+++ ofbiz/trunk/applications/order/script/org/ofbiz/order/request/CustRequestServices.xml Fri Jan 18 09:47:01 2008
@@ -211,6 +211,11 @@
         <iterate list-name="items" entry-name="item">
             <!-- a new request item is created -->
             <clear-field field-name="createCustRequestItemInMap"/>
+            <call-object-method obj-field-name="item" method-name="getConfigWrapper" ret-field-name="configWrapper"/>
+            <if-not-empty field-name="configWrapper">
+                <call-object-method obj-field-name="configWrapper" method-name="getConfigId" ret-field-name="configId"/>
+                <set from-field="configId" field="createCustRequestItemInMap.configId"/>
+            </if-not-empty>
             <call-object-method obj-field-name="item" method-name="getIsPromo" ret-field-name="isPromo"/>
             <if-compare field-name="isPromo" value="false" operator="equals" type="Boolean">
                 <set from-field="custRequest.custRequestId" field="createCustRequestItemInMap.custRequestId"/>

Modified: ofbiz/trunk/applications/order/servicedef/services_shoppinglist.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/servicedef/services_shoppinglist.xml?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/servicedef/services_shoppinglist.xml (original)
+++ ofbiz/trunk/applications/order/servicedef/services_shoppinglist.xml Fri Jan 18 09:47:01 2008
@@ -105,6 +105,7 @@
         <attribute name="reservLength" type="Double" mode="IN" optional="true"/>
         <attribute name="reservPersons" type="Double" mode="IN" optional="true"/>
         <attribute name="quantityPurchased" type="Double" mode="IN" optional="true"/>
+        <attribute name="configId" type="String" mode="IN" optional="true"/>
     </service>
     <service name="createShoppingListItem" engine="simple" auth="true"
             location="org/ofbiz/order/shoppinglist/ShoppingListServices.xml" invoke="createShoppingListItem">

Modified: ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/CartEventListener.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/CartEventListener.java?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/CartEventListener.java (original)
+++ ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/CartEventListener.java Fri Jan 18 09:47:01 2008
@@ -92,6 +92,9 @@
                 cartAbandonedLine.set("unitPrice", new Double(cartItem.getBasePrice()));
                 cartAbandonedLine.set("reserv2ndPPPerc", new Double(cartItem.getReserv2ndPPPerc()));
                 cartAbandonedLine.set("reservNthPPPerc", new Double(cartItem.getReservNthPPPerc()));
+                if (cartItem.getConfigWrapper() != null) {
+                    cartAbandonedLine.set("configId", cartItem.getConfigWrapper().getConfigId());
+                }
                 cartAbandonedLine.set("totalWithAdjustments", new Double(cartItem.getItemSubTotal()));
                 //not doing pre-reservations now, so this is always N
                 cartAbandonedLine.set("wasReserved", "N");

Modified: ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/CheckOutHelper.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/CheckOutHelper.java?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/CheckOutHelper.java (original)
+++ ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/CheckOutHelper.java Fri Jan 18 09:47:01 2008
@@ -630,7 +630,7 @@
                     GenericValue permUserLogin = delegator.findByPrimaryKeyCache("UserLogin", UtilMisc.toMap("userLoginId", "system"));
                     GenericValue productStore = ProductStoreWorker.getProductStore(productStoreId, delegator);
                     GenericValue product = delegator.findByPrimaryKey("Product", UtilMisc.toMap("productId", productId));
-                    if ("AGGREGATED".equals(product.getString("productTypeId"))) {
+                    if ("AGGREGATED_CONF".equals(product.getString("productTypeId"))) {
                         org.ofbiz.product.config.ProductConfigWrapper config = this.cart.findCartItem(counter).getConfigWrapper();
                         Map inputMap = new HashMap();
                         inputMap.put("config", config);

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=613216&r1=613215&r2=613216&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 Fri Jan 18 09:47:01 2008
@@ -39,6 +39,7 @@
 import org.ofbiz.product.product.ProductWorker;
 import org.ofbiz.product.store.ProductStoreWorker;
 import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ServiceUtil;
 
 import java.io.Serializable;
 import java.math.BigDecimal;
@@ -532,6 +533,11 @@
     }
 
     /** Add an item to the shopping cart. */
+    public int addItemToEnd(String productId, Double amount, double quantity, Double unitPrice, HashMap features, HashMap attributes, String prodCatalogId, String itemType, ProductConfigWrapper configWrapper, LocalDispatcher dispatcher, Boolean triggerExternalOps, Boolean triggerPriceRules) throws CartItemModifyException, ItemNotFoundException {
+        return addItemToEnd(ShoppingCartItem.makeItem(null, productId, amount, quantity, unitPrice, null, null, null, null, null, features, attributes, prodCatalogId, configWrapper, itemType, null, dispatcher, this, triggerExternalOps, triggerPriceRules, null, Boolean.FALSE, Boolean.FALSE));
+    }
+
+    /** Add an item to the shopping cart. */
     public int addItemToEnd(String productId, Double amount, double quantity, Double unitPrice, HashMap features, HashMap attributes, String prodCatalogId, String itemType, LocalDispatcher dispatcher, Boolean triggerExternalOps, Boolean triggerPriceRules) throws CartItemModifyException, ItemNotFoundException {
         return addItemToEnd(productId, amount, quantity, unitPrice, features, attributes, prodCatalogId, itemType, dispatcher, triggerExternalOps, triggerPriceRules, Boolean.FALSE, Boolean.FALSE);
     }
@@ -544,7 +550,12 @@
     /** Add an (rental)item to the shopping cart. */
     public int addItemToEnd(String productId, Double amount, double quantity, Double unitPrice, Timestamp reservStart, Double reservLengthDbl, Double reservPersonsDbl, HashMap features, HashMap attributes, String prodCatalogId, String itemType, LocalDispatcher dispatcher, Boolean triggerExternalOps, Boolean triggerPriceRules, Boolean skipInventoryChecks, Boolean skipProductChecks) throws CartItemModifyException, ItemNotFoundException {
         return addItemToEnd(ShoppingCartItem.makeItem(null, productId, amount, quantity, unitPrice, reservStart, reservLengthDbl, reservPersonsDbl, null, null, features, attributes, prodCatalogId, null, itemType, null, dispatcher, this, triggerExternalOps, triggerPriceRules, null, skipInventoryChecks, skipProductChecks));
-    }    
+    }
+
+    /** Add an (rental/aggregated)item to the shopping cart. */
+    public int addItemToEnd(String productId, Double amount, double quantity, Double unitPrice, Timestamp reservStart, Double reservLengthDbl, Double reservPersonsDbl, HashMap features, HashMap attributes, String prodCatalogId, ProductConfigWrapper configWrapper, String itemType, LocalDispatcher dispatcher, Boolean triggerExternalOps, Boolean triggerPriceRules, Boolean skipInventoryChecks, Boolean skipProductChecks) throws CartItemModifyException, ItemNotFoundException {
+        return addItemToEnd(ShoppingCartItem.makeItem(null, productId, amount, quantity, unitPrice, reservStart, reservLengthDbl, reservPersonsDbl, null, null, features, attributes, prodCatalogId, configWrapper, itemType, null, dispatcher, this, triggerExternalOps, triggerPriceRules, null, skipInventoryChecks, skipProductChecks));
+    }
     
     /** Add an item to the shopping cart. */
     public int addItemToEnd(String productId, Double amount, double quantity, Double unitPrice, HashMap features, HashMap attributes, String prodCatalogId, String itemType, LocalDispatcher dispatcher, Boolean triggerExternalOps, Boolean triggerPriceRules, Boolean skipInventoryChecks, Boolean skipProductChecks) throws CartItemModifyException, ItemNotFoundException {
@@ -3167,6 +3178,81 @@
     // Methods used for order creation
     // =======================================================================
     
+    /**
+     * Returns the Id of an AGGREGATED_CONF product having exact configId.
+     * If AGGREGATED_CONF product do not exist, creates one, associates it to the AGGREGATED product, and copy its production run template.
+     * @param item
+     * @param dispatcher
+     */    
+    public String getAggregatedInstanceId (ShoppingCartItem item, LocalDispatcher dispatcher) {
+        if (UtilValidate.isEmpty(item.getConfigWrapper()) || UtilValidate.isEmpty(item.getConfigWrapper().getConfigId())) {
+            return null;
+        }
+        String newProductId = null;
+        String configId = item.getConfigWrapper().getConfigId();
+        try {
+            //first search for existing productId
+            newProductId = ProductWorker.getAggregatedInstanceId(getDelegator(), item.getProductId(), configId);
+            if (configId.equals(newProductId)) {
+                return newProductId;
+            }
+            
+            //create new product and associate it
+            Map serviceContext = new HashMap();
+            GenericValue permUserLogin = delegator.findByPrimaryKey("UserLogin", UtilMisc.toMap("userLoginId", "system"));
+            String internalName = item.getProductId() + "_" + configId;
+            serviceContext.put("internalName", internalName);
+            serviceContext.put("productTypeId", "AGGREGATED_CONF");
+            serviceContext.put("configId", configId);
+            serviceContext.put("userLogin", permUserLogin);
+            
+            Map result = dispatcher.runSync("createProduct", serviceContext);
+            if (ServiceUtil.isError(result)) {
+                Debug.logError(ServiceUtil.getErrorMessage(result), module);
+                return null;
+            }
+            
+            serviceContext.clear();
+            newProductId = (String) result.get("productId");
+            serviceContext.put("productId", item.getProductId());
+            serviceContext.put("productIdTo", newProductId);
+            serviceContext.put("productAssocTypeId", "PRODUCT_CONF");
+            serviceContext.put("fromDate", UtilDateTime.nowTimestamp());
+            serviceContext.put("userLogin", permUserLogin);            
+
+            result = dispatcher.runSync("createProductAssoc", serviceContext);
+            if (ServiceUtil.isError(result)) {
+                Debug.logError(ServiceUtil.getErrorMessage(result), module);
+                return null;
+            }
+            
+            //create a new WorkEffortGoodStandard based on existing one of AGGREGATED product .
+            //Another approach could be to get WorkEffortGoodStandard of the AGGREGATED product while creating production run.
+            List productionRunTemplates = getDelegator().findByAnd("WorkEffortGoodStandard", UtilMisc.toMap("productId", item.getProductId(), "workEffortGoodStdTypeId", "ROU_PROD_TEMPLATE", "statusId", "WEGS_CREATED"));
+            GenericValue productionRunTemplate = EntityUtil.getFirst(EntityUtil.filterByDate(productionRunTemplates));
+            if (productionRunTemplate != null) {
+                serviceContext.clear();
+                serviceContext.put("workEffortId", productionRunTemplate.getString("workEffortId"));
+                serviceContext.put("productId", newProductId);
+                serviceContext.put("workEffortGoodStdTypeId", "ROU_PROD_TEMPLATE");
+                serviceContext.put("statusId", "WEGS_CREATED");
+                serviceContext.put("userLogin", permUserLogin);
+
+                result = dispatcher.runSync("createWorkEffortGoodStandard", serviceContext);
+                if (ServiceUtil.isError(result)) {
+                    Debug.logError(ServiceUtil.getErrorMessage(result), module);
+                    return null;
+                }
+            }
+            
+        } catch (Exception e) {
+            Debug.logError(e, module);
+            return null;
+        }
+
+        return newProductId;
+    }
+    
     public List makeOrderItemGroups() {
         List result = FastList.newInstance();
         Iterator groupValueIter = this.itemGroupByNumberMap.values().iterator();
@@ -3221,10 +3307,10 @@
     }
 
     public List makeOrderItems() {
-        return makeOrderItems(false, null);
+        return makeOrderItems(false, false, null);
     }
 
-    public List makeOrderItems(boolean explodeItems, LocalDispatcher dispatcher) {
+    public List makeOrderItems(boolean explodeItems, boolean replaceAggregatedId, LocalDispatcher dispatcher) {
         // do the explosion
         if (explodeItems && dispatcher != null) {
             explodeItems(dispatcher);
@@ -3259,13 +3345,18 @@
                 if (status == null) {
                     status = initialStatus;
                 }
+                //check for aggregated products
+                String aggregatedInstanceId = null;
+                if (replaceAggregatedId && UtilValidate.isNotEmpty(item.getConfigWrapper())) {
+                    aggregatedInstanceId = getAggregatedInstanceId(item, dispatcher);
+                }
 
                 GenericValue orderItem = getDelegator().makeValue("OrderItem");
                 orderItem.set("orderItemSeqId", item.getOrderItemSeqId());
                 orderItem.set("externalId", item.getExternalId());
                 orderItem.set("orderItemTypeId", item.getItemType());
                 if (item.getItemGroup() != null) orderItem.set("orderItemGroupSeqId", item.getItemGroup().getGroupNumber());
-                orderItem.set("productId", item.getProductId());
+                orderItem.set("productId", UtilValidate.isNotEmpty(aggregatedInstanceId) ? aggregatedInstanceId : item.getProductId());
                 orderItem.set("prodCatalogId", item.getProdCatalogId());
                 orderItem.set("productCategoryId", item.getProductCategoryId());
                 orderItem.set("quantity", new Double(item.getQuantity()));
@@ -3720,7 +3811,7 @@
         result.put("internalCode", this.getInternalCode());
         result.put("salesChannelEnumId", this.getChannelType());
         result.put("orderItemGroups", this.makeOrderItemGroups());
-        result.put("orderItems", this.makeOrderItems(explodeItems, dispatcher));
+        result.put("orderItems", this.makeOrderItems(explodeItems, Boolean.TRUE, dispatcher));
         result.put("workEfforts", this.makeWorkEfforts());
         result.put("orderAdjustments", this.makeAllAdjustments());
         result.put("orderTerms", this.getOrderTerms());

Modified: ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartEvents.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartEvents.java?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartEvents.java (original)
+++ ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartEvents.java Fri Jan 18 09:47:01 2008
@@ -212,8 +212,16 @@
         configWrapper = ProductConfigWorker.getProductConfigWrapper(productId, cart.getCurrency(), request);
 
         if (configWrapper != null) {
+            if (paramMap.containsKey("configId")) {
+                try {
+                    configWrapper.loadConfig(delegator, (String) paramMap.remove("configId"));
+                } catch (Exception e) {
+                    Debug.logWarning(e,"Could not load configuration", module);
+                }
+            } else {
             // The choices selected by the user are taken from request and set in the wrapper
             ProductConfigWorker.fillProductConfigWrapper(configWrapper, request);
+            }
             if (!configWrapper.isCompleted()) {
                 // The configuration is not valid
                 request.setAttribute("product_id", productId);

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=613216&r1=613215&r2=613216&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 Fri Jan 18 09:47:01 2008
@@ -33,7 +33,10 @@
 import org.ofbiz.entity.GenericValue;
 import org.ofbiz.entity.util.EntityUtil;
 import org.ofbiz.order.shoppingcart.product.ProductPromoWorker;
+import org.ofbiz.order.order.OrderReadHelper;
 import org.ofbiz.product.config.ProductConfigWrapper;
+import org.ofbiz.product.config.ProductConfigWorker;
+import org.ofbiz.product.product.ProductWorker;
 import org.ofbiz.security.Security;
 import org.ofbiz.service.GenericServiceException;
 import org.ofbiz.service.LocalDispatcher;
@@ -246,84 +249,71 @@
         }
 
         boolean noItems = true;
-
+        List itemIdList = null;
+        Iterator itemIter = null;
+        OrderReadHelper orderHelper = new OrderReadHelper(delegator, orderId);
         if (addAll) {
-            Iterator itemIter = null;
-
-            try {
-                itemIter = UtilMisc.toIterator(delegator.findByAnd("OrderItem", UtilMisc.toMap("orderId", orderId), null));
-            } catch (GenericEntityException e) {
-                Debug.logWarning(e.getMessage(), module);
-                itemIter = null;
+            itemIdList = orderHelper.getOrderItems();
+        } else {
+            if (itemIds != null) {
+                itemIdList = Arrays.asList(itemIds);
             }
-
-            String orderItemTypeId = null;
-            if (itemIter != null && itemIter.hasNext()) {
-                while (itemIter.hasNext()) {
-                    GenericValue orderItem = (GenericValue) itemIter.next();
-                    orderItemTypeId = orderItem.getString("orderItemTypeId");
-                    // do not store rental items
-                    if (orderItemTypeId.equals("RENTAL_ORDER_ITEM"))
-                        continue;
-                    // never read: int itemId = -1;
-                    if (orderItem.get("productId") != null && orderItem.get("quantity") != null) {
-                        Double amount = orderItem.getDouble("selectedAmount");
+        }
+        if (UtilValidate.isNotEmpty(itemIdList)) {
+            itemIter = itemIdList.iterator();
+        }
+        
+        String orderItemTypeId = null;
+        String productId = null;
+        if (itemIter != null && itemIter.hasNext()) {
+            while (itemIter.hasNext()) {
+                GenericValue orderItem = null;
+                Object value = itemIter.next();
+                if (value instanceof GenericValue) {
+                    orderItem = (GenericValue) value;
+                } else {
+                    String orderItemSeqId = (String) value;
+                    orderItem = orderHelper.getOrderItem(orderItemSeqId);
+                }
+                orderItemTypeId = orderItem.getString("orderItemTypeId");
+                productId = orderItem.getString("productId");
+                // do not store rental items
+                if (orderItemTypeId.equals("RENTAL_ORDER_ITEM"))
+                    continue;
+                // never read: int itemId = -1;
+                if (UtilValidate.isNotEmpty(productId) && orderItem.get("quantity") != null) {
+                    Double amount = orderItem.getDouble("selectedAmount");
+                    ProductConfigWrapper configWrapper = null;
+                    String aggregatedProdId = null;
+                    if ("AGGREGATED_CONF".equals(ProductWorker.getProductTypeId(delegator, productId))) {
                         try {
-                            this.cart.addOrIncreaseItem(orderItem.getString("productId"), amount, orderItem.getDouble("quantity").doubleValue(),
-                                    null, null, null, null, null, null, null, catalogId, null, orderItemTypeId, itemGroupNumber, null, dispatcher);
-                            noItems = false;
-                        } catch (CartItemModifyException e) {
-                            errorMsgs.add(e.getMessage());
-                        } catch (ItemNotFoundException e) {
+                            GenericValue instanceProduct = delegator.findByPrimaryKey("Product", UtilMisc.toMap("productId", productId));
+                            String configId = instanceProduct.getString("configId");
+                            aggregatedProdId = ProductWorker.getInstanceAggregatedId(delegator, productId);
+                            configWrapper = ProductConfigWorker.loadProductConfigWrapper(delegator, dispatcher, configId, aggregatedProdId, cart.getProductStoreId(), catalogId, cart.getWebSiteId(), cart.getCurrency(), cart.getLocale(), cart.getAutoUserLogin());
+                        } catch (GenericEntityException e) {
                             errorMsgs.add(e.getMessage());
                         }
+                        
+                    }
+                    try {
+                        this.cart.addOrIncreaseItem(UtilValidate.isNotEmpty(aggregatedProdId) ? aggregatedProdId :  productId, amount, orderItem.getDouble("quantity").doubleValue(),
+                                null, null, null, null, null, null, null, catalogId, configWrapper, orderItemTypeId, itemGroupNumber, null, dispatcher);
+                        noItems = false;
+                    } catch (CartItemModifyException e) {
+                        errorMsgs.add(e.getMessage());
+                    } catch (ItemNotFoundException e) {
+                        errorMsgs.add(e.getMessage());
                     }
                 }
-                if (errorMsgs.size() > 0) {
-                    result = ServiceUtil.returnError(errorMsgs);
-                    result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
-                    return result; // don't return error because this is a non-critical error and should go back to the same page
-                }
-            } else {
-                noItems = true;
+            }
+            if (errorMsgs.size() > 0) {
+                result = ServiceUtil.returnError(errorMsgs);
+                result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
+                return result; // don't return error because this is a non-critical error and should go back to the same page
             }
         } else {
             noItems = true;
-            if (itemIds != null) {
-
-                for (int i = 0; i < itemIds.length; i++) {
-                    String orderItemSeqId = itemIds[i];
-                    GenericValue orderItem = null;
-
-                    try {
-                        orderItem = delegator.findByPrimaryKey("OrderItem", UtilMisc.toMap("orderId", orderId, "orderItemSeqId", orderItemSeqId));
-                    } catch (GenericEntityException e) {
-                        Debug.logWarning(e.getMessage(), module);
-                        errorMsgs.add("Order line \"" + orderItemSeqId + "\" not found, so not added.");
-                        continue;
-                    }
-                    if (orderItem != null) {
-                        if (orderItem.get("productId") != null && orderItem.get("quantity") != null) {
-                            Double amount = orderItem.getDouble("selectedAmount");
-                            try {
-                                this.cart.addOrIncreaseItem(orderItem.getString("productId"), amount,
-                                        orderItem.getDouble("quantity").doubleValue(), null, null, null, null, null, null, null,
-                                        catalogId, null, orderItem.getString("orderItemTypeId"), itemGroupNumber, null, dispatcher);
-                                noItems = false;
-                            } catch (CartItemModifyException e) {
-                                errorMsgs.add(e.getMessage());
-                            } catch (ItemNotFoundException e) {
-                                errorMsgs.add(e.getMessage());
-                            }
-                        }
-                    }
-                }
-                if (errorMsgs.size() > 0) {
-                    result = ServiceUtil.returnError(errorMsgs);
-                    result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
-                    return result; // don't return error because this is a non-critical error and should go back to the same page
-                }
-            } // else no items
         }
 
         if (noItems) {

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?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartItem.java (original)
+++ ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartItem.java Fri Jan 18 09:47:01 2008
@@ -52,6 +52,7 @@
 import org.ofbiz.order.shoppinglist.ShoppingListEvents;
 import org.ofbiz.product.catalog.CatalogWorker;
 import org.ofbiz.product.category.CategoryWorker;
+import org.ofbiz.product.config.ProductConfigWorker;
 import org.ofbiz.product.config.ProductConfigWrapper;
 import org.ofbiz.product.product.ProductContentWrapper;
 import org.ofbiz.product.product.ProductWorker;
@@ -675,7 +676,12 @@
         this.delegatorName = _product.getDelegator().getDelegatorName();
         this.addAllProductFeatureAndAppls(additionalProductFeatureAndAppls);
         this.locale = locale;
-        this.configWrapper = configWrapper;
+        if (UtilValidate.isNotEmpty(configWrapper)) {
+            this.configWrapper = configWrapper;
+            if (UtilValidate.isEmpty(configWrapper.getConfigId())) { //new product configuration. Persist it
+                ProductConfigWorker.storeProductConfigWrapper(configWrapper, getDelegator());
+            }
+        }
     }
 
     /** Creates new ShopingCartItem object. */

Modified: ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartServices.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartServices.java?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartServices.java (original)
+++ ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCartServices.java Fri Jan 18 09:47:01 2008
@@ -44,6 +44,8 @@
 import org.ofbiz.entity.condition.EntityOperator;
 import org.ofbiz.entity.util.EntityUtil;
 import org.ofbiz.order.order.OrderReadHelper;
+import org.ofbiz.product.config.ProductConfigWorker;
+import org.ofbiz.product.config.ProductConfigWrapper;
 import org.ofbiz.service.DispatchContext;
 import org.ofbiz.service.GenericServiceException;
 import org.ofbiz.service.LocalDispatcher;
@@ -338,8 +340,28 @@
                         reservPersons = workEffort.getDouble("reservPersons");
                     }    //end of rental data
                     
+                    //check for AGGREGATED products
+                    ProductConfigWrapper configWrapper = null;
+                    String configId = null;
                     try {
-                        itemIndex = cart.addItemToEnd(productId, amount, quantityDbl, null, reservStart, reservLength, reservPersons, null, null, prodCatalogId, item.getString("orderItemTypeId"), dispatcher, null, null, skipInventoryChecks, skipProductChecks);
+                        GenericValue product = delegator.findByPrimaryKey("Product", UtilMisc.toMap("productId", productId));
+                        if ("AGGREGATED_CONF".equals(product.getString("productTypeId"))) {
+                            List productAssocs = delegator.findByAnd("ProductAssoc", UtilMisc.toMap("productAssocTypeId", "PRODUCT_CONF", "productIdTo", product.getString("productId")));
+                            productAssocs = EntityUtil.filterByDate(productAssocs);
+                            if (UtilValidate.isNotEmpty(productAssocs)) {
+                                productId = EntityUtil.getFirst(productAssocs).getString("productId");
+                                configId = product.getString("configId");
+                            }
+                        }
+                    } catch (GenericEntityException e) {
+                        Debug.logError(e, module);
+                    }
+
+                    if (UtilValidate.isNotEmpty(configId)) {
+                        configWrapper = ProductConfigWorker.loadProductConfigWrapper(delegator, dispatcher, configId, productId, productStoreId, prodCatalogId, website, currency, locale, userLogin);
+                    }                    
+                    try {
+                        itemIndex = cart.addItemToEnd(productId, amount, quantityDbl, null, reservStart, reservLength, reservPersons, null, null, prodCatalogId, configWrapper, item.getString("orderItemTypeId"), dispatcher, null, null, skipInventoryChecks, skipProductChecks);
                     } catch (ItemNotFoundException e) {
                         Debug.logError(e, module);
                         return ServiceUtil.returnError(e.getMessage());
@@ -606,8 +628,12 @@
                 } else {
                     // product item
                     String productId = item.getString("productId");
+                    ProductConfigWrapper configWrapper = null;
+                    if (UtilValidate.isNotEmpty(item.getString("configId"))) {
+                        configWrapper = ProductConfigWorker.loadProductConfigWrapper(delegator, dispatcher, item.getString("configId"), productId, productStoreId, null, null, currency, locale, userLogin);
+                    }                    
                     try {
-                        itemIndex = cart.addItemToEnd(productId, amount, quantity.doubleValue(), quoteUnitPrice, reservStart, reservLength, reservPersons, null, null, null, null, dispatcher, new Boolean(!applyQuoteAdjustments), new Boolean(quoteUnitPrice.doubleValue() == 0));
+                        itemIndex = cart.addItemToEnd(productId, amount, quantity.doubleValue(), quoteUnitPrice, reservStart, reservLength, reservPersons, null, null, null, configWrapper, null, dispatcher, new Boolean(!applyQuoteAdjustments), new Boolean(quoteUnitPrice.doubleValue() == 0), Boolean.FALSE, Boolean.FALSE);
                     } catch (ItemNotFoundException e) {
                         Debug.logError(e, module);
                         return ServiceUtil.returnError(e.getMessage());
@@ -757,8 +783,12 @@
                 if (item.get("productId") != null) {
                     // product item
                     String productId = item.getString("productId");
+                    ProductConfigWrapper configWrapper = null;
+                    if (UtilValidate.isNotEmpty(item.getString("configId"))) {
+                        configWrapper = ProductConfigWorker.loadProductConfigWrapper(delegator, dispatcher, item.getString("configId"), productId, productStoreId, null, null, currency, locale, userLogin);
+                    }
                     try {
-                        itemIndex = cart.addItemToEnd(productId, null, quantity.doubleValue(), null, null, null, null, null, dispatcher, Boolean.TRUE, Boolean.TRUE);
+                        itemIndex = cart.addItemToEnd(productId, null, quantity.doubleValue(), null, null, null, null, null, configWrapper, dispatcher, Boolean.TRUE, Boolean.TRUE);
                     } catch (ItemNotFoundException e) {
                         Debug.logError(e, module);
                         return ServiceUtil.returnError(e.getMessage());

Modified: ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppinglist/ShoppingListEvents.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppinglist/ShoppingListEvents.java?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppinglist/ShoppingListEvents.java (original)
+++ ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppinglist/ShoppingListEvents.java Fri Jan 18 09:47:01 2008
@@ -48,6 +48,8 @@
 import org.ofbiz.order.shoppingcart.ShoppingCartEvents;
 import org.ofbiz.order.shoppingcart.ShoppingCartItem;
 import org.ofbiz.product.catalog.CatalogWorker;
+import org.ofbiz.product.config.ProductConfigWorker;
+import org.ofbiz.product.config.ProductConfigWrapper;
 import org.ofbiz.product.store.ProductStoreWorker;
 import org.ofbiz.service.GenericServiceException;
 import org.ofbiz.service.LocalDispatcher;
@@ -145,6 +147,9 @@
                         ctx.put("reservStart", item.getReservStart());
                         ctx.put("reservLength", new Double(item.getReservLength()));
                         ctx.put("reservPersons", new Double(item.getReservPersons()));
+                        if (item.getConfigWrapper() != null) {
+                            ctx.put("configId", item.getConfigWrapper().getConfigId());                            
+                        }
                         serviceResult = dispatcher.runSync("createShoppingListItem", ctx);
                     } catch (GenericServiceException e) {
                         Debug.logError(e, "Problems creating ShoppingList item entity", module);
@@ -253,6 +258,7 @@
             Timestamp reservStart = shoppingListItem.getTimestamp("reservStart");
             Double reservLength = shoppingListItem.getDouble("reservLength");
             Double reservPersons = shoppingListItem.getDouble("reservPersons");
+            String configId = shoppingListItem.getString("configId");
             try {
                 String listId = shoppingListItem.getString("shoppingListId");
                 String itemId = shoppingListItem.getString("shoppingListItemSeqId");
@@ -268,14 +274,18 @@
                 if (shoppingListSurveyInfo.containsKey(listId + "." + itemId)) {
                     attributes.put("surveyResponses", shoppingListSurveyInfo.get(listId + "." + itemId));
                 }
-
+                
+                ProductConfigWrapper configWrapper = null;
+                if (UtilValidate.isNotEmpty(configId)) {
+                    configWrapper = ProductConfigWorker.loadProductConfigWrapper(delegator, dispatcher, configId, productId, cart.getProductStoreId(), prodCatalogId, cart.getWebSiteId(), cart.getCurrency(), cart.getLocale(), cart.getAutoUserLogin());
+                }
                 // TODO: add code to check for survey response requirement
                 
                 // i cannot get the addOrDecrease function to accept a null reservStart field: i get a null pointer exception a null constant works....
                 if (reservStart == null) {
-                    cart.addOrIncreaseItem(productId, null, quantity.doubleValue(), null, null, null, null, null, null, attributes, prodCatalogId, null, null, null, null, dispatcher);
+                    cart.addOrIncreaseItem(productId, null, quantity.doubleValue(), null, null, null, null, null, null, attributes, prodCatalogId, configWrapper, null, null, null, dispatcher);
                 } else {
-                    cart.addOrIncreaseItem(productId, null, quantity.doubleValue(), reservStart, reservLength, reservPersons, null, null, null, attributes, prodCatalogId, null, null, null, null, dispatcher);
+                    cart.addOrIncreaseItem(productId, null, quantity.doubleValue(), reservStart, reservLength, reservPersons, null, null, null, attributes, prodCatalogId, configWrapper, null, null, null, dispatcher);
                 }
                 Map messageMap = UtilMisc.toMap("productId", productId);
                 errMsg = UtilProperties.getMessage(resource,"shoppinglistevents.added_product_to_cart", messageMap, cart.getLocale());

Modified: ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppinglist/ShoppingListServices.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppinglist/ShoppingListServices.java?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppinglist/ShoppingListServices.java (original)
+++ ofbiz/trunk/applications/order/src/org/ofbiz/order/shoppinglist/ShoppingListServices.java Fri Jan 18 09:47:01 2008
@@ -52,6 +52,9 @@
 import org.ofbiz.base.util.UtilDateTime;
 import org.ofbiz.base.util.GeneralException;
 import org.ofbiz.base.util.UtilProperties;
+import org.ofbiz.product.config.ProductConfigWorker;
+import org.ofbiz.product.config.ProductConfigWrapper;
+import org.ofbiz.product.product.ProductWorker;
 import org.ofbiz.product.store.ProductStoreWorker;
 
 /**
@@ -319,11 +322,25 @@
     
             List orderItems = orh.getOrderItems();
             Iterator i = orderItems.iterator();
+            String productId = null;
             while (i.hasNext()) {
                 GenericValue orderItem = (GenericValue) i.next();
-                if (orderItem.get("productId") != null) {
+                productId = orderItem.getString("productId");
+                if (UtilValidate.isNotEmpty(productId)) {
                     Map ctx = UtilMisc.toMap("userLogin", userLogin, "shoppingListId", shoppingListId, "productId",
                             orderItem.get("productId"), "quantity", orderItem.get("quantity"));
+                    if ("AGGREGATED_CONF".equals(ProductWorker.getProductTypeId(delegator, productId))) {
+                        try {
+                            GenericValue instanceProduct = delegator.findByPrimaryKey("Product", UtilMisc.toMap("productId", productId));
+                            String configId = instanceProduct.getString("configId");
+                            ctx.put("configId", configId);
+                            String aggregatedProductId = ProductWorker.getInstanceAggregatedId(delegator, productId);
+                            //override the instance productId with aggregated productId
+                            ctx.put("productId", aggregatedProductId);
+                        } catch (GenericEntityException e) {
+                            Debug.logError(e, module);
+                        }
+                    }
                     Map serviceResult = null;
                     try {
                         serviceResult = dispatcher.runSync("createShoppingListItem", ctx);
@@ -450,12 +467,14 @@
             
 
                 Iterator i = items.iterator();
+                ProductConfigWrapper configWrapper = null;
                 while (i.hasNext()) {
                     GenericValue shoppingListItem = (GenericValue) i.next();
                     String productId = shoppingListItem.getString("productId");
                     Double quantity = shoppingListItem.getDouble("quantity");
                     Timestamp reservStart = shoppingListItem.getTimestamp("reservStart");
                     Double reservLength = null;
+                    String configId = shoppingListItem.getString("configId");
                     if (shoppingListItem.get("reservLength") != null) {
                         reservLength = shoppingListItem.getDouble("reservLength");
                     }
@@ -464,13 +483,17 @@
                         reservPersons = shoppingListItem.getDouble("reservPersons");
                     }
                     if (UtilValidate.isNotEmpty(productId) && quantity != null) {
+
+                    if (UtilValidate.isNotEmpty(configId)) {
+                        configWrapper = ProductConfigWorker.loadProductConfigWrapper(delegator, dispatcher, configId, productId, listCart.getProductStoreId(), null, listCart.getWebSiteId(), listCart.getCurrency(), listCart.getLocale(), listCart.getAutoUserLogin());
+                    }
                         // list items are noted in the shopping cart
                         String listId = shoppingListItem.getString("shoppingListId");
                         String itemId = shoppingListItem.getString("shoppingListItemSeqId");
                         Map attributes = UtilMisc.toMap("shoppingListId", listId, "shoppingListItemSeqId", itemId);
 
                         try {
-                            listCart.addOrIncreaseItem(productId, null, quantity.doubleValue(), reservStart, reservLength, reservPersons, null, null, null, attributes, null, null, null, null, null, dispatcher);
+                            listCart.addOrIncreaseItem(productId, null, quantity.doubleValue(), reservStart, reservLength, reservPersons, null, null, null, attributes, null, configWrapper, null, null, null, dispatcher);
                         } catch (CartItemModifyException e) {
                             Debug.logError(e, "Unable to add product to List Cart - " + productId, module);
                         } catch (ItemNotFoundException e) {

Modified: ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/catalog/prepareconfigform.bsh
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/catalog/prepareconfigform.bsh?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/catalog/prepareconfigform.bsh (original)
+++ ofbiz/trunk/applications/order/webapp/ordermgr/WEB-INF/actions/entry/catalog/prepareconfigform.bsh Fri Jan 18 09:47:01 2008
@@ -25,6 +25,7 @@
 import org.ofbiz.order.shoppingcart.ShoppingCartEvents;
 import org.ofbiz.product.config.ProductConfigWorker;
 import org.ofbiz.product.store.ProductStoreWorker;
+import org.ofbiz.base.util.*;
 
 currencyUomId = ShoppingCartEvents.getCartObject(request).getCurrency();
 product = context.get("product");
@@ -34,12 +35,20 @@
     ProductConfigWorker.fillProductConfigWrapper(configWrapper, request);
 
     if (!configWrapper.isCompleted()) {
-        configWrapper.setDefaultConfig();
+        configId = request.getParameter("configId");
+        if (UtilValidate.isNotEmpty(configId)) {
+            configWrapper.loadConfig(delegator, configId);
+        } else {
+            configWrapper.setDefaultConfig();
+        }
+
     }
+    ProductConfigWorker.storeProductConfigWrapper(configWrapper, delegator);
     if (!ProductStoreWorker.isStoreInventoryAvailable(request, configWrapper, 1.0)) {
         context.put("productNotAvailable", "Y");
     }
     context.put("configwrapper", configWrapper);
+    context.put("configId", configWrapper.getConfigId());
     context.put("totalPrice", configWrapper.getTotalPrice());
     context.put("renderSingleChoiceWithRadioButtons", "Y");
     context.put("showOffsetPrice", "Y");

Modified: ofbiz/trunk/applications/order/webapp/ordermgr/entry/catalog/configproductdetail.ftl
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/webapp/ordermgr/entry/catalog/configproductdetail.ftl?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/webapp/ordermgr/entry/catalog/configproductdetail.ftl (original)
+++ ofbiz/trunk/applications/order/webapp/ordermgr/entry/catalog/configproductdetail.ftl Fri Jan 18 09:47:01 2008
@@ -332,6 +332,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="configId" value="${configId}">
           <select name="shoppingListId" class="selectBox">
             <#if shoppingLists?has_content>
               <#list shoppingLists as shoppingList>

Modified: ofbiz/trunk/applications/order/widget/ordermgr/OrderEntryForms.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/widget/ordermgr/OrderEntryForms.xml?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/widget/ordermgr/OrderEntryForms.xml (original)
+++ ofbiz/trunk/applications/order/widget/ordermgr/OrderEntryForms.xml Fri Jan 18 09:47:01 2008
@@ -121,7 +121,7 @@
             <display-entity entity-name="Product" description="${productId} - ${description}"/>
         </field>
         <field name="addToCart" title="${uiLabelMap.CommonEmptyHeader}" widget-style="buttontext">
-            <hyperlink target="additem/editShoppingList?shoppingListId=${shoppingListId}&amp;shoppingListItemSeqId=${shoppingListItemSeqId}&amp;add_product_id=${productId}&amp;quantity=${quantity}"
+            <hyperlink target="additem/editShoppingList?shoppingListId=${shoppingListId}&amp;shoppingListItemSeqId=${shoppingListItemSeqId}&amp;add_product_id=${productId}&amp;quantity=${quantity}&amp;configId=${configId}"
                 description="Add ${quantity} to Order" also-hidden="false"/>
         </field>
     </form>

Modified: ofbiz/trunk/applications/product/data/ProductTypeData.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/data/ProductTypeData.xml?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/data/ProductTypeData.xml (original)
+++ ofbiz/trunk/applications/product/data/ProductTypeData.xml Fri Jan 18 09:47:01 2008
@@ -176,6 +176,7 @@
     <ProductAssocType description="Manufacturing Bill of Materials" hasTable="N" parentTypeId="PRODUCT_COMPONENT" productAssocTypeId="MANUF_COMPONENT"/>
     <ProductAssocType description="Engineering Bill of Materials" hasTable="N" parentTypeId="PRODUCT_COMPONENT" productAssocTypeId="ENGINEER_COMPONENT"/>
     <ProductAssocType description="Product Manufactured As" hasTable="N" parentTypeId="" productAssocTypeId="PRODUCT_MANUFACTURED"/>
+    <ProductAssocType description="Configurable product instance" hasTable="N" parentTypeId="" productAssocTypeId="PRODUCT_CONF"/>
 
     <ProductCategoryType description="Catalog" hasTable="N" parentTypeId="" productCategoryTypeId="CATALOG_CATEGORY"/>
     <ProductCategoryType description="Industry" hasTable="N" parentTypeId="" productCategoryTypeId="INDUSTRY_CATEGORY"/>
@@ -422,6 +423,7 @@
     <ProductType description="Marketing Package: Auto Manufactured" isPhysical="Y" isDigital="N" hasTable="N" parentTypeId="GOOD" productTypeId="MARKETING_PKG_AUTO"/>
     <ProductType description="Marketing Package: Pick Assembly" isPhysical="Y" isDigital="N" hasTable="N" parentTypeId="GOOD" productTypeId="MARKETING_PKG_PICK"/>
     <ProductType description="Work In Process" isPhysical="Y" isDigital="N" hasTable="N" parentTypeId="GOOD" productTypeId="WIP"/>
+    <ProductType description="Configurable Good Configuration" isPhysical="N" isDigital="N" hasTable="N" parentTypeId="AGGREGATED" productTypeId="AGGREGATED_CONF"/>
 
     <EnumerationType description="Product Requirement Method" enumTypeId="PROD_REQ_METHOD" hasTable="N" parentTypeId=""/>
     <!-- NONE: no requirement is created (default) -->

Modified: ofbiz/trunk/applications/product/entitydef/entitymodel.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/entitydef/entitymodel.xml?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/entitydef/entitymodel.xml (original)
+++ ofbiz/trunk/applications/product/entitydef/entitymodel.xml Fri Jan 18 09:47:01 2008
@@ -2087,6 +2087,7 @@
       <field name="reservMaxPersons" type="floating-point"><description>maximum number of persons who can rent this asset at the same time</description></field>
       <field name="reserv2ndPPPerc" type="floating-point"><description>percentage of the end price for the 2nd person renting this asset connected to this product</description></field>
       <field name="reservNthPPPerc" type="floating-point"><description>percentage of the end price for the Nth person renting this asset connected to this product</description></field>
+      <field name="configId" type="id"><description>Used to safe the persisted configuration Id for AGGREGATED products.</description></field>
       <field name="createdDate" type="date-time"></field>
       <field name="createdByUserLogin" type="id-vlong"></field>
       <field name="lastModifiedDate" type="date-time"></field>

Modified: ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigWorker.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigWorker.java?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigWorker.java (original)
+++ ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigWorker.java Fri Jan 18 09:47:01 2008
@@ -18,15 +18,30 @@
  *******************************************************************************/
 package org.ofbiz.product.config;
 
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.jsp.tagext.TryCatchFinally;
 
 import org.ofbiz.base.util.Debug;
 import org.ofbiz.base.util.UtilHttp;
+import org.ofbiz.base.util.UtilMisc;
+import org.ofbiz.base.util.UtilValidate;
 import org.ofbiz.entity.GenericDelegator;
+import org.ofbiz.entity.GenericEntityException;
 import org.ofbiz.entity.GenericValue;
+import org.ofbiz.entity.condition.EntityExpr;
+import org.ofbiz.entity.condition.EntityOperator;
 import org.ofbiz.product.catalog.CatalogWorker;
+import org.ofbiz.product.config.ProductConfigWrapper.ConfigItem;
+import org.ofbiz.product.config.ProductConfigWrapper.ConfigOption;
 import org.ofbiz.product.store.ProductStoreWorker;
 import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.ServiceUtil;
 import org.ofbiz.base.util.cache.UtilCache;
 
 /**
@@ -87,5 +102,163 @@
             }
         }
     }
+    
+    /**
+     * First search persisted configurations and update configWrapper.configId if found.
+     * Otherwise store ProductConfigWrapper to ProductConfigConfig entity and updates configWrapper.configId with new configId
+     * This method persists only the selected options, price data is lost.
+     * @param ProductConfigWrapper
+     * @param delegator
+     */    
+    public static void storeProductConfigWrapper(ProductConfigWrapper configWrapper, GenericDelegator delegator) {
+        if (configWrapper == null || (!configWrapper.isCompleted()))  return;
+        String configId = null;
+        List questions = configWrapper.getQuestions();
+        List configsToCheck = new LinkedList();
+        int selectedOptionSize = 0;
+        for (int i = 0; i < questions.size(); i++) {
+            String configItemId = null;
+            Long sequenceNum = null;
+            List <ProductConfigWrapper.ConfigOption> selectedOptions = new ArrayList <ProductConfigWrapper.ConfigOption>();        
+            ConfigItem ci = (ConfigItem)questions.get(i);
+            List options = ci.getOptions();
+            if (ci.isStandard()) {
+                selectedOptions.addAll(options);
+            } else {
+                Iterator availOptions = options.iterator();
+                while (availOptions.hasNext()) {
+                    ConfigOption oneOption = (ConfigOption)availOptions.next();
+                    if (oneOption.isSelected()) {
+                        selectedOptions.add(oneOption);
+                    }
+                }
+            }
+
+            if (selectedOptions.size() > 0) {
+                selectedOptionSize += selectedOptions.size();
+                configItemId = ci.getConfigItemAssoc().getString("configItemId");
+                sequenceNum = ci.getConfigItemAssoc().getLong("sequenceNum");
+                try {
+                    List <GenericValue> configs = delegator.findByAnd("ProductConfigConfig", UtilMisc.toMap("configItemId",configItemId,"sequenceNum", sequenceNum));
+                    Iterator <GenericValue> configIt = configs.iterator();
+                    while (configIt.hasNext()) {
+                        GenericValue productConfigConfig = configIt.next();
+                        Iterator selOpIt = selectedOptions.iterator();
+                        while (selOpIt.hasNext()) {
+                            ConfigOption oneOption = (ConfigOption)selOpIt.next();
+                            String configOptionId = oneOption.configOption.getString("configOptionId");
+                            if (productConfigConfig.getString("configOptionId").equals(configOptionId)) {
+                                configsToCheck.add(productConfigConfig);
+                            }
+                        }
+                    }
+
+                } catch (GenericEntityException e) {
+                    Debug.logError(e, module);
+                }
+                          
+            }  
+        }
+        if (UtilValidate.isNotEmpty(configsToCheck)) {
+            Iterator <GenericValue> ctci = configsToCheck.iterator();
+            while (ctci.hasNext()) {
+                GenericValue productConfigConfig =  ctci.next();
+                String tempConfigId = productConfigConfig.getString("configId");
+                try {
+                    List tempResult = delegator.findByAnd("ProductConfigConfig", UtilMisc.toMap("configId",tempConfigId));
+                    if (tempResult.size() == selectedOptionSize && configsToCheck.containsAll(tempResult)) {
+                            configWrapper.configId = tempConfigId;
+                            Debug.logInfo("Existing configuration found with configId:"+ tempConfigId,  module);
+                            return;
+                    }
+                } catch (GenericEntityException e) {
+                    Debug.logError(e, module);
+                }
+                
+            }
+        }
+        
+        //Current configuration is not found in ProductConfigConfig entity. So lets store this one
+        boolean nextId = true;
+        for (int i = 0; i < questions.size(); i++) {
+            String configItemId = null;
+            Long sequenceNum = null;
+            List <ProductConfigWrapper.ConfigOption> selectedOptions = new ArrayList <ProductConfigWrapper.ConfigOption>();        
+            ConfigItem ci = (ConfigItem)questions.get(i);
+            List options = ci.getOptions();
+           if (ci.isStandard()) {
+                selectedOptions.addAll(options);
+            } else {
+                Iterator availOptions = options.iterator();
+                while (availOptions.hasNext()) {
+                    ConfigOption oneOption = (ConfigOption)availOptions.next();
+                    if (oneOption.isSelected()) {
+                        selectedOptions.add(oneOption);
+                    }
+                }
+            }
+            
+            if (selectedOptions.size() > 0) {
+                if (nextId) {
+                    configId = delegator.getNextSeqId("ProductConfigConfig");
+                    //get next configId only once and only if there are selectedOptions
+                    nextId = false;
+                }
+                configItemId = ci.getConfigItemAssoc().getString("configItemId");
+                sequenceNum = ci.getConfigItemAssoc().getLong("sequenceNum");
+                Iterator selOpIt = selectedOptions.iterator();
+                while (selOpIt.hasNext()) {
+                    ConfigOption oneOption = (ConfigOption)selOpIt.next();
+                    String configOptionId = oneOption.configOption.getString("configOptionId");
+                    GenericValue productConfigConfig = delegator.makeValue("ProductConfigConfig");
+                    productConfigConfig.put("configId", configId);
+                    productConfigConfig.put("configItemId", configItemId);
+                    productConfigConfig.put("sequenceNum", sequenceNum);
+                    productConfigConfig.put("configOptionId", configOptionId);
+                    try {
+                        productConfigConfig.create();
+                    } catch (GenericEntityException e) {
+                        configId = null;
+                        Debug.logWarning(e.getMessage(), module);
+                    }
+                }                            
+            }  
+        }
+        
+        //save  configId to configWrapper, so we can use it in shopping cart operations
+        configWrapper.configId = configId;
+        Debug.logInfo("New configId created:"+ configId,  module);
+        return;
+    }
+    
+    /**
+     * Creates a new ProductConfigWrapper for productId and configures it according to ProductConfigConfig entity with configId
+     * ProductConfigConfig entity stores only the selected options, and the product price is calculated from input params
+     * @param delegator
+     * @param dispatcher
+     * @param configId configuration Id
+     * @param productId AGGRAGATED productId
+     * @param productStoreId needed for price calculations
+     * @param catalogId needed for price calculations
+     * @param webSiteId needed for price calculations
+     * @param currencyUomId needed for price calculations
+     * @param locale
+     * @param autoUserLogin
+     * @return ProductConfigWrapper
+     */
+    public static ProductConfigWrapper loadProductConfigWrapper(GenericDelegator delegator, LocalDispatcher dispatcher, String configId, String productId, String productStoreId, String catalogId, String webSiteId, String currencyUomId, Locale locale, GenericValue autoUserLogin) {
+        ProductConfigWrapper configWrapper = null;
+        try {
+             configWrapper = new ProductConfigWrapper(delegator, dispatcher, productId, productStoreId, catalogId, webSiteId, currencyUomId, locale, autoUserLogin);
+            if (configWrapper != null && UtilValidate.isNotEmpty(configId)) {
+                configWrapper.loadConfig(delegator, configId);
+            }
+        } catch (Exception e) {
+            Debug.logWarning(e.getMessage(), module);
+            configWrapper = null;
+        }
+        return configWrapper;
+    }
+
 }
 

Modified: ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigWrapper.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigWrapper.java?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigWrapper.java (original)
+++ ofbiz/trunk/applications/product/src/org/ofbiz/product/config/ProductConfigWrapper.java Fri Jan 18 09:47:01 2008
@@ -47,8 +47,9 @@
     protected LocalDispatcher dispatcher;
     protected GenericValue product = null; // the aggregated product
     protected double basePrice = 0.0;
-    protected List questions = null; // ProductConfigs
     protected double defaultPrice = 0.0;
+    protected String configId = null; // Id of persisted ProductConfigWrapper
+    protected List questions = null; // ProductConfigs
     
     /** Creates a new instance of ProductConfigWrapper */
     public ProductConfigWrapper() {
@@ -109,6 +110,40 @@
             this.setDefaultPrice();
         }
     }
+
+    public void loadConfig(GenericDelegator delegator, String configId) throws Exception {
+        //configure ProductConfigWrapper according to ProductConfigConfig entity
+        if (UtilValidate.isNotEmpty(configId)) {
+            this.configId = configId;
+            List productConfigConfig = delegator.findByAnd("ProductConfigConfig", UtilMisc.toMap("configId", configId));
+            if (productConfigConfig != null && productConfigConfig.size() > 0) {
+                Iterator pccIt = productConfigConfig.iterator();
+                while (pccIt.hasNext()) {
+                    GenericValue pcc =(GenericValue) pccIt.next();
+                    String configItemId = pcc.getString("configItemId");
+                    String configOptionId = pcc.getString("configOptionId");
+                    Long sequenceNum = pcc.getLong("sequenceNum");
+                    this.setSelected(configItemId, sequenceNum, configOptionId);
+                }
+            }
+        }
+    }
+
+    public void setSelected(String configItemId, Long sequenceNum, String configOptionId) throws Exception {
+        for (int i = 0; i < questions.size(); i++) {
+            ConfigItem ci = (ConfigItem)questions.get(i);
+            if (ci.configItemAssoc.getString("configItemId").equals(configItemId) && ci.configItemAssoc.getLong("sequenceNum").equals(sequenceNum)) {
+                List avalOptions = ci.getOptions();
+                for (int j = 0; j < avalOptions.size(); j++) {
+                    ConfigOption oneOption = (ConfigOption)avalOptions.get(j);
+                    if (oneOption.configOption.getString("configOptionId").equals(configOptionId)) {
+                        setSelected(i, j);
+                        break;
+                    }
+                }
+            }
+        }
+    }    
     
     public void resetConfig() {
         for (int i = 0; i < questions.size(); i++) {
@@ -137,6 +172,10 @@
                 }
             }
         }
+    }
+    
+    public String getConfigId() {
+        return configId;
     }
     
     public boolean equals(Object obj) {

Modified: ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductWorker.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductWorker.java?rev=613216&r1=613215&r2=613216&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductWorker.java (original)
+++ ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductWorker.java Fri Jan 18 09:47:01 2008
@@ -173,6 +173,45 @@
             pageContext.setAttribute(attributeName, product);
     }
 
+    public static String getInstanceAggregatedId(GenericDelegator delegator, String instanceProductId) throws GenericEntityException {
+        GenericValue instanceProduct = delegator.findByPrimaryKey("Product", UtilMisc.toMap("productId", instanceProductId));
+        
+        if (UtilValidate.isNotEmpty(instanceProduct) && "AGGREGATED_CONF".equals(instanceProduct.getString("productTypeId"))) {
+            GenericValue productAssoc = EntityUtil.getFirst(EntityUtil.filterByDate(instanceProduct.getRelatedByAnd("AssocProductAssoc",
+                    UtilMisc.toMap("productAssocTypeId", "PRODUCT_CONF"))));
+            if (UtilValidate.isNotEmpty(productAssoc)) {
+                return productAssoc.getString("productId");
+            }
+        }
+        return null;
+    }
+
+    public static String getAggregatedInstanceId(GenericDelegator delegator, String  aggregatedProductId, String configId) throws GenericEntityException {
+        List productAssocs = getAggregatedAssocs(delegator, aggregatedProductId);
+        if (UtilValidate.isNotEmpty(productAssocs) && UtilValidate.isNotEmpty(configId)) {
+            Iterator pai = productAssocs.iterator();
+            while (pai.hasNext()) {
+                GenericValue productAssoc = (GenericValue) pai.next();
+                GenericValue product = productAssoc.getRelatedOne("AssocProduct");
+                if (configId.equals(product.getString("configId"))) {
+                    return productAssoc.getString("productIdTo");
+                }
+            }
+        }
+        return null;
+    }
+    
+    public static List getAggregatedAssocs(GenericDelegator delegator, String  aggregatedProductId) throws GenericEntityException {
+        GenericValue aggregatedProduct = delegator.findByPrimaryKey("Product", UtilMisc.toMap("productId", aggregatedProductId));
+        
+        if (UtilValidate.isNotEmpty(aggregatedProduct) && "AGGREGATED".equals(aggregatedProduct.getString("productTypeId"))) {
+            List productAssocs = EntityUtil.filterByDate(aggregatedProduct.getRelatedByAnd("MainProductAssoc",
+                    UtilMisc.toMap("productAssocTypeId", "PRODUCT_CONF")));
+            return productAssocs;
+        }
+        return null;
+    }
+    
     public static String getVariantVirtualId(GenericValue variantProduct) throws GenericEntityException {
         List productAssocs = getVariantVirtualAssocs(variantProduct);
         if (productAssocs == null) {