You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by ha...@apache.org on 2011/11/22 05:10:57 UTC

svn commit: r1204805 - in /ofbiz/trunk/applications: order/servicedef/ product/ product/config/ product/entitydef/ product/script/org/ofbiz/product/product/ product/script/org/ofbiz/product/test/ product/servicedef/ product/testdef/ product/webapp/cata...

Author: hansbak
Date: Tue Nov 22 04:10:55 2011
New Revision: 1204805

URL: http://svn.apache.org/viewvc?rev=1204805&view=rev
Log:
first version of the implementation of group orders

Added:
    ofbiz/trunk/applications/product/script/org/ofbiz/product/test/GroupOrderTest.xml   (with props)
    ofbiz/trunk/applications/product/testdef/GroupOrderTest.xml   (with props)
Modified:
    ofbiz/trunk/applications/order/servicedef/secas.xml
    ofbiz/trunk/applications/product/config/ProductUiLabels.xml
    ofbiz/trunk/applications/product/entitydef/entitymodel.xml
    ofbiz/trunk/applications/product/ofbiz-component.xml
    ofbiz/trunk/applications/product/script/org/ofbiz/product/product/ProductServices.xml
    ofbiz/trunk/applications/product/servicedef/services.xml
    ofbiz/trunk/applications/product/webapp/catalog/WEB-INF/controller.xml
    ofbiz/trunk/applications/product/widget/catalog/CatalogMenus.xml
    ofbiz/trunk/applications/product/widget/catalog/ProductForms.xml
    ofbiz/trunk/applications/product/widget/catalog/ProductScreens.xml

Modified: ofbiz/trunk/applications/order/servicedef/secas.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/servicedef/secas.xml?rev=1204805&r1=1204804&r2=1204805&view=diff
==============================================================================
--- ofbiz/trunk/applications/order/servicedef/secas.xml (original)
+++ ofbiz/trunk/applications/order/servicedef/secas.xml Tue Nov 22 04:10:55 2011
@@ -430,4 +430,10 @@ under the License.
         <condition field-name="paymentId" operator="is-not-empty"/>
         <action service="createOrderPaymentApplication" mode="sync"/>
     </eca>
+
+    <!-- Group Buying -->
+    <eca service="storeOrder" event="commit">
+        <condition field-name="orderTypeId" operator="equals" value="SALES_ORDER"/>
+        <action service="checkOrderItemForGroupOrder" mode="sync"/>
+    </eca>
 </service-eca>

Modified: ofbiz/trunk/applications/product/config/ProductUiLabels.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/config/ProductUiLabels.xml?rev=1204805&r1=1204804&r2=1204805&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/config/ProductUiLabels.xml (original)
+++ ofbiz/trunk/applications/product/config/ProductUiLabels.xml Tue Nov 22 04:10:55 2011
@@ -8887,6 +8887,9 @@
         <value xml:lang="zh">添加总账账户</value>
         <value xml:lang="zh_TW">添加總賬賬戶</value>
     </property>
+    <property key="ProductAddGroupOrder">
+        <value xml:lang="en">Add GroupOrder</value>
+    </property>
     <property key="ProductAddItemsFromInventory">
         <value xml:lang="de">Positionen vom Bestand hinzufügen</value>
         <value xml:lang="en">Add Items From Inventory</value>
@@ -11972,6 +11975,15 @@
         <value xml:lang="zh">货运天数</value>
         <value xml:lang="zh_TW">貨運天數</value>
     </property>
+    <property key="ProductDealEndDate">
+        <value xml:lang="en">Deal End Date</value>
+    </property>
+    <property key="ProductDealQuantity">
+        <value xml:lang="en">Deal Quantity</value>
+    </property>
+    <property key="ProductDealStartDate">
+        <value xml:lang="en">Deal Start Date</value>
+    </property>
     <property key="ProductDefaultAmount">
         <value xml:lang="de">Standart Betrag</value>
         <value xml:lang="en">Default Amount</value>
@@ -12442,6 +12454,9 @@
         <value xml:lang="zh">编辑特征:特征分类</value>
         <value xml:lang="zh_TW">特性分類的特性修改</value>
     </property>
+    <property key="ProductEditGroupOrder">
+        <value xml:lang="en">Edit GroupOrder</value>
+    </property>
     <property key="ProductEditInventoryItemWithId">
         <value xml:lang="de">Bestandsposition bearbeiten mit der ID</value>
         <value xml:lang="en">Edit Inventory Item with ID</value>
@@ -14108,6 +14123,9 @@
         <value xml:lang="zh">组成员维护</value>
         <value xml:lang="zh_TW">組成員維護</value>
     </property>
+    <property key="ProductGroupOrder">
+        <value xml:lang="en">GroupOrder</value>
+    </property>
     <property key="ProductGroupRollupChildGroupsAdd">
         <value xml:lang="de">Gruppe Rollup: Untergeordnete Gruppe hinzufügen</value>
         <value xml:lang="en">Group Rollup : Add Child Groups</value>
@@ -23034,6 +23052,9 @@
         <value xml:lang="zh">软标识</value>
         <value xml:lang="zh_TW">軟式ID</value>
     </property>
+    <property key="ProductSoldQuantity">
+        <value xml:lang="en">Sold Quantity</value>
+    </property>
     <property key="ProductSortOrder">
         <value xml:lang="cs">Pořadí řazení</value>
         <value xml:lang="de">Sortierungsreihenfolge</value>

Modified: ofbiz/trunk/applications/product/entitydef/entitymodel.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/entitydef/entitymodel.xml?rev=1204805&r1=1204804&r2=1204805&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/entitydef/entitymodel.xml (original)
+++ ofbiz/trunk/applications/product/entitydef/entitymodel.xml Tue Nov 22 04:10:55 2011
@@ -4809,4 +4809,23 @@ under the License.
         <key-map field-name="productPromoContentTypeId" rel-field-name="productContentTypeId"/>
       </relation>
     </entity>
+
+    <entity entity-name="GroupOrder"
+            package-name="org.ofbiz.product.product"
+            title="Group Order Entity">
+      <field name="groupOrderId" type="id-ne"></field>
+      <field name="productId" type="id-ne"></field>
+      <field name="fromDate" type="date-time"></field>
+      <field name="thruDate" type="date-time"></field>
+      <field name="reqOrderQty" type="fixed-point"></field>
+      <field name="soldOrderQty" type="fixed-point"></field>
+      <field name="jobId" type="id-ne"></field>
+      <prim-key field="groupOrderId"/>
+      <relation type="one" fk-name="GROUP_ORDER" rel-entity-name="Product">
+        <key-map field-name="productId"/>
+      </relation>
+      <relation type="one" fk-name="GROUP_ORDER_JOB" rel-entity-name="JobSandbox">
+        <key-map field-name="jobId"/>
+      </relation>
+    </entity>
 </entitymodel>

Modified: ofbiz/trunk/applications/product/ofbiz-component.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/ofbiz-component.xml?rev=1204805&r1=1204804&r2=1204805&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/ofbiz-component.xml (original)
+++ ofbiz/trunk/applications/product/ofbiz-component.xml Tue Nov 22 04:10:55 2011
@@ -71,6 +71,7 @@ under the License.
     <test-suite loader="main" location="testdef/CatalogTests.xml"/>
     <test-suite loader="main" location="testdef/FacilityTest.xml"/>
     <test-suite loader="main" location="testdef/CostTests.xml"/>
+    <test-suite loader="main" location="testdef/GroupOrderTest.xml"/>
 
     <webapp name="catalog" title="Catalog" server="default-server" location="webapp/catalog"
         base-permission="OFBTOOLS,CATALOG" mount-point="/catalog"/>

Modified: ofbiz/trunk/applications/product/script/org/ofbiz/product/product/ProductServices.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/script/org/ofbiz/product/product/ProductServices.xml?rev=1204805&r1=1204804&r2=1204805&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/script/org/ofbiz/product/product/ProductServices.xml (original)
+++ ofbiz/trunk/applications/product/script/org/ofbiz/product/product/ProductServices.xml Tue Nov 22 04:10:55 2011
@@ -1045,4 +1045,151 @@ under the License.
         <entity-one entity-name="ProductCategoryGlAccount" value-field="lookedUpValue"/>
         <remove-value value-field="lookedUpValue"/>
     </simple-method>
+
+    <!-- Product GroupOrder Services -->
+    <simple-method method-name="createGroupOrder" short-description="Create GroupOrder">
+        <!-- Create Job For GroupOrder -->
+        <make-value entity-name="JobSandbox" value-field="jobSandbox"/>
+        <sequenced-id sequence-name="JobSandbox" field="jobSandbox.jobId"/>
+        <set field="jobId" from-field="jobSandbox.jobId"/>
+        <set field="jobSandbox.jobName" value="Check GroupOrder Expired"/>
+        <set field="jobSandbox.runTime" from-field="parameters.thruDate"/>
+        <set field="jobSandbox.poolId" value="pool"/>
+        <set field="jobSandbox.statusId" value="SERVICE_PENDING"/>
+        <set field="jobSandbox.serviceName" value="checkGroupOrderExpired"/>
+        <set field="jobSandbox.runAsUser" value="system"/>
+        <set field="jobSandbox.runtimeDataId" from-field="runtimeData.runtimeDataId"/>
+        <set field="jobSandbox.maxRecurrenceCount" value="1" type="Long"/>
+        <create-value value-field="jobSandbox"/>
+        
+        <!-- Create GroupOrder -->
+        <make-value entity-name="GroupOrder" value-field="groupOrder"/>
+        <make-next-seq-id value-field="groupOrder" seq-field-name="groupOrderId"/>
+        <set field="groupOrderId" from-field="groupOrder.groupOrderId"/>
+        <set-nonpk-fields value-field="groupOrder" map="parameters"/>
+        <set field="groupOrder.jobId" from-field="jobId"/>
+        <create-value value-field="groupOrder"/>
+        
+        <!-- Create RuntimeData For GroupOrder -->
+        <set field="runtimeDataMap.groupOrderId" from-field="groupOrderId"/>
+        <call-class-method class-name="org.ofbiz.entity.serialize.XmlSerializer" method-name="serialize"  ret-field="runtimeInfo">
+            <field field="runtimeDataMap" type="Object"/>
+        </call-class-method>
+        <make-value entity-name="RuntimeData" value-field="runtimeData"/>
+        <sequenced-id sequence-name="RuntimeData" field="runtimeData.runtimeDataId"/>
+        <set field="runtimeDataId" from-field="runtimeData.runtimeDataId"/>
+        <set field="runtimeData.runtimeInfo" from-field="runtimeInfo"/>
+        <create-value value-field="runtimeData"/>
+        
+        <entity-one entity-name="JobSandbox" value-field="updateJobSandbox">
+            <field-map field-name="jobId" from-field="jobId"/>
+        </entity-one>
+        <set field="updateJobSandbox.runtimeDataId" from-field="runtimeDataId"/>
+        <store-value value-field="updateJobSandbox"/>
+    </simple-method>
+
+    <simple-method method-name="updateGroupOrder" short-description="Update GroupOrder">
+        <entity-one entity-name="GroupOrder" value-field="groupOrder"/>
+        <set-nonpk-fields value-field="groupOrder" map="parameters"/>
+        <store-value value-field="groupOrder"/>
+        
+        <entity-one entity-name="JobSandbox" value-field="jobSandbox">
+            <field-map field-name="jobId" from-field="groupOrder.jobId"/>
+        </entity-one>
+        <if-not-empty field="jobSandbox">
+            <set field="jobSandbox.runTime" from-field="parameters.thruDate"/>
+            <store-value value-field="jobSandbox"/>
+        </if-not-empty>
+        
+        <entity-one value-field="systemUserLogin" entity-name="UserLogin">
+            <field-map field-name="userLoginId" value="system"/>
+        </entity-one>
+        <if-compare field="groupOrder.soldOrderQty" operator="equals" value="${groupOrder.reqOrderQty}">
+            <set field="checkGroupOrderExpiredMap.userLogin" from-field="systemUserLogin"/>
+            <set field="checkGroupOrderExpiredMap.groupOrderId" from-field="groupOrder.groupOrderId"/>
+            <call-service service-name="checkGroupOrderExpired" in-map-name="checkGroupOrderExpiredMap"/>
+            
+            <set field="cancelScheduledJobMap.userLogin" from-field="systemUserLogin"/>
+            <set field="cancelScheduledJobMap.jobId" from-field="groupOrder.jobId"/>
+            <call-service service-name="cancelScheduledJob" in-map-name="cancelScheduledJobMap"/>
+        </if-compare>
+    </simple-method>
+
+    <simple-method method-name="deleteGroupOrder" short-description="Delete GroupOrder">
+        <entity-one entity-name="GroupOrder" value-field="groupOrder"/>
+        <remove-value value-field="groupOrder"/>
+    </simple-method>
+
+    <simple-method method-name="checkOrderItemForGroupOrder" short-description="Check Order Item For GroupOrder">
+        <entity-one value-field="systemUserLogin" entity-name="UserLogin">
+            <field-map field-name="userLoginId" value="system"/>
+        </entity-one>
+        <entity-and entity-name="OrderItem" list="orderItems">
+            <field-map field-name="orderId" from-field="parameters.orderId"/>
+        </entity-and>
+        <iterate entry="orderItem" list="orderItems">
+            <entity-and entity-name="GroupOrder" list="groupOrders" filter-by-date="true">
+                <field-map field-name="productId" from-field="orderItem.productId"/>
+            </entity-and>
+            <iterate entry="groupOrder" list="groupOrders">
+                <if-compare field="groupOrder.soldOrderQty" operator="less" value="${groupOrder.reqOrderQty}">
+                    <calculate field="groupOrder.soldOrderQty">
+                        <calcop field="groupOrder.soldOrderQty" operator="add">
+                            <calcop field="orderItem.quantity" operator="get"/>
+                        </calcop>
+                    </calculate>
+                    <store-value value-field="groupOrder"/>
+                    
+                    <if-compare field="groupOrder.soldOrderQty" operator="equals" value="${groupOrder.reqOrderQty}">
+                        <set field="checkGroupOrderExpiredMap.userLogin" from-field="systemUserLogin"/>
+                        <set field="checkGroupOrderExpiredMap.groupOrderId" from-field="groupOrder.groupOrderId"/>
+                        <call-service service-name="checkGroupOrderExpired" in-map-name="checkGroupOrderExpiredMap"/>
+                        
+                        <set field="cancelScheduledJobMap.userLogin" from-field="systemUserLogin"/>
+                        <set field="cancelScheduledJobMap.jobId" from-field="groupOrder.jobId"/>
+                        <call-service service-name="cancelScheduledJob" in-map-name="cancelScheduledJobMap"/>
+                    </if-compare>
+                </if-compare>
+            </iterate>
+        </iterate>
+    </simple-method>
+
+    <simple-method method-name="checkGroupOrderExpired" short-description="Check GroupOrder Expired">
+        <entity-one entity-name="GroupOrder" value-field="groupOrder"/>
+        <if-compare field="groupOrder.soldOrderQty" operator="equals" value="${groupOrder.reqOrderQty}">
+            <set field="newItemStatusId" value="ITEM_APPROVED"/>
+        <else>
+            <set field="newItemStatusId" value="ITEM_CANCELLED"/>
+        </else>
+        </if-compare>
+        <entity-condition entity-name="OrderItem" list="orderItems">
+            <condition-list combine="and">
+                <condition-expr field-name="productId" operator="equals" from-field="groupOrder.productId"/>
+                <condition-list combine="or">
+                    <condition-expr field-name="statusId" operator="equals" value="ITEM_CREATED"/>
+                    <condition-expr field-name="statusId" operator="equals" value="ITEM_APPROVED"/>
+                </condition-list>
+            </condition-list>
+        </entity-condition>
+        <iterate entry="orderItem" list="orderItems">
+            <entity-one value-field="orderHeader" entity-name="OrderHeader">
+                <field-map field-name="orderId" from-field="orderItem.orderId"/>
+            </entity-one>
+            <if>
+                <condition>
+                    <and>
+                        <if-compare field="orderHeader.orderTypeId" operator="equals" value="SALES_ORDER"/>
+                        <if-compare field="orderHeader.orderDate" operator="greater-equals" value="${groupOrder.fromDate}"/>
+                        <if-compare field="orderHeader.orderDate" operator="less" value="${groupOrder.thruDate}"/>
+                    </and>
+                </condition>
+                <then>
+                    <set field="changeOrderItemStatusMap.orderId" from-field="orderItem.orderId"/>
+                    <set field="changeOrderItemStatusMap.orderItemSeqId" from-field="orderItem.orderItemSeqId"/>
+                    <set field="changeOrderItemStatusMap.statusId" from-field="newItemStatusId"/>
+                    <call-service service-name="changeOrderItemStatus" in-map-name="changeOrderItemStatusMap"/>
+                </then>
+            </if>
+        </iterate>
+    </simple-method>
 </simple-methods>

Added: ofbiz/trunk/applications/product/script/org/ofbiz/product/test/GroupOrderTest.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/script/org/ofbiz/product/test/GroupOrderTest.xml?rev=1204805&view=auto
==============================================================================
--- ofbiz/trunk/applications/product/script/org/ofbiz/product/test/GroupOrderTest.xml (added)
+++ ofbiz/trunk/applications/product/script/org/ofbiz/product/test/GroupOrderTest.xml Tue Nov 22 04:10:55 2011
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<simple-methods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/simple-methods.xsd">
+
+    <simple-method method-name="testGroupOrderLimitReached" short-description="Test GroupOrder the limit is reached" login-required="false">
+        <!-- Test GroupOrder the limit is reached
+             Step 1) Create GroupOrder .
+             Step 2) Create order.
+             Step 3) Check soldOrderQty is added.
+             Step 4) Check Order Item should approved.
+        -->
+        <!-- Step 1 -->
+        <now-timestamp field="nowTimestamp"/>
+        <set field="days" value="1" type="Integer"/>
+        <call-class-method class-name="org.ofbiz.base.util.UtilDateTime" method-name="addDaysToTimestamp" ret-field="thruDate">
+            <field field="nowTimestamp" type="java.sql.Timestamp"/>
+            <field field="days" type="int"/>
+        </call-class-method>
+        <entity-one value-field="systemUserLogin" entity-name="UserLogin">
+            <field-map field-name="userLoginId" value="system"/>
+        </entity-one>
+        <set field="createGroupOrderMap.userLogin" from-field="systemUserLogin"/>
+        <set field="createGroupOrderMap.productId" value="GZ-1000"/>
+        <set field="createGroupOrderMap.fromDate" from-field="nowTimestamp"/>
+        <set field="createGroupOrderMap.thruDate" from-field="thruDate"/>
+        <set field="createGroupOrderMap.reqOrderQty" value="1" type="BigDecimal"/>
+        <set field="createGroupOrderMap.soldOrderQty" value="0" type="BigDecimal"/>
+        <call-service service-name="createGroupOrder" in-map-name="createGroupOrderMap"/>
+        <!-- Step 2 -->
+        <field-to-session field="nullField" session-name="orderMode"/>
+        <set field="request" from-field="parameters.request"/>
+        <set field="response" from-field="parameters.response"/>
+        <call-class-method method-name="routeOrderEntry" class-name="org.ofbiz.order.shoppingcart.ShoppingCartEvents" ret-field="result">
+            <field field="request" type="javax.servlet.http.HttpServletRequest"/>
+            <field field="response" type="javax.servlet.http.HttpServletResponse"/>
+        </call-class-method>
+        <log level="info" message="===== >>> Event : routeOrderEntry, Response : ${result}"/>
+        <entity-one value-field="userLogin" entity-name="UserLogin">
+            <field-map field-name="userLoginId" value="admin"/>
+        </entity-one>
+        <call-bsh><![CDATA[
+            request.setParameter("orderMode", "SALES_ORDER");
+            request.setParameter("productStoreId", "9000");
+            request.setParameter("partyId", "DemoCustomer");
+            request.setParameter("currencyUom", "USD");
+            session = request.getSession();
+            session.setAttribute("userLogin", userLogin);
+        ]]></call-bsh>
+        <call-class-method method-name="initializeOrderEntry" class-name="org.ofbiz.order.shoppingcart.ShoppingCartEvents" ret-field="result">
+            <field field="request" type="javax.servlet.http.HttpServletRequest"/>
+            <field field="response" type="javax.servlet.http.HttpServletResponse"/>
+        </call-class-method>
+        <log level="info" message="===== >>> Event : initializeOrderEntry, Response : ${result}"/>
+        <call-class-method method-name="setOrderCurrencyAgreementShipDates" class-name="org.ofbiz.order.shoppingcart.ShoppingCartEvents" ret-field="result">
+            <field field="request" type="javax.servlet.http.HttpServletRequest"/>
+            <field field="response" type="javax.servlet.http.HttpServletResponse"/>
+        </call-class-method>
+        <log level="info" message="===== >>> Event : setOrderCurrencyAgreementShipDates, Response : ${result}"/>
+        <call-bsh><![CDATA[
+            request.setParameter("add_product_id", "GZ-1000");
+        ]]></call-bsh>
+        <call-class-method method-name="addToCart" class-name="org.ofbiz.order.shoppingcart.ShoppingCartEvents" ret-field="result">
+            <field field="request" type="javax.servlet.http.HttpServletRequest"/>
+            <field field="response" type="javax.servlet.http.HttpServletResponse"/>
+        </call-class-method>
+        <log level="info" message="===== >>> Event : addToCart, Response : ${result}"/>
+        <call-bsh><![CDATA[
+            request.setParameter("checkoutpage", "quick");
+            request.setParameter("shipping_contact_mech_id", "9015");
+            request.setParameter("shipping_method", "GROUND@UPS");
+            request.setParameter("checkOutPaymentId", "EXT_PAYPAL");
+            request.setParameter("is_gift", "false");
+            request.setParameter("may_split", "false");
+        ]]></call-bsh>
+        <field-to-request field="nullField" request-name="shoppingCart"/>
+        <call-class-method method-name="setQuickCheckOutOptions" class-name="org.ofbiz.order.shoppingcart.CheckOutEvents" ret-field="result">
+            <field field="request" type="javax.servlet.http.HttpServletRequest"/>
+            <field field="response" type="javax.servlet.http.HttpServletResponse"/>
+        </call-class-method>
+        <log level="info" message="===== >>> Event : setQuickCheckOutOptions, Response : ${result}"/>
+        <call-class-method method-name="createOrder" class-name="org.ofbiz.order.shoppingcart.CheckOutEvents" ret-field="result">
+            <field field="request" type="javax.servlet.http.HttpServletRequest"/>
+            <field field="response" type="javax.servlet.http.HttpServletResponse"/>
+        </call-class-method>
+        <log level="info" message="===== >>> Event : createOrder, Response : ${result}"/>
+        <call-class-method method-name="processPayment" class-name="org.ofbiz.order.shoppingcart.CheckOutEvents" ret-field="result">
+            <field field="request" type="javax.servlet.http.HttpServletRequest"/>
+            <field field="response" type="javax.servlet.http.HttpServletResponse"/>
+        </call-class-method>
+        <log level="info" message="===== >>> Event : processPayment, Response : ${result}"/>
+        <call-service-asynch service-name="sendOrderConfirmation"/>
+        <call-class-method method-name="destroyCart" class-name="org.ofbiz.order.shoppingcart.ShoppingCartEvents" ret-field="result">
+            <field field="request" type="javax.servlet.http.HttpServletRequest"/>
+            <field field="response" type="javax.servlet.http.HttpServletResponse"/>
+        </call-class-method>
+        <log level="info" message="===== >>> Event : destroyCart, Response = ${result}"/>
+        <!-- Step 3 -->
+        <entity-condition entity-name="GroupOrder" list="groupOrders">
+            <condition-expr field-name="productId" value="GZ-1000"/>
+            <order-by field-name="-groupOrderId"/>
+        </entity-condition>
+        <first-from-list entry="groupOrder" list="groupOrders"/>
+        <assert>
+            <if-compare field="groupOrder.soldOrderQty" operator="not-equals" value="0"/>
+        </assert>
+        <!-- Step 4 -->
+        <entity-condition entity-name="OrderHeader" list="orderHeaders">
+            <condition-expr field-name="orderTypeId" value="SALES_ORDER"/>
+            <order-by field-name="-orderDate"/>
+        </entity-condition>
+        <first-from-list entry="orderHeader" list="orderHeaders"/>
+        <entity-and entity-name="OrderItem" list="orderItems">
+            <field-map field-name="orderId" from-field="orderHeader.orderId"/>
+            <field-map field-name="productId" value="GZ-1000"/>
+        </entity-and>
+        <first-from-list entry="orderItem" list="orderItems"/>
+        <assert>
+            <if-compare field="orderItem.statusId" operator="equals" value="ITEM_APPROVED"/>
+        </assert>
+        
+        <check-errors/>
+    </simple-method>
+
+    <simple-method method-name="testGroupOrderLimitNotReached" short-description="Test GroupOrder the limit is not reached" login-required="false">
+        <!-- Test GroupOrder the limit is not reached
+             Step 1) Create GroupOrder.
+             Step 2) Create order.
+             Step 2) Check GroupOrder expired.
+             Step 3) Check Order Item should cancelled.
+        -->
+        <!-- Step 1 -->
+        <now-timestamp field="nowTimestamp"/>
+        <set field="days" value="1" type="Integer"/>
+        <call-class-method class-name="org.ofbiz.base.util.UtilDateTime" method-name="addDaysToTimestamp" ret-field="thruDate">
+            <field field="nowTimestamp" type="java.sql.Timestamp"/>
+            <field field="days" type="int"/>
+        </call-class-method>
+        <entity-one value-field="systemUserLogin" entity-name="UserLogin">
+            <field-map field-name="userLoginId" value="system"/>
+        </entity-one>
+        <set field="createGroupOrderMap.userLogin" from-field="systemUserLogin"/>
+        <set field="createGroupOrderMap.productId" value="GZ-1000"/>
+        <set field="createGroupOrderMap.fromDate" from-field="nowTimestamp"/>
+        <set field="createGroupOrderMap.thruDate" from-field="thruDate"/>
+        <set field="createGroupOrderMap.reqOrderQty" value="2" type="BigDecimal"/>
+        <set field="createGroupOrderMap.soldOrderQty" value="0" type="BigDecimal"/>
+        <call-service service-name="createGroupOrder" in-map-name="createGroupOrderMap"/>
+        <!-- Step 2 -->
+        <field-to-session field="nullField" session-name="orderMode"/>
+        <set field="request" from-field="parameters.request"/>
+        <set field="response" from-field="parameters.response"/>
+        <call-class-method method-name="routeOrderEntry" class-name="org.ofbiz.order.shoppingcart.ShoppingCartEvents" ret-field="result">
+            <field field="request" type="javax.servlet.http.HttpServletRequest"/>
+            <field field="response" type="javax.servlet.http.HttpServletResponse"/>
+        </call-class-method>
+        <log level="info" message="===== >>> Event : routeOrderEntry, Response : ${result}"/>
+        <entity-one value-field="userLogin" entity-name="UserLogin">
+            <field-map field-name="userLoginId" value="admin"/>
+        </entity-one>
+        <call-bsh><![CDATA[
+            request.setParameter("orderMode", "SALES_ORDER");
+            request.setParameter("productStoreId", "9000");
+            request.setParameter("partyId", "DemoCustomer");
+            request.setParameter("currencyUom", "USD");
+            session = request.getSession();
+            session.setAttribute("userLogin", userLogin);
+        ]]></call-bsh>
+        <call-class-method method-name="initializeOrderEntry" class-name="org.ofbiz.order.shoppingcart.ShoppingCartEvents" ret-field="result">
+            <field field="request" type="javax.servlet.http.HttpServletRequest"/>
+            <field field="response" type="javax.servlet.http.HttpServletResponse"/>
+        </call-class-method>
+        <log level="info" message="===== >>> Event : initializeOrderEntry, Response : ${result}"/>
+        <call-class-method method-name="setOrderCurrencyAgreementShipDates" class-name="org.ofbiz.order.shoppingcart.ShoppingCartEvents" ret-field="result">
+            <field field="request" type="javax.servlet.http.HttpServletRequest"/>
+            <field field="response" type="javax.servlet.http.HttpServletResponse"/>
+        </call-class-method>
+        <log level="info" message="===== >>> Event : setOrderCurrencyAgreementShipDates, Response : ${result}"/>
+        <call-bsh><![CDATA[
+            request.setParameter("add_product_id", "GZ-1000");
+        ]]></call-bsh>
+        <call-class-method method-name="addToCart" class-name="org.ofbiz.order.shoppingcart.ShoppingCartEvents" ret-field="result">
+            <field field="request" type="javax.servlet.http.HttpServletRequest"/>
+            <field field="response" type="javax.servlet.http.HttpServletResponse"/>
+        </call-class-method>
+        <log level="info" message="===== >>> Event : addToCart, Response : ${result}"/>
+        <call-bsh><![CDATA[
+            request.setParameter("checkoutpage", "quick");
+            request.setParameter("shipping_contact_mech_id", "9015");
+            request.setParameter("shipping_method", "GROUND@UPS");
+            request.setParameter("checkOutPaymentId", "EXT_PAYPAL");
+            request.setParameter("is_gift", "false");
+            request.setParameter("may_split", "false");
+        ]]></call-bsh>
+        <field-to-request field="nullField" request-name="shoppingCart"/>
+        <call-class-method method-name="setQuickCheckOutOptions" class-name="org.ofbiz.order.shoppingcart.CheckOutEvents" ret-field="result">
+            <field field="request" type="javax.servlet.http.HttpServletRequest"/>
+            <field field="response" type="javax.servlet.http.HttpServletResponse"/>
+        </call-class-method>
+        <log level="info" message="===== >>> Event : setQuickCheckOutOptions, Response : ${result}"/>
+        <call-class-method method-name="createOrder" class-name="org.ofbiz.order.shoppingcart.CheckOutEvents" ret-field="result">
+            <field field="request" type="javax.servlet.http.HttpServletRequest"/>
+            <field field="response" type="javax.servlet.http.HttpServletResponse"/>
+        </call-class-method>
+        <log level="info" message="===== >>> Event : createOrder, Response : ${result}"/>
+        <call-class-method method-name="processPayment" class-name="org.ofbiz.order.shoppingcart.CheckOutEvents" ret-field="result">
+            <field field="request" type="javax.servlet.http.HttpServletRequest"/>
+            <field field="response" type="javax.servlet.http.HttpServletResponse"/>
+        </call-class-method>
+        <log level="info" message="===== >>> Event : processPayment, Response : ${result}"/>
+        <call-service-asynch service-name="sendOrderConfirmation"/>
+        <call-class-method method-name="destroyCart" class-name="org.ofbiz.order.shoppingcart.ShoppingCartEvents" ret-field="result">
+            <field field="request" type="javax.servlet.http.HttpServletRequest"/>
+            <field field="response" type="javax.servlet.http.HttpServletResponse"/>
+        </call-class-method>
+        <log level="info" message="===== >>> Event : destroyCart, Response = ${result}"/>
+        <!-- Step 3 -->
+        <entity-condition entity-name="GroupOrder" list="groupOrders">
+            <condition-expr field-name="productId" value="GZ-1000"/>
+            <order-by field-name="-groupOrderId"/>
+        </entity-condition>
+        <first-from-list entry="groupOrder" list="groupOrders"/>
+        <set field="checkGroupOrderExpiredMap.userLogin" from-field="systemUserLogin"/>
+        <set field="checkGroupOrderExpiredMap.groupOrderId" from-field="groupOrder.groupOrderId"/>
+        <call-service service-name="checkGroupOrderExpired" in-map-name="checkGroupOrderExpiredMap"/>
+        <!-- Step 4 -->
+        <entity-condition entity-name="OrderHeader" list="orderHeaders">
+            <condition-expr field-name="orderTypeId" value="SALES_ORDER"/>
+            <order-by field-name="-orderDate"/>
+        </entity-condition>
+        <first-from-list entry="orderHeader" list="orderHeaders"/>
+        <entity-and entity-name="OrderItem" list="orderItems">
+            <field-map field-name="orderId" from-field="orderHeader.orderId"/>
+            <field-map field-name="productId" value="GZ-1000"/>
+        </entity-and>
+        <first-from-list entry="orderItem" list="orderItems"/>
+        <assert>
+            <if-compare field="orderItem.statusId" operator="equals" value="ITEM_CANCELLED"/>
+        </assert>
+        
+        <check-errors/>
+    </simple-method>
+</simple-methods>

Propchange: ofbiz/trunk/applications/product/script/org/ofbiz/product/test/GroupOrderTest.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ofbiz/trunk/applications/product/script/org/ofbiz/product/test/GroupOrderTest.xml
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: ofbiz/trunk/applications/product/script/org/ofbiz/product/test/GroupOrderTest.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Modified: ofbiz/trunk/applications/product/servicedef/services.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/servicedef/services.xml?rev=1204805&r1=1204804&r2=1204805&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/servicedef/services.xml (original)
+++ ofbiz/trunk/applications/product/servicedef/services.xml Tue Nov 22 04:10:55 2011
@@ -1662,4 +1662,50 @@ under the License.
         <auto-attributes include="pk" mode="IN" optional="false"/>
     </service>
 
+    <service name="updateGroupOrder" default-entity-name="GroupOrder" engine="simple"
+        location="component://product/script/org/ofbiz/product/product/ProductServices.xml" invoke="updateGroupOrder" auth="true">
+        <description>Update a Group Order</description>
+        <auto-attributes include="pk" mode="IN" optional="false"/>
+        <auto-attributes include="nonpk" mode="IN" optional="true"/>
+    </service>
+
+    <!-- Product GroupOrder Services -->
+    <service name="createGroupOrder" default-entity-name="GroupOrder" engine="simple"
+        location="component://product/script/org/ofbiz/product/product/ProductServices.xml" invoke="createGroupOrder" auth="true">
+        <description>Create GroupOrder</description>
+        <attribute name="productId" mode="IN" type="String" optional="false"/>
+        <attribute name="soldOrderQty" mode="IN" type="BigDecimal" optional="false"/>
+        <attribute name="reqOrderQty" mode="IN" type="BigDecimal" optional="false"/>
+        <attribute name="fromDate" mode="IN" type="Timestamp" optional="false"/>
+        <attribute name="thruDate" mode="IN" type="Timestamp" optional="false"/>
+        <attribute name="groupOrderId" mode="OUT" type="String" optional="true"/>
+    </service>
+
+    <service name="updateGroupOrder" default-entity-name="GroupOrder" engine="simple"
+        location="component://product/script/org/ofbiz/product/product/ProductServices.xml" invoke="updateGroupOrder" auth="true">
+        <description>Update GroupOrder</description>
+        <attribute name="groupOrderId" mode="IN" type="String" optional="false"/>
+        <attribute name="reqOrderQty" mode="IN" type="BigDecimal" optional="false"/>
+        <attribute name="fromDate" mode="IN" type="Timestamp" optional="false"/>
+        <attribute name="thruDate" mode="IN" type="Timestamp" optional="false"/>
+    </service>
+
+    <service name="deleteGroupOrder" default-entity-name="GroupOrder" engine="simple"
+        location="component://product/script/org/ofbiz/product/product/ProductServices.xml" invoke="deleteGroupOrder" auth="true">
+        <description>Delete GroupOrder</description>
+        <auto-attributes include="pk" mode="IN" optional="false"/>
+    </service>
+
+    <service name="checkOrderItemForGroupOrder" engine="simple"
+        location="component://product/script/org/ofbiz/product/product/ProductServices.xml" invoke="checkOrderItemForGroupOrder" auth="true">
+        <description>Check Order Item For GroupOrder</description>
+        <attribute name="orderId" mode="IN" type="String" optional="false"/>
+    </service>
+
+    <service name="checkGroupOrderExpired" engine="simple"
+        location="component://product/script/org/ofbiz/product/product/ProductServices.xml" invoke="checkGroupOrderExpired" auth="true">
+        <description>Check GroupOrder Expired</description>
+        <attribute name="groupOrderId" mode="IN" type="String" optional="false"/>
+    </service>
+
 </services>

Added: ofbiz/trunk/applications/product/testdef/GroupOrderTest.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/testdef/GroupOrderTest.xml?rev=1204805&view=auto
==============================================================================
--- ofbiz/trunk/applications/product/testdef/GroupOrderTest.xml (added)
+++ ofbiz/trunk/applications/product/testdef/GroupOrderTest.xml Tue Nov 22 04:10:55 2011
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<test-suite suite-name="groupordertests"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/test-suite.xsd">
+
+    <test-case case-name="limitreached-test">
+        <simple-method-test location="component://product/script/org/ofbiz/product/test/GroupOrderTest.xml" name="testGroupOrderLimitReached"/>
+    </test-case>
+
+    <test-case case-name="limitnotreached-test">
+        <simple-method-test location="component://product/script/org/ofbiz/product/test/GroupOrderTest.xml" name="testGroupOrderLimitNotReached"/>
+    </test-case>
+
+</test-suite>

Propchange: ofbiz/trunk/applications/product/testdef/GroupOrderTest.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: ofbiz/trunk/applications/product/testdef/GroupOrderTest.xml
------------------------------------------------------------------------------
    svn:keywords = Date Rev Author URL Id

Propchange: ofbiz/trunk/applications/product/testdef/GroupOrderTest.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Modified: ofbiz/trunk/applications/product/webapp/catalog/WEB-INF/controller.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/webapp/catalog/WEB-INF/controller.xml?rev=1204805&r1=1204804&r2=1204805&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/webapp/catalog/WEB-INF/controller.xml (original)
+++ ofbiz/trunk/applications/product/webapp/catalog/WEB-INF/controller.xml Tue Nov 22 04:10:55 2011
@@ -2961,8 +2961,6 @@ under the License.
         <response name="error" type="view" value="EditVendorProduct"/>
     </request-map>
 
-    <!-- end of request mappings -->
-    
     <!-- ================ Product Promo Content Requests ================= -->
     <request-map uri="EditProductPromoContent">
         <security https="true" auth="true"/>
@@ -2992,6 +2990,39 @@ under the License.
         <response name="success" type="view" value="listMiniproduct"/>
     </request-map>
 
+    <!-- ================ Product GroupOrder  Requests ================= -->
+    <request-map uri="ViewProductGroupOrder">
+        <security https="true" auth="true"/>
+        <response name="success" type="view" value="ViewProductGroupOrder"/>
+    </request-map>
+
+    <request-map uri="EditProductGroupOrder">
+        <security https="true" auth="true"/>
+        <response name="success" type="view" value="EditProductGroupOrder"/>
+    </request-map>
+
+    <request-map uri="createGroupOrder">
+        <security https="true" auth="true"/>
+        <event type="service" invoke="createGroupOrder"/>
+        <response name="success" type="view" value="ViewProductGroupOrder"/>
+        <response name="error" type="view" value="ViewProductGroupOrder"/>
+    </request-map>
+
+    <request-map uri="updateGroupOrder">
+        <security https="true" auth="true"/>
+        <event type="service" invoke="updateGroupOrder"/>
+        <response name="success" type="view" value="ViewProductGroupOrder"/>
+        <response name="error" type="view" value="EditProductGroupOrder"/>
+    </request-map>
+
+    <request-map uri="deleteGroupOrder">
+        <security https="true" auth="true"/>
+        <event type="service" invoke="deleteGroupOrder"/>
+        <response name="success" type="view" value="ViewProductGroupOrder"/>
+        <response name="error" type="view" value="ViewProductGroupOrder"/>
+    </request-map>
+    <!-- end of request mappings -->
+
     <!-- View Mappings -->
     <view-map name="main" type="screen" page="component://product/widget/catalog/CommonScreens.xml#main"/>
 
@@ -3146,6 +3177,8 @@ under the License.
     <view-map name="EditProductConfigItemContentContent" type="screen" page="component://product/widget/catalog/ConfigScreens.xml#EditProductConfigItemContentContent"/>
 
     <view-map name="EditProductWorkEfforts" type="screen" page="component://product/widget/catalog/ProductScreens.xml#EditProductWorkEfforts"/>
+    <view-map name="ViewProductGroupOrder" type="screen" page="component://product/widget/catalog/ProductScreens.xml#ViewProductGroupOrder"/>
+    <view-map name="EditProductGroupOrder" type="screen" page="component://product/widget/catalog/ProductScreens.xml#EditProductGroupOrder"/>
 
     <view-map name="ListQuantityBreaks" type="screen" page="component://product/widget/catalog/ShippingScreens.xml#ListQuantityBreaks"/>
     <view-map name="ListShipmentMethodTypes" type="screen" page="component://product/widget/catalog/ShippingScreens.xml#ListShipmentMethodTypes"/>

Modified: ofbiz/trunk/applications/product/widget/catalog/CatalogMenus.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/widget/catalog/CatalogMenus.xml?rev=1204805&r1=1204804&r2=1204805&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/widget/catalog/CatalogMenus.xml (original)
+++ ofbiz/trunk/applications/product/widget/catalog/CatalogMenus.xml Tue Nov 22 04:10:55 2011
@@ -502,6 +502,11 @@ under the License.
                 <parameter param-name="productId"/>
             </link>
         </menu-item>
+        <menu-item name="ViewProductGroupOrder" title="${uiLabelMap.ProductGroupOrder}">
+            <link target="ViewProductGroupOrder">
+                <parameter param-name="productId"/>
+            </link>
+        </menu-item>
     </menu>
 
     <menu name="ProductSubTabBar" menu-container-style="button-bar button-style-2" default-selected-style="selected">

Modified: ofbiz/trunk/applications/product/widget/catalog/ProductForms.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/widget/catalog/ProductForms.xml?rev=1204805&r1=1204804&r2=1204805&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/widget/catalog/ProductForms.xml (original)
+++ ofbiz/trunk/applications/product/widget/catalog/ProductForms.xml Tue Nov 22 04:10:55 2011
@@ -2110,5 +2110,47 @@ under the License.
         <field name="changedByUserLogin" title="${uiLabelMap.ProductLastModifiedBy}"><display/></field>
         <field name="changedDate"><display/></field>
     </form>
+
+    <form name="ListProductGroupOrder" type="list" target="" title="" list-name="groupOrders"
+        odd-row-style="alternate-row" default-table-style="basic-table">
+        <field name="productId"><hidden/></field>
+        <field name="groupOrderId"><display/></field>
+        <field name="reqOrderQty" title="${uiLabelMap.ProductDealQuantity}"><display/></field>
+        <field name="soldOrderQty" title="${uiLabelMap.ProductSoldQuantity}"><display/></field>
+        <field name="fromDate" title="${uiLabelMap.ProductDealStartDate}"><display/></field>
+        <field name="thruDate" title="${uiLabelMap.ProductDealEndDate}"><display/></field>
+        <field name="editLink" use-when="${groovy: return reqOrderQty.compareTo(soldOrderQty)!= 0;}" title="${uiLabelMap.CommonEmptyHeader}" widget-style="buttontext">
+            <hyperlink target="EditProductGroupOrder" description="${uiLabelMap.CommonEdit}" also-hidden="false">
+                <parameter param-name="productId"/>
+                <parameter param-name="groupOrderId"/>
+            </hyperlink>
+        </field>
+        <field name="deleteLink" title="${uiLabelMap.CommonEmptyHeader}" widget-style="buttontext">
+            <hyperlink target="deleteGroupOrder" description="${uiLabelMap.CommonDelete}" also-hidden="false">
+                <parameter param-name="productId"/>
+                <parameter param-name="groupOrderId"/>
+            </hyperlink>
+        </field>
+    </form>
+
+    <form name="CreateProductGroupOrder" type="single" target="createGroupOrder" title=""
+        header-row-style="header-row" default-table-style="basic-table">
+        <field name="productId"><hidden/></field>
+        <field name="soldOrderQty"><hidden value="0"/></field>
+        <field name="reqOrderQty" title="${uiLabelMap.ProductDealQuantity}*"><text/></field>
+        <field name="fromDate" title="${uiLabelMap.ProductDealStartDate}*"><date-time/></field>
+        <field name="thruDate" title="${uiLabelMap.ProductDealEndDate}*"><date-time/></field>
+        <field name="submitButton" title="${uiLabelMap.CommonCreate}" widget-style="smallSubmit"><submit button-type="button"/></field>
+    </form>
+
+    <form name="EditProductGroupOrder" type="single" target="updateGroupOrder" title="" default-map-name="groupOrder"
+        header-row-style="header-row" default-table-style="basic-table">
+        <field name="groupOrderId"><hidden/></field>
+        <field name="productId"><hidden/></field>
+        <field name="reqOrderQty" title="${uiLabelMap.ProductDealQuantity}*"><text/></field>
+        <field name="fromDate" title="${uiLabelMap.ProductDealStartDate}*"><date-time/></field>
+        <field name="thruDate" title="${uiLabelMap.ProductDealEndDate}*"><date-time/></field>
+        <field name="submitButton" title="${uiLabelMap.CommonUpdate}" widget-style="smallSubmit"><submit button-type="button"/></field>
+    </form>
  </forms>
  

Modified: ofbiz/trunk/applications/product/widget/catalog/ProductScreens.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/widget/catalog/ProductScreens.xml?rev=1204805&r1=1204804&r2=1204805&view=diff
==============================================================================
--- ofbiz/trunk/applications/product/widget/catalog/ProductScreens.xml (original)
+++ ofbiz/trunk/applications/product/widget/catalog/ProductScreens.xml Tue Nov 22 04:10:55 2011
@@ -1384,4 +1384,51 @@ under the License.
             </widgets>
         </section>
     </screen>
+
+    <screen name="ViewProductGroupOrder">
+        <section>
+            <actions>
+                <set field="titleProperty" value="PageTitleViewProductGroupOrder"/>
+                <set field="tabButtonItem" value="ViewProductGroupOrder"/>
+                <set field="labelTitleProperty" value="ProductGroupOrder"/>
+                <set field="productId" from-field="parameters.productId"/>
+                <entity-and entity-name="GroupOrder" list="groupOrders">
+                    <field-map field-name="productId" from-field="productId"/>
+                </entity-and>
+            </actions>
+            <widgets>
+                <decorator-screen name="CommonProductDecorator" location="${parameters.productDecoratorLocation}">
+                    <decorator-section name="body">
+                        <screenlet title="${uiLabelMap.ProductGroupOrder}">
+                            <include-form name="ListProductGroupOrder" location="component://product/widget/catalog/ProductForms.xml"/>
+                        </screenlet>
+                        <screenlet title="${uiLabelMap.ProductAddGroupOrder}">
+                            <include-form name="CreateProductGroupOrder" location="component://product/widget/catalog/ProductForms.xml"/>
+                        </screenlet>
+                    </decorator-section>
+                </decorator-screen>
+            </widgets>
+        </section>
+    </screen>
+
+    <screen name="EditProductGroupOrder">
+        <section>
+            <actions>
+                <set field="titleProperty" value="PageTitleEditProductGroupOrder"/>
+                <set field="tabButtonItem" value="EditProductGroupOrder"/>
+                <set field="labelTitleProperty" value="ProductGroupOrder"/>
+                <set field="productId" from-field="parameters.productId"/>
+                <entity-one entity-name="GroupOrder" value-field="groupOrder"/>
+            </actions>
+            <widgets>
+                <decorator-screen name="CommonProductDecorator" location="${parameters.productDecoratorLocation}">
+                    <decorator-section name="body">
+                        <screenlet title="${uiLabelMap.ProductEditGroupOrder}">
+                            <include-form name="EditProductGroupOrder" location="component://product/widget/catalog/ProductForms.xml"/>
+                        </screenlet>
+                    </decorator-section>
+                </decorator-screen>
+            </widgets>
+        </section>
+    </screen>
 </screens>