0001: /*******************************************************************************
0002: * Licensed to the Apache Software Foundation (ASF) under one
0003: * or more contributor license agreements. See the NOTICE file
0004: * distributed with this work for additional information
0005: * regarding copyright ownership. The ASF licenses this file
0006: * to you under the Apache License, Version 2.0 (the
0007: * "License"); you may not use this file except in compliance
0008: * with the License. You may obtain a copy of the License at
0009: *
0010: * http://www.apache.org/licenses/LICENSE-2.0
0011: *
0012: * Unless required by applicable law or agreed to in writing,
0013: * software distributed under the License is distributed on an
0014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0015: * KIND, either express or implied. See the License for the
0016: * specific language governing permissions and limitations
0017: * under the License.
0018: *******************************************************************************/package org.ofbiz.order.order;
0019:
0020: import java.math.BigDecimal;
0021: import java.sql.Timestamp;
0022: import java.text.NumberFormat;
0023: import java.text.ParseException;
0024: import java.util.*;
0025:
0026: import javolution.util.FastList;
0027: import javolution.util.FastMap;
0028:
0029: import org.ofbiz.base.util.*;
0030: import org.ofbiz.base.util.collections.ResourceBundleMapWrapper;
0031: import org.ofbiz.common.DataModelConstants;
0032: import org.ofbiz.entity.GenericDelegator;
0033: import org.ofbiz.entity.GenericEntity;
0034: import org.ofbiz.entity.GenericEntityException;
0035: import org.ofbiz.entity.GenericValue;
0036: import org.ofbiz.entity.transaction.TransactionUtil;
0037: import org.ofbiz.entity.transaction.GenericTransactionException;
0038: import org.ofbiz.entity.condition.EntityCondition;
0039: import org.ofbiz.entity.condition.EntityConditionList;
0040: import org.ofbiz.entity.condition.EntityExpr;
0041: import org.ofbiz.entity.condition.EntityOperator;
0042: import org.ofbiz.entity.util.EntityListIterator;
0043: import org.ofbiz.entity.util.EntityUtil;
0044: import org.ofbiz.order.shoppingcart.CartItemModifyException;
0045: import org.ofbiz.order.shoppingcart.CheckOutHelper;
0046: import org.ofbiz.order.shoppingcart.ItemNotFoundException;
0047: import org.ofbiz.order.shoppingcart.ShoppingCart;
0048: import org.ofbiz.order.shoppingcart.ShoppingCartItem;
0049: import org.ofbiz.order.shoppingcart.shipping.ShippingEvents;
0050: import org.ofbiz.party.contact.ContactHelper;
0051: import org.ofbiz.party.party.PartyWorker;
0052: import org.ofbiz.product.product.ProductWorker;
0053: import org.ofbiz.product.store.ProductStoreWorker;
0054: import org.ofbiz.security.Security;
0055: import org.ofbiz.service.DispatchContext;
0056: import org.ofbiz.service.GenericServiceException;
0057: import org.ofbiz.service.LocalDispatcher;
0058: import org.ofbiz.service.ModelService;
0059: import org.ofbiz.service.ServiceUtil;
0060: import org.ofbiz.workflow.WfUtil;
0061:
0062: import javax.transaction.Transaction;
0063:
0064: /**
0065: * Order Processing Services
0066: */
0067:
0068: public class OrderServices {
0069:
0070: public static final String module = OrderServices.class.getName();
0071: public static final String resource = "OrderUiLabels";
0072: public static final String resource_error = "OrderErrorUiLabels";
0073:
0074: public static Map salesAttributeRoleMap = FastMap.newInstance();
0075: public static Map purchaseAttributeRoleMap = FastMap.newInstance();
0076: static {
0077: salesAttributeRoleMap.put("placingCustomerPartyId",
0078: "PLACING_CUSTOMER");
0079: salesAttributeRoleMap.put("billToCustomerPartyId",
0080: "BILL_TO_CUSTOMER");
0081: salesAttributeRoleMap.put("billFromVendorPartyId",
0082: "BILL_FROM_VENDOR");
0083: salesAttributeRoleMap.put("shipToCustomerPartyId",
0084: "SHIP_TO_CUSTOMER");
0085: salesAttributeRoleMap.put("endUserCustomerPartyId",
0086: "END_USER_CUSTOMER");
0087:
0088: purchaseAttributeRoleMap.put("billToCustomerPartyId",
0089: "BILL_TO_CUSTOMER");
0090: purchaseAttributeRoleMap.put("billFromVendorPartyId",
0091: "BILL_FROM_VENDOR");
0092: purchaseAttributeRoleMap.put("shipFromVendorPartyId",
0093: "SHIP_FROM_VENDOR");
0094: purchaseAttributeRoleMap.put("supplierAgentPartyId",
0095: "SUPPLIER_AGENT");
0096: }
0097: public static final int taxDecimals = UtilNumber
0098: .getBigDecimalScale("salestax.calc.decimals");
0099: public static final int taxRounding = UtilNumber
0100: .getBigDecimalRoundingMode("salestax.rounding");
0101: public static final int orderDecimals = UtilNumber
0102: .getBigDecimalScale("order.decimals");
0103: public static final int orderRounding = UtilNumber
0104: .getBigDecimalRoundingMode("order.rounding");
0105: public static final BigDecimal ZERO = (new BigDecimal("0"))
0106: .setScale(taxDecimals, taxRounding);
0107:
0108: /** Service for creating a new order */
0109: public static Map createOrder(DispatchContext ctx, Map context) {
0110: GenericDelegator delegator = ctx.getDelegator();
0111: LocalDispatcher dispatcher = ctx.getDispatcher();
0112: Security security = ctx.getSecurity();
0113: List toBeStored = new LinkedList();
0114: Locale locale = (Locale) context.get("locale");
0115: Map successResult = ServiceUtil.returnSuccess();
0116:
0117: GenericValue userLogin = (GenericValue) context
0118: .get("userLogin");
0119: // get the order type
0120: String orderTypeId = (String) context.get("orderTypeId");
0121: String partyId = (String) context.get("partyId");
0122: String billFromVendorPartyId = (String) context
0123: .get("billFromVendorPartyId");
0124:
0125: // check security permissions for order:
0126: // SALES ORDERS - if userLogin has ORDERMGR_SALES_CREATE or ORDERMGR_CREATE permission, or if it is same party as the partyId, or
0127: // if it is an AGENT (sales rep) creating an order for his customer
0128: // PURCHASE ORDERS - if there is a PURCHASE_ORDER permission
0129: Map resultSecurity = new HashMap();
0130: boolean hasPermission = false;
0131: if (orderTypeId.equals("SALES_ORDER")) {
0132: if (security.hasEntityPermission("ORDERMGR",
0133: "_SALES_CREATE", userLogin)) {
0134: hasPermission = true;
0135: } else {
0136: // check sales agent/customer relationship
0137: List repsCustomers = new LinkedList();
0138: try {
0139: repsCustomers = EntityUtil.filterByDate(userLogin
0140: .getRelatedOne("Party").getRelatedByAnd(
0141: "FromPartyRelationship",
0142: UtilMisc.toMap("roleTypeIdFrom",
0143: "AGENT", "roleTypeIdTo",
0144: "CUSTOMER", "partyIdTo",
0145: partyId)));
0146: } catch (GenericEntityException ex) {
0147: Debug.logError("Could not determine if " + partyId
0148: + " is a customer of user "
0149: + userLogin.getString("userLoginId")
0150: + " due to " + ex.getMessage(), module);
0151: }
0152: if ((repsCustomers != null)
0153: && (repsCustomers.size() > 0)
0154: && (security.hasEntityPermission("SALESREP",
0155: "_ORDER_CREATE", userLogin))) {
0156: hasPermission = true;
0157: }
0158: }
0159: } else if ((orderTypeId.equals("PURCHASE_ORDER") && (security
0160: .hasEntityPermission("ORDERMGR", "_PURCHASE_CREATE",
0161: userLogin)))) {
0162: hasPermission = true;
0163: }
0164: // final check - will pass if userLogin's partyId = partyId for order or if userLogin has ORDERMGR_CREATE permission
0165: if (!hasPermission) {
0166: partyId = ServiceUtil.getPartyIdCheckSecurity(userLogin,
0167: security, context, resultSecurity, "ORDERMGR",
0168: "_CREATE");
0169: if (resultSecurity.size() > 0) {
0170: return resultSecurity;
0171: }
0172: }
0173:
0174: // get the product store for the order, but it is required only for sales orders
0175: String productStoreId = (String) context.get("productStoreId");
0176: GenericValue productStore = null;
0177: if ((orderTypeId.equals("SALES_ORDER"))
0178: && (UtilValidate.isNotEmpty(productStoreId))) {
0179: try {
0180: productStore = delegator.findByPrimaryKeyCache(
0181: "ProductStore", UtilMisc.toMap(
0182: "productStoreId", productStoreId));
0183: } catch (GenericEntityException e) {
0184: return ServiceUtil
0185: .returnError(UtilProperties
0186: .getMessage(
0187: resource_error,
0188: "OrderErrorCouldNotFindProductStoreWithID",
0189: UtilMisc.toMap(
0190: "productStoreId",
0191: productStoreId), locale)
0192: + e.toString());
0193: }
0194: }
0195:
0196: // figure out if the order is immediately fulfilled based on product store settings
0197: boolean isImmediatelyFulfilled = false;
0198: if (productStore != null) {
0199: isImmediatelyFulfilled = "Y".equals(productStore
0200: .getString("isImmediatelyFulfilled"));
0201: }
0202:
0203: successResult.put("orderTypeId", orderTypeId);
0204:
0205: // lookup the order type entity
0206: GenericValue orderType = null;
0207: try {
0208: orderType = delegator.findByPrimaryKeyCache("OrderType",
0209: UtilMisc.toMap("orderTypeId", orderTypeId));
0210: } catch (GenericEntityException e) {
0211: return ServiceUtil.returnError(UtilProperties.getMessage(
0212: resource_error, "OrderErrorOrderTypeLookupFailed",
0213: locale)
0214: + e.toString());
0215: }
0216:
0217: // make sure we have a valid order type
0218: if (orderType == null) {
0219: return ServiceUtil
0220: .returnError(UtilProperties.getMessage(
0221: resource_error,
0222: "OrderErrorInvalidOrderTypeWithID",
0223: UtilMisc.toMap("orderTypeId", orderTypeId),
0224: locale));
0225: }
0226:
0227: // check to make sure we have something to order
0228: List orderItems = (List) context.get("orderItems");
0229: if (orderItems.size() < 1) {
0230: return ServiceUtil.returnError(UtilProperties.getMessage(
0231: resource, "items.none", locale));
0232: }
0233:
0234: // all this marketing pkg auto stuff is deprecated in favor of MARKETING_PKG_AUTO productTypeId and a BOM of MANUF_COMPONENT assocs
0235: // these need to be retrieved now because they might be needed for exploding MARKETING_PKG_AUTO
0236: List orderAdjustments = (List) context.get("orderAdjustments");
0237: List orderItemShipGroupInfo = (List) context
0238: .get("orderItemShipGroupInfo");
0239: List orderItemPriceInfo = (List) context
0240: .get("orderItemPriceInfos");
0241:
0242: // check inventory and other things for each item
0243: List errorMessages = FastList.newInstance();
0244: Map normalizedItemQuantities = FastMap.newInstance();
0245: Map normalizedItemNames = FastMap.newInstance();
0246: Map itemValuesBySeqId = FastMap.newInstance();
0247: Iterator itemIter = orderItems.iterator();
0248: java.sql.Timestamp nowTimestamp = UtilDateTime.nowTimestamp();
0249:
0250: //
0251: // need to run through the items combining any cases where multiple lines refer to the
0252: // same product so the inventory check will work correctly
0253: // also count quantities ordered while going through the loop
0254: while (itemIter.hasNext()) {
0255: GenericValue orderItem = (GenericValue) itemIter.next();
0256:
0257: // start by putting it in the itemValuesById Map
0258: itemValuesBySeqId.put(
0259: orderItem.getString("orderItemSeqId"), orderItem);
0260:
0261: String currentProductId = (String) orderItem
0262: .get("productId");
0263: if (currentProductId != null) {
0264: // only normalize items with a product associated (ignore non-product items)
0265: if (normalizedItemQuantities.get(currentProductId) == null) {
0266: normalizedItemQuantities.put(currentProductId,
0267: new Double(orderItem.getDouble("quantity")
0268: .doubleValue()));
0269: normalizedItemNames.put(currentProductId, orderItem
0270: .getString("itemDescription"));
0271: } else {
0272: Double currentQuantity = (Double) normalizedItemQuantities
0273: .get(currentProductId);
0274: normalizedItemQuantities.put(currentProductId,
0275: new Double(currentQuantity.doubleValue()
0276: + orderItem.getDouble("quantity")
0277: .doubleValue()));
0278: }
0279:
0280: try {
0281: // count product ordered quantities
0282: // run this synchronously so it will run in the same transaction
0283: dispatcher.runSync("countProductQuantityOrdered",
0284: UtilMisc.toMap("productId",
0285: currentProductId, "quantity",
0286: orderItem.getDouble("quantity"),
0287: "userLogin", userLogin));
0288: } catch (GenericServiceException e1) {
0289: Debug
0290: .logError(
0291: e1,
0292: "Error calling countProductQuantityOrdered service",
0293: module);
0294: return ServiceUtil
0295: .returnError(UtilProperties
0296: .getMessage(
0297: resource_error,
0298: "OrderErrorCallingCountProductQuantityOrderedService",
0299: locale)
0300: + e1.toString());
0301: }
0302: }
0303: }
0304:
0305: if (!"PURCHASE_ORDER".equals(orderTypeId)
0306: && productStoreId == null) {
0307: return ServiceUtil
0308: .returnError(UtilProperties
0309: .getMessage(
0310: resource_error,
0311: "OrderErrorTheProductStoreIdCanOnlyBeNullForPurchaseOrders",
0312: locale));
0313: }
0314:
0315: Iterator normalizedIter = normalizedItemQuantities.keySet()
0316: .iterator();
0317: while (normalizedIter.hasNext()) {
0318: // lookup the product entity for each normalized item; error on products not found
0319: String currentProductId = (String) normalizedIter.next();
0320: Double currentQuantity = (Double) normalizedItemQuantities
0321: .get(currentProductId);
0322: String itemName = (String) normalizedItemNames
0323: .get(currentProductId);
0324: GenericValue product = null;
0325:
0326: try {
0327: product = delegator.findByPrimaryKeyCache("Product",
0328: UtilMisc.toMap("productId", currentProductId));
0329: } catch (GenericEntityException e) {
0330: String errMsg = UtilProperties.getMessage(resource,
0331: "product.not_found",
0332: new Object[] { currentProductId }, locale);
0333: Debug.logError(e, errMsg, module);
0334: errorMessages.add(errMsg);
0335: continue;
0336: }
0337:
0338: if (product == null) {
0339: String errMsg = UtilProperties.getMessage(resource,
0340: "product.not_found",
0341: new Object[] { currentProductId }, locale);
0342: Debug.logError(errMsg, module);
0343: errorMessages.add(errMsg);
0344: continue;
0345: }
0346:
0347: if ("SALES_ORDER".equals(orderTypeId)) {
0348: // check to see if introductionDate hasn't passed yet
0349: if (product.get("introductionDate") != null
0350: && nowTimestamp.before(product
0351: .getTimestamp("introductionDate"))) {
0352: String excMsg = UtilProperties.getMessage(resource,
0353: "product.not_yet_for_sale", new Object[] {
0354: getProductName(product, itemName),
0355: product.getString("productId") },
0356: locale);
0357: Debug.logWarning(excMsg, module);
0358: errorMessages.add(excMsg);
0359: continue;
0360: }
0361: }
0362:
0363: if ("SALES_ORDER".equals(orderTypeId)) {
0364: // check to see if salesDiscontinuationDate has passed
0365: if (product.get("salesDiscontinuationDate") != null
0366: && nowTimestamp
0367: .after(product
0368: .getTimestamp("salesDiscontinuationDate"))) {
0369: String excMsg = UtilProperties.getMessage(resource,
0370: "product.no_longer_for_sale", new Object[] {
0371: getProductName(product, itemName),
0372: product.getString("productId") },
0373: locale);
0374: Debug.logWarning(excMsg, module);
0375: errorMessages.add(excMsg);
0376: continue;
0377: }
0378: }
0379:
0380: if ("SALES_ORDER".equals(orderTypeId)) {
0381: // check to see if we have inventory available
0382: try {
0383: Map invReqResult = dispatcher.runSync(
0384: "isStoreInventoryAvailableOrNotRequired",
0385: UtilMisc.toMap("productStoreId",
0386: productStoreId, "productId",
0387: product.get("productId"),
0388: "product", product, "quantity",
0389: currentQuantity));
0390: if (ServiceUtil.isError(invReqResult)) {
0391: errorMessages.add(invReqResult
0392: .get(ModelService.ERROR_MESSAGE));
0393: errorMessages.addAll((List) invReqResult
0394: .get(ModelService.ERROR_MESSAGE_LIST));
0395: } else if (!"Y".equals((String) invReqResult
0396: .get("availableOrNotRequired"))) {
0397: String invErrMsg = UtilProperties.getMessage(
0398: resource, "product.out_of_stock",
0399: new Object[] {
0400: getProductName(product,
0401: itemName),
0402: currentProductId }, locale);
0403: Debug.logWarning(invErrMsg, module);
0404: errorMessages.add(invErrMsg);
0405: continue;
0406: }
0407: } catch (GenericServiceException e) {
0408: String errMsg = "Fatal error calling inventory checking services: "
0409: + e.toString();
0410: Debug.logError(e, errMsg, module);
0411: errorMessages.add(errMsg);
0412: }
0413: }
0414: }
0415:
0416: // add the fixedAsset id to the workefforts map by obtaining the fixed Asset number from the FixedAssetProduct table
0417: List workEfforts = (List) context.get("workEfforts"); // is an optional parameter from this service but mandatory for rental items
0418: Iterator orderItemIter = orderItems.iterator();
0419: while (orderItemIter.hasNext()) {
0420: GenericValue orderItem = (GenericValue) orderItemIter
0421: .next();
0422: if ("RENTAL_ORDER_ITEM".equals(orderItem
0423: .getString("orderItemTypeId"))) {
0424: // check to see if workefforts are available for this order type.
0425: if (workEfforts == null || workEfforts.size() == 0) {
0426: String errMsg = "Work Efforts missing for ordertype RENTAL_ORDER_ITEM "
0427: + "Product: "
0428: + orderItem.getString("productId");
0429: Debug.logError(errMsg, module);
0430: errorMessages.add(errMsg);
0431: return ServiceUtil.returnError(UtilProperties
0432: .getMessage(resource_error,
0433: "OrderRentalOrderItems", locale));
0434: }
0435: Iterator we = workEfforts.iterator(); // find the related workEffortItem (workEffortId = orderSeqId)
0436: while (we.hasNext()) {
0437: // create the entity maps required.
0438: GenericValue workEffort = (GenericValue) we.next();
0439: if (workEffort.getString("workEffortId").equals(
0440: orderItem.getString("orderItemSeqId"))) {
0441: List selFixedAssetProduct = null;
0442: try {
0443: List allFixedAssetProduct = delegator
0444: .findByAnd(
0445: "FixedAssetProduct",
0446: UtilMisc
0447: .toMap(
0448: "productId",
0449: orderItem
0450: .getString("productId"),
0451: "fixedAssetProductTypeId",
0452: "FAPT_USE"));
0453: selFixedAssetProduct = EntityUtil
0454: .filterByDate(allFixedAssetProduct,
0455: nowTimestamp, "fromDate",
0456: "thruDate", true);
0457: } catch (GenericEntityException e) {
0458: String excMsg = "Could not find related Fixed Asset for the product: "
0459: + orderItem.getString("productId");
0460: Debug.logError(excMsg, module);
0461: errorMessages.add(excMsg);
0462: return ServiceUtil
0463: .returnError(UtilProperties
0464: .getMessage(
0465: resource_error,
0466: "OrderCouldNotFindRelatedFixedAssetForTheProduct",
0467: UtilMisc
0468: .toMap(
0469: "productId",
0470: orderItem
0471: .getString("productId")),
0472: locale));
0473: }
0474: if (selFixedAssetProduct != null
0475: && selFixedAssetProduct.size() > 0) {
0476: Iterator firstOne = selFixedAssetProduct
0477: .iterator();
0478: if (firstOne.hasNext()) {
0479: GenericValue fixedAssetProduct = delegator
0480: .makeValue("FixedAssetProduct",
0481: null);
0482: fixedAssetProduct = (GenericValue) firstOne
0483: .next();
0484: workEffort.set("fixedAssetId",
0485: fixedAssetProduct
0486: .get("fixedAssetId"));
0487: workEffort.set("quantityToProduce",
0488: orderItem.get("quantity")); // have quantity easy available later...
0489: }
0490: }
0491: break; // item found, so go to next orderitem.
0492: }
0493: }
0494: }
0495: }
0496:
0497: if (errorMessages.size() > 0) {
0498: return ServiceUtil.returnError(errorMessages);
0499: }
0500:
0501: // the inital status for ALL order types
0502: String initialStatus = "ORDER_CREATED";
0503: successResult.put("statusId", initialStatus);
0504:
0505: // create the order object
0506: String orderId = null;
0507: String orgPartyId = null;
0508: if (productStore != null) {
0509: orgPartyId = productStore.getString("payToPartyId");
0510: } else if (billFromVendorPartyId != null) {
0511: orgPartyId = billFromVendorPartyId;
0512: }
0513:
0514: if (UtilValidate.isNotEmpty(orgPartyId)) {
0515: Map getNextOrderIdContext = UtilMisc.toMap("partyId",
0516: orgPartyId, "userLogin", userLogin);
0517:
0518: if ((orderTypeId.equals("SALES_ORDER"))
0519: || (productStoreId != null)) {
0520: getNextOrderIdContext.put("productStoreId",
0521: productStoreId);
0522: }
0523:
0524: try {
0525: Map getNextOrderIdResult = dispatcher.runSync(
0526: "getNextOrderId", getNextOrderIdContext);
0527: if (ServiceUtil.isError(getNextOrderIdResult)) {
0528: return ServiceUtil
0529: .returnError(
0530: "Error getting next orderId while creating order",
0531: null, null, getNextOrderIdResult);
0532: }
0533:
0534: orderId = (String) getNextOrderIdResult.get("orderId");
0535: } catch (GenericServiceException e) {
0536: String errMsg = "Error creating order while getting orderId: "
0537: + e.toString();
0538: Debug.logError(e, errMsg, module);
0539: return ServiceUtil.returnError(errMsg);
0540: }
0541: }
0542:
0543: if (UtilValidate.isEmpty(orderId)) {
0544: // for purchase orders or when other orderId generation fails, a product store id should not be required to make an order
0545: orderId = delegator.getNextSeqId("OrderHeader");
0546: }
0547:
0548: String billingAccountId = (String) context
0549: .get("billingAccountId");
0550: Timestamp orderDate = (Timestamp) context.get("orderDate");
0551: if (orderDate == null) {
0552: orderDate = nowTimestamp;
0553: }
0554:
0555: Map orderHeaderMap = UtilMisc.toMap("orderId", orderId,
0556: "orderTypeId", orderTypeId, "orderDate", orderDate,
0557: "entryDate", nowTimestamp, "statusId", initialStatus,
0558: "billingAccountId", billingAccountId);
0559: orderHeaderMap.put("orderName", context.get("orderName"));
0560: if (isImmediatelyFulfilled) {
0561: // also flag this order as needing inventory issuance so that when it is set to complete it will be issued immediately (needsInventoryIssuance = Y)
0562: orderHeaderMap.put("needsInventoryIssuance", "Y");
0563: }
0564: GenericValue orderHeader = delegator.makeValue("OrderHeader",
0565: orderHeaderMap);
0566:
0567: // determine the sales channel
0568: String salesChannelEnumId = (String) context
0569: .get("salesChannelEnumId");
0570: if ((salesChannelEnumId == null)
0571: || salesChannelEnumId.equals("UNKNWN_SALES_CHANNEL")) {
0572: // try the default store sales channel
0573: if (orderTypeId.equals("SALES_ORDER")
0574: && (productStore != null)) {
0575: salesChannelEnumId = productStore
0576: .getString("defaultSalesChannelEnumId");
0577: }
0578: // if there's still no channel, set to unknown channel
0579: if (salesChannelEnumId == null) {
0580: salesChannelEnumId = "UNKNWN_SALES_CHANNEL";
0581: }
0582: }
0583: orderHeader.set("salesChannelEnumId", salesChannelEnumId);
0584:
0585: if (context.get("currencyUom") != null) {
0586: orderHeader.set("currencyUom", context.get("currencyUom"));
0587: }
0588:
0589: if (context.get("firstAttemptOrderId") != null) {
0590: orderHeader.set("firstAttemptOrderId", context
0591: .get("firstAttemptOrderId"));
0592: }
0593:
0594: if (context.get("grandTotal") != null) {
0595: orderHeader.set("grandTotal", context.get("grandTotal"));
0596: }
0597:
0598: if (UtilValidate.isNotEmpty((String) context.get("visitId"))) {
0599: orderHeader.set("visitId", context.get("visitId"));
0600: }
0601:
0602: if (UtilValidate.isNotEmpty((String) context
0603: .get("internalCode"))) {
0604: orderHeader
0605: .set("internalCode", context.get("internalCode"));
0606: }
0607:
0608: if (UtilValidate.isNotEmpty((String) context.get("externalId"))) {
0609: orderHeader.set("externalId", context.get("externalId"));
0610: }
0611:
0612: if (UtilValidate.isNotEmpty((String) context
0613: .get("originFacilityId"))) {
0614: orderHeader.set("originFacilityId", context
0615: .get("originFacilityId"));
0616: }
0617:
0618: if (UtilValidate.isNotEmpty((String) context
0619: .get("productStoreId"))) {
0620: orderHeader.set("productStoreId", context
0621: .get("productStoreId"));
0622: }
0623:
0624: if (UtilValidate.isNotEmpty((String) context
0625: .get("transactionId"))) {
0626: orderHeader.set("transactionId", context
0627: .get("transactionId"));
0628: }
0629:
0630: if (UtilValidate.isNotEmpty((String) context.get("terminalId"))) {
0631: orderHeader.set("terminalId", context.get("terminalId"));
0632: }
0633:
0634: if (UtilValidate.isNotEmpty((String) context
0635: .get("autoOrderShoppingListId"))) {
0636: orderHeader.set("autoOrderShoppingListId", context
0637: .get("autoOrderShoppingListId"));
0638: }
0639:
0640: if (UtilValidate.isNotEmpty((String) context.get("webSiteId"))) {
0641: orderHeader.set("webSiteId", context.get("webSiteId"));
0642: }
0643:
0644: if (userLogin != null && userLogin.get("userLoginId") != null) {
0645: orderHeader.set("createdBy", userLogin
0646: .getString("userLoginId"));
0647: }
0648:
0649: // first try to create the OrderHeader; if this does not fail, continue.
0650: try {
0651: delegator.create(orderHeader);
0652: } catch (GenericEntityException e) {
0653: Debug
0654: .logError(
0655: e,
0656: "Cannot create OrderHeader entity; problems with insert",
0657: module);
0658: return ServiceUtil
0659: .returnError(UtilProperties
0660: .getMessage(
0661: resource_error,
0662: "OrderOrderCreationFailedPleaseNotifyCustomerService",
0663: locale));
0664: }
0665:
0666: // create the order status record
0667: String orderStatusSeqId = delegator.getNextSeqId("OrderStatus");
0668: GenericValue orderStatus = delegator.makeValue("OrderStatus",
0669: UtilMisc.toMap("orderStatusId", orderStatusSeqId));
0670: orderStatus.set("orderId", orderId);
0671: orderStatus.set("statusId", orderHeader.getString("statusId"));
0672: orderStatus.set("statusDatetime", nowTimestamp);
0673: orderStatus.set("statusUserLogin", userLogin
0674: .getString("userLoginId"));
0675: toBeStored.add(orderStatus);
0676:
0677: // before processing orderItems process orderItemGroups so that they'll be in place for the foreign keys and what not
0678: List orderItemGroups = (List) context.get("orderItemGroups");
0679: if (orderItemGroups != null && orderItemGroups.size() > 0) {
0680: Iterator orderItemGroupIter = orderItemGroups.iterator();
0681: while (orderItemGroupIter.hasNext()) {
0682: GenericValue orderItemGroup = (GenericValue) orderItemGroupIter
0683: .next();
0684: orderItemGroup.set("orderId", orderId);
0685: toBeStored.add(orderItemGroup);
0686: }
0687: }
0688:
0689: // set the order items
0690: Iterator oi = orderItems.iterator();
0691: while (oi.hasNext()) {
0692: GenericValue orderItem = (GenericValue) oi.next();
0693: orderItem.set("orderId", orderId);
0694: toBeStored.add(orderItem);
0695:
0696: // create the item status record
0697: String itemStatusId = delegator.getNextSeqId("OrderStatus");
0698: GenericValue itemStatus = delegator.makeValue(
0699: "OrderStatus", UtilMisc.toMap("orderStatusId",
0700: itemStatusId));
0701: itemStatus.put("statusId", orderItem.get("statusId"));
0702: itemStatus.put("orderId", orderId);
0703: itemStatus.put("orderItemSeqId", orderItem
0704: .get("orderItemSeqId"));
0705: itemStatus.put("statusDatetime", nowTimestamp);
0706: itemStatus.set("statusUserLogin", userLogin
0707: .getString("userLoginId"));
0708: toBeStored.add(itemStatus);
0709: }
0710:
0711: // set the order attributes
0712: List orderAttributes = (List) context.get("orderAttributes");
0713: if (orderAttributes != null && orderAttributes.size() > 0) {
0714: Iterator oattr = orderAttributes.iterator();
0715: while (oattr.hasNext()) {
0716: GenericValue oatt = (GenericValue) oattr.next();
0717: oatt.set("orderId", orderId);
0718: toBeStored.add(oatt);
0719: }
0720: }
0721:
0722: // set the order item attributes
0723: List orderItemAttributes = (List) context
0724: .get("orderItemAttributes");
0725: if (orderItemAttributes != null
0726: && orderItemAttributes.size() > 0) {
0727: Iterator oiattr = orderItemAttributes.iterator();
0728: while (oiattr.hasNext()) {
0729: GenericValue oiatt = (GenericValue) oiattr.next();
0730: oiatt.set("orderId", orderId);
0731: toBeStored.add(oiatt);
0732: }
0733: }
0734:
0735: // create the order internal notes
0736: List orderInternalNotes = (List) context
0737: .get("orderInternalNotes");
0738: if (orderInternalNotes != null && orderInternalNotes.size() > 0) {
0739: Iterator orderInternalNotesIt = orderInternalNotes
0740: .iterator();
0741: while (orderInternalNotesIt.hasNext()) {
0742: String orderInternalNote = (String) orderInternalNotesIt
0743: .next();
0744: try {
0745: Map noteOutputMap = dispatcher.runSync(
0746: "createOrderNote", UtilMisc.toMap(
0747: "orderId", orderId, "internalNote",
0748: "Y", "note", orderInternalNote,
0749: "userLogin", userLogin));
0750: if (ServiceUtil.isError(noteOutputMap)) {
0751: return ServiceUtil
0752: .returnError(
0753: "Error creating internal notes while creating order",
0754: null, null, noteOutputMap);
0755: }
0756: } catch (GenericServiceException e) {
0757: String errMsg = "Error creating internal notes while creating order: "
0758: + e.toString();
0759: Debug.logError(e, errMsg, module);
0760: return ServiceUtil.returnError(errMsg);
0761: }
0762: }
0763: }
0764:
0765: // create the order public notes
0766: List orderNotes = (List) context.get("orderNotes");
0767: if (orderNotes != null && orderNotes.size() > 0) {
0768: Iterator orderNotesIt = orderNotes.iterator();
0769: while (orderNotesIt.hasNext()) {
0770: String orderNote = (String) orderNotesIt.next();
0771: try {
0772: Map noteOutputMap = dispatcher.runSync(
0773: "createOrderNote", UtilMisc.toMap(
0774: "orderId", orderId, "internalNote",
0775: "N", "note", orderNote,
0776: "userLogin", userLogin));
0777: if (ServiceUtil.isError(noteOutputMap)) {
0778: return ServiceUtil
0779: .returnError(
0780: "Error creating notes while creating order",
0781: null, null, noteOutputMap);
0782: }
0783: } catch (GenericServiceException e) {
0784: String errMsg = "Error creating notes while creating order: "
0785: + e.toString();
0786: Debug.logError(e, errMsg, module);
0787: return ServiceUtil.returnError(errMsg);
0788: }
0789: }
0790: }
0791:
0792: // create the workeffort records
0793: // and connect them with the orderitem over the WorkOrderItemFulfillment
0794: // create also the techData calendars to keep track of availability of the fixed asset.
0795: if (workEfforts != null && workEfforts.size() > 0) {
0796: List tempList = new LinkedList();
0797: Iterator we = workEfforts.iterator();
0798: while (we.hasNext()) {
0799: // create the entity maps required.
0800: GenericValue workEffort = (GenericValue) we.next();
0801: GenericValue workOrderItemFulfillment = delegator
0802: .makeValue("WorkOrderItemFulfillment", null);
0803: // find fixed asset supplied on the workeffort map
0804: GenericValue fixedAsset = null;
0805: Debug.logInfo("find the fixedAsset", module);
0806: try {
0807: fixedAsset = delegator.findByPrimaryKey(
0808: "FixedAsset", UtilMisc.toMap(
0809: "fixedAssetId", workEffort
0810: .get("fixedAssetId")));
0811: } catch (GenericEntityException e) {
0812: return ServiceUtil
0813: .returnError(UtilProperties
0814: .getMessage(
0815: resource_error,
0816: "OrderFixedAssetNotFoundFixedAssetId ",
0817: UtilMisc
0818: .toMap(
0819: "fixedAssetId",
0820: workEffort
0821: .get("fixedAssetId")),
0822: locale));
0823: }
0824: if (fixedAsset == null) {
0825: return ServiceUtil
0826: .returnError(UtilProperties
0827: .getMessage(
0828: resource_error,
0829: "OrderFixedAssetNotFoundFixedAssetId ",
0830: UtilMisc
0831: .toMap(
0832: "fixedAssetId",
0833: workEffort
0834: .get("fixedAssetId")),
0835: locale));
0836: }
0837: // see if this fixed asset has a calendar, when no create one and attach to fixed asset
0838: Debug.logInfo("find the techdatacalendar", module);
0839: GenericValue techDataCalendar = null;
0840: try {
0841: techDataCalendar = fixedAsset
0842: .getRelatedOne("TechDataCalendar");
0843: } catch (GenericEntityException e) {
0844: Debug.logInfo(
0845: "TechData calendar does not exist yet so create for fixedAsset: "
0846: + fixedAsset.get("fixedAssetId"),
0847: module);
0848: }
0849: if (techDataCalendar == null) {
0850: Iterator fai = tempList.iterator();
0851: while (fai.hasNext()) {
0852: GenericValue currentValue = (GenericValue) fai
0853: .next();
0854: if ("FixedAsset".equals(currentValue
0855: .getEntityName())
0856: && currentValue
0857: .getString("fixedAssetId")
0858: .equals(
0859: workEffort
0860: .getString("fixedAssetId"))) {
0861: fixedAsset = currentValue;
0862: break;
0863: }
0864: }
0865: Iterator tdci = tempList.iterator();
0866: while (tdci.hasNext()) {
0867: GenericValue currentValue = (GenericValue) tdci
0868: .next();
0869: if ("TechDataCalendar".equals(currentValue
0870: .getEntityName())
0871: && currentValue
0872: .getString("calendarId")
0873: .equals(
0874: fixedAsset
0875: .getString("calendarId"))) {
0876: techDataCalendar = currentValue;
0877: break;
0878: }
0879: }
0880: }
0881: if (techDataCalendar == null) {
0882: techDataCalendar = delegator.makeValue(
0883: "TechDataCalendar", null);
0884: Debug
0885: .logInfo(
0886: "create techdata calendar because it does not exist",
0887: module);
0888: String calendarId = delegator
0889: .getNextSeqId("techDataCalendar");
0890: techDataCalendar.set("calendarId", calendarId);
0891: tempList.add(techDataCalendar);
0892: Debug.logInfo("update fixed Asset", module);
0893: fixedAsset.set("calendarId", calendarId);
0894: tempList.add(fixedAsset);
0895: }
0896: // then create the workEffort and the workOrderItemFulfillment to connect to the order and orderItem
0897: workOrderItemFulfillment.set("orderItemSeqId",
0898: workEffort.get("workEffortId").toString()); // orderItemSeqNo is stored here so save first
0899: // workeffort
0900: String workEffortId = delegator
0901: .getNextSeqId("WorkEffort"); // find next available workEffortId
0902: workEffort.set("workEffortId", workEffortId);
0903: workEffort.set("workEffortTypeId", "ASSET_USAGE");
0904: toBeStored.add(workEffort); // store workeffort before workOrderItemFulfillment because of workEffortId key constraint
0905: // workOrderItemFulfillment
0906: workOrderItemFulfillment.set("workEffortId",
0907: workEffortId);
0908: workOrderItemFulfillment.set("orderId", orderId);
0909: toBeStored.add(workOrderItemFulfillment);
0910: // Debug.logInfo("Workeffort "+ workEffortId + " created for asset " + workEffort.get("fixedAssetId") + " and order "+ workOrderItemFulfillment.get("orderId") + "/" + workOrderItemFulfillment.get("orderItemSeqId") + " created", module);
0911: //
0912: // now create the TechDataExcDay, when they do not exist, create otherwise update the capacity values
0913: // please note that calendarId is the same for (TechData)Calendar, CalendarExcDay and CalendarExWeek
0914: Timestamp estimatedStartDate = workEffort
0915: .getTimestamp("estimatedStartDate");
0916: Timestamp estimatedCompletionDate = workEffort
0917: .getTimestamp("estimatedCompletionDate");
0918: long dayCount = (estimatedCompletionDate.getTime() - estimatedStartDate
0919: .getTime()) / 86400000;
0920: while (--dayCount >= 0) {
0921: GenericValue techDataCalendarExcDay = null;
0922: // find an existing Day exception record
0923: Timestamp exceptionDateStartTime = UtilDateTime
0924: .getDayStart(new Timestamp(
0925: estimatedStartDate.getTime()),
0926: (int) dayCount);
0927: try {
0928: techDataCalendarExcDay = delegator
0929: .findByPrimaryKey(
0930: "TechDataCalendarExcDay",
0931: UtilMisc
0932: .toMap(
0933: "calendarId",
0934: fixedAsset
0935: .get("calendarId"),
0936: "exceptionDateStartTime",
0937: exceptionDateStartTime));
0938: } catch (GenericEntityException e) {
0939: Debug
0940: .logInfo(
0941: " techData excday record not found so creating........",
0942: module);
0943: }
0944: if (techDataCalendarExcDay == null) {
0945: Iterator tdcedi = tempList.iterator();
0946: while (tdcedi.hasNext()) {
0947: GenericValue currentValue = (GenericValue) tdcedi
0948: .next();
0949: if ("TechDataCalendarExcDay"
0950: .equals(currentValue
0951: .getEntityName())
0952: && currentValue
0953: .getString("calendarId")
0954: .equals(
0955: fixedAsset
0956: .getString("calendarId"))
0957: && currentValue
0958: .getTimestamp(
0959: "exceptionDateStartTime")
0960: .equals(
0961: exceptionDateStartTime)) {
0962: techDataCalendarExcDay = currentValue;
0963: break;
0964: }
0965: }
0966: }
0967: if (techDataCalendarExcDay == null) {
0968: techDataCalendarExcDay = delegator.makeValue(
0969: "TechDataCalendarExcDay", null);
0970: techDataCalendarExcDay.set("calendarId",
0971: fixedAsset.get("calendarId"));
0972: techDataCalendarExcDay.set(
0973: "exceptionDateStartTime",
0974: exceptionDateStartTime);
0975: techDataCalendarExcDay.set("usedCapacity",
0976: new Double(00.00)); // initialise to zero
0977: techDataCalendarExcDay
0978: .set(
0979: "exceptionCapacity",
0980: fixedAsset
0981: .getDouble("productionCapacity"));
0982: // Debug.logInfo(" techData excday record not found creating for calendarId: " + techDataCalendarExcDay.getString("calendarId") +
0983: // " and date: " + exceptionDateStartTime.toString(), module);
0984: }
0985: // add the quantity to the quantity on the date record
0986: Double newUsedCapacity = new Double(
0987: techDataCalendarExcDay.getDouble(
0988: "usedCapacity").doubleValue()
0989: + workEffort.getDouble(
0990: "quantityToProduce")
0991: .doubleValue());
0992: // check to see if the requested quantity is available on the requested day but only when the maximum capacity is set on the fixed asset
0993: if (fixedAsset.get("productionCapacity") != null) {
0994: // Debug.logInfo("see if maximum not reached, available: " + techDataCalendarExcDay.getString("exceptionCapacity") +
0995: // " already allocated: " + techDataCalendarExcDay.getString("usedCapacity") +
0996: // " Requested: " + workEffort.getString("quantityToProduce"), module);
0997: if (newUsedCapacity
0998: .compareTo(techDataCalendarExcDay
0999: .getDouble("exceptionCapacity")) > 0) {
1000: String errMsg = "ERROR: fixed_Asset_sold_out AssetId: "
1001: + workEffort.get("fixedAssetId")
1002: + " on date: "
1003: + techDataCalendarExcDay
1004: .getString("exceptionDateStartTime");
1005: Debug.logError(errMsg, module);
1006: errorMessages.add(errMsg);
1007: continue;
1008: }
1009: }
1010: techDataCalendarExcDay.set("usedCapacity",
1011: newUsedCapacity);
1012: tempList.add(techDataCalendarExcDay);
1013: // Debug.logInfo("Update success CalendarID: " + techDataCalendarExcDay.get("calendarId").toString() +
1014: // " and for date: " + techDataCalendarExcDay.get("exceptionDateStartTime").toString() +
1015: // " and for quantity: " + techDataCalendarExcDay.getDouble("usedCapacity").toString(), module);
1016: }
1017: }
1018: if (tempList.size() > 0) {
1019: toBeStored.addAll(tempList);
1020: }
1021: }
1022: if (errorMessages.size() > 0) {
1023: return ServiceUtil.returnError(errorMessages);
1024: }
1025:
1026: // set the orderId on all adjustments; this list will include order and
1027: // item adjustments...
1028: if (orderAdjustments != null && orderAdjustments.size() > 0) {
1029: Iterator iter = orderAdjustments.iterator();
1030:
1031: while (iter.hasNext()) {
1032: GenericValue orderAdjustment = (GenericValue) iter
1033: .next();
1034: try {
1035: orderAdjustment.set("orderAdjustmentId", delegator
1036: .getNextSeqId("OrderAdjustment"));
1037: } catch (IllegalArgumentException e) {
1038: return ServiceUtil
1039: .returnError(UtilProperties
1040: .getMessage(
1041: resource_error,
1042: "OrderErrorCouldNotGetNextSequenceIdForOrderAdjustmentCannotCreateOrder",
1043: locale));
1044: }
1045:
1046: orderAdjustment.set("orderId", orderId);
1047: orderAdjustment.set("createdDate", UtilDateTime
1048: .nowTimestamp());
1049: orderAdjustment.set("createdByUserLogin", userLogin
1050: .getString("userLoginId"));
1051:
1052: if (orderAdjustment.get("orderItemSeqId") == null
1053: || orderAdjustment.getString("orderItemSeqId")
1054: .length() == 0) {
1055: orderAdjustment.set("orderItemSeqId",
1056: DataModelConstants.SEQ_ID_NA);
1057: }
1058: if (orderAdjustment.get("shipGroupSeqId") == null
1059: || orderAdjustment.getString("shipGroupSeqId")
1060: .length() == 0) {
1061: orderAdjustment.set("shipGroupSeqId",
1062: DataModelConstants.SEQ_ID_NA);
1063: }
1064: toBeStored.add(orderAdjustment);
1065: }
1066: }
1067:
1068: // set the order contact mechs
1069: List orderContactMechs = (List) context
1070: .get("orderContactMechs");
1071: if (orderContactMechs != null && orderContactMechs.size() > 0) {
1072: Iterator ocmi = orderContactMechs.iterator();
1073:
1074: while (ocmi.hasNext()) {
1075: GenericValue ocm = (GenericValue) ocmi.next();
1076: ocm.set("orderId", orderId);
1077: toBeStored.add(ocm);
1078: }
1079: }
1080:
1081: // set the order item contact mechs
1082: List orderItemContactMechs = (List) context
1083: .get("orderItemContactMechs");
1084: if (orderItemContactMechs != null
1085: && orderItemContactMechs.size() > 0) {
1086: Iterator oicmi = orderItemContactMechs.iterator();
1087:
1088: while (oicmi.hasNext()) {
1089: GenericValue oicm = (GenericValue) oicmi.next();
1090: oicm.set("orderId", orderId);
1091: toBeStored.add(oicm);
1092: }
1093: }
1094:
1095: // set the order item ship groups
1096: List dropShipGroupIds = FastList.newInstance(); // this list will contain the ids of all the ship groups for drop shipments (no reservations)
1097: if (orderItemShipGroupInfo != null
1098: && orderItemShipGroupInfo.size() > 0) {
1099: Iterator osiInfos = orderItemShipGroupInfo.iterator();
1100: while (osiInfos.hasNext()) {
1101: GenericValue valueObj = (GenericValue) osiInfos.next();
1102: valueObj.set("orderId", orderId);
1103: if ("OrderItemShipGroup".equals(valueObj
1104: .getEntityName())) {
1105: // ship group
1106: if (valueObj.get("carrierRoleTypeId") == null) {
1107: valueObj.set("carrierRoleTypeId", "CARRIER");
1108: }
1109: if (!UtilValidate.isEmpty(valueObj
1110: .getString("supplierPartyId"))) {
1111: dropShipGroupIds.add(valueObj
1112: .getString("shipGroupSeqId"));
1113: }
1114: } else if ("OrderAdjustment".equals(valueObj
1115: .getEntityName())) {
1116: // shipping / tax adjustment(s)
1117: if (valueObj.get("orderItemSeqId") == null
1118: || valueObj.getString("orderItemSeqId")
1119: .length() == 0) {
1120: valueObj.set("orderItemSeqId",
1121: DataModelConstants.SEQ_ID_NA);
1122: }
1123: valueObj.set("orderAdjustmentId", delegator
1124: .getNextSeqId("OrderAdjustment"));
1125: valueObj.set("createdDate", UtilDateTime
1126: .nowTimestamp());
1127: valueObj.set("createdByUserLogin", userLogin
1128: .getString("userLoginId"));
1129: }
1130: toBeStored.add(valueObj);
1131: }
1132: }
1133:
1134: // set the additional party roles
1135: Map additionalPartyRole = (Map) context
1136: .get("orderAdditionalPartyRoleMap");
1137: if (additionalPartyRole != null) {
1138: Iterator aprIt = additionalPartyRole.entrySet().iterator();
1139: while (aprIt.hasNext()) {
1140: Map.Entry entry = (Map.Entry) aprIt.next();
1141: String additionalRoleTypeId = (String) entry.getKey();
1142: List parties = (List) entry.getValue();
1143: if (parties != null) {
1144: Iterator apIt = parties.iterator();
1145: while (apIt.hasNext()) {
1146: String additionalPartyId = (String) apIt.next();
1147: toBeStored.add(delegator.makeValue("PartyRole",
1148: UtilMisc.toMap("partyId",
1149: additionalPartyId,
1150: "roleTypeId",
1151: additionalRoleTypeId)));
1152: toBeStored.add(delegator.makeValue("OrderRole",
1153: UtilMisc.toMap("orderId", orderId,
1154: "partyId", additionalPartyId,
1155: "roleTypeId",
1156: additionalRoleTypeId)));
1157: }
1158: }
1159: }
1160: }
1161:
1162: // set the item survey responses
1163: List surveyResponses = (List) context
1164: .get("orderItemSurveyResponses");
1165: if (surveyResponses != null && surveyResponses.size() > 0) {
1166: Iterator oisr = surveyResponses.iterator();
1167: while (oisr.hasNext()) {
1168: GenericValue surveyResponse = (GenericValue) oisr
1169: .next();
1170: surveyResponse.set("orderId", orderId);
1171: toBeStored.add(surveyResponse);
1172: }
1173: }
1174:
1175: // set the item price info; NOTE: this must be after the orderItems are stored for referential integrity
1176: if (orderItemPriceInfo != null && orderItemPriceInfo.size() > 0) {
1177: Iterator oipii = orderItemPriceInfo.iterator();
1178:
1179: while (oipii.hasNext()) {
1180: GenericValue oipi = (GenericValue) oipii.next();
1181: try {
1182: oipi.set("orderItemPriceInfoId", delegator
1183: .getNextSeqId("OrderItemPriceInfo"));
1184: } catch (IllegalArgumentException e) {
1185: return ServiceUtil
1186: .returnError(UtilProperties
1187: .getMessage(
1188: resource_error,
1189: "OrderErrorCouldNotGetNextSequenceIdForOrderItemPriceInfoCannotCreateOrder",
1190: locale));
1191: }
1192:
1193: oipi.set("orderId", orderId);
1194: toBeStored.add(oipi);
1195: }
1196: }
1197:
1198: // set the item associations
1199: List orderItemAssociations = (List) context
1200: .get("orderItemAssociations");
1201: if (orderItemAssociations != null
1202: && orderItemAssociations.size() > 0) {
1203: Iterator oia = orderItemAssociations.iterator();
1204: while (oia.hasNext()) {
1205: GenericValue orderItemAssociation = (GenericValue) oia
1206: .next();
1207: if (orderItemAssociation.get("toOrderId") == null) {
1208: orderItemAssociation.set("toOrderId", orderId);
1209: } else if (orderItemAssociation.get("orderId") == null) {
1210: orderItemAssociation.set("orderId", orderId);
1211: }
1212: toBeStored.add(orderItemAssociation);
1213: }
1214: }
1215:
1216: // store the orderProductPromoUseInfos
1217: List orderProductPromoUses = (List) context
1218: .get("orderProductPromoUses");
1219: if (orderProductPromoUses != null
1220: && orderProductPromoUses.size() > 0) {
1221: Iterator orderProductPromoUseIter = orderProductPromoUses
1222: .iterator();
1223: while (orderProductPromoUseIter.hasNext()) {
1224: GenericValue productPromoUse = (GenericValue) orderProductPromoUseIter
1225: .next();
1226: productPromoUse.set("orderId", orderId);
1227: toBeStored.add(productPromoUse);
1228: }
1229: }
1230:
1231: /* DEJ20050529 the OLD way, where a single party had all roles... no longer doing things this way...
1232: // define the roles for the order
1233: List userOrderRoleTypes = null;
1234: if ("SALES_ORDER".equals(orderTypeId)) {
1235: userOrderRoleTypes = UtilMisc.toList("END_USER_CUSTOMER", "SHIP_TO_CUSTOMER", "BILL_TO_CUSTOMER", "PLACING_CUSTOMER");
1236: } else if ("PURCHASE_ORDER".equals(orderTypeId)) {
1237: userOrderRoleTypes = UtilMisc.toList("SHIP_FROM_VENDOR", "BILL_FROM_VENDOR", "SUPPLIER_AGENT");
1238: } else {
1239: // TODO: some default behavior
1240: }
1241:
1242: // now add the roles
1243: if (userOrderRoleTypes != null) {
1244: Iterator i = userOrderRoleTypes.iterator();
1245: while (i.hasNext()) {
1246: String roleType = (String) i.next();
1247: String thisParty = partyId;
1248: if (thisParty == null) {
1249: thisParty = "_NA_"; // will always set these roles so we can query
1250: }
1251: // make sure the party is in the role before adding
1252: toBeStored.add(delegator.makeValue("PartyRole", UtilMisc.toMap("partyId", partyId, "roleTypeId", roleType)));
1253: toBeStored.add(delegator.makeValue("OrderRole", UtilMisc.toMap("orderId", orderId, "partyId", partyId, "roleTypeId", roleType)));
1254: }
1255: }
1256: */
1257:
1258: // see the attributeRoleMap definition near the top of this file for attribute-role mappings
1259: Map attributeRoleMap = salesAttributeRoleMap;
1260: if ("PURCHASE_ORDER".equals(orderTypeId)) {
1261: attributeRoleMap = purchaseAttributeRoleMap;
1262: }
1263: Iterator attributeRoleEntryIter = attributeRoleMap.entrySet()
1264: .iterator();
1265: while (attributeRoleEntryIter.hasNext()) {
1266: Map.Entry attributeRoleEntry = (Map.Entry) attributeRoleEntryIter
1267: .next();
1268:
1269: if (UtilValidate.isNotEmpty((String) context
1270: .get(attributeRoleEntry.getKey()))) {
1271: // make sure the party is in the role before adding
1272: toBeStored.add(delegator.makeValue("PartyRole",
1273: UtilMisc.toMap("partyId", context
1274: .get(attributeRoleEntry.getKey()),
1275: "roleTypeId", attributeRoleEntry
1276: .getValue())));
1277: toBeStored.add(delegator.makeValue("OrderRole",
1278: UtilMisc.toMap("orderId", orderId, "partyId",
1279: context
1280: .get(attributeRoleEntry
1281: .getKey()),
1282: "roleTypeId", attributeRoleEntry
1283: .getValue())));
1284: }
1285: }
1286:
1287: // set the affiliate -- This is going to be removed...
1288: String affiliateId = (String) context.get("affiliateId");
1289: if (UtilValidate.isNotEmpty(affiliateId)) {
1290: toBeStored.add(delegator.makeValue("OrderRole", UtilMisc
1291: .toMap("orderId", orderId, "partyId", affiliateId,
1292: "roleTypeId", "AFFILIATE")));
1293: }
1294:
1295: // set the distributor
1296: String distributorId = (String) context.get("distributorId");
1297: if (UtilValidate.isNotEmpty(distributorId)) {
1298: toBeStored.add(delegator
1299: .makeValue("OrderRole", UtilMisc.toMap("orderId",
1300: orderId, "partyId", distributorId,
1301: "roleTypeId", "DISTRIBUTOR")));
1302: }
1303:
1304: // find all parties in role VENDOR associated with WebSite OR ProductStore (where WebSite overrides, if specified), associated first valid with the Order
1305: if (UtilValidate.isNotEmpty((String) context
1306: .get("productStoreId"))) {
1307: try {
1308: List productStoreRoles = delegator.findByAnd(
1309: "ProductStoreRole", UtilMisc.toMap(
1310: "roleTypeId", "VENDOR",
1311: "productStoreId", context
1312: .get("productStoreId")),
1313: UtilMisc.toList("-fromDate"));
1314: productStoreRoles = EntityUtil.filterByDate(
1315: productStoreRoles, true);
1316: GenericValue productStoreRole = EntityUtil
1317: .getFirst(productStoreRoles);
1318: if (productStoreRole != null) {
1319: toBeStored.add(delegator.makeValue("OrderRole",
1320: UtilMisc.toMap("orderId", orderId,
1321: "partyId", productStoreRole
1322: .get("partyId"),
1323: "roleTypeId", "VENDOR")));
1324: }
1325: } catch (GenericEntityException e) {
1326: Debug
1327: .logError(
1328: e,
1329: "Error looking up Vendor for the current Product Store",
1330: module);
1331: }
1332:
1333: }
1334: if (UtilValidate.isNotEmpty((String) context.get("webSiteId"))) {
1335: try {
1336: List webSiteRoles = delegator.findByAnd("WebSiteRole",
1337: UtilMisc.toMap("roleTypeId", "VENDOR",
1338: "webSiteId", context.get("webSiteId")),
1339: UtilMisc.toList("-fromDate"));
1340: webSiteRoles = EntityUtil.filterByDate(webSiteRoles,
1341: true);
1342: GenericValue webSiteRole = EntityUtil
1343: .getFirst(webSiteRoles);
1344: if (webSiteRole != null) {
1345: toBeStored.add(delegator.makeValue("OrderRole",
1346: UtilMisc.toMap("orderId", orderId,
1347: "partyId", webSiteRole
1348: .get("partyId"),
1349: "roleTypeId", "VENDOR")));
1350: }
1351: } catch (GenericEntityException e) {
1352: Debug
1353: .logError(
1354: e,
1355: "Error looking up Vendor for the current Web Site",
1356: module);
1357: }
1358:
1359: }
1360:
1361: // set the order payment info
1362: List orderPaymentInfos = (List) context.get("orderPaymentInfo");
1363: if (orderPaymentInfos != null && orderPaymentInfos.size() > 0) {
1364: Iterator oppIter = orderPaymentInfos.iterator();
1365: while (oppIter.hasNext()) {
1366: GenericValue valueObj = (GenericValue) oppIter.next();
1367: valueObj.set("orderId", orderId);
1368: if ("OrderPaymentPreference".equals(valueObj
1369: .getEntityName())) {
1370: if (valueObj.get("orderPaymentPreferenceId") == null) {
1371: valueObj
1372: .set(
1373: "orderPaymentPreferenceId",
1374: delegator
1375: .getNextSeqId("OrderPaymentPreference"));
1376: valueObj.set("createdDate", UtilDateTime
1377: .nowTimestamp());
1378: valueObj.set("createdByUserLogin", userLogin
1379: .getString("userLoginId"));
1380: }
1381: if (valueObj.get("statusId") == null) {
1382: valueObj
1383: .set("statusId", "PAYMENT_NOT_RECEIVED");
1384: }
1385: }
1386: toBeStored.add(valueObj);
1387: }
1388: }
1389:
1390: // store the trackingCodeOrder entities
1391: List trackingCodeOrders = (List) context
1392: .get("trackingCodeOrders");
1393: if (trackingCodeOrders != null && trackingCodeOrders.size() > 0) {
1394: Iterator tkcdordIter = trackingCodeOrders.iterator();
1395: while (tkcdordIter.hasNext()) {
1396: GenericValue trackingCodeOrder = (GenericValue) tkcdordIter
1397: .next();
1398: trackingCodeOrder.set("orderId", orderId);
1399: toBeStored.add(trackingCodeOrder);
1400: }
1401: }
1402:
1403: // store the OrderTerm entities
1404:
1405: List orderTerms = (List) context.get("orderTerms");
1406: if (orderTerms != null && orderTerms.size() > 0) {
1407: Iterator orderTermIter = orderTerms.iterator();
1408: while (orderTermIter.hasNext()) {
1409: GenericValue orderTerm = (GenericValue) orderTermIter
1410: .next();
1411: orderTerm.set("orderId", orderId);
1412: orderTerm.set("orderItemSeqId", "_NA_");
1413: toBeStored.add(orderTerm);
1414: }
1415: }
1416:
1417: try {
1418: // store line items, etc so that they will be there for the foreign key checks
1419: delegator.storeAll(toBeStored);
1420:
1421: // START inventory reservation
1422: List resErrorMessages = new LinkedList();
1423: try {
1424: reserveInventory(delegator, dispatcher, userLogin,
1425: locale, orderItemShipGroupInfo,
1426: dropShipGroupIds, itemValuesBySeqId,
1427: orderTypeId, productStoreId, resErrorMessages);
1428: } catch (GeneralException e) {
1429: return ServiceUtil.returnError(e.getMessage());
1430: }
1431:
1432: if (resErrorMessages.size() > 0) {
1433: return ServiceUtil.returnError(resErrorMessages);
1434: }
1435: // END inventory reservation
1436:
1437: successResult.put("orderId", orderId);
1438: } catch (GenericEntityException e) {
1439: Debug.logError(e,
1440: "Problem with order storage or reservations",
1441: module);
1442: return ServiceUtil.returnError(UtilProperties.getMessage(
1443: resource_error,
1444: "OrderErrorCouldNotCreateOrderWriteError", locale)
1445: + e.getMessage() + ").");
1446: }
1447:
1448: return successResult;
1449: }
1450:
1451: public static void reserveInventory(GenericDelegator delegator,
1452: LocalDispatcher dispatcher, GenericValue userLogin,
1453: Locale locale, List orderItemShipGroupInfo,
1454: List dropShipGroupIds, Map itemValuesBySeqId,
1455: String orderTypeId, String productStoreId,
1456: List resErrorMessages) throws GeneralException {
1457: boolean isImmediatelyFulfilled = false;
1458: GenericValue productStore = null;
1459: if (UtilValidate.isNotEmpty(productStoreId)) {
1460: try {
1461: productStore = delegator.findByPrimaryKeyCache(
1462: "ProductStore", UtilMisc.toMap(
1463: "productStoreId", productStoreId));
1464: } catch (GenericEntityException e) {
1465: throw new GeneralException(
1466: UtilProperties
1467: .getMessage(
1468: resource_error,
1469: "OrderErrorCouldNotFindProductStoreWithID",
1470: UtilMisc.toMap(
1471: "productStoreId",
1472: productStoreId), locale)
1473: + e.toString());
1474: }
1475: }
1476: if (productStore != null) {
1477: isImmediatelyFulfilled = "Y".equals(productStore
1478: .getString("isImmediatelyFulfilled"));
1479: }
1480:
1481: boolean reserveInventory = ("SALES_ORDER".equals(orderTypeId));
1482: if (reserveInventory && isImmediatelyFulfilled) {
1483: // don't reserve inventory if the product store has isImmediatelyFulfilled set, ie don't if in this store things are immediately fulfilled
1484: reserveInventory = false;
1485: }
1486:
1487: if (reserveInventory) {
1488: // START inventory reservation
1489: // decrement inventory available for each OrderItemShipGroupAssoc, within the same transaction
1490: if (orderItemShipGroupInfo != null
1491: && orderItemShipGroupInfo.size() > 0) {
1492: Iterator osiInfos = orderItemShipGroupInfo.iterator();
1493: while (osiInfos.hasNext()) {
1494: GenericValue orderItemShipGroupAssoc = (GenericValue) osiInfos
1495: .next();
1496: if ("OrderItemShipGroupAssoc"
1497: .equals(orderItemShipGroupAssoc
1498: .getEntityName())) {
1499: if (dropShipGroupIds != null
1500: && dropShipGroupIds
1501: .contains(orderItemShipGroupAssoc
1502: .getString("shipGroupSeqId"))) {
1503: // the items in the drop ship groups are not reserved
1504: continue;
1505: }
1506: GenericValue orderItem = (GenericValue) itemValuesBySeqId
1507: .get(orderItemShipGroupAssoc
1508: .get("orderItemSeqId"));
1509: String itemStatus = orderItem
1510: .getString("statusId");
1511: if ("ITEM_REJECTED".equals(itemStatus)
1512: || "ITEM_CANCELLED".equals(itemStatus)
1513: || "ITEM_COMPLETED".equals(itemStatus)) {
1514: Debug
1515: .logInfo(
1516: "Order item ["
1517: + orderItem
1518: .getString("orderId")
1519: + " / "
1520: + orderItem
1521: .getString("orderItemSeqId")
1522: + "] is not in a proper status for reservation",
1523: module);
1524: continue;
1525: }
1526: if (UtilValidate.isNotEmpty(orderItem
1527: .getString("productId"))
1528: && // only reserve product items, ignore non-product items
1529: !"RENTAL_ORDER_ITEM".equals(orderItem
1530: .getString("orderItemTypeId")) // ignore for rental
1531: ) {
1532: try {
1533: Map reserveInput = new HashMap();
1534: reserveInput.put("productStoreId",
1535: productStoreId);
1536: reserveInput.put("productId", orderItem
1537: .getString("productId"));
1538: reserveInput.put("orderId", orderItem
1539: .getString("orderId"));
1540: reserveInput
1541: .put(
1542: "orderItemSeqId",
1543: orderItem
1544: .getString("orderItemSeqId"));
1545: reserveInput
1546: .put(
1547: "shipGroupSeqId",
1548: orderItemShipGroupAssoc
1549: .getString("shipGroupSeqId"));
1550: // use the quantity from the orderItemShipGroupAssoc, NOT the orderItem, these are reserved by item-group assoc
1551: reserveInput.put("quantity",
1552: orderItemShipGroupAssoc
1553: .getDouble("quantity"));
1554: reserveInput
1555: .put("userLogin", userLogin);
1556: Map reserveResult = dispatcher.runSync(
1557: "reserveStoreInventory",
1558: reserveInput);
1559:
1560: if (ServiceUtil.isError(reserveResult)) {
1561: GenericValue product = null;
1562: try {
1563: product = delegator
1564: .findByPrimaryKeyCache(
1565: "Product",
1566: UtilMisc
1567: .toMap(
1568: "productId",
1569: orderItem
1570: .getString("productId")));
1571: } catch (GenericEntityException e) {
1572: Debug
1573: .logError(
1574: e,
1575: "Error when looking up product in createOrder service, product failed inventory reservation",
1576: module);
1577: }
1578:
1579: String invErrMsg = "The product ";
1580: if (product != null) {
1581: invErrMsg += getProductName(
1582: product, orderItem);
1583: }
1584: invErrMsg += " with ID "
1585: + orderItem
1586: .getString("productId")
1587: + " is no longer in stock. Please try reducing the quantity or removing the product from this order.";
1588: resErrorMessages.add(invErrMsg);
1589: // If the product is a marketing package auto, attempt to create enough packages to bring ATP back to 0, won't necessarily create enough to cover this order.
1590: if ("MARKETING_PKG_AUTO"
1591: .equals(product
1592: .get("productTypeId"))) {
1593: // do something tricky here: run as the "system" user
1594: // that can actually create and run a production run
1595: GenericValue permUserLogin = delegator
1596: .findByPrimaryKeyCache(
1597: "UserLogin",
1598: UtilMisc
1599: .toMap(
1600: "userLoginId",
1601: "system"));
1602: Map inputMap = new HashMap();
1603: inputMap
1604: .put(
1605: "facilityId",
1606: productStore
1607: .getString("inventoryFacilityId"));
1608: inputMap
1609: .put(
1610: "orderId",
1611: orderItem
1612: .getString("orderId"));
1613: inputMap
1614: .put(
1615: "orderItemSeqId",
1616: orderItem
1617: .getString("orderItemSeqId"));
1618: inputMap.put("userLogin",
1619: permUserLogin);
1620: Map prunResult = dispatcher
1621: .runSync(
1622: "createProductionRunForMktgPkg",
1623: inputMap);
1624: if (ServiceUtil
1625: .isError(prunResult)) {
1626: Debug
1627: .logError(
1628: ServiceUtil
1629: .getErrorMessage(prunResult)
1630: + " for input:"
1631: + inputMap,
1632: module);
1633: }
1634: }
1635: }
1636: } catch (GenericServiceException e) {
1637: String errMsg = "Fatal error calling reserveStoreInventory service: "
1638: + e.toString();
1639: Debug.logError(e, errMsg, module);
1640: resErrorMessages.add(errMsg);
1641: }
1642: }
1643: }
1644: }
1645: }
1646: }
1647: }
1648:
1649: public static String getProductName(GenericValue product,
1650: GenericValue orderItem) {
1651: if (UtilValidate.isNotEmpty(product.getString("productName"))) {
1652: return product.getString("productName");
1653: } else {
1654: return orderItem.getString("itemDescription");
1655: }
1656: }
1657:
1658: public static String getProductName(GenericValue product,
1659: String orderItemName) {
1660: if (UtilValidate.isNotEmpty(product.getString("productName"))) {
1661: return product.getString("productName");
1662: } else {
1663: return orderItemName;
1664: }
1665: }
1666:
1667: public static String determineSingleFacilityFromOrder(
1668: GenericValue orderHeader) {
1669: if (orderHeader != null) {
1670: String productStoreId = orderHeader
1671: .getString("productStoreId");
1672: if (productStoreId != null) {
1673: return ProductStoreWorker
1674: .determineSingleFacilityForStore(orderHeader
1675: .getDelegator(), productStoreId);
1676: }
1677: }
1678: return null;
1679: }
1680:
1681: /** Service for resetting the OrderHeader grandTotal */
1682: public static Map resetGrandTotal(DispatchContext ctx, Map context) {
1683: GenericDelegator delegator = ctx.getDelegator();
1684: //appears to not be used: GenericValue userLogin = (GenericValue) context.get("userLogin");
1685: String orderId = (String) context.get("orderId");
1686:
1687: GenericValue orderHeader = null;
1688: try {
1689: orderHeader = delegator.findByPrimaryKey("OrderHeader",
1690: UtilMisc.toMap("orderId", orderId));
1691: } catch (GenericEntityException e) {
1692: String errMsg = "ERROR: Could not set grantTotal on OrderHeader entity: "
1693: + e.toString();
1694: Debug.logError(e, errMsg, module);
1695: return ServiceUtil.returnError(errMsg);
1696: }
1697:
1698: if (orderHeader != null) {
1699: OrderReadHelper orh = new OrderReadHelper(orderHeader);
1700: BigDecimal currentTotal = orderHeader
1701: .getBigDecimal("grandTotal");
1702: BigDecimal currentSubTotal = orderHeader
1703: .getBigDecimal("remainingSubTotal");
1704:
1705: // get the new grand total
1706: BigDecimal updatedTotal = orh.getOrderGrandTotalBd();
1707:
1708: // calculate subTotal as grandTotal - returnsTotal - (tax + shipping of items not returned)
1709: BigDecimal remainingSubTotal = updatedTotal.subtract(
1710: orh.getOrderReturnedTotalBd()).subtract(
1711: orh.getOrderNonReturnedTaxAndShippingBd());
1712:
1713: if (currentTotal == null
1714: || currentSubTotal == null
1715: || updatedTotal.compareTo(currentTotal) != 0
1716: || remainingSubTotal.compareTo(currentSubTotal) != 0) {
1717: orderHeader.set("grandTotal", updatedTotal);
1718: orderHeader.set("remainingSubTotal", remainingSubTotal);
1719: try {
1720: orderHeader.store();
1721: } catch (GenericEntityException e) {
1722: String errMsg = "ERROR: Could not set grandTotal on OrderHeader entity: "
1723: + e.toString();
1724: Debug.logError(e, errMsg, module);
1725: return ServiceUtil.returnError(errMsg);
1726: }
1727: }
1728: }
1729:
1730: return ServiceUtil.returnSuccess();
1731: }
1732:
1733: /** Service for setting the OrderHeader grandTotal for all OrderHeaders with no grandTotal */
1734: public static Map setEmptyGrandTotals(DispatchContext ctx,
1735: Map context) {
1736: GenericDelegator delegator = ctx.getDelegator();
1737: LocalDispatcher dispatcher = ctx.getDispatcher();
1738: GenericValue userLogin = (GenericValue) context
1739: .get("userLogin");
1740: Boolean forceAll = (Boolean) context.get("forceAll");
1741: Locale locale = (Locale) context.get("locale");
1742: if (forceAll == null) {
1743: forceAll = Boolean.FALSE;
1744: }
1745:
1746: EntityCondition cond = null;
1747: if (!forceAll.booleanValue()) {
1748: List exprs = UtilMisc.toList(new EntityExpr("grandTotal",
1749: EntityOperator.EQUALS, null), new EntityExpr(
1750: "remainingSubTotal", EntityOperator.EQUALS, null));
1751: cond = new EntityConditionList(exprs, EntityOperator.OR);
1752: }
1753: List fields = UtilMisc.toList("orderId");
1754:
1755: EntityListIterator eli = null;
1756: try {
1757: eli = delegator.findListIteratorByCondition("OrderHeader",
1758: cond, fields, null);
1759: } catch (GenericEntityException e) {
1760: Debug.logError(e, module);
1761: return ServiceUtil.returnError(e.getMessage());
1762: }
1763:
1764: if (eli != null) {
1765: // reset each order
1766: GenericValue orderHeader = null;
1767: while ((orderHeader = (GenericValue) eli.next()) != null) {
1768: String orderId = orderHeader.getString("orderId");
1769: Map resetResult = null;
1770: try {
1771: resetResult = dispatcher.runSync("resetGrandTotal",
1772: UtilMisc.toMap("orderId", orderId,
1773: "userLogin", userLogin));
1774: } catch (GenericServiceException e) {
1775: Debug.logError(e,
1776: "ERROR: Cannot reset order totals - "
1777: + orderId, module);
1778: }
1779:
1780: if (resetResult != null
1781: && ServiceUtil.isError(resetResult)) {
1782: Debug
1783: .logWarning(
1784: UtilProperties
1785: .getMessage(
1786: resource_error,
1787: "OrderErrorCannotResetOrderTotals",
1788: UtilMisc
1789: .toMap(
1790: "orderId",
1791: orderId,
1792: "resetResult",
1793: ServiceUtil
1794: .getErrorMessage(resetResult)),
1795: locale), module);
1796: }
1797: }
1798:
1799: // close the ELI
1800: try {
1801: eli.close();
1802: } catch (GenericEntityException e) {
1803: Debug.logError(e, module);
1804: }
1805: } else {
1806: Debug.logInfo("No orders found for reset processing",
1807: module);
1808: }
1809:
1810: return ServiceUtil.returnSuccess();
1811: }
1812:
1813: /** Service for checking and re-calc the tax amount */
1814: public static Map recalcOrderTax(DispatchContext ctx, Map context) {
1815: LocalDispatcher dispatcher = ctx.getDispatcher();
1816: GenericDelegator delegator = ctx.getDelegator();
1817: String orderId = (String) context.get("orderId");
1818: GenericValue userLogin = (GenericValue) context
1819: .get("userLogin");
1820: Locale locale = (Locale) context.get("locale");
1821:
1822: // check and make sure we have permission to change the order
1823: Security security = ctx.getSecurity();
1824: if (!security.hasEntityPermission("ORDERMGR", "_UPDATE",
1825: userLogin)) {
1826: GenericValue placingCustomer = null;
1827: try {
1828: Map placingCustomerFields = UtilMisc.toMap("orderId",
1829: orderId, "partyId", userLogin
1830: .getString("partyId"), "roleTypeId",
1831: "PLACING_CUSTOMER");
1832: placingCustomer = delegator.findByPrimaryKey(
1833: "OrderRole", placingCustomerFields);
1834: } catch (GenericEntityException e) {
1835: return ServiceUtil.returnError(UtilProperties
1836: .getMessage(resource_error,
1837: "OrderErrorCannotGetOrderRoleEntity ",
1838: locale)
1839: + e.getMessage());
1840: }
1841: if (placingCustomer == null)
1842: return ServiceUtil
1843: .returnError(UtilProperties
1844: .getMessage(
1845: resource_error,
1846: "OrderYouDoNotHavePermissionToChangeThisOrdersStatus",
1847: locale));
1848: }
1849:
1850: // get the order header
1851: GenericValue orderHeader = null;
1852: try {
1853: orderHeader = delegator.findByPrimaryKey("OrderHeader",
1854: UtilMisc.toMap("orderId", orderId));
1855: } catch (GenericEntityException e) {
1856: return ServiceUtil.returnError(UtilProperties.getMessage(
1857: resource_error,
1858: "OrderErrorCannotGetOrderHeaderEntity", locale)
1859: + e.getMessage());
1860: }
1861:
1862: if (orderHeader == null) {
1863: return ServiceUtil.returnError(UtilProperties.getMessage(
1864: resource_error,
1865: "OrderErrorNoValidOrderHeaderFoundForOrderId",
1866: UtilMisc.toMap("orderId", orderId), locale));
1867: }
1868:
1869: // don't charge tax on purchase orders
1870: if ("PURCHASE_ORDER".equals(orderHeader
1871: .getString("orderTypeId"))) {
1872: return ServiceUtil.returnSuccess();
1873: }
1874:
1875: // Retrieve the order tax adjustments
1876: List orderTaxAdjustments = null;
1877: try {
1878: orderTaxAdjustments = delegator.findByAnd(
1879: "OrderAdjustment", UtilMisc.toMap("orderId",
1880: orderId, "orderAdjustmentTypeId",
1881: "SALES_TAX"));
1882: } catch (GenericEntityException e) {
1883: Debug.logError(e,
1884: "Unable to retrieve SALES_TAX adjustments for order : "
1885: + orderId, module);
1886: return ServiceUtil
1887: .returnError(UtilProperties.getMessage(
1888: resource_error,
1889: "OrderUnableToRetrieveSalesTaxAdjustments",
1890: locale));
1891: }
1892:
1893: // Accumulate the total existing tax adjustment
1894: BigDecimal totalExistingOrderTax = ZERO;
1895: Iterator otait = UtilMisc.toIterator(orderTaxAdjustments);
1896: while (otait != null && otait.hasNext()) {
1897: GenericValue orderTaxAdjustment = (GenericValue) otait
1898: .next();
1899: if (orderTaxAdjustment.get("amount") != null) {
1900: totalExistingOrderTax = totalExistingOrderTax
1901: .add(orderTaxAdjustment.getBigDecimal("amount")
1902: .setScale(taxDecimals, taxRounding));
1903: }
1904: }
1905:
1906: // Recalculate the taxes for the order
1907: BigDecimal totalNewOrderTax = ZERO;
1908: OrderReadHelper orh = new OrderReadHelper(orderHeader);
1909: List shipGroups = orh.getOrderItemShipGroups();
1910: if (shipGroups != null) {
1911: Iterator itr = shipGroups.iterator();
1912: while (itr.hasNext()) {
1913: GenericValue shipGroup = (GenericValue) itr.next();
1914: String shipGroupSeqId = shipGroup
1915: .getString("shipGroupSeqId");
1916:
1917: List validOrderItems = orh
1918: .getValidOrderItems(shipGroupSeqId);
1919: if (validOrderItems != null) {
1920: // prepare the inital lists
1921: List products = new ArrayList(validOrderItems
1922: .size());
1923: List amounts = new ArrayList(validOrderItems.size());
1924: List shipAmts = new ArrayList(validOrderItems
1925: .size());
1926: List itPrices = new ArrayList(validOrderItems
1927: .size());
1928:
1929: // adjustments and total
1930: List allAdjustments = orh.getAdjustments();
1931: List orderHeaderAdjustments = OrderReadHelper
1932: .getOrderHeaderAdjustments(allAdjustments,
1933: shipGroupSeqId);
1934: BigDecimal orderSubTotal = OrderReadHelper
1935: .getOrderItemsSubTotalBd(validOrderItems,
1936: allAdjustments);
1937:
1938: // shipping amount
1939: BigDecimal orderShipping = OrderReadHelper
1940: .calcOrderAdjustmentsBd(
1941: orderHeaderAdjustments,
1942: orderSubTotal, false, false, true);
1943:
1944: // build up the list of tax calc service parameters
1945: for (int i = 0; i < validOrderItems.size(); i++) {
1946: GenericValue orderItem = (GenericValue) validOrderItems
1947: .get(i);
1948: String productId = orderItem
1949: .getString("productId");
1950: try {
1951: products.add(i, delegator.findByPrimaryKey(
1952: "Product", UtilMisc.toMap(
1953: "productId", productId))); // get the product entity
1954: amounts.add(i,
1955: OrderReadHelper
1956: .getOrderItemSubTotalBd(
1957: orderItem,
1958: allAdjustments,
1959: true, false)); // get the item amount
1960: shipAmts.add(i, OrderReadHelper
1961: .getOrderItemAdjustmentsTotalBd(
1962: orderItem, allAdjustments,
1963: false, false, true)); // get the shipping amount
1964: itPrices.add(i, orderItem
1965: .getBigDecimal("unitPrice"));
1966: } catch (GenericEntityException e) {
1967: Debug.logError(e,
1968: "Cannot read order item entity : "
1969: + orderItem, module);
1970: return ServiceUtil
1971: .returnError(UtilProperties
1972: .getMessage(
1973: resource_error,
1974: "OrderCannotReadTheOrderItemEntity",
1975: locale));
1976: }
1977: }
1978:
1979: GenericValue shippingAddress = orh
1980: .getShippingAddress(shipGroupSeqId);
1981: // no shipping address, try the billing address
1982: if (shippingAddress == null) {
1983: List billingAddressList = orh
1984: .getBillingLocations();
1985: if (billingAddressList.size() > 0) {
1986: shippingAddress = (GenericValue) billingAddressList
1987: .get(0);
1988: }
1989: }
1990:
1991: // TODO and NOTE DEJ20070816: this is NOT a good way to determine if this is a face-to-face or immediatelyFulfilled order
1992: //this should be made consistent with the CheckOutHelper.makeTaxContext(int shipGroup, GenericValue shipAddress) method
1993: if (shippingAddress == null) {
1994: // face-to-face order; use the facility address
1995: String facilityId = orderHeader
1996: .getString("originFacilityId");
1997: if (facilityId != null) {
1998: List fcp = null;
1999: try {
2000: fcp = delegator
2001: .findByAnd(
2002: "FacilityContactMechPurpose",
2003: UtilMisc
2004: .toMap(
2005: "facilityId",
2006: facilityId,
2007: "contactMechPurposeTypeId",
2008: "SHIP_ORIG_LOCATION"));
2009: } catch (GenericEntityException e) {
2010: Debug.logError(e, module);
2011: }
2012: fcp = EntityUtil.filterByDate(fcp);
2013: GenericValue purp = EntityUtil
2014: .getFirst(fcp);
2015: if (purp != null) {
2016: try {
2017: shippingAddress = delegator
2018: .findByPrimaryKey(
2019: "PostalAddress",
2020: UtilMisc
2021: .toMap(
2022: "contactMechId",
2023: purp
2024: .getString("contactMechId")));
2025: } catch (GenericEntityException e) {
2026: Debug.logError(e, module);
2027: }
2028: }
2029: }
2030: }
2031:
2032: // if shippingAddress is still null then don't calculate tax; it may be an situation where no tax is applicable, or the data is bad and we don't have a way to find an address to check tax for
2033: if (shippingAddress == null) {
2034: continue;
2035: }
2036:
2037: // prepare the service context
2038: // pass in BigDecimal values instead of Double
2039: Map serviceContext = UtilMisc.toMap(
2040: "productStoreId", orh.getProductStoreId(),
2041: "itemProductList", products,
2042: "itemAmountList", amounts,
2043: "itemShippingList", shipAmts,
2044: "itemPriceList", itPrices,
2045: "orderShippingAmount", orderShipping);
2046: serviceContext.put("shippingAddress",
2047: shippingAddress);
2048: if (orh.getBillToParty() != null)
2049: serviceContext.put("billToPartyId", orh
2050: .getBillToParty().getString("partyId"));
2051:
2052: // invoke the calcTax service
2053: Map serviceResult = null;
2054: try {
2055: serviceResult = dispatcher.runSync("calcTax",
2056: serviceContext);
2057: } catch (GenericServiceException e) {
2058: Debug.logError(e, module);
2059: return ServiceUtil
2060: .returnError(UtilProperties
2061: .getMessage(
2062: resource_error,
2063: "OrderProblemOccurredInTaxService",
2064: locale));
2065: }
2066:
2067: if (ServiceUtil.isError(serviceResult)) {
2068: return ServiceUtil.returnError(ServiceUtil
2069: .getErrorMessage(serviceResult));
2070: }
2071:
2072: // the adjustments (returned in order) from the tax service
2073: List orderAdj = (List) serviceResult
2074: .get("orderAdjustments");
2075: List itemAdj = (List) serviceResult
2076: .get("itemAdjustments");
2077:
2078: // Accumulate the new tax total from the recalculated header adjustments
2079: if (orderAdj != null && orderAdj.size() > 0) {
2080: Iterator oai = orderAdj.iterator();
2081: while (oai.hasNext()) {
2082: GenericValue oa = (GenericValue) oai.next();
2083: if (oa.get("amount") != null) {
2084: totalNewOrderTax = totalNewOrderTax
2085: .add(oa.getBigDecimal("amount")
2086: .setScale(taxDecimals,
2087: taxRounding));
2088: }
2089:
2090: }
2091: }
2092:
2093: // Accumulate the new tax total from the recalculated item adjustments
2094: if (itemAdj != null && itemAdj.size() > 0) {
2095: for (int i = 0; i < itemAdj.size(); i++) {
2096: List itemAdjustments = (List) itemAdj
2097: .get(i);
2098: Iterator ida = itemAdjustments.iterator();
2099: while (ida.hasNext()) {
2100: GenericValue ia = (GenericValue) ida
2101: .next();
2102: if (ia.get("amount") != null) {
2103: totalNewOrderTax = totalNewOrderTax
2104: .add(ia.getBigDecimal(
2105: "amount").setScale(
2106: taxDecimals,
2107: taxRounding));
2108: }
2109: }
2110: }
2111: }
2112: }
2113: }
2114:
2115: // Determine the difference between existing and new tax adjustment totals, if any
2116: BigDecimal orderTaxDifference = totalNewOrderTax.subtract(
2117: totalExistingOrderTax).setScale(taxDecimals,
2118: taxRounding);
2119:
2120: // If the total has changed, create an OrderAdjustment to reflect the fact
2121: if (orderTaxDifference.signum() != 0) {
2122: Map createOrderAdjContext = new HashMap();
2123: createOrderAdjContext.put("orderAdjustmentTypeId",
2124: "SALES_TAX");
2125: createOrderAdjContext.put("orderId", orderId);
2126: createOrderAdjContext.put("orderItemSeqId", "_NA_");
2127: createOrderAdjContext.put("shipGroupSeqId", "_NA_");
2128: createOrderAdjContext.put("description",
2129: "Tax adjustment due to order change");
2130: createOrderAdjContext.put("amount", new Double(
2131: orderTaxDifference.doubleValue()));
2132: createOrderAdjContext.put("amount", new Double(
2133: orderTaxDifference.doubleValue()));
2134: createOrderAdjContext.put("userLogin", userLogin);
2135: Map createOrderAdjResponse = null;
2136: try {
2137: createOrderAdjResponse = dispatcher.runSync(
2138: "createOrderAdjustment",
2139: createOrderAdjContext);
2140: } catch (GenericServiceException e) {
2141: String createOrderAdjErrMsg = UtilProperties
2142: .getMessage(
2143: resource_error,
2144: "OrderErrorCallingCreateOrderAdjustmentService",
2145: locale);
2146: Debug.logError(createOrderAdjErrMsg, module);
2147: return ServiceUtil
2148: .returnError(createOrderAdjErrMsg);
2149: }
2150: if (ServiceUtil.isError(createOrderAdjResponse)) {
2151: Debug.logError(ServiceUtil
2152: .getErrorMessage(createOrderAdjResponse),
2153: module);
2154: return ServiceUtil.returnError(ServiceUtil
2155: .getErrorMessage(createOrderAdjResponse));
2156: }
2157: }
2158: }
2159:
2160: return ServiceUtil.returnSuccess();
2161: }
2162:
2163: /** Service for checking and re-calc the shipping amount */
2164: public static Map recalcOrderShipping(DispatchContext ctx,
2165: Map context) {
2166: LocalDispatcher dispatcher = ctx.getDispatcher();
2167: GenericDelegator delegator = ctx.getDelegator();
2168: String orderId = (String) context.get("orderId");
2169: GenericValue userLogin = (GenericValue) context
2170: .get("userLogin");
2171: Locale locale = (Locale) context.get("locale");
2172:
2173: // check and make sure we have permission to change the order
2174: Security security = ctx.getSecurity();
2175: if (!security.hasEntityPermission("ORDERMGR", "_UPDATE",
2176: userLogin)) {
2177: GenericValue placingCustomer = null;
2178: try {
2179: Map placingCustomerFields = UtilMisc.toMap("orderId",
2180: orderId, "partyId", userLogin
2181: .getString("partyId"), "roleTypeId",
2182: "PLACING_CUSTOMER");
2183: placingCustomer = delegator.findByPrimaryKey(
2184: "OrderRole", placingCustomerFields);
2185: } catch (GenericEntityException e) {
2186: return ServiceUtil.returnError(UtilProperties
2187: .getMessage(resource_error,
2188: "OrderErrorCannotGetOrderRoleEntity",
2189: locale)
2190: + e.getMessage());
2191: }
2192: if (placingCustomer == null)
2193: return ServiceUtil
2194: .returnError(UtilProperties
2195: .getMessage(
2196: resource_error,
2197: "OrderYouDoNotHavePermissionToChangeThisOrdersStatus",
2198: locale));
2199: }
2200:
2201: // get the order header
2202: GenericValue orderHeader = null;
2203: try {
2204: orderHeader = delegator.findByPrimaryKey("OrderHeader",
2205: UtilMisc.toMap("orderId", orderId));
2206: } catch (GenericEntityException e) {
2207: return ServiceUtil.returnError(UtilProperties.getMessage(
2208: resource_error,
2209: "OrderErrorCannotGetOrderHeaderEntity", locale)
2210: + e.getMessage());
2211: }
2212:
2213: if (orderHeader == null) {
2214: return ServiceUtil.returnError(UtilProperties.getMessage(
2215: resource_error,
2216: "OrderErrorNoValidOrderHeaderFoundForOrderId",
2217: UtilMisc.toMap("orderId", orderId), locale));
2218: }
2219:
2220: OrderReadHelper orh = new OrderReadHelper(orderHeader);
2221: List shipGroups = orh.getOrderItemShipGroups();
2222: if (shipGroups != null) {
2223: Iterator i = shipGroups.iterator();
2224: while (i.hasNext()) {
2225: GenericValue shipGroup = (GenericValue) i.next();
2226: String shipGroupSeqId = shipGroup
2227: .getString("shipGroupSeqId");
2228:
2229: if (shipGroup.get("contactMechId") == null
2230: || shipGroup.get("shipmentMethodTypeId") == null) {
2231: // not shipped (face-to-face order)
2232: continue;
2233: }
2234:
2235: Map shippingEstMap = ShippingEvents.getShipEstimate(
2236: dispatcher, delegator, orh, shipGroupSeqId);
2237: BigDecimal shippingTotal = null;
2238: if (orh.getValidOrderItems(shipGroupSeqId) == null
2239: || orh.getValidOrderItems(shipGroupSeqId)
2240: .size() == 0) {
2241: shippingTotal = ZERO;
2242: Debug.log("No valid order items found - "
2243: + shippingTotal, module);
2244: } else {
2245: shippingTotal = UtilValidate.isEmpty(shippingEstMap
2246: .get("shippingTotal")) ? ZERO
2247: : new BigDecimal(((Double) shippingEstMap
2248: .get("shippingTotal"))
2249: .doubleValue());
2250: shippingTotal = shippingTotal.setScale(
2251: orderDecimals, orderRounding);
2252: Debug.log("Got new shipping estimate - "
2253: + shippingTotal, module);
2254: }
2255: if (Debug.infoOn()) {
2256: Debug.log("New Shipping Total [" + orderId + " / "
2257: + shipGroupSeqId + "] : " + shippingTotal,
2258: module);
2259: }
2260:
2261: BigDecimal currentShipping = OrderReadHelper
2262: .getAllOrderItemsAdjustmentsTotalBd(
2263: orh
2264: .getOrderItemAndShipGroupAssoc(shipGroupSeqId),
2265: orh.getAdjustments(), false, false,
2266: true);
2267: currentShipping = currentShipping
2268: .add(OrderReadHelper
2269: .calcOrderAdjustmentsBd(
2270: orh
2271: .getOrderHeaderAdjustments(shipGroupSeqId),
2272: orh.getOrderItemsSubTotalBd(),
2273: false, false, true));
2274:
2275: if (Debug.infoOn()) {
2276: Debug.log(
2277: "Old Shipping Total [" + orderId + " / "
2278: + shipGroupSeqId + "] : "
2279: + currentShipping, module);
2280: }
2281:
2282: List errorMessageList = (List) shippingEstMap
2283: .get(ModelService.ERROR_MESSAGE_LIST);
2284: if (errorMessageList != null) {
2285: Debug
2286: .logWarning(
2287: "Problem finding shipping estimates for ["
2288: + orderId + "/ "
2289: + shipGroupSeqId + "] = "
2290: + errorMessageList, module);
2291: continue;
2292: }
2293:
2294: if ((shippingTotal != null)
2295: && (shippingTotal.compareTo(currentShipping) != 0)) {
2296: // place the difference as a new shipping adjustment
2297: BigDecimal adjustmentAmount = shippingTotal
2298: .subtract(currentShipping);
2299: String adjSeqId = delegator
2300: .getNextSeqId("OrderAdjustment");
2301: GenericValue orderAdjustment = delegator.makeValue(
2302: "OrderAdjustment", UtilMisc.toMap(
2303: "orderAdjustmentId", adjSeqId));
2304: orderAdjustment.set("orderAdjustmentTypeId",
2305: "SHIPPING_CHARGES");
2306: orderAdjustment.set("amount", adjustmentAmount);
2307: orderAdjustment.set("orderId", orh.getOrderId());
2308: orderAdjustment.set("shipGroupSeqId",
2309: shipGroupSeqId);
2310: orderAdjustment.set("orderItemSeqId",
2311: DataModelConstants.SEQ_ID_NA);
2312: orderAdjustment.set("createdDate", UtilDateTime
2313: .nowTimestamp());
2314: orderAdjustment.set("createdByUserLogin", userLogin
2315: .getString("userLoginId"));
2316: //orderAdjustment.set("comments", "Shipping Re-Calc Adjustment");
2317: try {
2318: orderAdjustment.create();
2319: } catch (GenericEntityException e) {
2320: Debug.logError(e,
2321: "Problem creating shipping re-calc adjustment : "
2322: + orderAdjustment, module);
2323: return ServiceUtil
2324: .returnError(UtilProperties
2325: .getMessage(
2326: resource_error,
2327: "OrderErrorCannotCreateAdjustment",
2328: locale));
2329: }
2330: }
2331:
2332: // TODO: re-balance free shipping adjustment
2333: }
2334: }
2335:
2336: return ServiceUtil.returnSuccess();
2337:
2338: }
2339:
2340: /** Service for checking to see if an order is fully completed or canceled */
2341: public static Map checkItemStatus(DispatchContext ctx, Map context) {
2342: GenericDelegator delegator = ctx.getDelegator();
2343: LocalDispatcher dispatcher = ctx.getDispatcher();
2344: Locale locale = (Locale) context.get("locale");
2345:
2346: GenericValue userLogin = (GenericValue) context
2347: .get("userLogin");
2348: String orderId = (String) context.get("orderId");
2349:
2350: // check and make sure we have permission to change the order
2351: Security security = ctx.getSecurity();
2352: if (!security.hasEntityPermission("ORDERMGR", "_UPDATE",
2353: userLogin)) {
2354: GenericValue placingCustomer = null;
2355: try {
2356: Map placingCustomerFields = UtilMisc.toMap("orderId",
2357: orderId, "partyId", userLogin
2358: .getString("partyId"), "roleTypeId",
2359: "PLACING_CUSTOMER");
2360: placingCustomer = delegator.findByPrimaryKey(
2361: "OrderRole", placingCustomerFields);
2362: } catch (GenericEntityException e) {
2363: return ServiceUtil.returnError(UtilProperties
2364: .getMessage(resource_error,
2365: "OrderErrorCannotGetOrderRoleEntity",
2366: locale)
2367: + e.getMessage());
2368: }
2369: if (placingCustomer == null) {
2370: return ServiceUtil
2371: .returnError(UtilProperties
2372: .getMessage(
2373: resource_error,
2374: "OrderYouDoNotHavePermissionToChangeThisOrdersStatus",
2375: locale));
2376: }
2377: }
2378:
2379: // get the order header
2380: GenericValue orderHeader = null;
2381: try {
2382: orderHeader = delegator.findByPrimaryKey("OrderHeader",
2383: UtilMisc.toMap("orderId", orderId));
2384: } catch (GenericEntityException e) {
2385: Debug.logError(e, "Cannot get OrderHeader record", module);
2386: }
2387: if (orderHeader == null) {
2388: Debug.logError("OrderHeader came back as null", module);
2389: return ServiceUtil.returnError(UtilProperties.getMessage(
2390: resource_error, "OrderCannotUpdateNullOrderHeader",
2391: UtilMisc.toMap("orderId", orderId), locale));
2392: }
2393:
2394: // get the order items
2395: List orderItems = null;
2396: try {
2397: orderItems = delegator.findByAnd("OrderItem", UtilMisc
2398: .toMap("orderId", orderId));
2399: } catch (GenericEntityException e) {
2400: Debug.logError(e, "Cannot get OrderItem records", module);
2401: return ServiceUtil.returnError(UtilProperties.getMessage(
2402: resource_error,
2403: "OrderProblemGettingOrderItemRecords", locale));
2404: }
2405:
2406: boolean allCanceled = true;
2407: boolean allComplete = true;
2408: boolean allApproved = true;
2409: if (orderItems != null) {
2410: Iterator itemIter = orderItems.iterator();
2411: while (itemIter.hasNext()) {
2412: GenericValue item = (GenericValue) itemIter.next();
2413: String statusId = item.getString("statusId");
2414: //Debug.log("Item Status: " + statusId, module);
2415: if (!"ITEM_CANCELLED".equals(statusId)) {
2416: //Debug.log("Not set to cancel", module);
2417: allCanceled = false;
2418: if (!"ITEM_COMPLETED".equals(statusId)) {
2419: //Debug.log("Not set to complete", module);
2420: allComplete = false;
2421: if (!"ITEM_APPROVED".equals(statusId)) {
2422: //Debug.log("Not set to approve", module);
2423: allApproved = false;
2424: break;
2425: }
2426: }
2427: }
2428: }
2429:
2430: // find the next status to set to (if any)
2431: String newStatus = null;
2432: if (allCanceled) {
2433: newStatus = "ORDER_CANCELLED";
2434: } else if (allComplete) {
2435: newStatus = "ORDER_COMPLETED";
2436: } else if (allApproved) {
2437: if (!"ORDER_SENT".equals(orderHeader
2438: .getString("statusId"))) {
2439: newStatus = "ORDER_APPROVED";
2440: }
2441: }
2442:
2443: // now set the new order status
2444: if (newStatus != null) {
2445: Map serviceContext = UtilMisc.toMap("orderId", orderId,
2446: "statusId", newStatus, "userLogin", userLogin);
2447: Map newSttsResult = null;
2448: try {
2449: newSttsResult = dispatcher.runSync(
2450: "changeOrderStatus", serviceContext);
2451: } catch (GenericServiceException e) {
2452: Debug
2453: .logError(
2454: e,
2455: "Problem calling the changeOrderStatus service",
2456: module);
2457: }
2458: if (ServiceUtil.isError(newSttsResult)) {
2459: return ServiceUtil.returnError(ServiceUtil
2460: .getErrorMessage(newSttsResult));
2461: }
2462: }
2463: } else {
2464: Debug
2465: .logWarning(
2466: UtilProperties
2467: .getMessage(
2468: resource_error,
2469: "OrderReceivedNullForOrderItemRecordsOrderId",
2470: UtilMisc.toMap("orderId",
2471: orderId), locale),
2472: module);
2473: }
2474:
2475: return ServiceUtil.returnSuccess();
2476: }
2477:
2478: /** Service to cancel an order item quantity */
2479: public static Map cancelOrderItem(DispatchContext ctx, Map context) {
2480: LocalDispatcher dispatcher = ctx.getDispatcher();
2481: GenericDelegator delegator = ctx.getDelegator();
2482: Locale locale = (Locale) context.get("locale");
2483:
2484: GenericValue userLogin = (GenericValue) context
2485: .get("userLogin");
2486: Double cancelQuantity = (Double) context.get("cancelQuantity");
2487: String orderId = (String) context.get("orderId");
2488: String orderItemSeqId = (String) context.get("orderItemSeqId");
2489: String shipGroupSeqId = (String) context.get("shipGroupSeqId");
2490:
2491: // debugging message info
2492: String itemMsgInfo = orderId + " / " + orderItemSeqId + " / "
2493: + shipGroupSeqId;
2494:
2495: // check and make sure we have permission to change the order
2496: Security security = ctx.getSecurity();
2497: if (!security.hasEntityPermission("ORDERMGR", "_UPDATE",
2498: userLogin)) {
2499: GenericValue placingCustomer = null;
2500: try {
2501: Map placingCustomerFields = UtilMisc.toMap("orderId",
2502: orderId, "partyId", userLogin
2503: .getString("partyId"), "roleTypeId",
2504: "PLACING_CUSTOMER");
2505: placingCustomer = delegator.findByPrimaryKey(
2506: "OrderRole", placingCustomerFields);
2507: } catch (GenericEntityException e) {
2508: Debug.logError(e, module);
2509: return ServiceUtil.returnError(UtilProperties
2510: .getMessage(resource_error,
2511: "OrderErrorCannotGetOrderRoleEntity",
2512: UtilMisc.toMap("itemMsgInfo",
2513: itemMsgInfo), locale));
2514: }
2515: if (placingCustomer == null)
2516: return ServiceUtil
2517: .returnError(UtilProperties
2518: .getMessage(
2519: resource_error,
2520: "OrderYouDoNotHavePermissionToChangeThisOrdersStatus",
2521: locale));
2522: }
2523:
2524: Map fields = UtilMisc.toMap("orderId", orderId);
2525: if (orderItemSeqId != null) {
2526: fields.put("orderItemSeqId", orderItemSeqId);
2527: }
2528: if (shipGroupSeqId != null) {
2529: fields.put("shipGroupSeqId", shipGroupSeqId);
2530: }
2531:
2532: List orderItemShipGroupAssocs = null;
2533: try {
2534: orderItemShipGroupAssocs = delegator.findByAnd(
2535: "OrderItemShipGroupAssoc", fields);
2536: } catch (GenericEntityException e) {
2537: Debug.logError(e, module);
2538: return ServiceUtil
2539: .returnError(UtilProperties.getMessage(
2540: resource_error,
2541: "OrderErrorCannotGetOrderItemAssocEntity",
2542: UtilMisc.toMap("itemMsgInfo", itemMsgInfo),
2543: locale));
2544: }
2545:
2546: if (orderItemShipGroupAssocs != null) {
2547: if (orderItemShipGroupAssocs == null) {
2548: return ServiceUtil
2549: .returnError(UtilProperties
2550: .getMessage(
2551: resource_error,
2552: "OrderErrorCannotCancelItemItemNotFound",
2553: UtilMisc.toMap("itemMsgInfo",
2554: itemMsgInfo), locale));
2555: }
2556:
2557: Iterator i = orderItemShipGroupAssocs.iterator();
2558: while (i.hasNext()) {
2559: GenericValue orderItemShipGroupAssoc = (GenericValue) i
2560: .next();
2561: GenericValue orderItem = null;
2562: try {
2563: orderItem = orderItemShipGroupAssoc
2564: .getRelatedOne("OrderItem");
2565: } catch (GenericEntityException e) {
2566: Debug.logError(e, module);
2567: }
2568:
2569: if (orderItem == null) {
2570: return ServiceUtil
2571: .returnError(UtilProperties
2572: .getMessage(
2573: resource_error,
2574: "OrderErrorCannotCancelItemItemNotFound",
2575: UtilMisc.toMap(
2576: "itemMsgInfo",
2577: itemMsgInfo),
2578: locale));
2579: }
2580:
2581: Double availableQuantity = orderItemShipGroupAssoc
2582: .getDouble("quantity");
2583: Double itemQuantity = orderItem.getDouble("quantity");
2584: if (availableQuantity == null)
2585: availableQuantity = new Double(0.0);
2586: if (itemQuantity == null)
2587: itemQuantity = new Double(0.0);
2588:
2589: Double this CancelQty = null;
2590: if (cancelQuantity != null) {
2591: this CancelQty = new Double(cancelQuantity
2592: .doubleValue());
2593: } else {
2594: this CancelQty = new Double(availableQuantity
2595: .doubleValue());
2596: }
2597:
2598: if (availableQuantity.doubleValue() >= this CancelQty
2599: .doubleValue()) {
2600: orderItem.set("cancelQuantity", this CancelQty);
2601: orderItemShipGroupAssoc.set("cancelQuantity",
2602: this CancelQty);
2603:
2604: try {
2605: List toStore = UtilMisc.toList(orderItem,
2606: orderItemShipGroupAssoc);
2607: delegator.storeAll(toStore);
2608: } catch (GenericEntityException e) {
2609: Debug.logError(e, module);
2610: return ServiceUtil
2611: .returnError(UtilProperties
2612: .getMessage(
2613: resource_error,
2614: "OrderUnableToSetCancelQuantity",
2615: UtilMisc.toMap(
2616: "itemMsgInfo",
2617: itemMsgInfo),
2618: locale));
2619: }
2620:
2621: if (this CancelQty.doubleValue() >= itemQuantity
2622: .doubleValue()) {
2623: // all items are cancelled -- mark the item as cancelled
2624: Map statusCtx = UtilMisc.toMap("orderId",
2625: orderId, "orderItemSeqId",
2626: orderItemSeqId, "statusId",
2627: "ITEM_CANCELLED", "userLogin",
2628: userLogin);
2629: try {
2630: dispatcher.runSyncIgnore(
2631: "changeOrderItemStatus", statusCtx);
2632: } catch (GenericServiceException e) {
2633: Debug.logError(e, module);
2634: return ServiceUtil
2635: .returnError(UtilProperties
2636: .getMessage(
2637: resource_error,
2638: "OrderUnableToCancelOrderLine",
2639: UtilMisc
2640: .toMap(
2641: "itemMsgInfo",
2642: itemMsgInfo),
2643: locale));
2644: }
2645: } else {
2646: // reverse the inventory reservation
2647: Map invCtx = UtilMisc.toMap("orderId", orderId,
2648: "orderItemSeqId", orderItemSeqId,
2649: "shipGroupSeqId", shipGroupSeqId,
2650: "cancelQuantity", this CancelQty,
2651: "userLogin", userLogin);
2652: try {
2653: dispatcher.runSyncIgnore(
2654: "cancelOrderItemInvResQty", invCtx);
2655: } catch (GenericServiceException e) {
2656: Debug.logError(e, module);
2657: return ServiceUtil
2658: .returnError(UtilProperties
2659: .getMessage(
2660: resource_error,
2661: "OrderUnableToUpdateInventoryReservations",
2662: UtilMisc
2663: .toMap(
2664: "itemMsgInfo",
2665: itemMsgInfo),
2666: locale));
2667: }
2668: }
2669: } else {
2670: return ServiceUtil
2671: .returnError(UtilProperties
2672: .getMessage(
2673: resource_error,
2674: "OrderInvalidCancelQuantityCannotCancel",
2675: UtilMisc.toMap(
2676: "thisCancelQty",
2677: this CancelQty),
2678: locale));
2679: }
2680: }
2681: }
2682:
2683: return ServiceUtil.returnSuccess();
2684: }
2685:
2686: /** Service for changing the status on order item(s) */
2687: public static Map setItemStatus(DispatchContext ctx, Map context) {
2688: GenericDelegator delegator = ctx.getDelegator();
2689:
2690: GenericValue userLogin = (GenericValue) context
2691: .get("userLogin");
2692: String orderId = (String) context.get("orderId");
2693: String orderItemSeqId = (String) context.get("orderItemSeqId");
2694: String fromStatusId = (String) context.get("fromStatusId");
2695: String statusId = (String) context.get("statusId");
2696: Timestamp statusDateTime = (Timestamp) context
2697: .get("statusDateTime");
2698: Locale locale = (Locale) context.get("locale");
2699:
2700: // check and make sure we have permission to change the order
2701: Security security = ctx.getSecurity();
2702: if (!security.hasEntityPermission("ORDERMGR", "_UPDATE",
2703: userLogin)) {
2704: GenericValue placingCustomer = null;
2705: try {
2706: Map placingCustomerFields = UtilMisc.toMap("orderId",
2707: orderId, "partyId", userLogin
2708: .getString("partyId"), "roleTypeId",
2709: "PLACING_CUSTOMER");
2710: placingCustomer = delegator.findByPrimaryKey(
2711: "OrderRole", placingCustomerFields);
2712: } catch (GenericEntityException e) {
2713: return ServiceUtil.returnError(UtilProperties
2714: .getMessage(resource_error,
2715: "OrderErrorCannotGetOrderRoleEntity",
2716: locale)
2717: + e.getMessage());
2718: }
2719: if (placingCustomer == null)
2720: return ServiceUtil
2721: .returnError(UtilProperties
2722: .getMessage(
2723: resource_error,
2724: "OrderYouDoNotHavePermissionToChangeThisOrdersStatus",
2725: locale));
2726: }
2727:
2728: Map fields = UtilMisc.toMap("orderId", orderId);
2729: if (orderItemSeqId != null)
2730: fields.put("orderItemSeqId", orderItemSeqId);
2731: if (fromStatusId != null)
2732: fields.put("statusId", fromStatusId);
2733:
2734: List orderItems = null;
2735: try {
2736: orderItems = delegator.findByAnd("OrderItem", fields);
2737: } catch (GenericEntityException e) {
2738: return ServiceUtil.returnError(UtilProperties.getMessage(
2739: resource_error,
2740: "OrderErrorCannotGetOrderItemEntity ", locale)
2741: + e.getMessage());
2742: }
2743:
2744: if (orderItems != null && orderItems.size() > 0) {
2745: List toBeStored = new ArrayList();
2746: Iterator itemsIterator = orderItems.iterator();
2747: while (itemsIterator.hasNext()) {
2748: GenericValue orderItem = (GenericValue) itemsIterator
2749: .next();
2750: if (orderItem == null) {
2751: return ServiceUtil
2752: .returnError(UtilProperties
2753: .getMessage(
2754: resource_error,
2755: "OrderErrorCannotChangeItemStatusItemNotFound",
2756: locale));
2757: }
2758: if (Debug.verboseOn())
2759: Debug
2760: .logVerbose(
2761: "[OrderServices.setItemStatus] : Status Change: ["
2762: + orderId
2763: + "] ("
2764: + orderItem
2765: .getString("orderItemSeqId"),
2766: module);
2767: if (Debug.verboseOn())
2768: Debug.logVerbose(
2769: "[OrderServices.setItemStatus] : From Status : "
2770: + orderItem.getString("statusId"),
2771: module);
2772: if (Debug.verboseOn())
2773: Debug.logVerbose(
2774: "[OrderServices.setOrderStatus] : To Status : "
2775: + statusId, module);
2776:
2777: if (orderItem.getString("statusId").equals(statusId)) {
2778: continue;
2779: }
2780:
2781: try {
2782: Map statusFields = UtilMisc.toMap("statusId",
2783: orderItem.getString("statusId"),
2784: "statusIdTo", statusId);
2785: GenericValue statusChange = delegator
2786: .findByPrimaryKeyCache("StatusValidChange",
2787: statusFields);
2788:
2789: if (statusChange == null) {
2790: Debug
2791: .logWarning(
2792: UtilProperties
2793: .getMessage(
2794: resource_error,
2795: "OrderItemStatusNotChangedIsNotAValidChange",
2796: UtilMisc
2797: .toMap(
2798: "orderStatusId",
2799: orderItem
2800: .getString("statusId"),
2801: "statusId",
2802: statusId),
2803: locale), module);
2804: continue;
2805: }
2806: } catch (GenericEntityException e) {
2807: return ServiceUtil
2808: .returnError(UtilProperties
2809: .getMessage(
2810: resource_error,
2811: "OrderErrorCouldNotChangeItemStatus",
2812: locale)
2813: + e.getMessage());
2814: }
2815:
2816: orderItem.set("statusId", statusId);
2817: toBeStored.add(orderItem);
2818: if (statusDateTime == null) {
2819: statusDateTime = UtilDateTime.nowTimestamp();
2820: }
2821: // now create a status change
2822: Map changeFields = new HashMap();
2823: changeFields.put("orderStatusId", delegator
2824: .getNextSeqId("OrderStatus"));
2825: changeFields.put("statusId", statusId);
2826: changeFields.put("orderId", orderId);
2827: changeFields.put("orderItemSeqId", orderItem
2828: .getString("orderItemSeqId"));
2829: changeFields.put("statusDatetime", statusDateTime);
2830: changeFields.put("statusUserLogin", userLogin
2831: .getString("userLoginId"));
2832: GenericValue orderStatus = delegator.makeValue(
2833: "OrderStatus", changeFields);
2834: toBeStored.add(orderStatus);
2835: }
2836:
2837: // store the changes
2838: if (toBeStored.size() > 0) {
2839: try {
2840: delegator.storeAll(toBeStored);
2841: } catch (GenericEntityException e) {
2842: return ServiceUtil
2843: .returnError(UtilProperties
2844: .getMessage(
2845: resource_error,
2846: "OrderErrorCannotStoreStatusChanges",
2847: locale)
2848: + e.getMessage());
2849: }
2850: }
2851:
2852: }
2853:
2854: return ServiceUtil.returnSuccess();
2855: }
2856:
2857: /** Service for changing the status on an order header */
2858: public static Map setOrderStatus(DispatchContext ctx, Map context) {
2859: GenericDelegator delegator = ctx.getDelegator();
2860: GenericValue userLogin = (GenericValue) context
2861: .get("userLogin");
2862: String orderId = (String) context.get("orderId");
2863: String statusId = (String) context.get("statusId");
2864: Map successResult = ServiceUtil.returnSuccess();
2865: Locale locale = (Locale) context.get("locale");
2866:
2867: // check and make sure we have permission to change the order
2868: Security security = ctx.getSecurity();
2869: if (!security.hasEntityPermission("ORDERMGR", "_UPDATE",
2870: userLogin)) {
2871: GenericValue placingCustomer = null;
2872: try {
2873: Map placingCustomerFields = UtilMisc.toMap("orderId",
2874: orderId, "partyId", userLogin
2875: .getString("partyId"), "roleTypeId",
2876: "PLACING_CUSTOMER");
2877: placingCustomer = delegator.findByPrimaryKey(
2878: "OrderRole", placingCustomerFields);
2879: } catch (GenericEntityException e) {
2880: return ServiceUtil.returnError(UtilProperties
2881: .getMessage(resource_error,
2882: "OrderErrorCannotGetOrderRoleEntity",
2883: locale)
2884: + e.getMessage());
2885: }
2886: if (placingCustomer == null)
2887: return ServiceUtil
2888: .returnError(UtilProperties
2889: .getMessage(
2890: resource_error,
2891: "OrderYouDoNotHavePermissionToChangeThisOrdersStatus",
2892: locale));
2893: }
2894:
2895: try {
2896: GenericValue orderHeader = delegator.findByPrimaryKey(
2897: "OrderHeader", UtilMisc.toMap("orderId", orderId));
2898:
2899: if (orderHeader == null) {
2900: return ServiceUtil
2901: .returnError(UtilProperties
2902: .getMessage(
2903: resource_error,
2904: "OrderErrorCouldNotChangeOrderStatusOrderCannotBeFound",
2905: locale));
2906: }
2907: // first save off the old status
2908: successResult.put("oldStatusId", orderHeader
2909: .get("statusId"));
2910:
2911: if (Debug.verboseOn())
2912: Debug.logVerbose(
2913: "[OrderServices.setOrderStatus] : From Status : "
2914: + orderHeader.getString("statusId"),
2915: module);
2916: if (Debug.verboseOn())
2917: Debug.logVerbose(
2918: "[OrderServices.setOrderStatus] : To Status : "
2919: + statusId, module);
2920:
2921: if (orderHeader.getString("statusId").equals(statusId)) {
2922: Debug
2923: .logWarning(
2924: UtilProperties
2925: .getMessage(
2926: resource_error,
2927: "OrderTriedToSetOrderStatusWithTheSameStatusIdforOrderWithId",
2928: UtilMisc.toMap(
2929: "statusId",
2930: statusId,
2931: "orderId",
2932: orderId),
2933: locale), module);
2934: return successResult;
2935: }
2936: try {
2937: Map statusFields = UtilMisc.toMap("statusId",
2938: orderHeader.getString("statusId"),
2939: "statusIdTo", statusId);
2940: GenericValue statusChange = delegator
2941: .findByPrimaryKeyCache("StatusValidChange",
2942: statusFields);
2943: if (statusChange == null) {
2944: return ServiceUtil
2945: .returnError(UtilProperties
2946: .getMessage(
2947: resource_error,
2948: "OrderErrorCouldNotChangeOrderStatusStatusIsNotAValidChange",
2949: locale));
2950: }
2951: } catch (GenericEntityException e) {
2952: return ServiceUtil.returnError(UtilProperties
2953: .getMessage(resource_error,
2954: "OrderErrorCouldNotChangeOrderStatus",
2955: locale)
2956: + e.getMessage() + ").");
2957: }
2958:
2959: // update the current status
2960: orderHeader.set("statusId", statusId);
2961:
2962: // now create a status change
2963: GenericValue orderStatus = delegator.makeValue(
2964: "OrderStatus", null);
2965: orderStatus.put("orderStatusId", delegator
2966: .getNextSeqId("OrderStatus"));
2967: orderStatus.put("statusId", statusId);
2968: orderStatus.put("orderId", orderId);
2969: orderStatus.put("statusDatetime", UtilDateTime
2970: .nowTimestamp());
2971: orderStatus.put("statusUserLogin", userLogin
2972: .getString("userLoginId"));
2973:
2974: orderHeader.store();
2975: orderStatus.create();
2976:
2977: successResult.put("needsInventoryIssuance", orderHeader
2978: .get("needsInventoryIssuance"));
2979: successResult.put("grandTotal", orderHeader
2980: .get("grandTotal"));
2981: successResult.put("orderTypeId", orderHeader
2982: .get("orderTypeId"));
2983: //Debug.logInfo("For setOrderStatus orderHeader is " + orderHeader, module);
2984: } catch (GenericEntityException e) {
2985: return ServiceUtil.returnError(UtilProperties.getMessage(
2986: resource_error,
2987: "OrderErrorCouldNotChangeOrderStatus", locale)
2988: + e.getMessage() + ").");
2989: }
2990:
2991: // release the inital hold if we are cancelled or approved
2992: if ("ORDER_CANCELLED".equals(statusId)
2993: || "ORDER_APPROVED".equals(statusId)) {
2994: OrderChangeHelper.releaseInitialOrderHold(ctx
2995: .getDispatcher(), orderId);
2996:
2997: // cancel any order processing if we are cancelled
2998: if ("ORDER_CANCELLED".equals(statusId)) {
2999: OrderChangeHelper.abortOrderProcessing(ctx
3000: .getDispatcher(), orderId);
3001: }
3002: }
3003:
3004: successResult.put("orderStatusId", statusId);
3005: //Debug.logInfo("For setOrderStatus successResult is " + successResult, module);
3006: return successResult;
3007: }
3008:
3009: /** Service to update the order tracking number */
3010: public static Map updateTrackingNumber(DispatchContext dctx,
3011: Map context) {
3012: Map result = new HashMap();
3013: GenericDelegator delegator = dctx.getDelegator();
3014: String orderId = (String) context.get("orderId");
3015: String shipGroupSeqId = (String) context.get("shipGroupSeqId");
3016: String trackingNumber = (String) context.get("trackingNumber");
3017: //Locale locale = (Locale) context.get("locale");
3018:
3019: try {
3020: GenericValue shipGroup = delegator.findByPrimaryKey(
3021: "OrderItemShipGroup", UtilMisc.toMap("orderId",
3022: orderId, "shipGroupSeqId", shipGroupSeqId));
3023:
3024: if (shipGroup == null) {
3025: result.put(ModelService.RESPONSE_MESSAGE,
3026: ModelService.RESPOND_ERROR);
3027: result.put(ModelService.ERROR_MESSAGE,
3028: "ERROR: No order shipment preference found!");
3029: } else {
3030: shipGroup.set("trackingNumber", trackingNumber);
3031: shipGroup.store();
3032: result.put(ModelService.RESPONSE_MESSAGE,
3033: ModelService.RESPOND_SUCCESS);
3034: }
3035: } catch (GenericEntityException e) {
3036: Debug.logError(e, module);
3037: result.put(ModelService.RESPONSE_MESSAGE,
3038: ModelService.RESPOND_ERROR);
3039: result.put(ModelService.ERROR_MESSAGE,
3040: "ERROR: Could not set tracking number ("
3041: + e.getMessage() + ").");
3042: }
3043: return result;
3044: }
3045:
3046: /** Service to add a role type to an order */
3047: public static Map addRoleType(DispatchContext ctx, Map context) {
3048: Map result = new HashMap();
3049: GenericDelegator delegator = ctx.getDelegator();
3050: String orderId = (String) context.get("orderId");
3051: String partyId = (String) context.get("partyId");
3052: String roleTypeId = (String) context.get("roleTypeId");
3053: Boolean removeOld = (Boolean) context.get("removeOld");
3054: //Locale locale = (Locale) context.get("locale");
3055:
3056: if (removeOld != null && removeOld.booleanValue()) {
3057: try {
3058: delegator.removeByAnd("OrderRole", UtilMisc.toMap(
3059: "orderId", orderId, "roleTypeId", roleTypeId));
3060: } catch (GenericEntityException e) {
3061: result.put(ModelService.RESPONSE_MESSAGE,
3062: ModelService.RESPOND_ERROR);
3063: result.put(ModelService.ERROR_MESSAGE,
3064: "ERROR: Could not remove old roles ("
3065: + e.getMessage() + ").");
3066: return result;
3067: }
3068: }
3069:
3070: Map fields = UtilMisc.toMap("orderId", orderId, "partyId",
3071: partyId, "roleTypeId", roleTypeId);
3072:
3073: try {
3074: // first check and see if we are already there; if so, just return success
3075: GenericValue testValue = delegator.findByPrimaryKey(
3076: "OrderRole", fields);
3077: if (testValue != null) {
3078: ServiceUtil.returnSuccess();
3079: } else {
3080: GenericValue value = delegator.makeValue("OrderRole",
3081: fields);
3082: delegator.create(value);
3083: }
3084: } catch (GenericEntityException e) {
3085: result.put(ModelService.RESPONSE_MESSAGE,
3086: ModelService.RESPOND_ERROR);
3087: result.put(ModelService.ERROR_MESSAGE,
3088: "ERROR: Could not add role to order ("
3089: + e.getMessage() + ").");
3090: return result;
3091: }
3092: result.put(ModelService.RESPONSE_MESSAGE,
3093: ModelService.RESPOND_SUCCESS);
3094: return result;
3095: }
3096:
3097: /** Service to remove a role type from an order */
3098: public static Map removeRoleType(DispatchContext ctx, Map context) {
3099: Map result = new HashMap();
3100: GenericDelegator delegator = ctx.getDelegator();
3101: String orderId = (String) context.get("orderId");
3102: String partyId = (String) context.get("partyId");
3103: String roleTypeId = (String) context.get("roleTypeId");
3104: Map fields = UtilMisc.toMap("orderId", orderId, "partyId",
3105: partyId, "roleTypeId", roleTypeId);
3106: //Locale locale = (Locale) context.get("locale");
3107:
3108: GenericValue testValue = null;
3109:
3110: try {
3111: testValue = delegator.findByPrimaryKey("OrderRole", fields);
3112: } catch (GenericEntityException e) {
3113: result.put(ModelService.RESPONSE_MESSAGE,
3114: ModelService.RESPOND_ERROR);
3115: result.put(ModelService.ERROR_MESSAGE,
3116: "ERROR: Could not add role to order ("
3117: + e.getMessage() + ").");
3118: return result;
3119: }
3120:
3121: if (testValue == null) {
3122: result.put(ModelService.RESPONSE_MESSAGE,
3123: ModelService.RESPOND_SUCCESS);
3124: return result;
3125: }
3126:
3127: try {
3128: GenericValue value = delegator.findByPrimaryKey(
3129: "OrderRole", fields);
3130:
3131: value.remove();
3132: } catch (GenericEntityException e) {
3133: result.put(ModelService.RESPONSE_MESSAGE,
3134: ModelService.RESPOND_ERROR);
3135: result.put(ModelService.ERROR_MESSAGE,
3136: "ERROR: Could not remove role from order ("
3137: + e.getMessage() + ").");
3138: return result;
3139: }
3140: result.put(ModelService.RESPONSE_MESSAGE,
3141: ModelService.RESPOND_SUCCESS);
3142: return result;
3143: }
3144:
3145: /** Service to email a customer with initial order confirmation */
3146: public static Map sendOrderConfirmNotification(DispatchContext ctx,
3147: Map context) {
3148: return sendOrderNotificationScreen(ctx, context,
3149: "PRDS_ODR_CONFIRM");
3150: }
3151:
3152: /** Service to email a customer with order changes */
3153: public static Map sendOrderCompleteNotification(
3154: DispatchContext ctx, Map context) {
3155: return sendOrderNotificationScreen(ctx, context,
3156: "PRDS_ODR_COMPLETE");
3157: }
3158:
3159: /** Service to email a customer with order changes */
3160: public static Map sendOrderBackorderNotification(
3161: DispatchContext ctx, Map context) {
3162: return sendOrderNotificationScreen(ctx, context,
3163: "PRDS_ODR_BACKORDER");
3164: }
3165:
3166: /** Service to email a customer with order changes */
3167: public static Map sendOrderChangeNotification(DispatchContext ctx,
3168: Map context) {
3169: return sendOrderNotificationScreen(ctx, context,
3170: "PRDS_ODR_CHANGE");
3171: }
3172:
3173: /** Service to email a customer with order payment retry results */
3174: public static Map sendOrderPayRetryNotification(
3175: DispatchContext ctx, Map context) {
3176: return sendOrderNotificationScreen(ctx, context,
3177: "PRDS_ODR_PAYRETRY");
3178: }
3179:
3180: protected static Map sendOrderNotificationScreen(
3181: DispatchContext dctx, Map context, String emailType) {
3182: LocalDispatcher dispatcher = dctx.getDispatcher();
3183: GenericDelegator delegator = dctx.getDelegator();
3184: GenericValue userLogin = (GenericValue) context
3185: .get("userLogin");
3186: String orderId = (String) context.get("orderId");
3187: String orderItemSeqId = (String) context.get("orderItemSeqId");
3188: String sendTo = (String) context.get("sendTo");
3189: String sendCc = (String) context.get("sendCc");
3190: String note = (String) context.get("note");
3191: String screenUri = (String) context.get("screenUri");
3192:
3193: GenericValue temporaryAnonymousUserLogin = (GenericValue) context
3194: .get("temporaryAnonymousUserLogin");
3195: if (userLogin == null) {
3196: // this may happen during anonymous checkout, try to the special case user
3197: userLogin = temporaryAnonymousUserLogin;
3198: }
3199:
3200: // prepare the order information
3201: Map sendMap = FastMap.newInstance();
3202:
3203: // get the order header and store
3204: GenericValue orderHeader = null;
3205: try {
3206: orderHeader = delegator.findByPrimaryKey("OrderHeader",
3207: UtilMisc.toMap("orderId", orderId));
3208: } catch (GenericEntityException e) {
3209: Debug.logError(e, "Problem getting OrderHeader", module);
3210: }
3211:
3212: if (orderHeader == null) {
3213: return ServiceUtil
3214: .returnFailure("Could not find OrderHeader with ID ["
3215: + orderId + "]");
3216: }
3217:
3218: if (orderHeader.get("webSiteId") == null) {
3219: return ServiceUtil
3220: .returnFailure("No website attached to order; cannot generate notification ["
3221: + orderId + "]");
3222: }
3223:
3224: GenericValue productStoreEmail = null;
3225: try {
3226: productStoreEmail = delegator.findByPrimaryKey(
3227: "ProductStoreEmailSetting", UtilMisc.toMap(
3228: "productStoreId", orderHeader
3229: .get("productStoreId"),
3230: "emailType", emailType));
3231: } catch (GenericEntityException e) {
3232: Debug.logError(e,
3233: "Problem getting the ProductStoreEmailSetting for productStoreId="
3234: + orderHeader.get("productStoreId")
3235: + " and emailType=" + emailType, module);
3236: }
3237: if (productStoreEmail == null) {
3238: return ServiceUtil
3239: .returnFailure("No valid email setting for store with productStoreId="
3240: + orderHeader.get("productStoreId")
3241: + " and emailType=" + emailType);
3242: }
3243:
3244: // the override screenUri
3245: if (UtilValidate.isEmpty(screenUri)) {
3246: String bodyScreenLocation = productStoreEmail
3247: .getString("bodyScreenLocation");
3248: if (UtilValidate.isEmpty(bodyScreenLocation)) {
3249: bodyScreenLocation = ProductStoreWorker
3250: .getDefaultProductStoreEmailScreenLocation(emailType);
3251: }
3252: sendMap.put("bodyScreenUri", bodyScreenLocation);
3253: String xslfoAttachScreenLocation = productStoreEmail
3254: .getString("xslfoAttachScreenLocation");
3255: sendMap.put("xslfoAttachScreenLocation",
3256: xslfoAttachScreenLocation);
3257: } else {
3258: sendMap.put("bodyScreenUri", screenUri);
3259: }
3260:
3261: // website
3262: sendMap.put("webSiteId", orderHeader.get("webSiteId"));
3263:
3264: OrderReadHelper orh = new OrderReadHelper(orderHeader);
3265: String emailString = orh.getOrderEmailString();
3266: if (UtilValidate.isEmpty(emailString)) {
3267: Debug.logInfo(
3268: "Customer is not setup to receive emails; no address(s) found ["
3269: + orderId + "]", module);
3270: return ServiceUtil
3271: .returnError("No sendTo email address found");
3272: }
3273:
3274: // where to get the locale... from PLACING_CUSTOMER's UserLogin.lastLocale,
3275: // or if not available then from ProductStore.defaultLocaleString
3276: // or if not available then the system Locale
3277: Locale locale = null;
3278: GenericValue placingParty = orh.getPlacingParty();
3279: GenericValue placingUserLogin = placingParty == null ? null
3280: : PartyWorker.findPartyLatestUserLogin(placingParty
3281: .getString("partyId"), delegator);
3282: if (locale == null && placingParty != null) {
3283: locale = PartyWorker.findPartyLastLocale(placingParty
3284: .getString("partyId"), delegator);
3285: }
3286:
3287: // for anonymous orders, use the temporaryAnonymousUserLogin as the placingUserLogin will be null
3288: if (placingUserLogin == null) {
3289: placingUserLogin = temporaryAnonymousUserLogin;
3290: }
3291:
3292: GenericValue productStore = OrderReadHelper
3293: .getProductStoreFromOrder(orderHeader);
3294: if (locale == null && productStore != null) {
3295: String localeString = productStore
3296: .getString("defaultLocaleString");
3297: if (UtilValidate.isNotEmpty(localeString)) {
3298: locale = UtilMisc.parseLocale(localeString);
3299: }
3300: }
3301: if (locale == null) {
3302: locale = Locale.getDefault();
3303: }
3304:
3305: ResourceBundleMapWrapper uiLabelMap = (ResourceBundleMapWrapper) UtilProperties
3306: .getResourceBundleMap("EcommerceUiLabels", locale);
3307: uiLabelMap.addBottomResourceBundle("OrderUiLabels");
3308: uiLabelMap.addBottomResourceBundle("CommonUiLabels");
3309:
3310: Map bodyParameters = UtilMisc.toMap("orderId", orderId,
3311: "orderItemSeqId", orderItemSeqId, "userLogin",
3312: placingUserLogin, "uiLabelMap", uiLabelMap, "locale",
3313: locale);
3314: if (placingParty != null) {
3315: bodyParameters.put("partyId", placingParty.get("partyId"));
3316: }
3317: bodyParameters.put("note", note);
3318: sendMap.put("bodyParameters", bodyParameters);
3319: sendMap.put("userLogin", userLogin);
3320:
3321: String subjectString = productStoreEmail.getString("subject");
3322: sendMap.put("subject", subjectString);
3323:
3324: sendMap
3325: .put("contentType", productStoreEmail
3326: .get("contentType"));
3327: sendMap.put("sendFrom", productStoreEmail.get("fromAddress"));
3328: sendMap.put("sendCc", productStoreEmail.get("ccAddress"));
3329: sendMap.put("sendBcc", productStoreEmail.get("bccAddress"));
3330: if ((sendTo != null) && UtilValidate.isEmail(sendTo)) {
3331: sendMap.put("sendTo", sendTo);
3332: } else {
3333: sendMap.put("sendTo", emailString);
3334: }
3335: if ((sendCc != null) && UtilValidate.isEmail(sendCc)) {
3336: sendMap.put("sendCc", sendCc);
3337: } else {
3338: sendMap.put("sendCc", productStoreEmail.get("ccAddress"));
3339: }
3340:
3341: // send the notification
3342: Map sendResp = null;
3343: try {
3344: sendResp = dispatcher
3345: .runSync("sendMailFromScreen", sendMap);
3346: } catch (Exception e) {
3347: Debug.logError(e, module);
3348: return ServiceUtil.returnError(UtilProperties.getMessage(
3349: resource_error, "OrderServiceExceptionSeeLogs",
3350: locale));
3351: }
3352:
3353: // check for errors
3354: if (sendResp != null && !ServiceUtil.isError(sendResp)) {
3355: sendResp.put("emailType", emailType);
3356: }
3357: return sendResp;
3358: }
3359:
3360: /** Service to email order notifications for pending actions */
3361: public static Map sendProcessNotification(DispatchContext ctx,
3362: Map context) {
3363: //appears to not be used: Map result = new HashMap();
3364: GenericDelegator delegator = ctx.getDelegator();
3365: LocalDispatcher dispatcher = ctx.getDispatcher();
3366: String adminEmailList = (String) context.get("adminEmailList");
3367: String assignedToUser = (String) context.get("assignedPartyId");
3368: //appears to not be used: String assignedToRole = (String) context.get("assignedRoleTypeId");
3369: String workEffortId = (String) context.get("workEffortId");
3370: Locale locale = (Locale) context.get("locale");
3371:
3372: GenericValue workEffort = null;
3373: GenericValue orderHeader = null;
3374: //appears to not be used: String assignedEmail = null;
3375:
3376: // get the order/workflow info
3377: try {
3378: workEffort = delegator.findByPrimaryKey("WorkEffort",
3379: UtilMisc.toMap("workEffortId", workEffortId));
3380: String sourceReferenceId = workEffort
3381: .getString("sourceReferenceId");
3382: if (sourceReferenceId != null)
3383: orderHeader = delegator.findByPrimaryKey("OrderHeader",
3384: UtilMisc.toMap("orderId", sourceReferenceId));
3385: } catch (GenericEntityException e) {
3386: return ServiceUtil.returnError(UtilProperties.getMessage(
3387: resource_error, "OrderProblemWithEntityLookup",
3388: locale));
3389: }
3390:
3391: // find the assigned user's email address(s)
3392: GenericValue party = null;
3393: Collection assignedToEmails = null;
3394: try {
3395: party = delegator.findByPrimaryKey("Party", UtilMisc.toMap(
3396: "partyId", assignedToUser));
3397: } catch (GenericEntityException e) {
3398: return ServiceUtil.returnError(UtilProperties.getMessage(
3399: resource_error, "OrderProblemWithEntityLookup",
3400: locale));
3401: }
3402: if (party != null)
3403: assignedToEmails = ContactHelper.getContactMechByPurpose(
3404: party, "PRIMARY_EMAIL", false);
3405:
3406: Map templateData = new HashMap(context);
3407: String omgStatusId = WfUtil.getOMGStatus(workEffort
3408: .getString("currentStatusId"));
3409: templateData.putAll(orderHeader);
3410: templateData.putAll(workEffort);
3411: templateData.put("omgStatusId", omgStatusId);
3412:
3413: // get the assignments
3414: List assignments = null;
3415: if (workEffort != null) {
3416: try {
3417: assignments = workEffort
3418: .getRelated("WorkEffortPartyAssignment");
3419: } catch (GenericEntityException e1) {
3420: Debug.logError(e1, "Problems getting assignements",
3421: module);
3422: }
3423: }
3424: templateData.put("assignments", assignments);
3425:
3426: StringBuffer emailList = new StringBuffer();
3427: if (assignedToEmails != null) {
3428: Iterator aei = assignedToEmails.iterator();
3429: while (aei.hasNext()) {
3430: GenericValue ct = (GenericValue) aei.next();
3431: if (ct != null && ct.get("infoString") != null) {
3432: if (emailList.length() > 1)
3433: emailList.append(",");
3434: emailList.append(ct.getString("infoString"));
3435: }
3436: }
3437: }
3438: if (adminEmailList != null) {
3439: if (emailList.length() > 1)
3440: emailList.append(",");
3441: emailList.append(adminEmailList);
3442: }
3443:
3444: // prepare the mail info
3445: String ofbizHome = System.getProperty("ofbiz.home");
3446: String templateName = ofbizHome
3447: + "/applications/order/email/default/emailprocessnotify.ftl";
3448:
3449: Map sendMailContext = new HashMap();
3450: sendMailContext.put("sendTo", emailList.toString());
3451: sendMailContext.put("sendFrom", "workflow@ofbiz.org"); // fixme
3452: sendMailContext.put("subject", "Workflow Notification");
3453: sendMailContext.put("templateName", templateName);
3454: sendMailContext.put("templateData", templateData);
3455:
3456: try {
3457: dispatcher.runAsync("sendGenericNotificationEmail",
3458: sendMailContext);
3459: } catch (GenericServiceException e) {
3460: return ServiceUtil.returnError(UtilProperties.getMessage(
3461: resource_error, "OrderSendMailServiceFailed",
3462: locale)
3463: + e.getMessage());
3464: }
3465: return ServiceUtil.returnSuccess();
3466: }
3467:
3468: /** Service to create an order payment preference */
3469: public static Map createPaymentPreference(DispatchContext ctx,
3470: Map context) {
3471: Map result = new HashMap();
3472: GenericDelegator delegator = ctx.getDelegator();
3473: String orderId = (String) context.get("orderId");
3474: String paymentMethodTypeId = (String) context
3475: .get("paymentMethodTypeId");
3476: String paymentMethodId = (String) context
3477: .get("paymentMethodId");
3478: BigDecimal maxAmount = (BigDecimal) context.get("maxAmount");
3479: GenericValue userLogin = (GenericValue) context
3480: .get("userLogin");
3481: Locale locale = (Locale) context.get("locale");
3482:
3483: String prefId = null;
3484:
3485: try {
3486: prefId = delegator.getNextSeqId("OrderPaymentPreference");
3487: } catch (IllegalArgumentException e) {
3488: return ServiceUtil
3489: .returnError(UtilProperties
3490: .getMessage(
3491: resource_error,
3492: "OrderErrorCouldNotCreateOrderPaymentPreferenceIdGenerationFailure",
3493: locale));
3494: }
3495:
3496: Map fields = UtilMisc.toMap("orderPaymentPreferenceId", prefId,
3497: "orderId", orderId, "paymentMethodTypeId",
3498: paymentMethodTypeId, "paymentMethodId",
3499: paymentMethodId, "maxAmount", maxAmount);
3500:
3501: try {
3502: GenericValue v = delegator.makeValue(
3503: "OrderPaymentPreference", fields);
3504: v.set("createdDate", UtilDateTime.nowTimestamp());
3505: if (userLogin != null) {
3506: v.set("createdByUserLogin", userLogin
3507: .getString("userLoginId"));
3508: }
3509: delegator.create(v);
3510: } catch (GenericEntityException e) {
3511: result.put(ModelService.RESPONSE_MESSAGE,
3512: ModelService.RESPOND_ERROR);
3513: result.put(ModelService.ERROR_MESSAGE,
3514: "ERROR: Could not create OrderPaymentPreference ("
3515: + e.getMessage() + ").");
3516: return result;
3517: }
3518: result.put("orderPaymentPreferenceId", prefId);
3519: result.put(ModelService.RESPONSE_MESSAGE,
3520: ModelService.RESPOND_SUCCESS);
3521: return result;
3522: }
3523:
3524: /** Service to get order header information as standard results. */
3525: public static Map getOrderHeaderInformation(DispatchContext dctx,
3526: Map context) {
3527: GenericDelegator delegator = dctx.getDelegator();
3528: String orderId = (String) context.get("orderId");
3529: Locale locale = (Locale) context.get("locale");
3530:
3531: GenericValue orderHeader = null;
3532: try {
3533: orderHeader = delegator.findByPrimaryKey("OrderHeader",
3534: UtilMisc.toMap("orderId", orderId));
3535: } catch (GenericEntityException e) {
3536: Debug.logError(e, "Problem getting order header detial",
3537: module);
3538: return ServiceUtil.returnError(UtilProperties.getMessage(
3539: resource_error, "OrderCannotGetOrderHeader ",
3540: locale)
3541: + e.getMessage());
3542: }
3543: if (orderHeader != null) {
3544: Map result = ServiceUtil.returnSuccess();
3545: result.putAll(orderHeader);
3546: return result;
3547: }
3548: return ServiceUtil.returnError(UtilProperties.getMessage(
3549: resource_error,
3550: "OrderErrorGettingOrderHeaderInformationNull", locale));
3551: }
3552:
3553: /** Service to get the total shipping for an order. */
3554: public static Map getOrderShippingAmount(DispatchContext dctx,
3555: Map context) {
3556: GenericDelegator delegator = dctx.getDelegator();
3557: String orderId = (String) context.get("orderId");
3558: Locale locale = (Locale) context.get("locale");
3559:
3560: GenericValue orderHeader = null;
3561: try {
3562: orderHeader = delegator.findByPrimaryKey("OrderHeader",
3563: UtilMisc.toMap("orderId", orderId));
3564: } catch (GenericEntityException e) {
3565: Debug.logError(e, module);
3566: return ServiceUtil.returnError(UtilProperties.getMessage(
3567: resource_error,
3568: "OrderErrorCouldNotGetOrderInformation", locale)
3569: + e.getMessage() + ").");
3570: }
3571:
3572: Map result = null;
3573: if (orderHeader != null) {
3574: OrderReadHelper orh = new OrderReadHelper(orderHeader);
3575: List orderItems = orh.getValidOrderItems();
3576: List orderAdjustments = orh.getAdjustments();
3577: List orderHeaderAdjustments = orh
3578: .getOrderHeaderAdjustments();
3579: BigDecimal orderSubTotal = orh.getOrderItemsSubTotalBd();
3580:
3581: BigDecimal shippingAmount = OrderReadHelper
3582: .getAllOrderItemsAdjustmentsTotalBd(orderItems,
3583: orderAdjustments, false, false, true);
3584: shippingAmount = shippingAmount.add(OrderReadHelper
3585: .calcOrderAdjustmentsBd(orderHeaderAdjustments,
3586: orderSubTotal, false, false, true));
3587:
3588: result = ServiceUtil.returnSuccess();
3589: result.put("shippingAmount", shippingAmount);
3590: } else {
3591: result = ServiceUtil
3592: .returnError(UtilProperties
3593: .getMessage(
3594: resource_error,
3595: "OrderUnableToFindOrderHeaderCannotGetShippingAmount",
3596: locale));
3597: }
3598: return result;
3599: }
3600:
3601: /** Service to get an order contact mech. */
3602: public static Map getOrderAddress(DispatchContext dctx, Map context) {
3603: Map result = new HashMap();
3604: GenericDelegator delegator = dctx.getDelegator();
3605:
3606: String orderId = (String) context.get("orderId");
3607: //appears to not be used: GenericValue v = null;
3608: String purpose[] = { "BILLING_LOCATION", "SHIPPING_LOCATION" };
3609: String outKey[] = { "billingAddress", "shippingAddress" };
3610: GenericValue orderHeader = null;
3611: //Locale locale = (Locale) context.get("locale");
3612:
3613: try {
3614: orderHeader = delegator.findByPrimaryKeyCache(
3615: "OrderHeader", UtilMisc.toMap("orderId", orderId));
3616: if (orderHeader != null)
3617: result.put("orderHeader", orderHeader);
3618: } catch (GenericEntityException e) {
3619: result.put(ModelService.RESPONSE_MESSAGE,
3620: ModelService.RESPOND_ERROR);
3621: result.put(ModelService.ERROR_MESSAGE,
3622: "ERROR: Could not get OrderHeader ("
3623: + e.getMessage() + ").");
3624: return result;
3625: }
3626: if (orderHeader == null) {
3627: result.put(ModelService.RESPONSE_MESSAGE,
3628: ModelService.RESPOND_ERROR);
3629: result.put(ModelService.ERROR_MESSAGE,
3630: "ERROR: Could get the OrderHeader.");
3631: return result;
3632: }
3633: for (int i = 0; i < purpose.length; i++) {
3634: try {
3635: GenericValue orderContactMech = EntityUtil
3636: .getFirst(orderHeader.getRelatedByAnd(
3637: "OrderContactMech", UtilMisc.toMap(
3638: "contactMechPurposeTypeId",
3639: purpose[i])));
3640: GenericValue contactMech = orderContactMech
3641: .getRelatedOne("ContactMech");
3642:
3643: if (contactMech != null) {
3644: result.put(outKey[i], contactMech
3645: .getRelatedOne("PostalAddress"));
3646: }
3647: } catch (GenericEntityException e) {
3648: result.put(ModelService.RESPONSE_MESSAGE,
3649: ModelService.RESPOND_ERROR);
3650: result.put(ModelService.ERROR_MESSAGE,
3651: "ERROR: Problems getting contact mech ("
3652: + e.getMessage() + ").");
3653: return result;
3654: }
3655: }
3656:
3657: result.put("orderId", orderId);
3658: return result;
3659: }
3660:
3661: /** Service to create a order header note. */
3662: public static Map createOrderNote(DispatchContext dctx, Map context) {
3663: GenericDelegator delegator = dctx.getDelegator();
3664: LocalDispatcher dispatcher = dctx.getDispatcher();
3665: GenericValue userLogin = (GenericValue) context
3666: .get("userLogin");
3667: String noteString = (String) context.get("note");
3668: String orderId = (String) context.get("orderId");
3669: String internalNote = (String) context.get("internalNote");
3670: Map noteCtx = UtilMisc.toMap("note", noteString, "userLogin",
3671: userLogin);
3672: Locale locale = (Locale) context.get("locale");
3673:
3674: try {
3675: // Store the note.
3676: Map noteRes = dispatcher.runSync("createNote", noteCtx);
3677:
3678: if (ServiceUtil.isError(noteRes))
3679: return noteRes;
3680:
3681: String noteId = (String) noteRes.get("noteId");
3682:
3683: if (noteId == null || noteId.length() == 0) {
3684: return ServiceUtil
3685: .returnError(UtilProperties
3686: .getMessage(
3687: resource_error,
3688: "OrderProblemCreatingTheNoteNoNoteIdReturned",
3689: locale));
3690: }
3691:
3692: // Set the order info
3693: Map fields = UtilMisc.toMap("orderId", orderId, "noteId",
3694: noteId, "internalNote", internalNote);
3695: GenericValue v = delegator.makeValue("OrderHeaderNote",
3696: fields);
3697:
3698: delegator.create(v);
3699: } catch (GenericEntityException ee) {
3700: Debug.logError(ee, module);
3701: return ServiceUtil
3702: .returnError("Problem associating note with order ("
3703: + ee.getMessage() + ")");
3704: } catch (GenericServiceException se) {
3705: Debug.logError(se, module);
3706: return ServiceUtil
3707: .returnError("Problem associating note with order ("
3708: + se.getMessage() + ")");
3709: }
3710:
3711: return ServiceUtil.returnSuccess();
3712: }
3713:
3714: public static Map allowOrderSplit(DispatchContext ctx, Map context) {
3715: GenericDelegator delegator = ctx.getDelegator();
3716: GenericValue userLogin = (GenericValue) context
3717: .get("userLogin");
3718: String orderId = (String) context.get("orderId");
3719: String shipGroupSeqId = (String) context.get("shipGroupSeqId");
3720: Locale locale = (Locale) context.get("locale");
3721:
3722: // check and make sure we have permission to change the order
3723: Security security = ctx.getSecurity();
3724: if (!security.hasEntityPermission("ORDERMGR", "_UPDATE",
3725: userLogin)) {
3726: GenericValue placingCustomer = null;
3727: try {
3728: Map placingCustomerFields = UtilMisc.toMap("orderId",
3729: orderId, "partyId", userLogin
3730: .getString("partyId"), "roleTypeId",
3731: "PLACING_CUSTOMER");
3732: placingCustomer = delegator.findByPrimaryKey(
3733: "OrderRole", placingCustomerFields);
3734: } catch (GenericEntityException e) {
3735: return ServiceUtil.returnError(UtilProperties
3736: .getMessage(resource_error,
3737: "OrderErrorCannotGetOrderRoleEntity",
3738: locale)
3739: + e.getMessage());
3740: }
3741: if (placingCustomer == null) {
3742: return ServiceUtil
3743: .returnError(UtilProperties
3744: .getMessage(
3745: resource_error,
3746: "OrderYouDoNotHavePermissionToChangeThisOrdersStatus",
3747: locale));
3748: }
3749: }
3750:
3751: GenericValue shipGroup = null;
3752: try {
3753: Map fields = UtilMisc.toMap("orderId", orderId,
3754: "shipGroupSeqId", shipGroupSeqId);
3755: shipGroup = delegator.findByPrimaryKey(
3756: "OrderItemShipGroup", fields);
3757: } catch (GenericEntityException e) {
3758: Debug.logError(e,
3759: "Problems getting OrderItemShipGroup for : "
3760: + orderId + " / " + shipGroupSeqId, module);
3761: return ServiceUtil
3762: .returnError(UtilProperties
3763: .getMessage(
3764: resource_error,
3765: "OrderCannotUpdateProblemGettingOrderShipmentPreference",
3766: locale));
3767: }
3768:
3769: if (shipGroup != null) {
3770: shipGroup.set("maySplit", "Y");
3771: try {
3772: shipGroup.store();
3773: } catch (GenericEntityException e) {
3774: Debug.logError(
3775: "Problem saving OrderItemShipGroup for : "
3776: + orderId + " / " + shipGroupSeqId,
3777: module);
3778: return ServiceUtil
3779: .returnError(UtilProperties
3780: .getMessage(
3781: resource_error,
3782: "OrderCannotUpdateProblemSettingOrderShipmentPreference",
3783: locale));
3784: }
3785: } else {
3786: Debug.logError("ERROR: Got a NULL OrderItemShipGroup",
3787: module);
3788: return ServiceUtil.returnError(UtilProperties.getMessage(
3789: resource_error,
3790: "OrderCannotUpdateNoAvailableGroupsToChange",
3791: locale));
3792: }
3793: return ServiceUtil.returnSuccess();
3794: }
3795:
3796: public static Map cancelFlaggedSalesOrders(DispatchContext dctx,
3797: Map context) {
3798: GenericDelegator delegator = dctx.getDelegator();
3799: LocalDispatcher dispatcher = dctx.getDispatcher();
3800: GenericValue userLogin = (GenericValue) context
3801: .get("userLogin");
3802: //Locale locale = (Locale) context.get("locale");
3803:
3804: List ordersToCheck = null;
3805: List exprs = new ArrayList();
3806:
3807: // create the query expressions
3808: exprs.add(new EntityExpr("orderTypeId", EntityOperator.EQUALS,
3809: "SALES_ORDER"));
3810: exprs.add(new EntityExpr("statusId", EntityOperator.NOT_EQUAL,
3811: "ORDER_COMPLETED"));
3812: exprs.add(new EntityExpr("statusId", EntityOperator.NOT_EQUAL,
3813: "ORDER_CANCELLED"));
3814: exprs.add(new EntityExpr("statusId", EntityOperator.NOT_EQUAL,
3815: "ORDER_REJECTED"));
3816:
3817: // get the orders
3818: try {
3819: ordersToCheck = delegator.findByAnd("OrderHeader", exprs,
3820: UtilMisc.toList("orderDate"));
3821: } catch (GenericEntityException e) {
3822: Debug.logError(e, "Problem getting order headers", module);
3823: }
3824:
3825: if (ordersToCheck == null || ordersToCheck.size() == 0) {
3826: Debug.logInfo("No orders to check, finished", module);
3827: return ServiceUtil.returnSuccess();
3828: }
3829:
3830: Timestamp nowTimestamp = UtilDateTime.nowTimestamp();
3831: Iterator i = ordersToCheck.iterator();
3832: while (i.hasNext()) {
3833: GenericValue orderHeader = (GenericValue) i.next();
3834: String orderId = orderHeader.getString("orderId");
3835: String orderStatus = orderHeader.getString("statusId");
3836:
3837: if (orderStatus.equals("ORDER_CREATED")) {
3838: // first check for un-paid orders
3839: Timestamp orderDate = orderHeader
3840: .getTimestamp("entryDate");
3841:
3842: // need the store for the order
3843: GenericValue productStore = null;
3844: try {
3845: productStore = orderHeader
3846: .getRelatedOne("ProductStore");
3847: } catch (GenericEntityException e) {
3848: Debug
3849: .logError(
3850: e,
3851: "Unable to get ProductStore from OrderHeader",
3852: module);
3853: }
3854:
3855: // default days to cancel
3856: int daysTillCancel = 30;
3857:
3858: // get the value from the store
3859: if (productStore != null
3860: && productStore.get("daysToCancelNonPay") != null) {
3861: daysTillCancel = productStore.getLong(
3862: "daysToCancelNonPay").intValue();
3863: }
3864:
3865: if (daysTillCancel > 0) {
3866: // 0 days means do not auto-cancel
3867: Calendar cal = Calendar.getInstance();
3868: cal.setTimeInMillis(orderDate.getTime());
3869: cal.add(Calendar.DAY_OF_YEAR, daysTillCancel);
3870: Date cancelDate = cal.getTime();
3871: Date nowDate = new Date();
3872: //Debug.log("Cancel Date : " + cancelDate, module);
3873: //Debug.log("Current Date : " + nowDate, module);
3874: if (cancelDate.equals(nowDate)
3875: || nowDate.after(cancelDate)) {
3876: // cancel the order item(s)
3877: Map svcCtx = UtilMisc.toMap("orderId", orderId,
3878: "statusId", "ITEM_CANCELLED",
3879: "userLogin", userLogin);
3880: try {
3881: // TODO: looks like result is ignored here, but we should be looking for errors
3882: Map ores = dispatcher.runSync(
3883: "changeOrderItemStatus", svcCtx);
3884: } catch (GenericServiceException e) {
3885: Debug.logError(e,
3886: "Problem calling change item status service : "
3887: + svcCtx, module);
3888: }
3889: }
3890: }
3891: } else {
3892: // check for auto-cancel items
3893: List itemsExprs = new ArrayList();
3894:
3895: // create the query expressions
3896: itemsExprs.add(new EntityExpr("orderId",
3897: EntityOperator.EQUALS, orderId));
3898: itemsExprs.add(new EntityConditionList(UtilMisc
3899: .toList(new EntityExpr("statusId",
3900: EntityOperator.EQUALS, "ITEM_CREATED"),
3901: new EntityExpr("statusId",
3902: EntityOperator.EQUALS,
3903: "ITEM_APPROVED")),
3904: EntityOperator.OR));
3905: itemsExprs
3906: .add(new EntityExpr("dontCancelSetUserLogin",
3907: EntityOperator.EQUALS,
3908: GenericEntity.NULL_FIELD));
3909: itemsExprs
3910: .add(new EntityExpr("dontCancelSetDate",
3911: EntityOperator.EQUALS,
3912: GenericEntity.NULL_FIELD));
3913: itemsExprs.add(new EntityExpr("autoCancelDate",
3914: EntityOperator.NOT_EQUAL,
3915: GenericEntity.NULL_FIELD));
3916:
3917: List orderItems = null;
3918: try {
3919: orderItems = delegator.findByAnd("OrderItem",
3920: itemsExprs, null);
3921: } catch (GenericEntityException e) {
3922: Debug.logError(e,
3923: "Problem getting order item records",
3924: module);
3925: }
3926: if (orderItems != null && orderItems.size() > 0) {
3927: Iterator oii = orderItems.iterator();
3928: while (oii.hasNext()) {
3929: GenericValue orderItem = (GenericValue) oii
3930: .next();
3931: String orderItemSeqId = orderItem
3932: .getString("orderItemSeqId");
3933: Timestamp autoCancelDate = orderItem
3934: .getTimestamp("autoCancelDate");
3935:
3936: if (autoCancelDate != null) {
3937: if (nowTimestamp.equals(autoCancelDate)
3938: || nowTimestamp
3939: .after(autoCancelDate)) {
3940: // cancel the order item
3941: Map svcCtx = UtilMisc.toMap("orderId",
3942: orderId, "orderItemSeqId",
3943: orderItemSeqId, "statusId",
3944: "ITEM_CANCELLED", "userLogin",
3945: userLogin);
3946: try {
3947: // TODO: check service result for an error return
3948: Map res = dispatcher.runSync(
3949: "changeOrderItemStatus",
3950: svcCtx);
3951: } catch (GenericServiceException e) {
3952: Debug.logError(e,
3953: "Problem calling change item status service : "
3954: + svcCtx, module);
3955: }
3956: }
3957: }
3958: }
3959: }
3960: }
3961: }
3962: return ServiceUtil.returnSuccess();
3963: }
3964:
3965: public static Map checkDigitalItemFulfillment(DispatchContext dctx,
3966: Map context) {
3967: GenericDelegator delegator = dctx.getDelegator();
3968: LocalDispatcher dispatcher = dctx.getDispatcher();
3969: GenericValue userLogin = (GenericValue) context
3970: .get("userLogin");
3971: String orderId = (String) context.get("orderId");
3972: Locale locale = (Locale) context.get("locale");
3973:
3974: // need the order header
3975: GenericValue orderHeader = null;
3976: try {
3977: orderHeader = delegator.findByPrimaryKey("OrderHeader",
3978: UtilMisc.toMap("orderId", orderId));
3979: } catch (GenericEntityException e) {
3980: Debug.logError(e,
3981: "ERROR: Unable to get OrderHeader for orderId : "
3982: + orderId, module);
3983: return ServiceUtil.returnError(UtilProperties.getMessage(
3984: resource_error,
3985: "OrderErrorUnableToGetOrderHeaderForOrderId",
3986: UtilMisc.toMap("orderId", orderId), locale));
3987: }
3988:
3989: // get all the items for the order
3990: List orderItems = null;
3991: if (orderHeader != null) {
3992: try {
3993: orderItems = orderHeader.getRelated("OrderItem");
3994: } catch (GenericEntityException e) {
3995: Debug.logError(e,
3996: "ERROR: Unable to get OrderItem list for orderId : "
3997: + orderId, module);
3998: return ServiceUtil
3999: .returnError(UtilProperties
4000: .getMessage(
4001: resource_error,
4002: "OrderErrorUnableToGetOrderItemListForOrderId",
4003: UtilMisc.toMap("orderId",
4004: orderId), locale));
4005: }
4006: }
4007:
4008: // find any digital or non-product items
4009: List nonProductItems = new ArrayList();
4010: List digitalItems = new ArrayList();
4011: Map digitalProducts = new HashMap();
4012:
4013: if (orderItems != null && orderItems.size() > 0) {
4014: Iterator i = orderItems.iterator();
4015: while (i.hasNext()) {
4016: GenericValue item = (GenericValue) i.next();
4017: GenericValue product = null;
4018: try {
4019: product = item.getRelatedOne("Product");
4020: } catch (GenericEntityException e) {
4021: Debug
4022: .logError(
4023: e,
4024: "ERROR: Unable to get Product from OrderItem",
4025: module);
4026: }
4027: if (product != null) {
4028: GenericValue productType = null;
4029: try {
4030: productType = product
4031: .getRelatedOne("ProductType");
4032: } catch (GenericEntityException e) {
4033: Debug
4034: .logError(
4035: e,
4036: "ERROR: Unable to get ProductType from Product",
4037: module);
4038: }
4039:
4040: if (productType != null) {
4041: String isPhysical = productType
4042: .getString("isPhysical");
4043: String isDigital = productType
4044: .getString("isDigital");
4045:
4046: // check for digital and finished/digital goods
4047: if (isDigital != null
4048: && "Y".equalsIgnoreCase(isDigital)) {
4049: // we only invoice APPROVED items
4050: if ("ITEM_APPROVED".equals(item
4051: .getString("statusId"))) {
4052: digitalItems.add(item);
4053: }
4054: if (isPhysical == null
4055: || !"Y"
4056: .equalsIgnoreCase(isPhysical)) {
4057: // 100% digital goods need status change
4058: digitalProducts.put(item, product);
4059: }
4060: }
4061: }
4062: } else {
4063: String itemType = item.getString("orderItemTypeId");
4064: if (!"PRODUCT_ORDER_ITEM".equals(itemType)) {
4065: nonProductItems.add(item);
4066: }
4067: }
4068: }
4069: }
4070:
4071: // now process the digital items
4072: if (digitalItems.size() > 0 || nonProductItems.size() > 0) {
4073: GenericValue productStore = OrderReadHelper
4074: .getProductStoreFromOrder(
4075: dispatcher.getDelegator(), orderId);
4076: boolean invoiceItems = true;
4077: if (productStore != null
4078: && productStore.get("autoInvoiceDigitalItems") != null) {
4079: invoiceItems = "Y".equalsIgnoreCase(productStore
4080: .getString("autoInvoiceDigitalItems"));
4081: }
4082:
4083: // single list with all invoice items
4084: List itemsToInvoice = FastList.newInstance();
4085: itemsToInvoice.addAll(nonProductItems);
4086: itemsToInvoice.addAll(digitalItems);
4087:
4088: if (invoiceItems) {
4089: // invoice all APPROVED digital/non-product goods
4090:
4091: // do something tricky here: run as a different user that can actually create an invoice, post transaction, etc
4092: Map invoiceResult = null;
4093: try {
4094: GenericValue permUserLogin = delegator
4095: .findByPrimaryKey("UserLogin", UtilMisc
4096: .toMap("userLoginId", "system"));
4097: Map invoiceContext = UtilMisc.toMap("orderId",
4098: orderId, "billItems", itemsToInvoice,
4099: "userLogin", permUserLogin);
4100: invoiceResult = dispatcher.runSync(
4101: "createInvoiceForOrder", invoiceContext);
4102: } catch (GenericEntityException e) {
4103: Debug.logError(e,
4104: "ERROR: Unable to invoice digital items",
4105: module);
4106: return ServiceUtil
4107: .returnError(UtilProperties
4108: .getMessage(
4109: resource_error,
4110: "OrderProblemWithInvoiceCreationDigitalItemsNotFulfilled",
4111: locale));
4112: } catch (GenericServiceException e) {
4113: Debug.logError(e,
4114: "ERROR: Unable to invoice digital items",
4115: module);
4116: return ServiceUtil
4117: .returnError(UtilProperties
4118: .getMessage(
4119: resource_error,
4120: "OrderProblemWithInvoiceCreationDigitalItemsNotFulfilled",
4121: locale));
4122: }
4123: if (ModelService.RESPOND_ERROR.equals(invoiceResult
4124: .get(ModelService.RESPONSE_MESSAGE))) {
4125: return ServiceUtil
4126: .returnError((String) invoiceResult
4127: .get(ModelService.ERROR_MESSAGE));
4128: }
4129:
4130: // update the status of digital goods to COMPLETED; leave physical/digital as APPROVED for pick/ship
4131: Iterator dii = itemsToInvoice.iterator();
4132: while (dii.hasNext()) {
4133: GenericValue productType = null;
4134: GenericValue item = (GenericValue) dii.next();
4135: GenericValue product = (GenericValue) digitalProducts
4136: .get(item);
4137: boolean markComplete = false;
4138:
4139: if (product != null) {
4140: try {
4141: productType = product
4142: .getRelatedOne("ProductType");
4143: } catch (GenericEntityException e) {
4144: Debug
4145: .logError(
4146: e,
4147: "ERROR: Unable to get ProductType from Product",
4148: module);
4149: }
4150: } else {
4151: String itemType = item
4152: .getString("orderItemTypeId");
4153: if (!"PRODUCT_ORDER_ITEM".equals(itemType)) {
4154: markComplete = true;
4155: }
4156: }
4157:
4158: if (product != null && productType != null) {
4159: String isPhysical = productType
4160: .getString("isPhysical");
4161: String isDigital = productType
4162: .getString("isDigital");
4163:
4164: // we were set as a digital good; one more check and change status
4165: if ((isDigital != null && "Y"
4166: .equalsIgnoreCase(isDigital))
4167: && (isPhysical == null || !"Y"
4168: .equalsIgnoreCase(isPhysical))) {
4169: markComplete = true;
4170: }
4171: }
4172:
4173: if (markComplete) {
4174: Map statusCtx = new HashMap();
4175: statusCtx.put("orderId", item
4176: .getString("orderId"));
4177: statusCtx.put("orderItemSeqId", item
4178: .getString("orderItemSeqId"));
4179: statusCtx.put("statusId", "ITEM_COMPLETED");
4180: statusCtx.put("userLogin", userLogin);
4181: try {
4182: dispatcher.runSyncIgnore(
4183: "changeOrderItemStatus", statusCtx);
4184: } catch (GenericServiceException e) {
4185: Debug.logError(e,
4186: "ERROR: Problem setting the status to COMPLETED : "
4187: + item, module);
4188: }
4189: }
4190: }
4191: }
4192:
4193: // fulfill the digital goods
4194: Map fulfillContext = UtilMisc.toMap("orderId", orderId,
4195: "orderItems", digitalItems, "userLogin", userLogin);
4196: Map fulfillResult = null;
4197: try {
4198: // will be running in an isolated transaction to prevent rollbacks
4199: fulfillResult = dispatcher.runSync(
4200: "fulfillDigitalItems", fulfillContext, 300,
4201: true);
4202: } catch (GenericServiceException e) {
4203: Debug.logError(e,
4204: "ERROR: Unable to fulfill digital items",
4205: module);
4206: }
4207: if (ModelService.RESPOND_ERROR.equals(fulfillResult
4208: .get(ModelService.RESPONSE_MESSAGE))) {
4209: // this service cannot return error at this point or we will roll back the invoice
4210: // since payments are already captured; errors should have been logged already.
4211: // the response message here will be passed as an error to the user.
4212: return ServiceUtil.returnSuccess((String) fulfillResult
4213: .get(ModelService.ERROR_MESSAGE));
4214: }
4215: }
4216:
4217: return ServiceUtil.returnSuccess();
4218: }
4219:
4220: public static Map fulfillDigitalItems(DispatchContext ctx,
4221: Map context) {
4222: GenericDelegator delegator = ctx.getDelegator();
4223: LocalDispatcher dispatcher = ctx.getDispatcher();
4224: //appears to not be used: String orderId = (String) context.get("orderId");
4225: List orderItems = (List) context.get("orderItems");
4226: GenericValue userLogin = (GenericValue) context
4227: .get("userLogin");
4228: Locale locale = (Locale) context.get("locale");
4229:
4230: if (orderItems != null && orderItems.size() > 0) {
4231: // loop through the digital items to fulfill
4232: Iterator itemsIterator = orderItems.iterator();
4233: while (itemsIterator.hasNext()) {
4234: GenericValue orderItem = (GenericValue) itemsIterator
4235: .next();
4236:
4237: // make sure we have a valid item
4238: if (orderItem == null) {
4239: return ServiceUtil
4240: .returnError(UtilProperties
4241: .getMessage(
4242: resource_error,
4243: "OrderErrorCannotCheckForFulfillmentItemNotFound",
4244: locale));
4245: }
4246:
4247: // locate the Product & ProductContent records
4248: GenericValue product = null;
4249: List productContent = null;
4250: try {
4251: product = orderItem.getRelatedOne("Product");
4252: if (product == null) {
4253: return ServiceUtil
4254: .returnError(UtilProperties
4255: .getMessage(
4256: resource_error,
4257: "OrderErrorCannotCheckForFulfillmentProductNotFound",
4258: locale));
4259: }
4260:
4261: List allProductContent = product
4262: .getRelated("ProductContent");
4263:
4264: // try looking up the parent product if the product has no content and is a variant
4265: if (((allProductContent == null) || allProductContent
4266: .size() == 0)
4267: && ("Y".equals(product
4268: .getString("isVariant")))) {
4269: GenericValue parentProduct = ProductWorker
4270: .getParentProduct(product
4271: .getString("productId"),
4272: delegator);
4273: if (allProductContent == null) {
4274: allProductContent = FastList.newInstance();
4275: }
4276: if (parentProduct != null) {
4277: allProductContent.addAll(parentProduct
4278: .getRelated("ProductContent"));
4279: }
4280: }
4281:
4282: if (allProductContent != null
4283: && allProductContent.size() > 0) {
4284: // only keep ones with valid dates
4285: productContent = EntityUtil.filterByDate(
4286: allProductContent, UtilDateTime
4287: .nowTimestamp(), "fromDate",
4288: "thruDate", true);
4289: Debug.logInfo("Product has "
4290: + allProductContent.size()
4291: + " associations, "
4292: + (productContent == null ? "0" : ""
4293: + productContent.size())
4294: + " has valid from/thru dates", module);
4295: }
4296: } catch (GenericEntityException e) {
4297: return ServiceUtil.returnError(UtilProperties
4298: .getMessage(resource_error,
4299: "OrderErrorCannotGetProductEntity",
4300: locale)
4301: + e.getMessage());
4302: }
4303:
4304: // now use the ProductContent to fulfill the item
4305: if (productContent != null && productContent.size() > 0) {
4306: Iterator prodcontentIterator = productContent
4307: .iterator();
4308: while (prodcontentIterator.hasNext()) {
4309: GenericValue productContentItem = (GenericValue) prodcontentIterator
4310: .next();
4311: GenericValue content = null;
4312: try {
4313: content = productContentItem
4314: .getRelatedOne("Content");
4315: } catch (GenericEntityException e) {
4316: Debug.logError(e,
4317: "ERROR: Cannot get Content entity: "
4318: + e.getMessage(), module);
4319: continue;
4320: }
4321:
4322: String fulfillmentType = productContentItem
4323: .getString("productContentTypeId");
4324: if ("FULFILLMENT_EXTASYNC"
4325: .equals(fulfillmentType)
4326: || "FULFILLMENT_EXTSYNC"
4327: .equals(fulfillmentType)) {
4328: // enternal service fulfillment
4329: String fulfillmentService = (String) content
4330: .get("serviceName");
4331: if (fulfillmentService == null) {
4332: Debug
4333: .logError(
4334: "ProductContent of type FULFILLMENT_EXTERNAL had Content with empty serviceName, can not run fulfillment",
4335: module);
4336: }
4337: Map serviceCtx = UtilMisc.toMap(
4338: "userLogin", userLogin,
4339: "orderItem", orderItem);
4340: serviceCtx.putAll(productContentItem
4341: .getPrimaryKey());
4342: try {
4343: Debug.logInfo(
4344: "Running external fulfillment '"
4345: + fulfillmentService
4346: + "'", module);
4347: if ("FULFILLMENT_EXTASYNC"
4348: .equals(fulfillmentType)) {
4349: dispatcher.runAsync(
4350: fulfillmentService,
4351: serviceCtx, true);
4352: } else if ("FULFILLMENT_EXTSYNC"
4353: .equals(fulfillmentType)) {
4354: Map resp = dispatcher.runSync(
4355: fulfillmentService,
4356: serviceCtx);
4357: if (ServiceUtil.isError(resp)) {
4358: return ServiceUtil
4359: .returnError(ServiceUtil
4360: .getErrorMessage(resp));
4361: }
4362: }
4363: } catch (GenericServiceException e) {
4364: Debug.logError(e,
4365: "ERROR: Could not run external fulfillment service '"
4366: + fulfillmentService
4367: + "'; "
4368: + e.getMessage(),
4369: module);
4370: }
4371: } else if ("FULFILLMENT_EMAIL"
4372: .equals(fulfillmentType)) {
4373: // digital email fulfillment
4374: // TODO: Add support for fulfillment email
4375: return ServiceUtil
4376: .returnError(UtilProperties
4377: .getMessage(
4378: resource_error,
4379: "OrderEmailFulfillmentTypeNotYetImplemented",
4380: locale));
4381: } else if ("DIGITAL_DOWNLOAD"
4382: .equals(fulfillmentType)) {
4383: // digital download fulfillment
4384:
4385: // Nothing to do for here. Downloads are made available to the user
4386: // though a query of OrderItems with related ProductContent.
4387: } else {
4388: Debug
4389: .logError(
4390: "Invalid fulfillment type : "
4391: + fulfillmentType
4392: + " not supported.",
4393: module);
4394: }
4395: }
4396: }
4397: }
4398: }
4399: return ServiceUtil.returnSuccess();
4400: }
4401:
4402: public static Map addItemToApprovedOrder(DispatchContext dctx,
4403: Map context) {
4404: LocalDispatcher dispatcher = dctx.getDispatcher();
4405: GenericDelegator delegator = dctx.getDelegator();
4406: GenericValue userLogin = (GenericValue) context
4407: .get("userLogin");
4408: Locale locale = (Locale) context.get("locale");
4409: String shipGroupSeqId = (String) context.get("shipGroupSeqId");
4410: String orderId = (String) context.get("orderId");
4411: String productId = (String) context.get("productId");
4412: String prodCatalogId = (String) context.get("prodCatalogId");
4413: BigDecimal basePrice = (BigDecimal) context.get("basePrice");
4414: Double quantity = (Double) context.get("quantity");
4415: Double amount = (Double) context.get("amount");
4416: String overridePrice = (String) context.get("overridePrice");
4417:
4418: if (amount == null) {
4419: amount = new Double(0.00);
4420: }
4421:
4422: int shipGroupIdx = -1;
4423: try {
4424: shipGroupIdx = Integer.parseInt(shipGroupSeqId);
4425: shipGroupIdx--;
4426: } catch (NumberFormatException e) {
4427: Debug.logError(e, module);
4428: return ServiceUtil.returnError(e.getMessage());
4429: }
4430: if (shipGroupIdx < 0) {
4431: return ServiceUtil.returnError("Invalid shipGroupSeqId ["
4432: + shipGroupSeqId + "]");
4433: }
4434:
4435: // obtain a shopping cart object for updating
4436: ShoppingCart cart = null;
4437: try {
4438: cart = loadCartForUpdate(dispatcher, delegator, userLogin,
4439: orderId);
4440: } catch (GeneralException e) {
4441: return ServiceUtil.returnError(e.getMessage());
4442: }
4443: if (cart == null) {
4444: return ServiceUtil
4445: .returnError("ERROR: Null shopping cart object returned!");
4446: }
4447:
4448: // add in the new product
4449: try {
4450: ShoppingCartItem item = ShoppingCartItem.makeItem(null,
4451: productId, null, quantity.doubleValue(), null,
4452: null, null, null, null, null, null, null,
4453: prodCatalogId, null, null, null, dispatcher, cart,
4454: null, null, null, Boolean.FALSE, Boolean.FALSE);
4455: if (basePrice != null && overridePrice != null) {
4456: item.setBasePrice(basePrice.doubleValue());
4457: // special hack to make sure we re-calc the promos after a price change
4458: item.setQuantity(quantity.doubleValue() + 1,
4459: dispatcher, cart, false);
4460: item.setQuantity(quantity.doubleValue(), dispatcher,
4461: cart, false);
4462: item.setBasePrice(basePrice.doubleValue());
4463: item.setIsModifiedPrice(true);
4464: }
4465:
4466: // set the item in the selected ship group
4467: cart.setItemShipGroupQty(item, item.getQuantity(),
4468: shipGroupIdx);
4469: } catch (CartItemModifyException e) {
4470: Debug.logError(e, module);
4471: return ServiceUtil.returnError(e.getMessage());
4472: } catch (ItemNotFoundException e) {
4473: Debug.logError(e, module);
4474: return ServiceUtil.returnError(e.getMessage());
4475: }
4476:
4477: // save all the updated information
4478: try {
4479: saveUpdatedCartToOrder(dispatcher, delegator, cart, locale,
4480: userLogin, orderId);
4481: } catch (GeneralException e) {
4482: return ServiceUtil.returnError(e.getMessage());
4483: }
4484:
4485: // log an order note
4486: try {
4487: dispatcher.runSync("createOrderNote", UtilMisc.toMap(
4488: "orderId", orderId, "note", "Added item to order: "
4489: + productId + " (" + quantity + ")",
4490: "internalNote", "Y", "userLogin", userLogin));
4491: } catch (GenericServiceException e) {
4492: Debug.logError(e, module);
4493: }
4494:
4495: Map result = ServiceUtil.returnSuccess();
4496: result.put("shoppingCart", cart);
4497: result.put("orderId", orderId);
4498: return result;
4499: }
4500:
4501: public static Map updateApprovedOrderItems(DispatchContext dctx,
4502: Map context) {
4503: LocalDispatcher dispatcher = dctx.getDispatcher();
4504: GenericDelegator delegator = dctx.getDelegator();
4505: GenericValue userLogin = (GenericValue) context
4506: .get("userLogin");
4507: Locale locale = (Locale) context.get("locale");
4508: String orderId = (String) context.get("orderId");
4509: Map overridePriceMap = (Map) context.get("overridePriceMap");
4510: Map itemDescriptionMap = (Map) context
4511: .get("itemDescriptionMap");
4512: Map itemPriceMap = (Map) context.get("itemPriceMap");
4513: Map itemQtyMap = (Map) context.get("itemQtyMap");
4514:
4515: // obtain a shopping cart object for updating
4516: ShoppingCart cart = null;
4517: try {
4518: cart = loadCartForUpdate(dispatcher, delegator, userLogin,
4519: orderId);
4520: } catch (GeneralException e) {
4521: return ServiceUtil.returnError(e.getMessage());
4522: }
4523: if (cart == null) {
4524: return ServiceUtil
4525: .returnError("ERROR: Null shopping cart object returned!");
4526: }
4527:
4528: // go through the item map and obtain the totals per item
4529: Map itemTotals = new HashMap();
4530: Iterator i = itemQtyMap.keySet().iterator();
4531: while (i.hasNext()) {
4532: String key = (String) i.next();
4533: String quantityStr = (String) itemQtyMap.get(key);
4534: double groupQty = 0.0;
4535: try {
4536: groupQty = Double.parseDouble(quantityStr);
4537: } catch (NumberFormatException e) {
4538: Debug.logError(e, module);
4539: return ServiceUtil.returnError(e.getMessage());
4540: }
4541:
4542: if (groupQty == 0) {
4543: return ServiceUtil
4544: .returnError("Quantity must be >0, use cancel item to cancel completely!");
4545: }
4546:
4547: String[] itemInfo = key.split(":");
4548: Double tally = (Double) itemTotals.get(itemInfo[0]);
4549: if (tally == null) {
4550: tally = new Double(groupQty);
4551: } else {
4552: tally = new Double(tally.doubleValue() + groupQty);
4553: }
4554: itemTotals.put(itemInfo[0], tally);
4555: }
4556:
4557: // set the items amount/price
4558: Iterator iai = itemTotals.keySet().iterator();
4559: while (iai.hasNext()) {
4560: String itemSeqId = (String) iai.next();
4561: ShoppingCartItem cartItem = cart.findCartItem(itemSeqId);
4562:
4563: if (cartItem != null) {
4564: Double qty = (Double) itemTotals.get(itemSeqId);
4565: double priceSave = cartItem.getBasePrice();
4566:
4567: // set quantity
4568: try {
4569: cartItem.setQuantity(qty.doubleValue(), dispatcher,
4570: cart, true, false); // trigger external ops, don't reset ship groups (and update prices for both PO and SO items)
4571: } catch (CartItemModifyException e) {
4572: Debug.logError(e, module);
4573: return ServiceUtil.returnError(e.getMessage());
4574: }
4575: Debug.log("Set item quantity: [" + itemSeqId + "] "
4576: + qty, module);
4577:
4578: if (cartItem.getIsModifiedPrice()) // set price
4579: cartItem.setBasePrice(priceSave);
4580:
4581: if (overridePriceMap.containsKey(itemSeqId)) {
4582: String priceStr = (String) itemPriceMap
4583: .get(itemSeqId);
4584: if (UtilValidate.isNotEmpty(priceStr)) {
4585: double price = -1;
4586: //parse the price
4587: NumberFormat nf = null;
4588: if (locale != null) {
4589: nf = NumberFormat.getNumberInstance(locale);
4590: } else {
4591: nf = NumberFormat.getNumberInstance();
4592: }
4593: try {
4594: price = nf.parse(priceStr).doubleValue();
4595: } catch (ParseException e) {
4596: Debug.logError(e, module);
4597: return ServiceUtil.returnError(e
4598: .getMessage());
4599: }
4600: cartItem.setBasePrice(price);
4601: cartItem.setIsModifiedPrice(true);
4602: Debug.log("Set item price: [" + itemSeqId
4603: + "] " + price, module);
4604: }
4605:
4606: }
4607:
4608: // Update the item description
4609: if (itemDescriptionMap != null
4610: && itemDescriptionMap.containsKey(itemSeqId)) {
4611: String description = (String) itemDescriptionMap
4612: .get(itemSeqId);
4613: if (UtilValidate.isNotEmpty(description)) {
4614: cartItem.setName(description);
4615: Debug.log("Set item description: [" + itemSeqId
4616: + "] " + description, module);
4617: } else {
4618: return ServiceUtil
4619: .returnError("Item description must not be empty");
4620: }
4621: }
4622: } else {
4623: Debug.logInfo(
4624: "Unable to locate shopping cart item for seqId #"
4625: + itemSeqId, module);
4626: }
4627: }
4628:
4629: // update the group amounts
4630: Iterator gai = itemQtyMap.keySet().iterator();
4631: while (gai.hasNext()) {
4632: String key = (String) gai.next();
4633: String quantityStr = (String) itemQtyMap.get(key);
4634: double groupQty = 0.0;
4635: try {
4636: groupQty = Double.parseDouble(quantityStr);
4637: } catch (NumberFormatException e) {
4638: Debug.logError(e, module);
4639: return ServiceUtil.returnError(e.getMessage());
4640: }
4641:
4642: String[] itemInfo = key.split(":");
4643: int groupIdx = -1;
4644: try {
4645: groupIdx = Integer.parseInt(itemInfo[1]);
4646: } catch (NumberFormatException e) {
4647: Debug.logError(e, module);
4648: return ServiceUtil.returnError(e.getMessage());
4649: }
4650:
4651: // set the group qty
4652: ShoppingCartItem cartItem = cart.findCartItem(itemInfo[0]);
4653: if (cartItem != null) {
4654: Debug.log("Shipping info (before) for group #"
4655: + (groupIdx - 1) + " ["
4656: + cart.getShipmentMethodTypeId(groupIdx - 1)
4657: + " / " + cart.getCarrierPartyId(groupIdx - 1)
4658: + "]", module);
4659: cart.setItemShipGroupQty(cartItem, groupQty,
4660: groupIdx - 1);
4661: Debug.log("Set ship group qty: [" + itemInfo[0] + " / "
4662: + itemInfo[1] + " (" + (groupIdx - 1) + ")] "
4663: + groupQty, module);
4664: Debug.log("Shipping info (after) for group #"
4665: + (groupIdx - 1) + " ["
4666: + cart.getShipmentMethodTypeId(groupIdx - 1)
4667: + " / " + cart.getCarrierPartyId(groupIdx - 1)
4668: + "]", module);
4669: }
4670: }
4671:
4672: // save all the updated information
4673: try {
4674: saveUpdatedCartToOrder(dispatcher, delegator, cart, locale,
4675: userLogin, orderId);
4676: } catch (GeneralException e) {
4677: return ServiceUtil.returnError(e.getMessage());
4678: }
4679:
4680: // log an order note
4681: try {
4682: dispatcher.runSync("createOrderNote", UtilMisc.toMap(
4683: "orderId", orderId, "note", "Updated order.",
4684: "internalNote", "Y", "userLogin", userLogin));
4685: } catch (GenericServiceException e) {
4686: Debug.logError(e, module);
4687: }
4688:
4689: Map result = ServiceUtil.returnSuccess();
4690: result.put("shoppingCart", cart);
4691: result.put("orderId", orderId);
4692: return result;
4693: }
4694:
4695: /*
4696: * Warning: this method will remove all the existing reservations of the order
4697: * before returning the ShoppingCart object; for this reason, the cart
4698: * must be stored back using the method saveUpdatedCartToOrder(...).
4699: */
4700: private static ShoppingCart loadCartForUpdate(
4701: LocalDispatcher dispatcher, GenericDelegator delegator,
4702: GenericValue userLogin, String orderId)
4703: throws GeneralException {
4704: // find ship group associations
4705: List shipGroupAssocs = null;
4706: try {
4707: shipGroupAssocs = delegator.findByAnd(
4708: "OrderItemShipGroupAssoc", UtilMisc.toMap(
4709: "orderId", orderId));
4710: } catch (GenericEntityException e) {
4711: Debug.logError(e, module);
4712: throw new GeneralException(e.getMessage());
4713: }
4714:
4715: // cancel existing inventory reservations
4716: if (shipGroupAssocs != null) {
4717: Iterator iri = shipGroupAssocs.iterator();
4718: while (iri.hasNext()) {
4719: GenericValue shipGroupAssoc = (GenericValue) iri.next();
4720: String orderItemSeqId = shipGroupAssoc
4721: .getString("orderItemSeqId");
4722: String shipGroupSeqId = shipGroupAssoc
4723: .getString("shipGroupSeqId");
4724:
4725: Map cancelCtx = UtilMisc.toMap("userLogin", userLogin,
4726: "orderId", orderId);
4727: cancelCtx.put("orderItemSeqId", orderItemSeqId);
4728: cancelCtx.put("shipGroupSeqId", shipGroupSeqId);
4729:
4730: Map cancelResp = null;
4731: try {
4732: cancelResp = dispatcher.runSync(
4733: "cancelOrderInventoryReservation",
4734: cancelCtx);
4735: } catch (GenericServiceException e) {
4736: Debug.logError(e, module);
4737: throw new GeneralException(e.getMessage());
4738: }
4739: if (ServiceUtil.isError(cancelResp)) {
4740: throw new GeneralException(ServiceUtil
4741: .getErrorMessage(cancelResp));
4742: }
4743: }
4744: }
4745:
4746: // load the order into a shopping cart
4747: Map loadCartResp = null;
4748: try {
4749: loadCartResp = dispatcher.runSync("loadCartFromOrder",
4750: UtilMisc.toMap("orderId", orderId,
4751: "skipInventoryChecks", Boolean.TRUE,
4752: "skipProductChecks", Boolean.TRUE,
4753: "userLogin", userLogin));
4754: } catch (GenericServiceException e) {
4755: Debug.logError(e, module);
4756: throw new GeneralException(e.getMessage());
4757: }
4758: if (ServiceUtil.isError(loadCartResp)) {
4759: throw new GeneralException(ServiceUtil
4760: .getErrorMessage(loadCartResp));
4761: }
4762:
4763: ShoppingCart cart = (ShoppingCart) loadCartResp
4764: .get("shoppingCart");
4765: if (cart == null) {
4766: throw new GeneralException(
4767: "Error loading shopping cart from order ["
4768: + orderId + "]");
4769: } else {
4770: cart.setOrderId(orderId);
4771: }
4772:
4773: return cart;
4774: }
4775:
4776: private static void saveUpdatedCartToOrder(
4777: LocalDispatcher dispatcher, GenericDelegator delegator,
4778: ShoppingCart cart, Locale locale, GenericValue userLogin,
4779: String orderId) throws GeneralException {
4780: // get/set the shipping estimates. if it's a SALES ORDER, then return an error if there are no ship estimates
4781: int shipGroups = cart.getShipGroupSize();
4782: for (int gi = 0; gi < shipGroups; gi++) {
4783: String shipmentMethodTypeId = cart
4784: .getShipmentMethodTypeId(gi);
4785: String carrierPartyId = cart.getCarrierPartyId(gi);
4786: Debug.log("Getting ship estimate for group #" + gi + " ["
4787: + shipmentMethodTypeId + " / " + carrierPartyId
4788: + "]", module);
4789: Map result = ShippingEvents.getShipGroupEstimate(
4790: dispatcher, delegator, cart, gi);
4791: if (("SALES_ORDER".equals(cart.getOrderType()))
4792: && (ServiceUtil.isError(result))) {
4793: Debug.logError(ServiceUtil.getErrorMessage(result),
4794: module);
4795: throw new GeneralException(ServiceUtil
4796: .getErrorMessage(result));
4797: }
4798:
4799: Double shippingTotal = (Double) result.get("shippingTotal");
4800: if (shippingTotal == null) {
4801: shippingTotal = new Double(0.00);
4802: }
4803: cart.setItemShipGroupEstimate(shippingTotal.doubleValue(),
4804: gi);
4805: }
4806:
4807: // calc the sales tax
4808: CheckOutHelper coh = new CheckOutHelper(dispatcher, delegator,
4809: cart);
4810: try {
4811: coh.calcAndAddTax();
4812: } catch (GeneralException e) {
4813: Debug.logError(e, module);
4814: throw new GeneralException(e.getMessage());
4815: }
4816:
4817: // validate the payment methods
4818: Map validateResp = coh.validatePaymentMethods();
4819: if (ServiceUtil.isError(validateResp)) {
4820: throw new GeneralException(ServiceUtil
4821: .getErrorMessage(validateResp));
4822: }
4823:
4824: // get the new orderItems, adjustments, shipping info and payments from the cart
4825: List toStore = new LinkedList();
4826: toStore.addAll(cart.makeOrderItems());
4827: toStore.addAll(cart.makeAllAdjustments());
4828: toStore.addAll(cart.makeAllShipGroupInfos());
4829: toStore.addAll(cart.makeAllOrderPaymentInfos(dispatcher));
4830:
4831: // set the orderId & other information on all new value objects
4832: List dropShipGroupIds = FastList.newInstance(); // this list will contain the ids of all the ship groups for drop shipments (no reservations)
4833: Iterator tsi = toStore.iterator();
4834: while (tsi.hasNext()) {
4835: GenericValue valueObj = (GenericValue) tsi.next();
4836: valueObj.set("orderId", orderId);
4837: if ("OrderItemShipGroup".equals(valueObj.getEntityName())) {
4838: // ship group
4839: if (valueObj.get("carrierRoleTypeId") == null) {
4840: valueObj.set("carrierRoleTypeId", "CARRIER");
4841: }
4842: if (!UtilValidate.isEmpty(valueObj
4843: .get("supplierPartyId"))) {
4844: dropShipGroupIds.add(valueObj
4845: .getString("shipGroupSeqId"));
4846: }
4847: } else if ("OrderAdjustment".equals(valueObj
4848: .getEntityName())) {
4849: // shipping / tax adjustment(s)
4850: if (valueObj.get("orderItemSeqId") == null
4851: || valueObj.getString("orderItemSeqId")
4852: .length() == 0) {
4853: valueObj.set("orderItemSeqId",
4854: DataModelConstants.SEQ_ID_NA);
4855: }
4856: valueObj.set("orderAdjustmentId", delegator
4857: .getNextSeqId("OrderAdjustment"));
4858: valueObj
4859: .set("createdDate", UtilDateTime.nowTimestamp());
4860: valueObj.set("createdByUserLogin", userLogin
4861: .getString("userLoginId"));
4862: } else if ("OrderPaymentPreference".equals(valueObj
4863: .getEntityName())) {
4864: if (valueObj.get("orderPaymentPreferenceId") == null) {
4865: valueObj.set("orderPaymentPreferenceId", delegator
4866: .getNextSeqId("OrderPaymentPreference"));
4867: valueObj.set("createdDate", UtilDateTime
4868: .nowTimestamp());
4869: valueObj.set("createdByUserLogin", userLogin
4870: .getString("userLoginId"));
4871: }
4872: if (valueObj.get("statusId") == null) {
4873: valueObj.set("statusId", "PAYMENT_NOT_RECEIVED");
4874: }
4875: }
4876: }
4877: Debug.log("To Store Contains: " + toStore, module);
4878:
4879: // cancel promo items -- if the promo still qualifies it will be added by the cart
4880: List promoItems = null;
4881: try {
4882: promoItems = delegator.findByAnd("OrderItem", UtilMisc
4883: .toMap("orderId", orderId, "isPromo", "Y"));
4884: } catch (GenericEntityException e) {
4885: Debug.logError(e, module);
4886: throw new GeneralException(e.getMessage());
4887: }
4888: if (promoItems != null) {
4889: Iterator pii = promoItems.iterator();
4890: while (pii.hasNext()) {
4891: GenericValue promoItem = (GenericValue) pii.next();
4892: // Skip if the promo is already cancelled
4893: if ("ITEM_CANCELLED".equals(promoItem.get("statusId"))) {
4894: continue;
4895: }
4896: Map cancelPromoCtx = UtilMisc.toMap("orderId", orderId);
4897: cancelPromoCtx.put("orderItemSeqId", promoItem
4898: .getString("orderItemSeqId"));
4899: cancelPromoCtx.put("userLogin", userLogin);
4900: Map cancelResp = null;
4901: try {
4902: cancelResp = dispatcher.runSync(
4903: "cancelOrderItemNoActions", cancelPromoCtx);
4904: } catch (GenericServiceException e) {
4905: Debug.logError(e, module);
4906: throw new GeneralException(e.getMessage());
4907: }
4908: if (ServiceUtil.isError(cancelResp)) {
4909: throw new GeneralException(ServiceUtil
4910: .getErrorMessage(cancelResp));
4911: }
4912: }
4913: }
4914:
4915: // cancel exiting authorizations
4916: Map releaseResp = null;
4917: try {
4918: releaseResp = dispatcher.runSync("releaseOrderPayments",
4919: UtilMisc.toMap("orderId", orderId, "userLogin",
4920: userLogin));
4921: } catch (GenericServiceException e) {
4922: Debug.logError(e, module);
4923: throw new GeneralException(e.getMessage());
4924: }
4925: if (ServiceUtil.isError(releaseResp)) {
4926: throw new GeneralException(ServiceUtil
4927: .getErrorMessage(releaseResp));
4928: }
4929:
4930: // cancel other (non-completed and non-cancelled) payments
4931: List paymentPrefsToCancel = null;
4932: try {
4933: List exprs = UtilMisc.toList(new EntityExpr("orderId",
4934: EntityOperator.EQUALS, orderId));
4935: exprs.add(new EntityExpr("statusId",
4936: EntityOperator.NOT_EQUAL, "PAYMENT_RECEIVED"));
4937: exprs.add(new EntityExpr("statusId",
4938: EntityOperator.NOT_EQUAL, "PAYMENT_CANCELLED"));
4939: exprs.add(new EntityExpr("statusId",
4940: EntityOperator.NOT_EQUAL, "PAYMENT_DECLINED"));
4941: exprs.add(new EntityExpr("statusId",
4942: EntityOperator.NOT_EQUAL, "PAYMENT_SETTLED"));
4943: EntityCondition cond = new EntityConditionList(exprs,
4944: EntityOperator.AND);
4945: paymentPrefsToCancel = delegator.findByCondition(
4946: "OrderPaymentPreference", cond, null, null);
4947: } catch (GenericEntityException e) {
4948: Debug.logError(e, module);
4949: throw new GeneralException(e.getMessage());
4950: }
4951: if (paymentPrefsToCancel != null) {
4952: Iterator oppi = paymentPrefsToCancel.iterator();
4953: while (oppi.hasNext()) {
4954: GenericValue opp = (GenericValue) oppi.next();
4955: try {
4956: opp.set("statusId", "PAYMENT_CANCELLED");
4957: opp.store();
4958: } catch (GenericEntityException e) {
4959: Debug.logError(e, module);
4960: throw new GeneralException(e.getMessage());
4961: }
4962: }
4963: }
4964:
4965: // remove the adjustments
4966: try {
4967: List adjExprs = new LinkedList();
4968: adjExprs.add(new EntityExpr("orderId",
4969: EntityOperator.EQUALS, orderId));
4970: List exprs = new LinkedList();
4971: exprs.add(new EntityExpr("orderAdjustmentTypeId",
4972: EntityOperator.EQUALS, "PROMOTION_ADJUSTMENT"));
4973: exprs.add(new EntityExpr("orderAdjustmentTypeId",
4974: EntityOperator.EQUALS, "SHIPPING_CHARGES"));
4975: exprs.add(new EntityExpr("orderAdjustmentTypeId",
4976: EntityOperator.EQUALS, "SALES_TAX"));
4977: adjExprs.add(new EntityConditionList(exprs,
4978: EntityOperator.OR));
4979: EntityCondition cond = new EntityConditionList(adjExprs,
4980: EntityOperator.AND);
4981: delegator.removeByCondition("OrderAdjustment", cond);
4982: } catch (GenericEntityException e) {
4983: Debug.logError(e, module);
4984: throw new GeneralException(e.getMessage());
4985: }
4986:
4987: // store the new items/adjustments
4988: try {
4989: delegator.storeAll(toStore);
4990: } catch (GenericEntityException e) {
4991: Debug.logError(e, module);
4992: throw new GeneralException(e.getMessage());
4993: }
4994:
4995: // make the order item object map & the ship group assoc list
4996: List orderItemShipGroupAssoc = new LinkedList();
4997: Map itemValuesBySeqId = new HashMap();
4998: Iterator oii = toStore.iterator();
4999: while (oii.hasNext()) {
5000: GenericValue v = (GenericValue) oii.next();
5001: if ("OrderItem".equals(v.getEntityName())) {
5002: itemValuesBySeqId.put(v.getString("orderItemSeqId"), v);
5003: } else if ("OrderItemShipGroupAssoc".equals(v
5004: .getEntityName())) {
5005: orderItemShipGroupAssoc.add(v);
5006: }
5007: }
5008:
5009: // reserve the inventory
5010: String productStoreId = cart.getProductStoreId();
5011: String orderTypeId = cart.getOrderType();
5012: List resErrorMessages = new LinkedList();
5013: try {
5014: Debug.log("Calling reserve inventory...", module);
5015: reserveInventory(delegator, dispatcher, userLogin, locale,
5016: orderItemShipGroupAssoc, dropShipGroupIds,
5017: itemValuesBySeqId, orderTypeId, productStoreId,
5018: resErrorMessages);
5019: } catch (GeneralException e) {
5020: Debug.logError(e, module);
5021: throw new GeneralException(e.getMessage());
5022: }
5023:
5024: if (resErrorMessages.size() > 0) {
5025: throw new GeneralException(ServiceUtil
5026: .getErrorMessage(ServiceUtil
5027: .returnError(resErrorMessages)));
5028: }
5029: }
5030:
5031: public static Map processOrderPayments(DispatchContext dctx,
5032: Map context) {
5033: LocalDispatcher dispatcher = dctx.getDispatcher();
5034: GenericDelegator delegator = dctx.getDelegator();
5035: GenericValue userLogin = (GenericValue) context
5036: .get("userLogin");
5037: ShoppingCart cart = (ShoppingCart) context.get("shoppingCart");
5038: String orderId = (String) context.get("orderId");
5039:
5040: OrderReadHelper orh = new OrderReadHelper(delegator, orderId);
5041: String productStoreId = orh.getProductStoreId();
5042:
5043: if (cart == null) {
5044: // load the order into a shopping cart
5045: Map loadCartResp = null;
5046: try {
5047: loadCartResp = dispatcher.runSync("loadCartFromOrder",
5048: UtilMisc.toMap("orderId", orderId,
5049: "skipInventoryChecks", Boolean.TRUE,
5050: "skipProductChecks", Boolean.TRUE,
5051: "userLogin", userLogin));
5052: } catch (GenericServiceException e) {
5053: return ServiceUtil.returnError(e.getMessage());
5054: }
5055: cart = (ShoppingCart) loadCartResp.get("shoppingCart");
5056:
5057: if (cart == null) {
5058: return ServiceUtil
5059: .returnError("ERROR: Null shopping cart object returned!");
5060: }
5061:
5062: cart.setOrderId(orderId);
5063: }
5064: CheckOutHelper coh = new CheckOutHelper(dispatcher, delegator,
5065: cart);
5066: // process the payments
5067: if (!"PURCHASE_ORDER".equals(cart.getOrderType())) {
5068: GenericValue productStore = ProductStoreWorker
5069: .getProductStore(productStoreId, delegator);
5070: Map paymentResp = null;
5071: try {
5072: Debug.log("Calling process payments...", module);
5073: //Debug.set(Debug.VERBOSE, true);
5074: paymentResp = coh.processPayment(productStore,
5075: userLogin);
5076: //Debug.set(Debug.VERBOSE, false);
5077: } catch (GeneralException e) {
5078: Debug.logError(e, module);
5079: return ServiceUtil.returnError(e.getMessage());
5080: } catch (GeneralRuntimeException e) {
5081: Debug.logError(e, module);
5082: return ServiceUtil.returnError(e.getMessage());
5083: }
5084:
5085: if (ServiceUtil.isError(paymentResp)) {
5086: return ServiceUtil.returnError(ServiceUtil
5087: .getErrorMessage(paymentResp));
5088: }
5089: }
5090: return ServiceUtil.returnSuccess();
5091: }
5092:
5093: // sample test services
5094: public static Map shoppingCartTest(DispatchContext dctx, Map context) {
5095: Locale locale = (Locale) context.get("locale");
5096: ShoppingCart cart = new ShoppingCart(dctx.getDelegator(),
5097: "9000", "webStore", locale, "USD");
5098: try {
5099: cart.addOrIncreaseItem("GZ-1005", null, 1, null, null,
5100: null, null, null, null, null, "DemoCatalog", null,
5101: null, null, null, dctx.getDispatcher());
5102: } catch (CartItemModifyException e) {
5103: Debug.logError(e, module);
5104: } catch (ItemNotFoundException e) {
5105: Debug.logError(e, module);
5106: }
5107:
5108: try {
5109: dctx.getDispatcher().runAsync("shoppingCartRemoteTest",
5110: UtilMisc.toMap("cart", cart), true);
5111: } catch (GenericServiceException e) {
5112: Debug.logError(e, module);
5113: }
5114:
5115: return ServiceUtil.returnSuccess();
5116: }
5117:
5118: public static Map shoppingCartRemoteTest(DispatchContext dctx,
5119: Map context) {
5120: ShoppingCart cart = (ShoppingCart) context.get("cart");
5121: Debug.log(
5122: "Product ID : " + cart.findCartItem(0).getProductId(),
5123: module);
5124: return ServiceUtil.returnSuccess();
5125: }
5126:
5127: /**
5128: * Service to create a payment using an order payment preference.
5129: * @return Map
5130: */
5131: public static Map createPaymentFromPreference(DispatchContext dctx,
5132: Map context) {
5133: GenericDelegator delegator = dctx.getDelegator();
5134: LocalDispatcher dispatcher = dctx.getDispatcher();
5135: GenericValue userLogin = (GenericValue) context
5136: .get("userLogin");
5137:
5138: String orderPaymentPreferenceId = (String) context
5139: .get("orderPaymentPreferenceId");
5140: String paymentRefNum = (String) context.get("paymentRefNum");
5141: String paymentFromId = (String) context.get("paymentFromId");
5142: String comments = (String) context.get("comments");
5143: try {
5144: // get the order payment preference
5145: GenericValue orderPaymentPreference = delegator
5146: .findByPrimaryKey("OrderPaymentPreference",
5147: UtilMisc.toMap("orderPaymentPreferenceId",
5148: orderPaymentPreferenceId));
5149: if (orderPaymentPreference == null) {
5150: return ServiceUtil
5151: .returnError("Failed to create Payment: Cannot find OrderPaymentPreference with orderPaymentPreferenceId "
5152: + orderPaymentPreferenceId);
5153: }
5154:
5155: // get the order header
5156: GenericValue orderHeader = orderPaymentPreference
5157: .getRelatedOne("OrderHeader");
5158: if (orderHeader == null) {
5159: return ServiceUtil
5160: .returnError("Failed to create Payment: Cannot get related OrderHeader from payment preference");
5161: }
5162:
5163: // get the store for the order. It will be used to set the currency
5164: GenericValue productStore = orderHeader
5165: .getRelatedOne("ProductStore");
5166: if (productStore == null) {
5167: return ServiceUtil
5168: .returnError("Failed to create Payment: Cannot get the ProductStore for the order header");
5169: }
5170:
5171: // get the partyId billed to
5172: OrderReadHelper orh = new OrderReadHelper(orderHeader);
5173: GenericValue billToParty = orh.getBillToParty();
5174: if (billToParty == null) {
5175: return ServiceUtil
5176: .returnError("Failed to create Payment: cannot find the bill to customer party");
5177: }
5178:
5179: // set the payToPartyId
5180: String payToPartyId = productStore
5181: .getString("payToPartyId");
5182: if (payToPartyId == null) {
5183: return ServiceUtil
5184: .returnError("Failed to create Payment: Cannot get the ProductStore for the order header");
5185: }
5186:
5187: // create the payment
5188: Map paymentParams = new HashMap();
5189: double maxAmount = orderPaymentPreference.getDouble(
5190: "maxAmount").doubleValue();
5191: //if (maxAmount > 0.0) {
5192: paymentParams.put("paymentTypeId", "CUSTOMER_PAYMENT");
5193: paymentParams.put("paymentMethodTypeId",
5194: orderPaymentPreference
5195: .getString("paymentMethodTypeId"));
5196: paymentParams.put("paymentPreferenceId",
5197: orderPaymentPreference
5198: .getString("orderPaymentPreferenceId"));
5199: paymentParams.put("amount", new Double(maxAmount));
5200: paymentParams.put("statusId", "PMNT_RECEIVED");
5201: paymentParams.put("effectiveDate", UtilDateTime
5202: .nowTimestamp());
5203: paymentParams.put("partyIdFrom", billToParty
5204: .getString("partyId"));
5205: paymentParams.put("currencyUomId", productStore
5206: .getString("defaultCurrencyUomId"));
5207: paymentParams.put("partyIdTo", payToPartyId);
5208: /*}
5209: else {
5210: paymentParams.put("paymentTypeId", "CUSTOMER_REFUND"); // JLR 17/7/4 from a suggestion of Si cf. https://issues.apache.org/jira/browse/OFBIZ-828#action_12483045
5211: paymentParams.put("paymentMethodTypeId", orderPaymentPreference.getString("paymentMethodTypeId")); // JLR 20/7/4 Finally reverted for now, I prefer to see an amount in payment, even negative
5212: paymentParams.put("paymentPreferenceId", orderPaymentPreference.getString("orderPaymentPreferenceId"));
5213: paymentParams.put("amount", new Double(Math.abs(maxAmount)));
5214: paymentParams.put("statusId", "PMNT_RECEIVED");
5215: paymentParams.put("effectiveDate", UtilDateTime.nowTimestamp());
5216: paymentParams.put("partyIdFrom", payToPartyId);
5217: paymentParams.put("currencyUomId", productStore.getString("defaultCurrencyUomId"));
5218: paymentParams.put("partyIdTo", billToParty.getString("partyId"));
5219: }*/
5220: if (paymentRefNum != null) {
5221: paymentParams.put("paymentRefNum", paymentRefNum);
5222: }
5223: if (paymentFromId != null) {
5224: paymentParams.put("partyIdFrom", paymentFromId);
5225: } else {
5226: paymentParams.put("partyIdFrom", "_NA_");
5227: }
5228: if (comments != null) {
5229: paymentParams.put("comments", comments);
5230: }
5231: paymentParams.put("userLogin", userLogin);
5232:
5233: return dispatcher.runSync("createPayment", paymentParams);
5234:
5235: } catch (GenericEntityException ex) {
5236: Debug
5237: .logError(
5238: ex,
5239: "Unable to create payment using payment preference.",
5240: module);
5241: return (ServiceUtil.returnError(ex.getMessage()));
5242: } catch (GenericServiceException ex) {
5243: Debug
5244: .logError(
5245: ex,
5246: "Unable to create payment using payment preference.",
5247: module);
5248: return (ServiceUtil.returnError(ex.getMessage()));
5249: }
5250: }
5251:
5252: public static Map massChangeApproved(DispatchContext dctx,
5253: Map context) {
5254: LocalDispatcher dispatcher = dctx.getDispatcher();
5255: GenericDelegator delegator = dctx.getDelegator();
5256: GenericValue userLogin = (GenericValue) context
5257: .get("userLogin");
5258: List orderIds = (List) context.get("orderIdList");
5259: Iterator i = orderIds.iterator();
5260: while (i.hasNext()) {
5261: String orderId = (String) i.next();
5262: if (UtilValidate.isEmpty(orderId)) {
5263: continue;
5264: }
5265: GenericValue orderHeader = null;
5266: try {
5267: orderHeader = delegator.findByPrimaryKey("OrderHeader",
5268: UtilMisc.toMap("orderId", orderId));
5269: } catch (GenericEntityException e) {
5270: Debug.logError(e, module);
5271: return ServiceUtil.returnError(e.getMessage());
5272: }
5273: if (orderHeader == null) {
5274: return ServiceUtil.returnError("Order #" + orderId
5275: + " was not found.");
5276: }
5277:
5278: // by changing all the items to approved, the checkOrderItemStatus service will automatically set the order to approved.
5279: Map ctx = FastMap.newInstance();
5280: ctx.put("statusId", "ITEM_APPROVED");
5281: ctx.put("orderId", orderId);
5282: ctx.put("userLogin", userLogin);
5283: Map resp = null;
5284: try {
5285: resp = dispatcher.runSync("changeOrderItemStatus", ctx);
5286: } catch (GenericServiceException e) {
5287: Debug.logError(e, module);
5288: return ServiceUtil.returnError(e.getMessage());
5289: }
5290: if (ServiceUtil.isError(resp)) {
5291: return ServiceUtil.returnError(ServiceUtil
5292: .getErrorMessage(resp));
5293: }
5294: }
5295: return ServiceUtil.returnSuccess();
5296: }
5297:
5298: public static Map massPickOrders(DispatchContext dctx, Map context) {
5299: LocalDispatcher dispatcher = dctx.getDispatcher();
5300: GenericDelegator delegator = dctx.getDelegator();
5301: GenericValue userLogin = (GenericValue) context
5302: .get("userLogin");
5303:
5304: // grouped by facility
5305: Map facilityOrdersMap = FastMap.newInstance();
5306:
5307: // make the list per facility
5308: List orderIds = (List) context.get("orderIdList");
5309: Iterator i = orderIds.iterator();
5310: while (i.hasNext()) {
5311: String orderId = (String) i.next();
5312: if (UtilValidate.isEmpty(orderId)) {
5313: continue;
5314: }
5315: List invInfo = null;
5316: try {
5317: invInfo = delegator.findByAnd(
5318: "OrderItemAndShipGrpInvResAndItem", UtilMisc
5319: .toMap("orderId", orderId, "statusId",
5320: "ITEM_APPROVED"));
5321: } catch (GenericEntityException e) {
5322: Debug.logError(e, module);
5323: return ServiceUtil.returnError(e.getMessage());
5324: }
5325: if (invInfo != null) {
5326: Iterator ii = invInfo.iterator();
5327: while (ii.hasNext()) {
5328: GenericValue inv = (GenericValue) ii.next();
5329: String facilityId = inv.getString("facilityId");
5330: List orderIdsByFacility = (List) facilityOrdersMap
5331: .get(facilityId);
5332: if (orderIdsByFacility == null) {
5333: orderIdsByFacility = new ArrayList();
5334: }
5335: orderIdsByFacility.add(orderId);
5336: facilityOrdersMap.put(facilityId,
5337: orderIdsByFacility);
5338: }
5339: }
5340: }
5341:
5342: // now create the pick lists for each facility
5343: Iterator fi = facilityOrdersMap.keySet().iterator();
5344: while (fi.hasNext()) {
5345: String facilityId = (String) fi.next();
5346: List orderIdList = (List) facilityOrdersMap.get(facilityId);
5347:
5348: Map ctx = FastMap.newInstance();
5349: ctx.put("userLogin", userLogin);
5350: ctx.put("orderIdList", orderIdList);
5351: ctx.put("facilityId", facilityId);
5352:
5353: Map resp = null;
5354: try {
5355: resp = dispatcher.runSync("createPicklistFromOrders",
5356: ctx);
5357: } catch (GenericServiceException e) {
5358: Debug.logError(e, module);
5359: return ServiceUtil.returnError(e.getMessage());
5360: }
5361: if (ServiceUtil.isError(resp)) {
5362: return ServiceUtil.returnError(ServiceUtil
5363: .getErrorMessage(resp));
5364: }
5365: }
5366:
5367: return ServiceUtil.returnSuccess();
5368: }
5369:
5370: public static Map massPrintOrders(DispatchContext dctx, Map context) {
5371: LocalDispatcher dispatcher = dctx.getDispatcher();
5372: GenericValue userLogin = (GenericValue) context
5373: .get("userLogin");
5374: String screenLocation = (String) context.get("screenLocation");
5375: String printerName = (String) context.get("printerName");
5376:
5377: // make the list per facility
5378: List orderIds = (List) context.get("orderIdList");
5379: Iterator i = orderIds.iterator();
5380: while (i.hasNext()) {
5381: String orderId = (String) i.next();
5382: if (UtilValidate.isEmpty(orderId)) {
5383: continue;
5384: }
5385: Map ctx = FastMap.newInstance();
5386: ctx.put("userLogin", userLogin);
5387: ctx.put("screenLocation", screenLocation);
5388: //ctx.put("contentType", "application/postscript");
5389: if (UtilValidate.isNotEmpty(printerName)) {
5390: ctx.put("printerName", printerName);
5391: }
5392: ctx
5393: .put("screenContext", UtilMisc.toMap("orderId",
5394: orderId));
5395:
5396: try {
5397: dispatcher.runAsync("sendPrintFromScreen", ctx);
5398: } catch (GenericServiceException e) {
5399: Debug.logError(e, module);
5400: }
5401: }
5402: return ServiceUtil.returnSuccess();
5403: }
5404:
5405: public static Map massCreateFileForOrders(DispatchContext dctx,
5406: Map context) {
5407: LocalDispatcher dispatcher = dctx.getDispatcher();
5408: GenericValue userLogin = (GenericValue) context
5409: .get("userLogin");
5410: String screenLocation = (String) context.get("screenLocation");
5411:
5412: // make the list per facility
5413: List orderIds = (List) context.get("orderIdList");
5414: Iterator i = orderIds.iterator();
5415: while (i.hasNext()) {
5416: String orderId = (String) i.next();
5417: if (UtilValidate.isEmpty(orderId)) {
5418: continue;
5419: }
5420: Map ctx = FastMap.newInstance();
5421: ctx.put("userLogin", userLogin);
5422: ctx.put("screenLocation", screenLocation);
5423: //ctx.put("contentType", "application/postscript");
5424: ctx.put("fileName", "order_" + orderId + "_");
5425: ctx
5426: .put("screenContext", UtilMisc.toMap("orderId",
5427: orderId));
5428:
5429: try {
5430: dispatcher.runAsync("createFileFromScreen", ctx);
5431: } catch (GenericServiceException e) {
5432: Debug.logError(e, module);
5433: }
5434: }
5435: return ServiceUtil.returnSuccess();
5436: }
5437:
5438: public static Map checkCreateDropShipPurchaseOrders(
5439: DispatchContext ctx, Map context) {
5440: GenericDelegator delegator = ctx.getDelegator();
5441: LocalDispatcher dispatcher = ctx.getDispatcher();
5442: // TODO (use the "system" user)
5443: GenericValue userLogin = (GenericValue) context
5444: .get("userLogin");
5445:
5446: String orderId = (String) context.get("orderId");
5447: OrderReadHelper orh = new OrderReadHelper(delegator, orderId);
5448: // TODO: skip this if there is already a purchase order associated with the sales order (ship group)
5449:
5450: try {
5451: // if sales order
5452: if ("SALES_ORDER".equals(orh.getOrderTypeId())) {
5453: // get the order's ship groups
5454: Iterator shipGroups = orh.getOrderItemShipGroups()
5455: .iterator();
5456: while (shipGroups.hasNext()) {
5457: GenericValue shipGroup = (GenericValue) shipGroups
5458: .next();
5459: if (!UtilValidate.isEmpty(shipGroup
5460: .getString("supplierPartyId"))) {
5461: // This ship group is a drop shipment: we create a purchase order for it
5462: String supplierPartyId = shipGroup
5463: .getString("supplierPartyId");
5464: // create the cart
5465: ShoppingCart cart = new ShoppingCart(delegator,
5466: orh.getProductStoreId(), null, orh
5467: .getCurrency());
5468: cart.setOrderType("PURCHASE_ORDER");
5469: cart.setBillToCustomerPartyId(cart
5470: .getBillFromVendorPartyId()); //Company
5471: cart.setBillFromVendorPartyId(supplierPartyId);
5472: cart.setOrderPartyId(supplierPartyId);
5473: // Get the items associated to it and create po
5474: List items = orh.getValidOrderItems(shipGroup
5475: .getString("shipGroupSeqId"));
5476: if (!UtilValidate.isEmpty(items)) {
5477: Iterator itemsIt = items.iterator();
5478: while (itemsIt.hasNext()) {
5479: GenericValue item = (GenericValue) itemsIt
5480: .next();
5481: try {
5482: int itemIndex = cart
5483: .addOrIncreaseItem(
5484: item
5485: .getString("productId"),
5486: null, // amount
5487: item
5488: .getDouble(
5489: "quantity")
5490: .doubleValue(),
5491: null,
5492: null,
5493: null, // reserv
5494: item
5495: .getTimestamp("shipBeforeDate"),
5496: item
5497: .getTimestamp("shipAfterDate"),
5498: null, null, null,
5499: null, null, null,
5500: null, dispatcher);
5501: ShoppingCartItem sci = cart
5502: .findCartItem(itemIndex);
5503: sci.setAssociatedOrderId(orderId);
5504: sci
5505: .setAssociatedOrderItemSeqId(item
5506: .getString("orderItemSeqId"));
5507: sci
5508: .setOrderItemAssocTypeId("DROP_SHIPMENT");
5509: // TODO: we should consider also the ship group in the association between sales and purchase orders
5510: } catch (Exception e) {
5511: ServiceUtil
5512: .returnError("The following error occurred creating drop shipments for order ["
5513: + orderId
5514: + "]: "
5515: + e.getMessage());
5516: }
5517: }
5518: }
5519:
5520: // If there are indeed items to drop ship, then create the purchase order
5521: if (!UtilValidate.isEmpty(cart.items())) {
5522: // set checkout options
5523: cart.setDefaultCheckoutOptions(dispatcher);
5524: // the shipping address is the one of the customer
5525: cart.setShippingContactMechId(shipGroup
5526: .getString("contactMechId"));
5527: // create the order
5528: CheckOutHelper coh = new CheckOutHelper(
5529: dispatcher, delegator, cart);
5530: Map resultOrderMap = coh
5531: .createOrder(userLogin);
5532: String purchaseOrderId = (String) resultOrderMap
5533: .get("orderId");
5534:
5535: // TODO: associate the new purchase order with the sales order (ship group)
5536: } else {
5537: // if there are no items to drop ship, then clear out the supplier partyId
5538: Debug
5539: .logWarning(
5540: "No drop ship items found for order ["
5541: + shipGroup
5542: .getString("orderId")
5543: + "] and ship group ["
5544: + shipGroup
5545: .getString("shipGroupSeqId")
5546: + "] and supplier party ["
5547: + shipGroup
5548: .getString("supplierPartyId")
5549: + "]. Supplier party information will be cleared for this ship group",
5550: module);
5551: shipGroup.set("supplierPartyId", null);
5552: shipGroup.store();
5553:
5554: }
5555: }
5556: }
5557: }
5558: } catch (Exception exc) {
5559: // TODO: imporve error handling
5560: ServiceUtil
5561: .returnError("The following error occurred creating drop shipments for order ["
5562: + orderId + "]: " + exc.getMessage());
5563: }
5564:
5565: return ServiceUtil.returnSuccess();
5566: }
5567:
5568: public static Map updateOrderPaymentPreference(
5569: DispatchContext dctx, Map context) {
5570: GenericDelegator delegator = dctx.getDelegator();
5571: LocalDispatcher dispatcher = dctx.getDispatcher();
5572: GenericValue userLogin = (GenericValue) context
5573: .get("userLogin");
5574:
5575: String orderPaymentPreferenceId = (String) context
5576: .get("orderPaymentPreferenceId");
5577: String checkOutPaymentId = (String) context
5578: .get("checkOutPaymentId");
5579: boolean cancelThis = ("true".equals((String) context
5580: .get("cancelThis")));
5581: try {
5582: GenericValue opp = delegator.findByPrimaryKey(
5583: "OrderPaymentPreference", UtilMisc.toMap(
5584: "orderPaymentPreferenceId",
5585: orderPaymentPreferenceId));
5586: String paymentMethodId = null;
5587: String paymentMethodTypeId = null;
5588:
5589: // The checkOutPaymentId is either a paymentMethodId or paymentMethodTypeId
5590: // the original method did a "\d+" regexp to decide which is the case, this version is more explicit with its lookup of PaymentMethodType
5591: if (checkOutPaymentId != null) {
5592: List paymentMethodTypes = delegator
5593: .findAllCache("PaymentMethodType");
5594: for (Iterator iter = paymentMethodTypes.iterator(); iter
5595: .hasNext();) {
5596: GenericValue type = (GenericValue) iter.next();
5597: if (type.get("paymentMethodTypeId").equals(
5598: checkOutPaymentId)) {
5599: paymentMethodTypeId = (String) type
5600: .get("paymentMethodTypeId");
5601: break;
5602: }
5603: }
5604: if (paymentMethodTypeId == null) {
5605: GenericValue method = delegator.findByPrimaryKey(
5606: "PaymentMethod", UtilMisc.toMap(
5607: "paymentMethodTypeId",
5608: paymentMethodTypeId));
5609: paymentMethodId = checkOutPaymentId;
5610: paymentMethodTypeId = (String) method
5611: .get("paymentMethodTypeId");
5612: }
5613: }
5614:
5615: Map results = ServiceUtil.returnSuccess();
5616: if (cancelThis) {
5617: opp.set("statusId", "PAYMENT_CANCELLED");
5618: opp.store();
5619: results.put("orderPaymentPreferenceId", opp
5620: .get("orderPaymentPreferenceId"));
5621: } else {
5622: GenericValue newOpp = (GenericValue) opp.clone();
5623: opp.set("statusId", "PAYMENT_CANCELLED");
5624: opp.store();
5625:
5626: newOpp.set("orderPaymentPreferenceId", delegator
5627: .getNextSeqId("OrderPaymentPreference"));
5628: newOpp.set("paymentMethodId", paymentMethodId);
5629: newOpp.set("paymentMethodTypeId", paymentMethodTypeId);
5630: newOpp.setNonPKFields(context);
5631: newOpp.create();
5632: results.put("orderPaymentPreferenceId", newOpp
5633: .get("orderPaymentPreferenceId"));
5634: }
5635:
5636: return results;
5637: } catch (GenericEntityException e) {
5638: Debug.logError(e, module);
5639: return ServiceUtil.returnError(e.getMessage());
5640: }
5641: }
5642:
5643: /**
5644: * Generates a product requirement for the total cancelled quantity over all order items for each product
5645: * @param dctx
5646: * @param context
5647: * @return
5648: */
5649: public static Map generateReqsFromCancelledPOItems(
5650: DispatchContext dctx, Map context) {
5651: GenericDelegator delegator = dctx.getDelegator();
5652: LocalDispatcher dispatcher = dctx.getDispatcher();
5653: GenericValue userLogin = (GenericValue) context
5654: .get("userLogin");
5655: Locale locale = (Locale) context.get("locale");
5656:
5657: String orderId = (String) context.get("orderId");
5658: String facilityId = (String) context.get("facilityId");
5659:
5660: try {
5661:
5662: GenericValue orderHeader = delegator.findByPrimaryKey(
5663: "OrderHeader", UtilMisc.toMap("orderId", orderId));
5664:
5665: if (UtilValidate.isEmpty(orderHeader)) {
5666: String errorMessage = UtilProperties.getMessage(
5667: resource_error, "OrderErrorOrderIdNotFound",
5668: UtilMisc.toMap("orderId", orderId), locale);
5669: Debug.logError(errorMessage, module);
5670: return ServiceUtil.returnError(errorMessage);
5671: }
5672:
5673: if (!"PURCHASE_ORDER".equals(orderHeader
5674: .getString("orderTypeId"))) {
5675: String errorMessage = UtilProperties.getMessage(
5676: resource_error,
5677: "ProductErrorOrderNotPurchaseOrder", UtilMisc
5678: .toMap("orderId", orderId), locale);
5679: Debug.logError(errorMessage, module);
5680: return ServiceUtil.returnError(errorMessage);
5681: }
5682:
5683: // Build a map of productId -> quantity cancelled over all order items
5684: Map productRequirementQuantities = new HashMap();
5685: List orderItems = orderHeader.getRelated("OrderItem");
5686: Iterator oiit = orderItems.iterator();
5687: while (oiit.hasNext()) {
5688: GenericValue orderItem = (GenericValue) oiit.next();
5689: if (!"PRODUCT_ORDER_ITEM".equals(orderItem
5690: .getString("orderItemTypeId")))
5691: continue;
5692:
5693: // Get the cancelled quantity for the item
5694: double orderItemCancelQuantity = 0;
5695: if (!UtilValidate.isEmpty(orderItem
5696: .get("cancelQuantity"))) {
5697: orderItemCancelQuantity = orderItem.getDouble(
5698: "cancelQuantity").doubleValue();
5699: }
5700:
5701: if (orderItemCancelQuantity <= 0)
5702: continue;
5703:
5704: String productId = orderItem.getString("productId");
5705: if (productRequirementQuantities.containsKey(productId)) {
5706: orderItemCancelQuantity += ((Double) productRequirementQuantities
5707: .get(productId)).doubleValue();
5708: }
5709: productRequirementQuantities.put(productId, new Double(
5710: orderItemCancelQuantity));
5711:
5712: }
5713:
5714: // Generate requirements for each of the product quantities
5715: Iterator cqit = productRequirementQuantities.keySet()
5716: .iterator();
5717: while (cqit.hasNext()) {
5718: String productId = (String) cqit.next();
5719: Double requiredQuantity = (Double) productRequirementQuantities
5720: .get(productId);
5721: Map createRequirementResult = dispatcher.runSync(
5722: "createRequirement", UtilMisc.toMap(
5723: "requirementTypeId",
5724: "PRODUCT_REQUIREMENT", "facilityId",
5725: facilityId, "productId", productId,
5726: "quantity", requiredQuantity,
5727: "userLogin", userLogin));
5728: if (ServiceUtil.isError(createRequirementResult))
5729: return createRequirementResult;
5730: }
5731:
5732: } catch (GenericEntityException e) {
5733: Debug.logError(e, module);
5734: return ServiceUtil.returnError(e.getMessage());
5735: } catch (GenericServiceException se) {
5736: Debug.logError(se, module);
5737: return ServiceUtil.returnError(se.getMessage());
5738: }
5739:
5740: return ServiceUtil.returnSuccess();
5741: }
5742:
5743: /**
5744: * Cancels remaining (unreceived) quantities for items of an order. Does not consider received-but-rejected quantities.
5745: * @param dctx
5746: * @param context
5747: * @return
5748: */
5749: public static Map cancelRemainingPurchaseOrderItems(
5750: DispatchContext dctx, Map context) {
5751: GenericDelegator delegator = dctx.getDelegator();
5752: LocalDispatcher dispatcher = dctx.getDispatcher();
5753: GenericValue userLogin = (GenericValue) context
5754: .get("userLogin");
5755: Locale locale = (Locale) context.get("locale");
5756:
5757: String orderId = (String) context.get("orderId");
5758:
5759: try {
5760:
5761: GenericValue orderHeader = delegator.findByPrimaryKey(
5762: "OrderHeader", UtilMisc.toMap("orderId", orderId));
5763:
5764: if (UtilValidate.isEmpty(orderHeader)) {
5765: String errorMessage = UtilProperties.getMessage(
5766: resource_error, "OrderErrorOrderIdNotFound",
5767: UtilMisc.toMap("orderId", orderId), locale);
5768: Debug.logError(errorMessage, module);
5769: return ServiceUtil.returnError(errorMessage);
5770: }
5771:
5772: if (!"PURCHASE_ORDER".equals(orderHeader
5773: .getString("orderTypeId"))) {
5774: String errorMessage = UtilProperties.getMessage(
5775: resource_error,
5776: "OrderErrorOrderNotPurchaseOrder", UtilMisc
5777: .toMap("orderId", orderId), locale);
5778: Debug.logError(errorMessage, module);
5779: return ServiceUtil.returnError(errorMessage);
5780: }
5781:
5782: List orderItems = orderHeader.getRelated("OrderItem");
5783: Iterator oiit = orderItems.iterator();
5784: while (oiit.hasNext()) {
5785: GenericValue orderItem = (GenericValue) oiit.next();
5786: if (!"PRODUCT_ORDER_ITEM".equals(orderItem
5787: .getString("orderItemTypeId")))
5788: continue;
5789:
5790: // Get the ordered quantity for the item
5791: double orderItemQuantity = 0;
5792: if (!UtilValidate.isEmpty(orderItem.get("quantity"))) {
5793: orderItemQuantity = orderItem.getDouble("quantity")
5794: .doubleValue();
5795: }
5796: double orderItemCancelQuantity = 0;
5797: if (!UtilValidate.isEmpty(orderItem
5798: .get("cancelQuantity"))) {
5799: orderItemCancelQuantity = orderItem.getDouble(
5800: "cancelQuantity").doubleValue();
5801: }
5802:
5803: // Get the received quantity for the order item - ignore the quantityRejected, since rejected items should be reordered
5804: List shipmentReceipts = orderItem
5805: .getRelated("ShipmentReceipt");
5806: double receivedQuantity = 0;
5807: Iterator srit = shipmentReceipts.iterator();
5808: while (srit.hasNext()) {
5809: GenericValue shipmentReceipt = (GenericValue) srit
5810: .next();
5811: if (!UtilValidate.isEmpty(shipmentReceipt
5812: .get("quantityAccepted"))) {
5813: receivedQuantity += shipmentReceipt.getDouble(
5814: "quantityAccepted").doubleValue();
5815: }
5816: }
5817:
5818: double quantityToCancel = orderItemQuantity
5819: - orderItemCancelQuantity - receivedQuantity;
5820: if (quantityToCancel <= 0)
5821: continue;
5822:
5823: Map cancelOrderItemResult = dispatcher.runSync(
5824: "cancelOrderItem", UtilMisc.toMap("orderId",
5825: orderId, "orderItemSeqId", orderItem
5826: .get("orderItemSeqId"),
5827: "cancelQuantity", new Double(
5828: quantityToCancel), "userLogin",
5829: userLogin));
5830: if (ServiceUtil.isError(cancelOrderItemResult))
5831: return cancelOrderItemResult;
5832:
5833: orderItem.refresh();
5834: if ("ITEM_APPROVED".equals(orderItem
5835: .getString("statusId"))) {
5836: Map changeOrderItemStatusResult = dispatcher
5837: .runSync(
5838: "changeOrderItemStatus",
5839: UtilMisc
5840: .toMap(
5841: "orderId",
5842: orderId,
5843: "orderItemSeqId",
5844: orderItem
5845: .get("orderItemSeqId"),
5846: "statusId",
5847: "ITEM_COMPLETED",
5848: "userLogin",
5849: userLogin));
5850: if (ServiceUtil
5851: .isError(changeOrderItemStatusResult))
5852: return changeOrderItemStatusResult;
5853: }
5854: }
5855:
5856: } catch (GenericEntityException e) {
5857: Debug.logError(e, module);
5858: return ServiceUtil.returnError(e.getMessage());
5859: } catch (GenericServiceException se) {
5860: Debug.logError(se, module);
5861: return ServiceUtil.returnError(se.getMessage());
5862: }
5863:
5864: return ServiceUtil.returnSuccess();
5865: }
5866:
5867: // create simple non-product order
5868: public static Map createSimpleNonProductSalesOrder(
5869: DispatchContext dctx, Map context) {
5870: LocalDispatcher dispatcher = dctx.getDispatcher();
5871: GenericDelegator delegator = dctx.getDelegator();
5872:
5873: GenericValue userLogin = (GenericValue) context
5874: .get("userLogin");
5875: Locale locale = (Locale) context.get("locale");
5876:
5877: String paymentMethodId = (String) context
5878: .get("paymentMethodId");
5879: String productStoreId = (String) context.get("productStoreId");
5880: String currency = (String) context.get("currency");
5881: String partyId = (String) context.get("partyId");
5882: Map itemMap = (Map) context.get("itemMap");
5883:
5884: ShoppingCart cart = new ShoppingCart(delegator, productStoreId,
5885: null, locale, currency);
5886: try {
5887: cart.setUserLogin(userLogin, dispatcher);
5888: } catch (CartItemModifyException e) {
5889: Debug.logError(e, module);
5890: return ServiceUtil.returnError(e.getMessage());
5891: }
5892: cart.setOrderType("SALES_ORDER");
5893: cart.setOrderPartyId(partyId);
5894:
5895: Iterator i = itemMap.keySet().iterator();
5896: while (i.hasNext()) {
5897: String item = (String) i.next();
5898: Double price = (Double) itemMap.get(item);
5899: try {
5900: cart.addNonProductItem("BULK_ORDER_ITEM", item, null,
5901: price, 1, null, null, null, dispatcher);
5902: } catch (CartItemModifyException e) {
5903: Debug.logError(e, module);
5904: return ServiceUtil.returnError(e.getMessage());
5905: }
5906: }
5907:
5908: // set the payment method
5909: try {
5910: cart.addPayment(paymentMethodId);
5911: } catch (IllegalArgumentException e) {
5912: return ServiceUtil.returnError(e.getMessage());
5913: }
5914:
5915: // save the order (new tx)
5916: Map createResp;
5917: try {
5918: createResp = dispatcher.runSync(
5919: "createOrderFromShoppingCart", UtilMisc.toMap(
5920: "shoppingCart", cart), 90, true);
5921: } catch (GenericServiceException e) {
5922: Debug.logError(e, module);
5923: return ServiceUtil.returnError(e.getMessage());
5924: }
5925: if (ServiceUtil.isError(createResp)) {
5926: return createResp;
5927: }
5928:
5929: // auth the order (new tx)
5930: Map authResp;
5931: try {
5932: authResp = dispatcher.runSync("callProcessOrderPayments",
5933: UtilMisc.toMap("shoppingCart", cart), 180, true);
5934: } catch (GenericServiceException e) {
5935: Debug.logError(e, module);
5936: return ServiceUtil.returnError(e.getMessage());
5937: }
5938: if (ServiceUtil.isError(authResp)) {
5939: return authResp;
5940: }
5941:
5942: Map result = ServiceUtil.returnSuccess();
5943: result.put("orderId", createResp.get("orderId"));
5944: return result;
5945: }
5946:
5947: // generic method for creating an order from a shopping cart
5948: public static Map createOrderFromShoppingCart(DispatchContext dctx,
5949: Map context) {
5950: LocalDispatcher dispatcher = dctx.getDispatcher();
5951: GenericDelegator delegator = dctx.getDelegator();
5952:
5953: ShoppingCart cart = (ShoppingCart) context.get("shoppingCart");
5954: GenericValue userLogin = cart.getUserLogin();
5955:
5956: CheckOutHelper coh = new CheckOutHelper(dispatcher, delegator,
5957: cart);
5958: Map createOrder = coh.createOrder(userLogin);
5959: if (ServiceUtil.isError(createOrder)) {
5960: return createOrder;
5961: }
5962: String orderId = (String) createOrder.get("orderId");
5963:
5964: Map result = ServiceUtil.returnSuccess();
5965: result.put("shoppingCart", cart);
5966: result.put("orderId", orderId);
5967: return result;
5968: }
5969:
5970: // generic method for processing an order's payment(s)
5971: public static Map callProcessOrderPayments(DispatchContext dctx,
5972: Map context) {
5973: LocalDispatcher dispatcher = dctx.getDispatcher();
5974: GenericDelegator delegator = dctx.getDelegator();
5975:
5976: Transaction trans = null;
5977: try {
5978: // disable transaction procesing
5979: trans = TransactionUtil.suspend();
5980:
5981: // get the cart
5982: ShoppingCart cart = (ShoppingCart) context
5983: .get("shoppingCart");
5984: GenericValue userLogin = cart.getUserLogin();
5985: Boolean manualHold = (Boolean) context.get("manualHold");
5986: if (manualHold == null) {
5987: manualHold = Boolean.FALSE;
5988: }
5989:
5990: if (!"PURCHASE_ORDER".equals(cart.getOrderType())) {
5991: String productStoreId = cart.getProductStoreId();
5992: GenericValue productStore = ProductStoreWorker
5993: .getProductStore(productStoreId, delegator);
5994: CheckOutHelper coh = new CheckOutHelper(dispatcher,
5995: delegator, cart);
5996:
5997: // process payment
5998: Map payResp;
5999: try {
6000: payResp = coh
6001: .processPayment(productStore, userLogin,
6002: false, manualHold.booleanValue());
6003: } catch (GeneralException e) {
6004: Debug.logError(e, module);
6005: return ServiceUtil.returnError(e.getMessage());
6006: }
6007: if (ServiceUtil.isError(payResp)) {
6008: return ServiceUtil.returnError(ServiceUtil
6009: .getErrorMessage(payResp));
6010: }
6011: }
6012:
6013: return ServiceUtil.returnSuccess();
6014: } catch (GenericTransactionException e) {
6015: return ServiceUtil.returnError(e.getMessage());
6016: } finally {
6017: // resume transaction
6018: try {
6019: TransactionUtil.resume(trans);
6020: } catch (GenericTransactionException e) {
6021: Debug.logWarning(e, e.getMessage(), module);
6022: }
6023: }
6024: }
6025:
6026: /**
6027: * Calculates the value of a given orderItem by totalling the item subtotal, any adjustments for that item, and
6028: * the item's share of any order-level adjustments (that calculated by applying the percentage of the items total that the
6029: * item represents to the order-level adjustments total.
6030: * @param dctx DispatchContext
6031: * @param context Map
6032: * @return Map
6033: */
6034: public static Map getOrderItemValue(DispatchContext dctx,
6035: Map context) {
6036: GenericDelegator delegator = dctx.getDelegator();
6037: Locale locale = (Locale) context.get("locale");
6038:
6039: String orderId = (String) context.get("orderId");
6040: String orderItemSeqId = (String) context.get("orderItemSeqId");
6041:
6042: GenericValue orderHeader = null;
6043: GenericValue orderItem = null;
6044: try {
6045:
6046: orderHeader = delegator.findByPrimaryKey("OrderHeader",
6047: UtilMisc.toMap("orderId", orderId));
6048: if (UtilValidate.isEmpty(orderHeader)) {
6049: String errorMessage = UtilProperties.getMessage(
6050: resource_error, "OrderErrorOrderIdNotFound",
6051: context, locale);
6052: Debug.logError(errorMessage, module);
6053: return ServiceUtil.returnError(errorMessage);
6054: }
6055:
6056: orderItem = delegator.findByPrimaryKey("OrderItem",
6057: UtilMisc.toMap("orderId", orderId,
6058: "orderItemSeqId", orderItemSeqId));
6059: if (UtilValidate.isEmpty(orderItem)) {
6060: String errorMessage = UtilProperties.getMessage(
6061: resource_error, "OrderErrorOrderItemNotFound",
6062: context, locale);
6063: Debug.logError(errorMessage, module);
6064: return ServiceUtil.returnError(errorMessage);
6065: }
6066:
6067: } catch (GenericEntityException e) {
6068: Debug.logError(e, module);
6069: return ServiceUtil.returnError(e.getMessage());
6070: }
6071:
6072: OrderReadHelper orh = new OrderReadHelper(orderHeader);
6073:
6074: // How much of the order items total does this orderItem represent? (Includes item-level adjustments but not order-level adjustments)
6075: BigDecimal orderItemTotal = orh.getOrderItemTotalBd(orderItem);
6076: BigDecimal orderItemsTotal = orh.getOrderItemsTotalBd();
6077: BigDecimal proportionOfOrderItemsTotal = orderItemTotal.divide(
6078: orderItemsTotal, orderRounding);
6079: BigDecimal portionOfOrderItemsTotal = proportionOfOrderItemsTotal
6080: .multiply(orderItemsTotal).setScale(orderDecimals,
6081: orderRounding);
6082:
6083: // How much of the order-level adjustments total does this orderItem represent? The assumption is: the same
6084: // proportion of the adjustments as of the item to the items total
6085: BigDecimal orderAdjustmentsTotal = orh
6086: .getOrderAdjustmentsTotalBd();
6087: BigDecimal portionOfOrderAdjustmentsTotal = proportionOfOrderItemsTotal
6088: .multiply(orderAdjustmentsTotal).setScale(
6089: orderDecimals, orderRounding);
6090:
6091: // The total value of the item is the value of the item itself plus its adjustments, and the item's share of the order-level adjustments
6092: BigDecimal orderItemTotalValue = portionOfOrderItemsTotal
6093: .add(portionOfOrderAdjustmentsTotal);
6094:
6095: Map result = ServiceUtil.returnSuccess();
6096: result.put("orderItemValue", orderItemTotalValue);
6097: return result;
6098: }
6099: }
|