Hi Hans,
with this code you have broken the ability to add "bulk products" (items
without a product id) to a purchase order; I fixed the error happening in
checkout in rev. but please make sure that there are no other parts of the
systems affected by this.
Also, as I mentioned in another review (that you ignored) to one of your
commits, we should avoid code like:
if ("SERVICE_PRODUCT".equals(product.get("productTypeId")) ||
"AGGREGATEDSERV_CONF".equals(product.get("productTypeId"))
because it makes the system less extensible, the code less readable and instead
use the parentTypeId to define hierarchies of product types etc...
Jacopo
On Sep 8, 2011, at 9:07 AM, [email protected] wrote:
> Author: hansbak
> Date: Thu Sep 8 07:07:07 2011
> New Revision: 1166543
>
> URL: http://svn.apache.org/viewvc?rev=1166543&view=rev
> Log:
> New product type SERVICE_PRODUCT which was discussed in the mailing list.
> blog linked to the what is new file will be added later
>
> Modified:
> ofbiz/trunk/applications/order/data/OrderTypeData.xml
>
> ofbiz/trunk/applications/order/script/org/ofbiz/order/test/ShoppingCartTests.xml
> ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderServices.java
> ofbiz/trunk/applications/order/testdef/ShoppingCartTests.xml
> ofbiz/trunk/applications/product/data/ProductTypeData.xml
> ofbiz/trunk/specialpurpose/ecommerce/data/DemoProduct.xml
>
> Modified: ofbiz/trunk/applications/order/data/OrderTypeData.xml
> URL:
> http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/data/OrderTypeData.xml?rev=1166543&r1=1166542&r2=1166543&view=diff
> ==============================================================================
> --- ofbiz/trunk/applications/order/data/OrderTypeData.xml (original)
> +++ ofbiz/trunk/applications/order/data/OrderTypeData.xml Thu Sep 8 07:07:07
> 2011
> @@ -322,6 +322,7 @@ under the License.
> <ReturnItemTypeMap returnHeaderTypeId="CUSTOMER_RETURN"
> returnItemMapKey="SURCHARGE_ADJUSTMENT" returnItemTypeId="RET_SURCHARGE_ADJ"/>
> <ReturnItemTypeMap returnHeaderTypeId="CUSTOMER_RETURN"
> returnItemMapKey="ADDITIONAL_FEATURE" returnItemTypeId="RET_ADD_FEATURE_ADJ"/>
> <ReturnItemTypeMap returnHeaderTypeId="CUSTOMER_RETURN"
> returnItemMapKey="WARRANTY_ADJUSTMENT" returnItemTypeId="RET_WARRANTY_ADJ"/>
> + <ReturnItemTypeMap returnHeaderTypeId="CUSTOMER_RETURN"
> returnItemMapKey="SERVICE_PRODUCT" returnItemTypeId="RET_SPROD_ITEM"/>
> <ReturnItemTypeMap returnHeaderTypeId="VENDOR_RETURN"
> returnItemMapKey="FINISHED_GOOD" returnItemTypeId="RET_FPROD_ITEM"/>
> <ReturnItemTypeMap returnHeaderTypeId="VENDOR_RETURN"
> returnItemMapKey="MARKETING_PKG_AUTO" returnItemTypeId="RET_FPROD_ITEM"/>
> <ReturnItemTypeMap returnHeaderTypeId="VENDOR_RETURN"
> returnItemMapKey="MARKETING_PKG_PICK" returnItemTypeId="RET_FPROD_ITEM"/>
>
> Modified:
> ofbiz/trunk/applications/order/script/org/ofbiz/order/test/ShoppingCartTests.xml
> URL:
> http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/script/org/ofbiz/order/test/ShoppingCartTests.xml?rev=1166543&r1=1166542&r2=1166543&view=diff
> ==============================================================================
> ---
> ofbiz/trunk/applications/order/script/org/ofbiz/order/test/ShoppingCartTests.xml
> (original)
> +++
> ofbiz/trunk/applications/order/script/org/ofbiz/order/test/ShoppingCartTests.xml
> Thu Sep 8 07:07:07 2011
> @@ -260,4 +260,119 @@ under the License.
> <assert><not><if-empty field="orderMap.orderId"/></not></assert>
> <check-errors/>
> </simple-method>
> +
> + <simple-method method-name="testCreateOrderServiceProduct"
> short-description="Test create an order using a service product"
> login-required="false">
> + <entity-one entity-name="UserLogin" value-field="userLogin">
> + <field-map field-name="userLoginId" value="DemoCustomer"/>
> + </entity-one>
> +
> + <!-- Shopping Cart new Instance -->
> + <set field="delegator" from-field="parameters.delegator"
> type="Object"/>
> + <set field="dispatcher" from-field="parameters.dispatcher"
> type="Object"/>
> + <set field="locale" from-field="parameters.locale" type="Object" />
> + <set field="productStoreId" value="9000" type="String"/>
> + <set field="currencyUom" value="USD" type="String"/>
> + <set field="salesChannel" value="WEB_SALES_CHANNEL" type="String"/>
> +
> + <set field="partyId" value="DemoCustomer" type="String"/>
> +
> + <create-object
> class-name="org.ofbiz.order.shoppingcart.ShoppingCart" field="shoppingCart">
> + <field field="delegator" type="org.ofbiz.entity.Delegator"/>
> + <field field="productStoreId" type="String"/>
> + <field field="locale" type="java.util.Locale"/>
> + <field field="currencyUom" type="String"/>
> + </create-object>
> +
> + <set field="orderType" value="SALES_ORDER" type="String"/>
> + <call-object-method method-name="setOrderType"
> obj-field="shoppingCart">
> + <field field="orderType" type="String"/>
> + </call-object-method>
> +
> + <call-object-method method-name="setChannelType"
> obj-field="shoppingCart">
> + <field field="salesChannel" type="String"/>
> + </call-object-method>
> +
> + <call-object-method method-name="setProductStoreId"
> obj-field="shoppingCart">
> + <field field="productStoreId" type="String"/>
> + </call-object-method>
> +
> + <call-object-method method-name="setBillToCustomerPartyId"
> obj-field="shoppingCart">
> + <field field="partyId" type="String"/>
> + </call-object-method>
> +
> + <call-object-method method-name="setPlacingCustomerPartyId"
> obj-field="shoppingCart">
> + <field field="partyId" type="String"/>
> + </call-object-method>
> +
> + <call-object-method method-name="setShipToCustomerPartyId"
> obj-field="shoppingCart">
> + <field field="partyId" type="String"/>
> + </call-object-method>
> +
> + <call-object-method method-name="setEndUserCustomerPartyId"
> obj-field="shoppingCart">
> + <field field="partyId" type="String"/>
> + </call-object-method>
> +
> + <call-object-method method-name="setUserLogin"
> obj-field="shoppingCart">
> + <field field="userLogin" type="org.ofbiz.entity.GenericValue"/>
> + <field field="dispatcher"
> type="org.ofbiz.service.LocalDispatcher"/>
> + </call-object-method>
> +
> + <set field="productId" value="SV-1001" type="String"/>
> + <set field="prodCatalogId" value="DemoCatalog" type="String"/>
> + <set field="quantity" value="1" type="BigDecimal"/>
> +
> + <call-object-method method-name="addOrIncreaseItem"
> obj-field="shoppingCart">
> + <field field="productId" type="String"/>
> + <field field="selectedAmount" type="BigDecimal"/>
> + <field field="quantity" type="BigDecimal"/>
> + <field field="reservStart" type="Timestamp"/>
> + <field field="reservLength" type="BigDecimal"/>
> + <field field="reservPersons" type="BigDecimal"/>
> + <field field="shipBeforeDate" type="Timestamp"/>
> + <field field="shipAfterDate" type="Timestamp"/>
> + <field field="features" type="Map"/>
> + <field field="attributes" type="Map"/>
> + <field field="prodCatalogId" type="String"/>
> + <field field="configWrapper"
> type="org.ofbiz.product.config.ProductConfigWrapper"/>
> + <field field="itemType" type="String"/>
> + <field field="itemGroupNumber" type="String"/>
> + <field field="parentProductId" type="String"/>
> + <field field="dispatcher"
> type="org.ofbiz.service.LocalDispatcher"/>
> + </call-object-method>
> +
> + <call-object-method method-name="setDefaultCheckoutOptions"
> obj-field="shoppingCart">
> + <field field="dispatcher"
> type="org.ofbiz.service.LocalDispatcher"/>
> + </call-object-method>
> +
> + <create-object
> class-name="org.ofbiz.order.shoppingcart.CheckOutHelper"
> field="checkOutHelper">
> + <field field="dispatcher"
> type="org.ofbiz.service.LocalDispatcher"/>
> + <field field="delegator" type="org.ofbiz.entity.Delegator"/>
> + <field field="shoppingCart"
> type="org.ofbiz.order.shoppingcart.ShoppingCart"/>
> + </create-object>
> +
> + <call-object-method method-name="createOrder"
> obj-field="checkOutHelper" ret-field="orderCreateResult">
> + <field field="userLogin" type="org.ofbiz.entity.GenericValue"/>
> + </call-object-method>
> + <set field="orderId" from-field="orderCreateResult.orderId"
> type="String"/>
> + <if-not-empty field="orderId">
> + <call-class-method method-name="approveOrder"
> class-name="org.ofbiz.order.order.OrderChangeHelper" ret-field="approved">
> + <field field="dispatcher"
> type="org.ofbiz.service.LocalDispatcher"/>
> + <field field="userLogin"
> type="org.ofbiz.entity.GenericValue"/>
> + <field field="orderId" type="String"/>
> + </call-class-method>
> + <log level="info" message="======== Test order with id:
> [${orderId}] has been approved: [${approved}]========"/>
> +
> + <entity-one entity-name="UserLogin"
> value-field="systemUserLogin">
> + <field-map field-name="userLoginId" value="system"/>
> + </entity-one>
> +
> + <set field="quickShipEntireOrderMap.orderId" from-field="orderId"/>
> + <set field="quickShipEntireOrderMap.userLogin"
> from-field="systemUserLogin"/>
> + <call-service service-name="quickShipEntireOrder"
> in-map-name="quickShipEntireOrderMap"/>
> + <log level="info" message="========Test order with id: [${orderId}]
> has been shipped"/>
> + </if-not-empty>
> +
> + <assert><not><if-empty field="orderId"/></not></assert>
> + <check-errors/>
> + </simple-method>
> </simple-methods>
>
> Modified:
> ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderServices.java
> URL:
> http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderServices.java?rev=1166543&r1=1166542&r2=1166543&view=diff
> ==============================================================================
> ---
> ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderServices.java
> (original)
> +++
> ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderServices.java
> Thu Sep 8 07:07:07 2011
> @@ -1130,8 +1130,63 @@ public class OrderServices {
> // store line items, etc so that they will be there for the
> foreign key checks
> delegator.storeAll(toBeStored);
>
> - // START inventory reservation
> List<String> resErrorMessages = new LinkedList<String>();
> +
> + // add a product service to inventory
> + if (UtilValidate.isNotEmpty(orderItems)) {
> + for (GenericValue orderItem: orderItems) {
> + String productId = (String) orderItem.get("productId");
> + GenericValue product =
> delegator.getRelatedOne("Product", orderItem);
> +
> +
> if("SERVICE_PRODUCT".equals(product.get("productTypeId"))){
> + String inventoryFacilityId = null;
> + if
> ("Y".equals(productStore.getString("oneInventoryFacility"))) {
> + inventoryFacilityId =
> productStore.getString("inventoryFacilityId");
> +
> + if (UtilValidate.isEmpty(inventoryFacilityId)) {
> + Debug.logWarning("ProductStore with id " +
> productStoreId + " has Y for oneInventoryFacility but inventoryFacilityId is
> empty, returning false for inventory check", module);
> + }
> + } else {
> + List<GenericValue> productFacilities = null;
> + GenericValue productFacility = null;
> +
> + try {
> + productFacilities =
> delegator.getRelatedCache("ProductFacility", product);
> + } catch (GenericEntityException e) {
> + Debug.logWarning(e, "Error invoking
> getRelatedCache in isCatalogInventoryAvailable", module);
> + }
> +
> + if (UtilValidate.isNotEmpty(productFacilities)) {
> + productFacility =
> EntityUtil.getFirst(productFacilities);
> + inventoryFacilityId = (String)
> productFacility.get("facilityId");
> + }
> + }
> +
> + Map<String, Object> ripCtx = FastMap.newInstance();
> + if (UtilValidate.isNotEmpty(inventoryFacilityId) &&
> UtilValidate.isNotEmpty(productId) &&
> orderItem.getBigDecimal("quantity").compareTo(BigDecimal.ZERO) > 0) {
> + // do something tricky here: run as the "system"
> user
> + GenericValue permUserLogin =
> delegator.findByPrimaryKeyCache("UserLogin", UtilMisc.toMap("userLoginId",
> "system"));
> + ripCtx.put("productId", productId);
> + ripCtx.put("facilityId", inventoryFacilityId);
> + ripCtx.put("inventoryItemTypeId",
> "NON_SERIAL_INV_ITEM");
> + ripCtx.put("quantityAccepted",
> orderItem.getBigDecimal("quantity"));
> + ripCtx.put("quantityRejected", 0.0);
> + ripCtx.put("userLogin", permUserLogin);
> + try {
> + Map<String, Object> ripResult =
> dispatcher.runSync("receiveInventoryProduct", ripCtx);
> + if (ServiceUtil.isError(ripResult)) {
> + String errMsg =
> ServiceUtil.getErrorMessage(ripResult);
> + resErrorMessages.addAll((Collection<?
> extends String>) UtilMisc.<String, String>toMap("reasonCode",
> "ReceiveInventoryServiceError", "description", errMsg));
> + }
> + } catch (GenericServiceException e) {
> + Debug.logWarning(e, "Error invoking
> receiveInventoryProduct service in createOrder", module);
> + }
> + }
> + }
> + }
> + }
> +
> + // START inventory reservation
> try {
> reserveInventory(delegator, dispatcher, userLogin, locale,
> orderItemShipGroupInfo, dropShipGroupIds, itemValuesBySeqId,
> orderTypeId, productStoreId, resErrorMessages);
>
> Modified: ofbiz/trunk/applications/order/testdef/ShoppingCartTests.xml
> URL:
> http://svn.apache.org/viewvc/ofbiz/trunk/applications/order/testdef/ShoppingCartTests.xml?rev=1166543&r1=1166542&r2=1166543&view=diff
> ==============================================================================
> --- ofbiz/trunk/applications/order/testdef/ShoppingCartTests.xml (original)
> +++ ofbiz/trunk/applications/order/testdef/ShoppingCartTests.xml Thu Sep 8
> 07:07:07 2011
> @@ -25,4 +25,7 @@ under the License.
> <test-case case-name="shoppingCart-test">
> <simple-method-test
> location="component://order/script/org/ofbiz/order/test/ShoppingCartTests.xml"
> name="testCreateShoppingCart"/>
> </test-case>
> + <test-case case-name="productServiceOrder-test">
> + <simple-method-test
> location="component://order/script/org/ofbiz/order/test/ShoppingCartTests.xml"
> name="testCreateOrderServiceProduct"/>
> + </test-case>
> </test-suite>
>
> Modified: ofbiz/trunk/applications/product/data/ProductTypeData.xml
> URL:
> http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/data/ProductTypeData.xml?rev=1166543&r1=1166542&r2=1166543&view=diff
> ==============================================================================
> --- ofbiz/trunk/applications/product/data/ProductTypeData.xml (original)
> +++ ofbiz/trunk/applications/product/data/ProductTypeData.xml Thu Sep 8
> 07:07:07 2011
> @@ -498,6 +498,7 @@ under the License.
> <ProductType description="Marketing Package: Pick Assembly"
> isPhysical="Y" isDigital="N" hasTable="N" parentTypeId="MARKETING_PKG"
> 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="Y"
> isDigital="N" hasTable="N" parentTypeId="AGGREGATED"
> productTypeId="AGGREGATED_CONF"/>
> + <ProductType description="Service a product which is received to- and
> shipped from inventory" isPhysical="Y" isDigital="N" hasTable="N"
> parentTypeId="" productTypeId="SERVICE_PRODUCT"/>
>
> <EnumerationType description="Product Requirement Method"
> enumTypeId="PROD_REQ_METHOD" hasTable="N" parentTypeId=""/>
> <!-- NONE: no requirement is created (default) -->
>
> Modified: ofbiz/trunk/specialpurpose/ecommerce/data/DemoProduct.xml
> URL:
> http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ecommerce/data/DemoProduct.xml?rev=1166543&r1=1166542&r2=1166543&view=diff
> ==============================================================================
> --- ofbiz/trunk/specialpurpose/ecommerce/data/DemoProduct.xml (original)
> +++ ofbiz/trunk/specialpurpose/ecommerce/data/DemoProduct.xml Thu Sep 8
> 07:07:07 2011
> @@ -710,7 +710,7 @@ under the License.
> <ElectronicText dataResourceId="SERV-001-ALT" textData="service-product"/>
> <ElectronicText dataResourceId="DRSERV-001-ALTEN" textData="services"/>
> <ElectronicText dataResourceId="DRSERV-001-ALTEN"
> textData="service-product"/>
> -
> +
> <Content contentId="SERV-001-ALT" contentTypeId="DOCUMENT"
> dataResourceId="SERV-001-ALT" localeString="en"/>
> <Content contentId="CSERV-001-ALTEN" contentTypeId="DOCUMENT"
> dataResourceId="DRSERV-001-ALTEN" localeString="en_US"/>
> <Content contentId="SV-1000-ALT" contentTypeId="DOCUMENT"
> dataResourceId="SV-1000-ALT" localeString="en"/>
> @@ -720,6 +720,22 @@ under the License.
> <ProductCategoryContent productCategoryId="SERV-001"
> contentId="SERV-001-ALT" prodCatContentTypeId="ALTERNATIVE_URL"
> fromDate="2001-05-13 12:00:00.0"/>
> <ProductContent productId="SV-1000" contentId="SV-1000-ALT"
> productContentTypeId="ALTERNATIVE_URL" fromDate="2001-05-13 12:00:00.0"/>
>
> + <!-- test for service product type which is received to- and shipped
> from inventory-->
> + <Product productId="SV-1001" productTypeId="SERVICE_PRODUCT"
> primaryProductCategoryId="SERV-001" productName="Laundry service"
> internalName="Service type product which is received to- and shipped from
> inventory" description="Service type product which is received to- and
> shipped from inventory for demonstration use" taxable="Y" chargeShipping="N"
> autoCreateKeywords="Y" isVirtual="N" isVariant="N" createdDate="2008-12-02
> 12:00:00.0" createdByUserLogin="admin" lastModifiedDate="2008-12-02
> 12:00:00.0" lastModifiedByUserLogin="admin"/>
> + <ProductPrice productId="SV-1001" productPricePurposeId="PURCHASE"
> productPriceTypeId="DEFAULT_PRICE" currencyUomId="USD"
> productStoreGroupId="_NA_" fromDate="2011-08-02 12:00:00.0" price="10.99"
> createdDate="2011-08-02 12:00:00.0" createdByUserLogin="admin"/>
> + <ProductCategoryMember productCategoryId="SERV-001" productId="SV-1001"
> fromDate="2011-08-02 12:00:00.0"/>
> + <ProductCategoryMember productCategoryId="CATALOG1_SEARCH"
> productId="SV-1001" fromDate="2011-08-02 12:00:00.0"/>
> + <DataResource dataResourceId="SV-1001-ALT" dataResourceTypeId="LINK"
> objectInfo="lanudry-service-SV-1001-p"/>
> + <DataResource dataResourceTypeId="ELECTRONIC_TEXT"
> dataResourceId="SV-1001-ALT" localeString="en"/>
> + <DataResource dataResourceTypeId="ELECTRONIC_TEXT"
> dataResourceId="DRSV-1001-ALTEN" localeString="en_US"/>
> + <ElectronicText dataResourceId="SV-1001-ALT" textData="service-product"/>
> + <ElectronicText dataResourceId="DRSV-1001-ALTEN"
> textData="service-product"/>
> +
> + <Content contentId="SV-1001-ALT" contentTypeId="DOCUMENT"
> dataResourceId="SV-1001-ALT" localeString="en"/>
> + <Content contentId="CSV-1001-ALTEN" contentTypeId="DOCUMENT"
> dataResourceId="DRSV-1001-ALTEN" localeString="en_US"/>
> + <ContentAssoc contentId="SV-1001-ALT" contentIdTo="CSV-1001-ALTEN"
> contentAssocTypeId="ALTERNATE_LOCALE" fromDate="2011-08-02 12:00:00.0"/>
> + <ProductContent productId="SV-1001" contentId="SV-1001-ALT"
> productContentTypeId="ALTERNATIVE_URL" fromDate="2011-08-02 12:00:00.0"/>
> +
> <ProductFeatureCategory productFeatureCategoryId="8000"
> description="License Features"/>
> <ProductFeatureCategoryAppl productFeatureCategoryId="8000"
> productCategoryId="CATALOG1_SEARCH" fromDate="2001-05-13 12:00:00.0"/>
>
> @@ -975,6 +991,7 @@ under the License.
> <ProductFacility productId="GZ-1000" facilityId="WebStoreWarehouse"
> minimumStock="2" reorderQuantity="10" daysToShip="1"/>
> <ProductFacility productId="GZ-1001" facilityId="WebStoreWarehouse"
> minimumStock="2" reorderQuantity="10" daysToShip="1"/>
> <ProductFacility productId="GZ-1004" facilityId="WebStoreWarehouse"
> minimumStock="2" reorderQuantity="10" daysToShip="1"/>
> + <ProductFacility productId="SV-1001" facilityId="WebStoreWarehouse"
> minimumStock="2" reorderQuantity="10" daysToShip="1"/>
>
> <ProductFacilityLocation productId="GZ-2644"
> facilityId="WebStoreWarehouse" locationSeqId="TLTLTLUL01"/>
> <ProductFacilityLocation productId="GZ-2644"
> facilityId="WebStoreWarehouse" locationSeqId="TLTLTLLL01" minimumStock="2"
> moveQuantity="5"/>
> @@ -987,6 +1004,7 @@ under the License.
> <ProductFacilityLocation productId="GZ-1000"
> facilityId="WebStoreWarehouse" locationSeqId="TLTLTLUL01" minimumStock="5"
> moveQuantity="20"/>
> <ProductFacilityLocation productId="GZ-1001"
> facilityId="WebStoreWarehouse" locationSeqId="TLTLTLLL02" minimumStock="5"
> moveQuantity="20"/>
> <ProductFacilityLocation productId="GZ-1004"
> facilityId="WebStoreWarehouse" locationSeqId="TLTLTLLL04" minimumStock="5"
> moveQuantity="20"/>
> + <ProductFacilityLocation productId="SV-1001"
> facilityId="WebStoreWarehouse" locationSeqId="TLTLTLLL04" minimumStock="5"
> moveQuantity="20"/>
>
> <!-- some default inventory quantities, things are a bit underutilized
> without these... -->
> <InventoryItem facilityId="WebStoreWarehouse" locationSeqId="TLTLTLUL01"
> datetimeReceived="2008-08-01 08:00:00.000"
>
>