0001: /*
0002: * $Id: OrderServices.java,v 1.34 2004/03/05 20:30:26 ajzeneski Exp $
0003: *
0004: * Copyright (c) 2001, 2002 The Open For Business Project - www.ofbiz.org
0005: *
0006: * Permission is hereby granted, free of charge, to any person obtaining a
0007: * copy of this software and associated documentation files (the "Software"),
0008: * to deal in the Software without restriction, including without limitation
0009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0010: * and/or sell copies of the Software, and to permit persons to whom the
0011: * Software is furnished to do so, subject to the following conditions:
0012: *
0013: * The above copyright notice and this permission notice shall be included
0014: * in all copies or substantial portions of the Software.
0015: *
0016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
0019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
0020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
0021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
0022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0023: */
0024: package org.ofbiz.order.order;
0025:
0026: import java.sql.Timestamp;
0027: import java.text.DecimalFormat;
0028: import java.text.ParseException;
0029: import java.util.*;
0030:
0031: import org.ofbiz.base.util.*;
0032: import org.ofbiz.common.DataModelConstants;
0033: import org.ofbiz.entity.GenericDelegator;
0034: import org.ofbiz.entity.GenericEntityException;
0035: import org.ofbiz.entity.GenericValue;
0036: import org.ofbiz.entity.condition.EntityCondition;
0037: import org.ofbiz.entity.condition.EntityConditionList;
0038: import org.ofbiz.entity.condition.EntityExpr;
0039: import org.ofbiz.entity.condition.EntityOperator;
0040: import org.ofbiz.entity.condition.EntityFieldMap;
0041: import org.ofbiz.entity.util.EntityListIterator;
0042: import org.ofbiz.entity.util.EntityUtil;
0043: import org.ofbiz.entity.util.EntityFindOptions;
0044: import org.ofbiz.order.shoppingcart.ShoppingCart;
0045: import org.ofbiz.order.shoppingcart.shipping.ShippingEvents;
0046: import org.ofbiz.party.contact.ContactHelper;
0047: import org.ofbiz.product.store.ProductStoreWorker;
0048: import org.ofbiz.security.Security;
0049: import org.ofbiz.service.*;
0050: import org.ofbiz.workflow.WfUtil;
0051:
0052: /**
0053: * Order Processing Services
0054: *
0055: * @author <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a>
0056: * @author <a href="mailto:cnelson@einnovation.com">Chris Nelson</a>
0057: * @author <a href="mailto:jonesde@ofbiz.org">David E. Jones</a>
0058: * @version $Revision: 1.34 $
0059: * @since 2.0
0060: */
0061:
0062: public class OrderServices {
0063:
0064: public static final String module = OrderServices.class.getName();
0065: public static final String resource = "org.ofbiz.order.order.PackageMessages";
0066:
0067: /** Service for creating a new order */
0068: public static Map createOrder(DispatchContext ctx, Map context) {
0069: Map result = new HashMap();
0070: GenericDelegator delegator = ctx.getDelegator();
0071: LocalDispatcher dispatcher = ctx.getDispatcher();
0072: Security security = ctx.getSecurity();
0073: List toBeStored = new LinkedList();
0074: Locale locale = (Locale) context.get("locale");
0075:
0076: GenericValue userLogin = (GenericValue) context
0077: .get("userLogin");
0078: // check security
0079: String partyId = ServiceUtil.getPartyIdCheckSecurity(userLogin,
0080: security, context, result, "ORDERMGR", "_CREATE");
0081:
0082: if (result.size() > 0) {
0083: return result;
0084: }
0085:
0086: // get the order type
0087: String orderTypeId = (String) context.get("orderTypeId");
0088: result.put("orderTypeId", orderTypeId);
0089:
0090: // lookup the order type entity
0091: GenericValue orderType = null;
0092: try {
0093: orderType = delegator.findByPrimaryKeyCache("OrderType",
0094: UtilMisc.toMap("orderTypeId", orderTypeId));
0095: } catch (GenericEntityException e) {
0096: result.put(ModelService.RESPONSE_MESSAGE,
0097: ModelService.RESPOND_ERROR);
0098: result.put(ModelService.ERROR_MESSAGE,
0099: "ERROR: OrderType lookup failed: " + e.toString());
0100: return result;
0101: }
0102:
0103: // make sure we have a valid order type
0104: if (orderType == null) {
0105: result.put(ModelService.RESPONSE_MESSAGE,
0106: ModelService.RESPOND_ERROR);
0107: result.put(ModelService.ERROR_MESSAGE,
0108: "ERROR: Invalid OrderType");
0109: return result;
0110: }
0111:
0112: // check to make sure we have something to order
0113: List orderItems = (List) context.get("orderItems");
0114:
0115: if (orderItems.size() < 1) {
0116: result.put(ModelService.RESPONSE_MESSAGE,
0117: ModelService.RESPOND_ERROR);
0118: result.put(ModelService.ERROR_MESSAGE, UtilProperties
0119: .getMessage(resource, "items.none", locale));
0120: return result;
0121: }
0122:
0123: // check inventory and other things for each item
0124: String productStoreId = (String) context.get("productStoreId");
0125: List errorMessages = new LinkedList();
0126: Map normalizedItemQuantities = new HashMap();
0127: Map normalizedItemNames = new HashMap();
0128: Iterator itemIter = orderItems.iterator();
0129: java.sql.Timestamp nowTimestamp = UtilDateTime.nowTimestamp();
0130:
0131: // need to run through the items combining any cases where multiple lines refer to the
0132: // same product so the inventory check will work correctly
0133: while (itemIter.hasNext()) {
0134: GenericValue orderItem = (GenericValue) itemIter.next();
0135: String currentProductId = (String) orderItem
0136: .get("productId");
0137: if (currentProductId != null) {
0138: // only normalize items with a product associated (ignore non-product items)
0139: if (normalizedItemQuantities.get(currentProductId) == null) {
0140: normalizedItemQuantities.put(currentProductId,
0141: new Double(orderItem.getDouble("quantity")
0142: .doubleValue()));
0143: normalizedItemNames.put(currentProductId,
0144: new String(orderItem
0145: .getString("itemDescription")));
0146: } else {
0147: Double currentQuantity = (Double) normalizedItemQuantities
0148: .get(currentProductId);
0149: normalizedItemQuantities.put(currentProductId,
0150: new Double(currentQuantity.doubleValue()
0151: + orderItem.getDouble("quantity")
0152: .doubleValue()));
0153: }
0154: }
0155: }
0156:
0157: if (!"PURCHASE_ORDER".equals(orderTypeId)
0158: && productStoreId == null) {
0159: return ServiceUtil
0160: .returnError("ERROR: The productStoreId can only be null for purchase orders");
0161: }
0162:
0163: Iterator normalizedIter = normalizedItemQuantities.keySet()
0164: .iterator();
0165: while (normalizedIter.hasNext()) {
0166: // lookup the product entity for each normalized item; error on products not found
0167: String currentProductId = (String) normalizedIter.next();
0168: Double currentQuantity = (Double) normalizedItemQuantities
0169: .get(currentProductId);
0170: String itemName = (String) normalizedItemNames
0171: .get(currentProductId);
0172: GenericValue product = null;
0173:
0174: try {
0175: product = delegator.findByPrimaryKeyCache("Product",
0176: UtilMisc.toMap("productId", currentProductId));
0177: } catch (GenericEntityException e) {
0178: String errMsg = UtilProperties.getMessage(resource,
0179: "product.not_found",
0180: new Object[] { currentProductId }, locale);
0181: Debug.logError(e, errMsg, module);
0182: errorMessages.add(errMsg);
0183: continue;
0184: }
0185:
0186: if (product == null) {
0187: String errMsg = UtilProperties.getMessage(resource,
0188: "product.not_found",
0189: new Object[] { currentProductId }, locale);
0190: Debug.logError(errMsg, module);
0191: errorMessages.add(errMsg);
0192: continue;
0193: }
0194:
0195: if ("SALES_ORDER".equals(orderTypeId)
0196: || "WORK_ORDER".equals(orderTypeId)) {
0197: // check to see if introductionDate hasn't passed yet
0198: if (product.get("introductionDate") != null
0199: && nowTimestamp.before(product
0200: .getTimestamp("introductionDate"))) {
0201: String excMsg = UtilProperties.getMessage(resource,
0202: "product.not_yet_for_sale", new Object[] {
0203: getProductName(product, itemName),
0204: product.getString("productId") },
0205: locale);
0206: Debug.logWarning(excMsg, module);
0207: errorMessages.add(excMsg);
0208: continue;
0209: }
0210: }
0211:
0212: if ("SALES_ORDER".equals(orderTypeId)
0213: || "WORK_ORDER".equals(orderTypeId)) {
0214: // check to see if salesDiscontinuationDate has passed
0215: if (product.get("salesDiscontinuationDate") != null
0216: && nowTimestamp
0217: .after(product
0218: .getTimestamp("salesDiscontinuationDate"))) {
0219: String excMsg = UtilProperties.getMessage(resource,
0220: "product.no_longer_for_sale", new Object[] {
0221: getProductName(product, itemName),
0222: product.getString("productId") },
0223: locale);
0224: Debug.logWarning(excMsg, module);
0225: errorMessages.add(excMsg);
0226: continue;
0227: }
0228: }
0229:
0230: if ("SALES_ORDER".equals(orderTypeId)
0231: || "WORK_ORDER".equals(orderTypeId)) {
0232: // check to see if we have inventory available
0233: if (ProductStoreWorker.isStoreInventoryRequired(
0234: productStoreId, product, delegator)) {
0235: if (!ProductStoreWorker.isStoreInventoryAvailable(
0236: productStoreId, currentProductId,
0237: currentQuantity.doubleValue(), delegator,
0238: dispatcher)) {
0239: String invErrMsg = UtilProperties.getMessage(
0240: resource, "product.out_of_stock",
0241: new Object[] {
0242: getProductName(product,
0243: itemName),
0244: currentProductId }, locale);
0245: Debug.logWarning(invErrMsg, module);
0246: errorMessages.add(invErrMsg);
0247: continue;
0248: }
0249: }
0250: }
0251: }
0252:
0253: if (errorMessages.size() > 0) {
0254: result.put(ModelService.RESPONSE_MESSAGE,
0255: ModelService.RESPOND_ERROR);
0256: result.put(ModelService.ERROR_MESSAGE_LIST, errorMessages);
0257: return result;
0258: }
0259:
0260: // the inital status for ALL order types
0261: String initialStatus = "ORDER_CREATED";
0262: result.put("statusId", initialStatus);
0263:
0264: // create the order object
0265: String orderId = delegator.getNextSeqId("OrderHeader")
0266: .toString();
0267: String billingAccountId = (String) context
0268: .get("billingAccountId");
0269: GenericValue order = delegator.makeValue("OrderHeader",
0270: UtilMisc.toMap("orderId", orderId, "orderTypeId",
0271: orderTypeId, "orderDate", nowTimestamp,
0272: "entryDate", nowTimestamp, "statusId",
0273: initialStatus, "billingAccountId",
0274: billingAccountId));
0275:
0276: if (context.get("currencyUom") != null) {
0277: order.set("currencyUom", context.get("currencyUom"));
0278: }
0279:
0280: if (context.get("firstAttemptOrderId") != null) {
0281: order.set("firstAttemptOrderId", context
0282: .get("firstAttemptOrderId"));
0283: }
0284:
0285: if (context.get("grandTotal") != null) {
0286: order.set("grandTotal", context.get("grandTotal"));
0287: }
0288:
0289: if (UtilValidate.isNotEmpty((String) context.get("visitId"))) {
0290: order.set("visitId", context.get("visitId"));
0291: }
0292:
0293: if (UtilValidate.isNotEmpty((String) context
0294: .get("productStoreId"))) {
0295: order.set("productStoreId", context.get("productStoreId"));
0296: }
0297:
0298: if (UtilValidate.isNotEmpty((String) context.get("webSiteId"))) {
0299: order.set("webSiteId", context.get("webSiteId"));
0300: }
0301:
0302: if (userLogin != null && userLogin.get("userLoginId") != null) {
0303: order.set("createdBy", userLogin.getString("userLoginId"));
0304: }
0305:
0306: // first try to create the OrderHeader; if this does not fail, continue.
0307: try {
0308: delegator.create(order);
0309: } catch (GenericEntityException e) {
0310: Debug
0311: .logError(
0312: e,
0313: "Cannot create OrderHeader entity; problems with insert",
0314: module);
0315: result.put(ModelService.RESPONSE_MESSAGE,
0316: ModelService.RESPOND_ERROR);
0317: result
0318: .put(ModelService.ERROR_MESSAGE,
0319: "Order creation failed; please notify customer service.");
0320: return result;
0321: }
0322:
0323: // create the order status record
0324: String orderStatusSeqId = delegator.getNextSeqId("OrderStatus")
0325: .toString();
0326: GenericValue orderStatus = delegator.makeValue("OrderStatus",
0327: UtilMisc.toMap("orderStatusId", orderStatusSeqId));
0328: orderStatus.set("orderId", orderId);
0329: orderStatus.set("statusId", order.getString("statusId"));
0330: orderStatus.set("statusDatetime", nowTimestamp);
0331: toBeStored.add(orderStatus);
0332:
0333: // set the orderId on all adjustments; this list will include order and item adjustments...
0334: List orderAdjustments = (List) context.get("orderAdjustments");
0335: if (orderAdjustments != null && orderAdjustments.size() > 0) {
0336: Iterator iter = orderAdjustments.iterator();
0337:
0338: while (iter.hasNext()) {
0339: GenericValue orderAdjustment = (GenericValue) iter
0340: .next();
0341: Long adjSeqId = delegator
0342: .getNextSeqId("OrderAdjustment");
0343:
0344: if (adjSeqId == null) {
0345: result.put(ModelService.RESPONSE_MESSAGE,
0346: ModelService.RESPOND_ERROR);
0347: result
0348: .put(
0349: ModelService.ERROR_MESSAGE,
0350: "ERROR: Could not get next sequence id for OrderAdjustment, cannot create order.");
0351: return result;
0352: }
0353: orderAdjustment.set("orderAdjustmentId", adjSeqId
0354: .toString());
0355: orderAdjustment.set("orderId", orderId);
0356:
0357: if (orderAdjustment.get("orderItemSeqId") == null
0358: || orderAdjustment.getString("orderItemSeqId")
0359: .length() == 0) {
0360: orderAdjustment.set("orderItemSeqId",
0361: DataModelConstants.SEQ_ID_NA); // set the orderItemSeqId to _NA_ if not alredy set...
0362: }
0363:
0364: toBeStored.add(orderAdjustment);
0365: }
0366: }
0367:
0368: // set the order contact mechs
0369: List orderContactMechs = (List) context
0370: .get("orderContactMechs");
0371: if (orderContactMechs != null && orderContactMechs.size() > 0) {
0372: Iterator ocmi = orderContactMechs.iterator();
0373:
0374: while (ocmi.hasNext()) {
0375: GenericValue ocm = (GenericValue) ocmi.next();
0376: ocm.set("orderId", orderId);
0377: toBeStored.add(ocm);
0378: }
0379: }
0380:
0381: // set the order item contact mechs
0382: List orderItemContactMechs = (List) context
0383: .get("orderItemContactMechs");
0384: if (orderItemContactMechs != null
0385: && orderItemContactMechs.size() > 0) {
0386: Iterator oicmi = orderItemContactMechs.iterator();
0387:
0388: while (oicmi.hasNext()) {
0389: GenericValue oicm = (GenericValue) oicmi.next();
0390: oicm.set("orderId", orderId);
0391: toBeStored.add(oicm);
0392: }
0393: }
0394:
0395: // set the shipment preferences
0396: List orderShipmentPreferences = (List) context
0397: .get("orderShipmentPreferences");
0398: if (orderShipmentPreferences != null
0399: && orderShipmentPreferences.size() > 0) {
0400: Iterator oshprefs = orderShipmentPreferences.iterator();
0401:
0402: while (oshprefs.hasNext()) {
0403: GenericValue orderShipmentPreference = (GenericValue) oshprefs
0404: .next();
0405: orderShipmentPreference.set("orderId", orderId);
0406: orderShipmentPreference.set("carrierRoleTypeId",
0407: "CARRIER");
0408: if (orderShipmentPreference.get("orderItemSeqId") == null
0409: || orderShipmentPreference.getString(
0410: "orderItemSeqId").length() == 0) {
0411: orderShipmentPreference.set("orderItemSeqId",
0412: DataModelConstants.SEQ_ID_NA); // set the orderItemSeqId to _NA_ if not alredy set...
0413: }
0414: toBeStored.add(orderShipmentPreference);
0415: }
0416: }
0417:
0418: // set the order items
0419: Iterator oi = orderItems.iterator();
0420: while (oi.hasNext()) {
0421: GenericValue orderItem = (GenericValue) oi.next();
0422: orderItem.set("orderId", orderId);
0423: toBeStored.add(orderItem);
0424:
0425: // create the item status record
0426: String itemStatusId = delegator.getNextSeqId("OrderStatus")
0427: .toString();
0428: GenericValue itemStatus = delegator.makeValue(
0429: "OrderStatus", UtilMisc.toMap("orderStatusId",
0430: itemStatusId));
0431: itemStatus.put("statusId", orderItem.get("statusId"));
0432: itemStatus.put("orderId", orderId);
0433: itemStatus.put("orderItemSeqId", orderItem
0434: .get("orderItemSeqId"));
0435: itemStatus.put("statusDatetime", nowTimestamp);
0436: toBeStored.add(itemStatus);
0437: }
0438:
0439: // set the item survey responses
0440: List surveyResponses = (List) context
0441: .get("orderItemSurveyResponses");
0442: if (surveyResponses != null && surveyResponses.size() > 0) {
0443: Iterator oisr = surveyResponses.iterator();
0444: while (oisr.hasNext()) {
0445: GenericValue surveyResponse = (GenericValue) oisr
0446: .next();
0447: surveyResponse.set("orderId", orderId);
0448: toBeStored.add(surveyResponse);
0449: }
0450: }
0451:
0452: // set the item price info; NOTE: this must be after the orderItems are stored for referential integrity
0453: List orderItemPriceInfo = (List) context
0454: .get("orderItemPriceInfos");
0455: if (orderItemPriceInfo != null && orderItemPriceInfo.size() > 0) {
0456: Iterator oipii = orderItemPriceInfo.iterator();
0457:
0458: while (oipii.hasNext()) {
0459: GenericValue oipi = (GenericValue) oipii.next();
0460: Long oipiSeqId = delegator
0461: .getNextSeqId("OrderItemPriceInfo");
0462:
0463: if (oipiSeqId == null) {
0464: result.put(ModelService.RESPONSE_MESSAGE,
0465: ModelService.RESPOND_ERROR);
0466: result
0467: .put(
0468: ModelService.ERROR_MESSAGE,
0469: "ERROR: Could not get next sequence id for OrderItemPriceInfo, cannot create order.");
0470: return result;
0471: }
0472: oipi.set("orderItemPriceInfoId", oipiSeqId.toString());
0473: oipi.set("orderId", orderId);
0474: toBeStored.add(oipi);
0475: }
0476: }
0477:
0478: // store the orderProductPromoUseInfos
0479: List orderProductPromoUses = (List) context
0480: .get("orderProductPromoUses");
0481: if (orderProductPromoUses != null
0482: && orderProductPromoUses.size() > 0) {
0483: Iterator orderProductPromoUseIter = orderProductPromoUses
0484: .iterator();
0485: while (orderProductPromoUseIter.hasNext()) {
0486: GenericValue productPromoUse = (GenericValue) orderProductPromoUseIter
0487: .next();
0488: productPromoUse.set("orderId", orderId);
0489: toBeStored.add(productPromoUse);
0490: }
0491: }
0492:
0493: // define the roles for the order
0494: List userOrderRoleTypes = null;
0495: if ("SALES_ORDER".equals(orderTypeId)) {
0496: userOrderRoleTypes = UtilMisc.toList("END_USER_CUSTOMER",
0497: "SHIP_TO_CUSTOMER", "BILL_TO_CUSTOMER",
0498: "PLACING_CUSTOMER");
0499: } else if ("PURCHASE_ORDER".equals(orderTypeId)) {
0500: userOrderRoleTypes = UtilMisc.toList("SHIP_FROM_VENDOR",
0501: "BILL_FROM_VENDOR", "SUPPLIER_AGENT");
0502: } else if ("WORK_ORDER".equals(orderTypeId)) {
0503: // TODO: set the work order roles
0504: } else {
0505: // TODO: some default behavior
0506: }
0507:
0508: // now add the roles
0509: if (userOrderRoleTypes != null) {
0510: Iterator i = userOrderRoleTypes.iterator();
0511: while (i.hasNext()) {
0512: String roleType = (String) i.next();
0513: String this Party = partyId;
0514: if (this Party == null) {
0515: this Party = "_NA_"; // will always set these roles so we can query
0516: }
0517: // make sure the party is in the role before adding
0518: toBeStored.add(delegator.makeValue("PartyRole",
0519: UtilMisc.toMap("partyId", partyId,
0520: "roleTypeId", roleType)));
0521: toBeStored.add(delegator.makeValue("OrderRole",
0522: UtilMisc.toMap("orderId", orderId, "partyId",
0523: partyId, "roleTypeId", roleType)));
0524: }
0525: }
0526:
0527: // set the affiliate -- This is going to be removed...
0528: String affiliateId = (String) context.get("affiliateId");
0529: if (UtilValidate.isNotEmpty(affiliateId)) {
0530: toBeStored.add(delegator.makeValue("OrderRole", UtilMisc
0531: .toMap("orderId", orderId, "partyId", affiliateId,
0532: "roleTypeId", "AFFILIATE")));
0533: }
0534:
0535: // set the distributor
0536: String distributorId = (String) context.get("distributorId");
0537: if (UtilValidate.isNotEmpty(distributorId)) {
0538: toBeStored.add(delegator
0539: .makeValue("OrderRole", UtilMisc.toMap("orderId",
0540: orderId, "partyId", distributorId,
0541: "roleTypeId", "DISTRIBUTOR")));
0542: }
0543:
0544: // find all parties in role VENDOR associated with WebSite OR ProductStore (where WebSite overrides, if specified), associated first valid with the Order
0545: if (UtilValidate.isNotEmpty((String) context
0546: .get("productStoreId"))) {
0547: try {
0548: List productStoreRoles = delegator.findByAnd(
0549: "ProductStoreRole", UtilMisc.toMap(
0550: "roleTypeId", "VENDOR",
0551: "productStoreId", context
0552: .get("productStoreId")),
0553: UtilMisc.toList("-fromDate"));
0554: productStoreRoles = EntityUtil.filterByDate(
0555: productStoreRoles, true);
0556: GenericValue productStoreRole = EntityUtil
0557: .getFirst(productStoreRoles);
0558: if (productStoreRole != null) {
0559: toBeStored.add(delegator.makeValue("OrderRole",
0560: UtilMisc.toMap("orderId", orderId,
0561: "partyId", productStoreRole
0562: .get("partyId"),
0563: "roleTypeId", "VENDOR")));
0564: }
0565: } catch (GenericEntityException e) {
0566: Debug
0567: .logError(
0568: e,
0569: "Error looking up Vendor for the current Product Store",
0570: module);
0571: }
0572:
0573: }
0574: if (UtilValidate.isNotEmpty((String) context.get("webSiteId"))) {
0575: try {
0576: List webSiteRoles = delegator.findByAnd("WebSiteRole",
0577: UtilMisc.toMap("roleTypeId", "VENDOR",
0578: "webSiteId", context.get("webSiteId")),
0579: UtilMisc.toList("-fromDate"));
0580: webSiteRoles = EntityUtil.filterByDate(webSiteRoles,
0581: true);
0582: GenericValue webSiteRole = EntityUtil
0583: .getFirst(webSiteRoles);
0584: if (webSiteRole != null) {
0585: toBeStored.add(delegator.makeValue("OrderRole",
0586: UtilMisc.toMap("orderId", orderId,
0587: "partyId", webSiteRole
0588: .get("partyId"),
0589: "roleTypeId", "VENDOR")));
0590: }
0591: } catch (GenericEntityException e) {
0592: Debug
0593: .logError(
0594: e,
0595: "Error looking up Vendor for the current Web Site",
0596: module);
0597: }
0598:
0599: }
0600:
0601: // set the order payment preferences
0602: List paymentPreferences = (List) context
0603: .get("orderPaymentPreferences");
0604: if (paymentPreferences != null && paymentPreferences.size() > 0) {
0605: Iterator oppIter = paymentPreferences.iterator();
0606: while (oppIter.hasNext()) {
0607: GenericValue paymentPreference = (GenericValue) oppIter
0608: .next();
0609: if (paymentPreference.get("orderPaymentPreferenceId") == null)
0610: paymentPreference.set("orderPaymentPreferenceId",
0611: delegator.getNextSeqId(
0612: "OrderPaymentPreference")
0613: .toString());
0614: if (paymentPreference.get("statusId") == null)
0615: paymentPreference.set("statusId",
0616: "PAYMENT_NOT_RECEIVED");
0617: paymentPreference.set("orderId", orderId);
0618: toBeStored.add(paymentPreference);
0619: }
0620: }
0621:
0622: // store the trackingCodeOrder entities
0623: List trackingCodeOrders = (List) context
0624: .get("trackingCodeOrders");
0625: if (trackingCodeOrders != null && trackingCodeOrders.size() > 0) {
0626: Iterator tkcdordIter = trackingCodeOrders.iterator();
0627: while (tkcdordIter.hasNext()) {
0628: GenericValue trackingCodeOrder = (GenericValue) tkcdordIter
0629: .next();
0630: trackingCodeOrder.set("orderId", orderId);
0631: toBeStored.add(trackingCodeOrder);
0632: }
0633: }
0634:
0635: try {
0636: // store line items, etc so that they will be there for the foreign key checks
0637: delegator.storeAll(toBeStored);
0638:
0639: if ("SALES_ORDER".equals(orderTypeId)
0640: || "WORK_ORDER".equals(orderTypeId)) {
0641: // START inventory reservation
0642: // decrement inventory available for each item, within the same transaction
0643: List resErrorMessages = new LinkedList();
0644: Iterator invDecItemIter = orderItems.iterator();
0645:
0646: while (invDecItemIter.hasNext()) {
0647: GenericValue orderItem = (GenericValue) invDecItemIter
0648: .next();
0649: if (orderItem.get("productId") != null) {
0650: // only reserve product items; ignore non-product items
0651: Double inventoryNotReserved = ProductStoreWorker
0652: .reserveStoreInventory(
0653: productStoreId,
0654: orderItem
0655: .getString("productId"),
0656: orderItem.getDouble("quantity"),
0657: orderItem.getString("orderId"),
0658: orderItem
0659: .getString("orderItemSeqId"),
0660: userLogin, delegator,
0661: dispatcher);
0662:
0663: if (inventoryNotReserved != null) {
0664: // if inventoryNotReserved is not 0.0 then that is the amount that it couldn't reserve
0665: GenericValue product = null;
0666:
0667: try {
0668: product = delegator
0669: .findByPrimaryKeyCache(
0670: "Product",
0671: UtilMisc
0672: .toMap(
0673: "productId",
0674: orderItem
0675: .getString("productId")));
0676: } catch (GenericEntityException e) {
0677: Debug
0678: .logError(
0679: e,
0680: "Error when looking up product in createOrder service, product failed inventory reservation",
0681: module);
0682: }
0683: String invErrMsg = "The product ";
0684:
0685: if (product != null) {
0686: invErrMsg += getProductName(product,
0687: orderItem);
0688: }
0689: invErrMsg += " with ID "
0690: + orderItem.getString("productId")
0691: + " is no longer in stock. Please try reducing the quantity or removing the product from this order.";
0692: resErrorMessages.add(invErrMsg);
0693: }
0694: }
0695: }
0696:
0697: if (resErrorMessages.size() > 0) {
0698: result.put(ModelService.RESPONSE_MESSAGE,
0699: ModelService.RESPOND_ERROR);
0700: result.put(ModelService.ERROR_MESSAGE_LIST,
0701: resErrorMessages);
0702: return result;
0703: }
0704: // END inventory reservation
0705: }
0706:
0707: result.put("orderId", orderId);
0708: result.put(ModelService.RESPONSE_MESSAGE,
0709: ModelService.RESPOND_SUCCESS);
0710: } catch (GenericEntityException e) {
0711: Debug.logError(e, "Problem with reservations", module);
0712: result.put(ModelService.RESPONSE_MESSAGE,
0713: ModelService.RESPOND_ERROR);
0714: result.put(ModelService.ERROR_MESSAGE,
0715: "ERROR: Could not create order (write error: "
0716: + e.getMessage() + ").");
0717: }
0718:
0719: return result;
0720: }
0721:
0722: public static String getProductName(GenericValue product,
0723: GenericValue orderItem) {
0724: if (UtilValidate.isNotEmpty(product.getString("productName"))) {
0725: return product.getString("productName");
0726: } else {
0727: return orderItem.getString("itemDescription");
0728: }
0729: }
0730:
0731: public static String getProductName(GenericValue product,
0732: String orderItemName) {
0733: if (UtilValidate.isNotEmpty(product.getString("productName"))) {
0734: return product.getString("productName");
0735: } else {
0736: return orderItemName;
0737: }
0738: }
0739:
0740: /** Service for resetting the OrderHeader grandTotal */
0741: public static Map resetGrandTotal(DispatchContext ctx, Map context) {
0742: GenericDelegator delegator = ctx.getDelegator();
0743: //appears to not be used: GenericValue userLogin = (GenericValue) context.get("userLogin");
0744: String orderId = (String) context.get("orderId");
0745:
0746: GenericValue orderHeader = null;
0747: try {
0748: orderHeader = delegator.findByPrimaryKey("OrderHeader",
0749: UtilMisc.toMap("orderId", orderId));
0750: } catch (GenericEntityException e) {
0751: String errMsg = "ERROR: Could not set grantTotal on OrderHeader entity: "
0752: + e.toString();
0753: Debug.logError(e, errMsg, module);
0754: return ServiceUtil.returnError(errMsg);
0755: }
0756:
0757: if (orderHeader != null) {
0758: OrderReadHelper orh = new OrderReadHelper(orderHeader);
0759: Double currentTotal = orderHeader.getDouble("grandTotal");
0760: if (orh.getOrderGrandTotal() != currentTotal.doubleValue()) {
0761: orderHeader.set("grandTotal", new Double(orh
0762: .getOrderGrandTotal()));
0763: try {
0764: orderHeader.store();
0765: } catch (GenericEntityException e) {
0766: String errMsg = "ERROR: Could not set grantTotal on OrderHeader entity: "
0767: + e.toString();
0768: Debug.logError(e, errMsg, module);
0769: return ServiceUtil.returnError(errMsg);
0770: }
0771: }
0772: }
0773:
0774: return ServiceUtil.returnSuccess();
0775: }
0776:
0777: /** Service for setting the OrderHeader grandTotal for all OrderHeaders with no grandTotal */
0778: public static Map setEmptyGrandTotals(DispatchContext ctx,
0779: Map context) {
0780: GenericDelegator delegator = ctx.getDelegator();
0781: LocalDispatcher dispatcher = ctx.getDispatcher();
0782: GenericValue userLogin = (GenericValue) context
0783: .get("userLogin");
0784:
0785: try {
0786: EntityListIterator eli = delegator
0787: .findListIteratorByCondition("OrderHeader",
0788: new EntityExpr("grandTotal",
0789: EntityOperator.EQUALS, null),
0790: UtilMisc.toList("orderId"), null);
0791: GenericValue orderHeader = null;
0792: List orderIdList = new LinkedList();
0793: while ((orderHeader = (GenericValue) eli.next()) != null) {
0794: orderIdList.add(orderHeader.get("orderId"));
0795: }
0796: eli.close();
0797:
0798: Iterator orderIdIter = orderIdList.iterator();
0799: while (orderIdIter.hasNext()) {
0800: String orderId = (String) orderIdIter.next();
0801: Map results = dispatcher.runSync("resetGrandTotal",
0802: UtilMisc.toMap("orderId", orderId, "userLogin",
0803: userLogin));
0804: if (ServiceUtil.isError(results)) {
0805: return ServiceUtil.returnError(null, null, null,
0806: results);
0807: }
0808: }
0809: } catch (GenericServiceException e) {
0810: String errMsg = "ERROR: Could not set grantTotal on OrderHeader entity: "
0811: + e.toString();
0812: Debug.logError(e, errMsg, module);
0813: return ServiceUtil.returnError(errMsg);
0814: } catch (GenericEntityException e) {
0815: String errMsg = "ERROR: Could not set grantTotal on OrderHeader entity: "
0816: + e.toString();
0817: Debug.logError(e, errMsg, module);
0818: return ServiceUtil.returnError(errMsg);
0819: }
0820:
0821: return ServiceUtil.returnSuccess();
0822: }
0823:
0824: /** Service for checking and re-clac the tax amount */
0825: public static Map recalcOrderTax(DispatchContext ctx, Map context) {
0826: LocalDispatcher dispatcher = ctx.getDispatcher();
0827: GenericDelegator delegator = ctx.getDelegator();
0828: String orderId = (String) context.get("orderId");
0829: GenericValue userLogin = (GenericValue) context
0830: .get("userLogin");
0831:
0832: // check and make sure we have permission to change the order
0833: Security security = ctx.getSecurity();
0834: if (!security.hasEntityPermission("ORDERMGR", "_UPDATE",
0835: userLogin)) {
0836: GenericValue placingCustomer = null;
0837: try {
0838: Map placingCustomerFields = UtilMisc.toMap("orderId",
0839: orderId, "partyId", userLogin
0840: .getString("partyId"), "roleTypeId",
0841: "PLACING_CUSTOMER");
0842: placingCustomer = delegator.findByPrimaryKey(
0843: "OrderRole", placingCustomerFields);
0844: } catch (GenericEntityException e) {
0845: return ServiceUtil
0846: .returnError("ERROR: Cannot get OrderRole entity: "
0847: + e.getMessage());
0848: }
0849: if (placingCustomer == null)
0850: return ServiceUtil
0851: .returnError("You do not have permission to change this order's status.");
0852: }
0853:
0854: // get the order header
0855: GenericValue orderHeader = null;
0856: try {
0857: orderHeader = delegator.findByPrimaryKey("OrderHeader",
0858: UtilMisc.toMap("orderId", orderId));
0859: } catch (GenericEntityException e) {
0860: return ServiceUtil
0861: .returnError("ERROR: Cannot get OrderHeader entity: "
0862: + e.getMessage());
0863: }
0864:
0865: if (orderHeader == null) {
0866: return ServiceUtil
0867: .returnError("ERROR: No valid order header found for orderId : "
0868: + orderId);
0869: }
0870:
0871: // remove the tax adjustments
0872: int removed = 0;
0873: try {
0874: removed = delegator.removeByAnd("OrderAdjustment", UtilMisc
0875: .toMap("orderId", orderId, "orderAdjustmentTypeId",
0876: "SALES_TAX"));
0877: } catch (GenericEntityException e) {
0878: Debug.logError(e,
0879: "Unable to remove SALES_TAX adjustments for order : "
0880: + orderId, module);
0881: return ServiceUtil
0882: .returnError("Unable to remove SALES_TAX adjustments");
0883: }
0884: Debug.logInfo("Removed : " + removed
0885: + " SALES_TAX adjustments for order [" + orderId + "]",
0886: module);
0887:
0888: OrderReadHelper orh = new OrderReadHelper(orderHeader);
0889: List validOrderItems = orh.getValidOrderItems();
0890: if (validOrderItems != null) {
0891: // prepare the inital lists
0892: List products = new ArrayList(validOrderItems.size());
0893: List amounts = new ArrayList(validOrderItems.size());
0894: List shipAmts = new ArrayList(validOrderItems.size());
0895:
0896: // adjustments and total
0897: List allAdjustments = orh.getAdjustments();
0898: List orderHeaderAdjustments = OrderReadHelper
0899: .getOrderHeaderAdjustments(allAdjustments);
0900: double orderSubTotal = OrderReadHelper
0901: .getOrderItemsSubTotal(validOrderItems,
0902: allAdjustments);
0903:
0904: // shipping amount
0905: Double orderShipping = new Double(OrderReadHelper
0906: .calcOrderAdjustments(orderHeaderAdjustments,
0907: orderSubTotal, false, false, true));
0908:
0909: // build up the list of tax calc service parameters
0910: for (int i = 0; i < validOrderItems.size(); i++) {
0911: GenericValue orderItem = (GenericValue) validOrderItems
0912: .get(i);
0913:
0914: try {
0915: products.add(i, orderItem.getRelatedOne("Product")); // get the product entity
0916: amounts.add(i, new Double(OrderReadHelper
0917: .getOrderItemSubTotal(orderItem,
0918: allAdjustments, true, false))); // get the item amount
0919: shipAmts.add(i,
0920: new Double(OrderReadHelper
0921: .getOrderItemAdjustmentsTotal(
0922: orderItem, allAdjustments,
0923: false, false, true))); // get the shipping amount
0924: } catch (GenericEntityException e) {
0925: Debug.logError(e,
0926: "Cannot read order item entity : "
0927: + orderItem, module);
0928: return ServiceUtil
0929: .returnError("Cannot read the order item entity");
0930: }
0931: }
0932:
0933: // prepare the service context
0934: Map serviceContext = UtilMisc.toMap("productStoreId", orh
0935: .getProductStoreId(), "itemProductList", products,
0936: "itemAmountList", amounts, "itemShippingList",
0937: shipAmts, "orderShippingAmount", orderShipping,
0938: "shippingAddress", orh.getShippingAddress());
0939:
0940: // invoke the calcTax service
0941: Map serviceResult = null;
0942: try {
0943: serviceResult = dispatcher.runSync("calcTax",
0944: serviceContext);
0945: } catch (GenericServiceException e) {
0946: Debug.logError(e, module);
0947: return ServiceUtil
0948: .returnError("Problem occurred in tax service");
0949: }
0950:
0951: if (ServiceUtil.isError(serviceResult)) {
0952: return ServiceUtil.returnError(ServiceUtil
0953: .getErrorMessage(serviceResult));
0954: }
0955:
0956: // the adjustments (returned in order) from the tax service
0957: List orderAdj = (List) serviceResult
0958: .get("orderAdjustments");
0959: List itemAdj = (List) serviceResult.get("itemAdjustments");
0960:
0961: // the toStore List
0962: List toStore = new ArrayList();
0963:
0964: // set the order adjustments
0965: if (orderAdj != null && orderAdj.size() > 0) {
0966: Iterator oai = orderAdj.iterator();
0967: while (oai.hasNext()) {
0968: GenericValue oa = (GenericValue) oai.next();
0969:
0970: Long adjSeqId = delegator
0971: .getNextSeqId("OrderAdjustment");
0972: oa.set("orderAdjustmentId", adjSeqId.toString());
0973: oa.set("orderId", orderId);
0974: toStore.add(oa);
0975: }
0976: }
0977:
0978: // set the item adjustments
0979: if (itemAdj != null && itemAdj.size() > 0) {
0980: for (int i = 0; i < validOrderItems.size(); i++) {
0981: GenericValue orderItem = (GenericValue) validOrderItems
0982: .get(i);
0983: List itemAdjustments = (List) itemAdj.get(i);
0984: Iterator ida = itemAdjustments.iterator();
0985: while (ida.hasNext()) {
0986: GenericValue ia = (GenericValue) ida.next();
0987:
0988: Long adjSeqId = delegator
0989: .getNextSeqId("OrderAdjustment");
0990: ia
0991: .set("orderAdjustmentId", adjSeqId
0992: .toString());
0993: ia.set("orderId", orderId);
0994: ia.set("orderItemSeqId", orderItem
0995: .getString("orderItemSeqId"));
0996: toStore.add(ia);
0997: }
0998: }
0999: }
1000:
1001: // store the new adjustments
1002: try {
1003: delegator.storeAll(toStore);
1004: } catch (GenericEntityException e) {
1005: Debug.logError(e, module);
1006: return ServiceUtil
1007: .returnError("Unable to update order tax information : "
1008: + orderId);
1009: }
1010: }
1011:
1012: return ServiceUtil.returnSuccess();
1013: }
1014:
1015: /** Service for checking and re-calc the shipping amount */
1016: public static Map recalcOrderShipping(DispatchContext ctx,
1017: Map context) {
1018: GenericDelegator delegator = ctx.getDelegator();
1019: String orderId = (String) context.get("orderId");
1020: GenericValue userLogin = (GenericValue) context
1021: .get("userLogin");
1022:
1023: // check and make sure we have permission to change the order
1024: Security security = ctx.getSecurity();
1025: if (!security.hasEntityPermission("ORDERMGR", "_UPDATE",
1026: userLogin)) {
1027: GenericValue placingCustomer = null;
1028: try {
1029: Map placingCustomerFields = UtilMisc.toMap("orderId",
1030: orderId, "partyId", userLogin
1031: .getString("partyId"), "roleTypeId",
1032: "PLACING_CUSTOMER");
1033: placingCustomer = delegator.findByPrimaryKey(
1034: "OrderRole", placingCustomerFields);
1035: } catch (GenericEntityException e) {
1036: return ServiceUtil
1037: .returnError("ERROR: Cannot get OrderRole entity: "
1038: + e.getMessage());
1039: }
1040: if (placingCustomer == null)
1041: return ServiceUtil
1042: .returnError("You do not have permission to change this order's status.");
1043: }
1044:
1045: // get the order header
1046: GenericValue orderHeader = null;
1047: try {
1048: orderHeader = delegator.findByPrimaryKey("OrderHeader",
1049: UtilMisc.toMap("orderId", orderId));
1050: } catch (GenericEntityException e) {
1051: return ServiceUtil
1052: .returnError("ERROR: Cannot get OrderHeader entity: "
1053: + e.getMessage());
1054: }
1055:
1056: if (orderHeader == null) {
1057: return ServiceUtil
1058: .returnError("ERROR: No valid order header found for orderId : "
1059: + orderId);
1060: }
1061:
1062: OrderReadHelper orh = new OrderReadHelper(orderHeader);
1063: if (Debug.verboseOn()) {
1064: Debug.logVerbose("Shippable Total : "
1065: + orh.getShippableTotal(), module);
1066: }
1067:
1068: Map shippingEstMap = ShippingEvents.getShipEstimate(delegator,
1069: orh);
1070:
1071: Double shippingTotal = null;
1072: if (orh.getValidOrderItems() == null
1073: || orh.getValidOrderItems().size() == 0) {
1074: shippingTotal = new Double(0.00);
1075: } else {
1076: shippingTotal = (Double) shippingEstMap
1077: .get("shippingTotal");
1078: }
1079: if (Debug.verboseOn()) {
1080: Debug.logVerbose("New Shipping Total : " + shippingTotal,
1081: module);
1082: }
1083:
1084: double currentShipping = OrderReadHelper
1085: .getAllOrderItemsAdjustmentsTotal(orh.getOrderItems(),
1086: orh.getAdjustments(), false, false, true);
1087: currentShipping += OrderReadHelper.calcOrderAdjustments(orh
1088: .getOrderHeaderAdjustments(), orh
1089: .getOrderItemsSubTotal(), false, false, true);
1090:
1091: if (Debug.verboseOn()) {
1092: Debug.log("Old Shipping Total : " + currentShipping);
1093: }
1094:
1095: List errorMessageList = (List) shippingEstMap
1096: .get(ModelService.ERROR_MESSAGE_LIST);
1097: if (errorMessageList != null) {
1098: return ServiceUtil.returnError(errorMessageList);
1099: }
1100:
1101: if (shippingTotal.doubleValue() != currentShipping) {
1102: // place the difference as a new shipping adjustment
1103: Double adjustmentAmount = new Double(shippingTotal
1104: .doubleValue()
1105: - currentShipping);
1106: String adjSeqId = delegator.getNextSeqId("OrderAdjustment")
1107: .toString();
1108: GenericValue orderAdjustment = delegator.makeValue(
1109: "OrderAdjustment", UtilMisc.toMap(
1110: "orderAdjustmentId", adjSeqId));
1111: orderAdjustment.set("orderAdjustmentTypeId",
1112: "SHIPPING_CHARGES");
1113: orderAdjustment.set("amount", adjustmentAmount);
1114: orderAdjustment.set("orderId", orh.getOrderId());
1115: orderAdjustment.set("orderItemSeqId",
1116: DataModelConstants.SEQ_ID_NA);
1117: //orderAdjustment.set("comments", "Shipping Re-Calc Adjustment");
1118: try {
1119: orderAdjustment.create();
1120: } catch (GenericEntityException e) {
1121: Debug.logError(e,
1122: "Problem creating shipping re-calc adjustment : "
1123: + orderAdjustment, module);
1124: return ServiceUtil
1125: .returnError("ERROR: Cannot create adjustment");
1126: }
1127: }
1128:
1129: // TODO: re-balance free shipping adjustment
1130:
1131: return ServiceUtil.returnSuccess();
1132:
1133: }
1134:
1135: /** Service for checking to see if an order is fully completed or canceled */
1136: public static Map checkItemStatus(DispatchContext ctx, Map context) {
1137: GenericDelegator delegator = ctx.getDelegator();
1138: LocalDispatcher dispatcher = ctx.getDispatcher();
1139:
1140: GenericValue userLogin = (GenericValue) context
1141: .get("userLogin");
1142: String orderId = (String) context.get("orderId");
1143:
1144: // check and make sure we have permission to change the order
1145: Security security = ctx.getSecurity();
1146: if (!security.hasEntityPermission("ORDERMGR", "_UPDATE",
1147: userLogin)) {
1148: GenericValue placingCustomer = null;
1149: try {
1150: Map placingCustomerFields = UtilMisc.toMap("orderId",
1151: orderId, "partyId", userLogin
1152: .getString("partyId"), "roleTypeId",
1153: "PLACING_CUSTOMER");
1154: placingCustomer = delegator.findByPrimaryKey(
1155: "OrderRole", placingCustomerFields);
1156: } catch (GenericEntityException e) {
1157: return ServiceUtil
1158: .returnError("ERROR: Cannot get OrderRole entity: "
1159: + e.getMessage());
1160: }
1161: if (placingCustomer == null)
1162: return ServiceUtil
1163: .returnError("You do not have permission to change this order's status.");
1164: }
1165:
1166: // get the order header
1167: GenericValue orderHeader = null;
1168: try {
1169: orderHeader = delegator.findByPrimaryKey("OrderHeader",
1170: UtilMisc.toMap("orderId", orderId));
1171: } catch (GenericEntityException e) {
1172: Debug.logError(e, "Cannot get OrderHeader record", module);
1173: }
1174: if (orderHeader == null) {
1175: Debug.logError("OrderHeader came back as null", module);
1176: return ServiceUtil
1177: .returnError("Cannot update null order header ["
1178: + orderId + "]");
1179: }
1180:
1181: // get the order items
1182: List orderItems = null;
1183: try {
1184: orderItems = delegator.findByAnd("OrderItem", UtilMisc
1185: .toMap("orderId", orderId));
1186: } catch (GenericEntityException e) {
1187: Debug.logError(e, "Cannot get OrderItem records", module);
1188: return ServiceUtil
1189: .returnError("Problem getting OrderItem records");
1190: }
1191:
1192: boolean allCanceled = true;
1193: boolean allComplete = true;
1194: boolean allApproved = true;
1195: if (orderItems != null) {
1196: Iterator itemIter = orderItems.iterator();
1197: while (itemIter.hasNext()) {
1198: GenericValue item = (GenericValue) itemIter.next();
1199: String statusId = item.getString("statusId");
1200: //Debug.log("Item Status: " + statusId, module);
1201: if (!"ITEM_CANCELLED".equals(statusId)) {
1202: //Debug.log("Not set to cancel", module);
1203: allCanceled = false;
1204: if (!"ITEM_COMPLETED".equals(statusId)) {
1205: //Debug.log("Not set to complete", module);
1206: allComplete = false;
1207: if (!"ITEM_APPROVED".equals(statusId)) {
1208: //Debug.log("Not set to approve", module);
1209: allApproved = false;
1210: break;
1211: }
1212: }
1213: }
1214: }
1215:
1216: // find the next status to set to (if any)
1217: String newStatus = null;
1218: if (allCanceled) {
1219: newStatus = "ORDER_CANCELLED";
1220: } else if (allComplete) {
1221: newStatus = "ORDER_COMPLETED";
1222: } else if (allApproved) {
1223: if (!"ORDER_SENT".equals(orderHeader
1224: .getString("statusId"))) {
1225: newStatus = "ORDER_APPROVED";
1226: }
1227: }
1228:
1229: // now set the new order status
1230: if (newStatus != null) {
1231: Map serviceContext = UtilMisc.toMap("orderId", orderId,
1232: "statusId", newStatus, "userLogin", userLogin);
1233: try {
1234: Map result = dispatcher.runSync(
1235: "changeOrderStatus", serviceContext);
1236: } catch (GenericServiceException e) {
1237: Debug
1238: .logError(
1239: e,
1240: "Problem calling the changeOrderStatus service",
1241: module);
1242: }
1243: }
1244: } else {
1245: Debug.logWarning(
1246: "Received NULL for OrderItem records orderId : "
1247: + orderId, module);
1248: }
1249:
1250: return ServiceUtil.returnSuccess();
1251: }
1252:
1253: /** Service to cancel an order item quantity */
1254: public static Map cancelOrderItem(DispatchContext ctx, Map context) {
1255: LocalDispatcher dispatcher = ctx.getDispatcher();
1256: GenericDelegator delegator = ctx.getDelegator();
1257:
1258: GenericValue userLogin = (GenericValue) context
1259: .get("userLogin");
1260: Double cancelQuantity = (Double) context.get("cancelQuantity");
1261: String orderId = (String) context.get("orderId");
1262: String orderItemSeqId = (String) context.get("orderItemSeqId");
1263:
1264: // debugging message info
1265: String itemMsgInfo = orderId + " / " + orderItemSeqId;
1266:
1267: // check and make sure we have permission to change the order
1268: Security security = ctx.getSecurity();
1269: if (!security.hasEntityPermission("ORDERMGR", "_UPDATE",
1270: userLogin)) {
1271: GenericValue placingCustomer = null;
1272: try {
1273: Map placingCustomerFields = UtilMisc.toMap("orderId",
1274: orderId, "partyId", userLogin
1275: .getString("partyId"), "roleTypeId",
1276: "PLACING_CUSTOMER");
1277: placingCustomer = delegator.findByPrimaryKey(
1278: "OrderRole", placingCustomerFields);
1279: } catch (GenericEntityException e) {
1280: Debug.logError(e, module);
1281: return ServiceUtil
1282: .returnError("ERROR: Cannot get OrderRole entity: "
1283: + itemMsgInfo);
1284: }
1285: if (placingCustomer == null)
1286: return ServiceUtil
1287: .returnError("You do not have permission to change this order's status.");
1288: }
1289:
1290: Map fields = UtilMisc.toMap("orderId", orderId);
1291: if (orderItemSeqId != null) {
1292: fields.put("orderItemSeqId", orderItemSeqId);
1293: }
1294:
1295: List orderItems = null;
1296: try {
1297: orderItems = delegator.findByAnd("OrderItem", fields);
1298: } catch (GenericEntityException e) {
1299: Debug.logError(e, module);
1300: return ServiceUtil
1301: .returnError("ERROR: Cannot get OrderItem entity: "
1302: + itemMsgInfo);
1303: }
1304:
1305: if (orderItems != null && orderItems.size() > 0) {
1306: Iterator itemsIterator = orderItems.iterator();
1307: while (itemsIterator.hasNext()) {
1308: GenericValue orderItem = (GenericValue) itemsIterator
1309: .next();
1310: if (orderItem == null) {
1311: ServiceUtil
1312: .returnError("ERROR: Cannot cancel item; item not found : "
1313: + itemMsgInfo);
1314: }
1315:
1316: Double quantity = orderItem.getDouble("quantity");
1317: Double cancelQty = orderItem
1318: .getDouble("cancelQuantity");
1319: if (quantity == null)
1320: quantity = new Double(0.0);
1321: if (cancelQty == null)
1322: cancelQty = new Double(0.0);
1323: Double this CancelQty = null;
1324: if (cancelQuantity != null) {
1325: this CancelQty = new Double(cancelQuantity
1326: .doubleValue());
1327: } else {
1328: this CancelQty = new Double(quantity.doubleValue());
1329: }
1330: orderItem.set("cancelQuantity", this CancelQty);
1331: try {
1332: orderItem.store();
1333: } catch (GenericEntityException e) {
1334: Debug.logError(e, module);
1335: return ServiceUtil
1336: .returnError("Unable to set cancel quantity : "
1337: + itemMsgInfo);
1338: }
1339: if (this CancelQty.doubleValue() >= quantity
1340: .doubleValue()) {
1341: // all items are cancelled -- mark the item as cancelled
1342: Map statusCtx = UtilMisc.toMap("orderId", orderId,
1343: "orderItemSeqId", orderItemSeqId,
1344: "statusId", "ITEM_CANCELLED", "userLogin",
1345: userLogin);
1346: try {
1347: dispatcher.runSyncIgnore(
1348: "changeOrderItemStatus", statusCtx);
1349: } catch (GenericServiceException e) {
1350: Debug.logError(e, module);
1351: return ServiceUtil
1352: .returnError("Unable to cancel order line : "
1353: + itemMsgInfo);
1354: }
1355: } else {
1356: // reverse the inventory reservation
1357: Map invCtx = UtilMisc.toMap("orderId", orderId,
1358: "orderItemSeqId", orderItemSeqId,
1359: "cancelQuantity", this CancelQty,
1360: "userLogin", userLogin);
1361: try {
1362: dispatcher.runSyncIgnore(
1363: "cancelOrderItemInvResQty", invCtx);
1364: } catch (GenericServiceException e) {
1365: Debug.logError(e, module);
1366: return ServiceUtil
1367: .returnError("Unable to update inventory reservations : "
1368: + itemMsgInfo);
1369: }
1370: }
1371: }
1372: }
1373:
1374: return ServiceUtil.returnSuccess();
1375: }
1376:
1377: /** Service for changing the status on order item(s) */
1378: public static Map setItemStatus(DispatchContext ctx, Map context) {
1379: GenericDelegator delegator = ctx.getDelegator();
1380:
1381: GenericValue userLogin = (GenericValue) context
1382: .get("userLogin");
1383: String orderId = (String) context.get("orderId");
1384: String orderItemSeqId = (String) context.get("orderItemSeqId");
1385: String fromStatusId = (String) context.get("fromStatusId");
1386: String statusId = (String) context.get("statusId");
1387:
1388: // check and make sure we have permission to change the order
1389: Security security = ctx.getSecurity();
1390: if (!security.hasEntityPermission("ORDERMGR", "_UPDATE",
1391: userLogin)) {
1392: GenericValue placingCustomer = null;
1393: try {
1394: Map placingCustomerFields = UtilMisc.toMap("orderId",
1395: orderId, "partyId", userLogin
1396: .getString("partyId"), "roleTypeId",
1397: "PLACING_CUSTOMER");
1398: placingCustomer = delegator.findByPrimaryKey(
1399: "OrderRole", placingCustomerFields);
1400: } catch (GenericEntityException e) {
1401: return ServiceUtil
1402: .returnError("ERROR: Cannot get OrderRole entity: "
1403: + e.getMessage());
1404: }
1405: if (placingCustomer == null)
1406: return ServiceUtil
1407: .returnError("You do not have permission to change this order's status.");
1408: }
1409:
1410: Map fields = UtilMisc.toMap("orderId", orderId);
1411: if (orderItemSeqId != null)
1412: fields.put("orderItemSeqId", orderItemSeqId);
1413: if (fromStatusId != null)
1414: fields.put("statusId", fromStatusId);
1415:
1416: List orderItems = null;
1417: try {
1418: orderItems = delegator.findByAnd("OrderItem", fields);
1419: } catch (GenericEntityException e) {
1420: return ServiceUtil
1421: .returnError("ERROR: Cannot get OrderItem entity: "
1422: + e.getMessage());
1423: }
1424:
1425: if (orderItems != null && orderItems.size() > 0) {
1426: List toBeStored = new ArrayList();
1427: Iterator itemsIterator = orderItems.iterator();
1428: while (itemsIterator.hasNext()) {
1429: GenericValue orderItem = (GenericValue) itemsIterator
1430: .next();
1431: if (orderItem == null)
1432: ServiceUtil
1433: .returnError("ERROR: Cannot change item status; item not found.");
1434: if (Debug.verboseOn())
1435: Debug
1436: .logVerbose(
1437: "[OrderServices.setItemStatus] : Status Change: ["
1438: + orderId
1439: + "] ("
1440: + orderItem
1441: .getString("orderItemSeqId"),
1442: module);
1443: if (Debug.verboseOn())
1444: Debug.logVerbose(
1445: "[OrderServices.setIte,Status] : From Status : "
1446: + orderItem.getString("statusId"),
1447: module);
1448: if (Debug.verboseOn())
1449: Debug.logVerbose(
1450: "[OrderServices.setOrderStatus] : To Status : "
1451: + statusId, module);
1452:
1453: if (orderItem.getString("statusId").equals(statusId)) {
1454: continue;
1455: }
1456:
1457: try {
1458: Map statusFields = UtilMisc.toMap("statusId",
1459: orderItem.getString("statusId"),
1460: "statusIdTo", statusId);
1461: GenericValue statusChange = delegator
1462: .findByPrimaryKeyCache("StatusValidChange",
1463: statusFields);
1464:
1465: if (statusChange == null) {
1466: Debug.logWarning("Item status not changed "
1467: + orderItem.getString("statusId")
1468: + " -> " + statusId
1469: + " is not a valid change.", module);
1470: continue;
1471: }
1472: } catch (GenericEntityException e) {
1473: return ServiceUtil
1474: .returnError("ERROR: Could not change item status: "
1475: + e.getMessage());
1476: }
1477:
1478: orderItem.set("statusId", statusId);
1479: toBeStored.add(orderItem);
1480:
1481: // now create a status change
1482: Map changeFields = new HashMap();
1483: changeFields.put("orderStatusId", delegator
1484: .getNextSeqId("OrderStatus").toString());
1485: changeFields.put("statusId", statusId);
1486: changeFields.put("orderId", orderId);
1487: changeFields.put("orderItemSeqId", orderItem
1488: .getString("orderItemSeqId"));
1489: changeFields.put("statusDatetime", UtilDateTime
1490: .nowTimestamp());
1491: GenericValue orderStatus = delegator.makeValue(
1492: "OrderStatus", changeFields);
1493: toBeStored.add(orderStatus);
1494: }
1495:
1496: // store the changes
1497: if (toBeStored.size() > 0) {
1498: try {
1499: delegator.storeAll(toBeStored);
1500: } catch (GenericEntityException e) {
1501: return ServiceUtil
1502: .returnError("ERROR: Cannot store status changes: "
1503: + e.getMessage());
1504: }
1505: }
1506:
1507: }
1508:
1509: return ServiceUtil.returnSuccess();
1510: }
1511:
1512: /** Service for changing the status on an order header */
1513: public static Map setOrderStatus(DispatchContext ctx, Map context) {
1514: Map result = new HashMap();
1515: GenericDelegator delegator = ctx.getDelegator();
1516:
1517: GenericValue userLogin = (GenericValue) context
1518: .get("userLogin");
1519: String orderId = (String) context.get("orderId");
1520: String statusId = (String) context.get("statusId");
1521:
1522: // check and make sure we have permission to change the order
1523: Security security = ctx.getSecurity();
1524: if (!security.hasEntityPermission("ORDERMGR", "_UPDATE",
1525: userLogin)) {
1526: GenericValue placingCustomer = null;
1527: try {
1528: Map placingCustomerFields = UtilMisc.toMap("orderId",
1529: orderId, "partyId", userLogin
1530: .getString("partyId"), "roleTypeId",
1531: "PLACING_CUSTOMER");
1532: placingCustomer = delegator.findByPrimaryKey(
1533: "OrderRole", placingCustomerFields);
1534: } catch (GenericEntityException e) {
1535: return ServiceUtil
1536: .returnError("ERROR: Cannot get OrderRole entity: "
1537: + e.getMessage());
1538: }
1539: if (placingCustomer == null)
1540: return ServiceUtil
1541: .returnError("You do not have permission to change this order's status.");
1542: }
1543:
1544: try {
1545: GenericValue orderHeader = delegator.findByPrimaryKey(
1546: "OrderHeader", UtilMisc.toMap("orderId", orderId));
1547:
1548: if (orderHeader == null) {
1549: result.put(ModelService.RESPONSE_MESSAGE,
1550: ModelService.RESPOND_ERROR);
1551: result
1552: .put(ModelService.ERROR_MESSAGE,
1553: "ERROR: Could not change order status; order cannot be found.");
1554: return result;
1555: }
1556: if (Debug.verboseOn())
1557: Debug.logVerbose(
1558: "[OrderServices.setOrderStatus] : From Status : "
1559: + orderHeader.getString("statusId"),
1560: module);
1561: if (Debug.verboseOn())
1562: Debug.logVerbose(
1563: "[OrderServices.setOrderStatus] : To Status : "
1564: + statusId, module);
1565:
1566: if (orderHeader.getString("statusId").equals(statusId)) {
1567: result.put(ModelService.RESPONSE_MESSAGE,
1568: ModelService.RESPOND_SUCCESS);
1569: return result;
1570: }
1571: try {
1572: Map statusFields = UtilMisc.toMap("statusId",
1573: orderHeader.getString("statusId"),
1574: "statusIdTo", statusId);
1575: GenericValue statusChange = delegator
1576: .findByPrimaryKeyCache("StatusValidChange",
1577: statusFields);
1578:
1579: if (statusChange == null) {
1580: result.put(ModelService.RESPONSE_MESSAGE,
1581: ModelService.RESPOND_ERROR);
1582: result
1583: .put(ModelService.ERROR_MESSAGE,
1584: "ERROR: Could not change order status; status is not a valid change.");
1585: return result;
1586: }
1587: } catch (GenericEntityException e) {
1588: result.put(ModelService.RESPONSE_MESSAGE,
1589: ModelService.RESPOND_ERROR);
1590: result.put(ModelService.ERROR_MESSAGE,
1591: "ERROR: Could not change order status ("
1592: + e.getMessage() + ").");
1593: return result;
1594: }
1595:
1596: // update the current status
1597: orderHeader.set("statusId", statusId);
1598:
1599: // now create a status change
1600: Map fields = new HashMap();
1601: fields.put("orderStatusId", delegator.getNextSeqId(
1602: "OrderStatus").toString());
1603: fields.put("statusId", statusId);
1604: fields.put("orderId", orderId);
1605: fields.put("statusDatetime", UtilDateTime.nowTimestamp());
1606: GenericValue orderStatus = delegator.makeValue(
1607: "OrderStatus", fields);
1608: List toBeStored = new ArrayList();
1609:
1610: toBeStored.add(orderHeader);
1611: toBeStored.add(orderStatus);
1612: delegator.storeAll(toBeStored);
1613: } catch (GenericEntityException e) {
1614: result.put(ModelService.RESPONSE_MESSAGE,
1615: ModelService.RESPOND_ERROR);
1616: result.put(ModelService.ERROR_MESSAGE,
1617: "ERROR: Could not change order status ("
1618: + e.getMessage() + ").");
1619: return result;
1620: }
1621:
1622: // release the inital hold if we are cancelled or approved
1623: if ("ORDER_CANCELLED".equals(statusId)
1624: || "ORDER_APPROVED".equals(statusId)) {
1625: OrderChangeHelper.releaseInitialOrderHold(ctx
1626: .getDispatcher(), orderId);
1627:
1628: // cancel any order processing if we are cancelled
1629: if ("ORDER_CANCELLED".equals(statusId)) {
1630: OrderChangeHelper.abortOrderProcessing(ctx
1631: .getDispatcher(), orderId);
1632: }
1633: }
1634:
1635: result.put(ModelService.RESPONSE_MESSAGE,
1636: ModelService.RESPOND_SUCCESS);
1637: result.put("orderStatusId", statusId);
1638: return result;
1639: }
1640:
1641: /** Service to update the order tracking number */
1642: public static Map updateTrackingNumber(DispatchContext dctx,
1643: Map context) {
1644: Map result = new HashMap();
1645: GenericDelegator delegator = dctx.getDelegator();
1646: String orderId = (String) context.get("orderId");
1647: String orderItemSeqId = (String) context.get("orderItemSeqId");
1648: String trackingNumber = (String) context.get("trackingNumber");
1649:
1650: if (orderItemSeqId == null || orderItemSeqId.length() == 0)
1651: orderItemSeqId = DataModelConstants.SEQ_ID_NA;
1652: try {
1653: GenericValue shipPref = delegator.findByPrimaryKey(
1654: "OrderShipmentPreference", UtilMisc.toMap(
1655: "orderId", orderId, "orderItemSeqId",
1656: orderItemSeqId));
1657:
1658: if (shipPref == null) {
1659: result.put(ModelService.RESPONSE_MESSAGE,
1660: ModelService.RESPOND_ERROR);
1661: result.put(ModelService.ERROR_MESSAGE,
1662: "ERROR: No order shipment preference found!");
1663: } else {
1664: shipPref.set("trackingNumber", trackingNumber);
1665: shipPref.store();
1666: result.put(ModelService.RESPONSE_MESSAGE,
1667: ModelService.RESPOND_SUCCESS);
1668: }
1669: } catch (GenericEntityException e) {
1670: Debug.logError(e, module);
1671: result.put(ModelService.RESPONSE_MESSAGE,
1672: ModelService.RESPOND_ERROR);
1673: result.put(ModelService.ERROR_MESSAGE,
1674: "ERROR: Could not set tracking number ("
1675: + e.getMessage() + ").");
1676: }
1677: return result;
1678: }
1679:
1680: /** Service to add a role type to an order */
1681: public static Map addRoleType(DispatchContext ctx, Map context) {
1682: Map result = new HashMap();
1683: GenericDelegator delegator = ctx.getDelegator();
1684: String orderId = (String) context.get("orderId");
1685: String partyId = (String) context.get("partyId");
1686: String roleTypeId = (String) context.get("roleTypeId");
1687: Boolean removeOld = (Boolean) context.get("removeOld");
1688:
1689: if (removeOld != null && removeOld.booleanValue()) {
1690: try {
1691: delegator.removeByAnd("OrderRole", UtilMisc.toMap(
1692: "orderId", orderId, "roleTypeId", roleTypeId));
1693: } catch (GenericEntityException e) {
1694: result.put(ModelService.RESPONSE_MESSAGE,
1695: ModelService.RESPOND_ERROR);
1696: result.put(ModelService.ERROR_MESSAGE,
1697: "ERROR: Could not remove old roles ("
1698: + e.getMessage() + ").");
1699: return result;
1700: }
1701: }
1702:
1703: Map fields = UtilMisc.toMap("orderId", orderId, "partyId",
1704: partyId, "roleTypeId", roleTypeId);
1705:
1706: try {
1707: // first check and see if we are already there; if so, just return success
1708: GenericValue testValue = delegator.findByPrimaryKey(
1709: "OrderRole", fields);
1710: if (testValue != null) {
1711: ServiceUtil.returnSuccess();
1712: } else {
1713: GenericValue value = delegator.makeValue("OrderRole",
1714: fields);
1715: delegator.create(value);
1716: }
1717: } catch (GenericEntityException e) {
1718: result.put(ModelService.RESPONSE_MESSAGE,
1719: ModelService.RESPOND_ERROR);
1720: result.put(ModelService.ERROR_MESSAGE,
1721: "ERROR: Could not add role to order ("
1722: + e.getMessage() + ").");
1723: return result;
1724: }
1725: result.put(ModelService.RESPONSE_MESSAGE,
1726: ModelService.RESPOND_SUCCESS);
1727: return result;
1728: }
1729:
1730: /** Service to remove a role type from an order */
1731: public static Map removeRoleType(DispatchContext ctx, Map context) {
1732: Map result = new HashMap();
1733: GenericDelegator delegator = ctx.getDelegator();
1734: String orderId = (String) context.get("orderId");
1735: String partyId = (String) context.get("partyId");
1736: String roleTypeId = (String) context.get("roleTypeId");
1737: Map fields = UtilMisc.toMap("orderId", orderId, "partyId",
1738: partyId, "roleTypeId", roleTypeId);
1739:
1740: GenericValue testValue = null;
1741:
1742: try {
1743: testValue = delegator.findByPrimaryKey("OrderRole", fields);
1744: } catch (GenericEntityException e) {
1745: result.put(ModelService.RESPONSE_MESSAGE,
1746: ModelService.RESPOND_ERROR);
1747: result.put(ModelService.ERROR_MESSAGE,
1748: "ERROR: Could not add role to order ("
1749: + e.getMessage() + ").");
1750: return result;
1751: }
1752:
1753: if (testValue == null) {
1754: result.put(ModelService.RESPONSE_MESSAGE,
1755: ModelService.RESPOND_SUCCESS);
1756: return result;
1757: }
1758:
1759: try {
1760: GenericValue value = delegator.findByPrimaryKey(
1761: "OrderRole", fields);
1762:
1763: value.remove();
1764: } catch (GenericEntityException e) {
1765: result.put(ModelService.RESPONSE_MESSAGE,
1766: ModelService.RESPOND_ERROR);
1767: result.put(ModelService.ERROR_MESSAGE,
1768: "ERROR: Could not remove role from order ("
1769: + e.getMessage() + ").");
1770: return result;
1771: }
1772: result.put(ModelService.RESPONSE_MESSAGE,
1773: ModelService.RESPOND_SUCCESS);
1774: return result;
1775: }
1776:
1777: /** Service to prepare notification data */
1778: public static Map prepareOrderEmailData(DispatchContext ctx,
1779: Map context) {
1780: Map result = new HashMap();
1781: GenericDelegator delegator = ctx.getDelegator();
1782: String orderId = (String) context.get("orderId");
1783:
1784: try {
1785: GenericValue orderHeader = delegator.findByPrimaryKey(
1786: "OrderHeader", UtilMisc.toMap("orderId", orderId));
1787: OrderReadHelper orh = new OrderReadHelper(orderHeader);
1788: List orderItems = orh.getOrderItems();
1789: List orderAdjustments = orh.getAdjustments();
1790: List orderHeaderAdjustments = orh
1791: .getOrderHeaderAdjustments();
1792: double orderSubTotal = orh.getOrderItemsSubTotal();
1793: List headerAdjustmentsToShow = orh
1794: .getOrderHeaderAdjustmentsToShow();
1795:
1796: //templateContext.put("localOrderReadHelper", orh);
1797: result.put("orderId", orderId);
1798: result.put("orderItemSeqId", context.get("orderItemSeqId"));
1799: result.put("orderHeader", orderHeader);
1800: result.put("orderItems", orh.getOrderItems());
1801: result.put("statusString", orh.getStatusString());
1802: result.put("orderAdjustments", orderAdjustments);
1803: result
1804: .put("orderHeaderAdjustments",
1805: orderHeaderAdjustments);
1806: result.put("orderSubTotal", new Double(orderSubTotal));
1807: result.put("headerAdjustmentsToShow",
1808: headerAdjustmentsToShow);
1809:
1810: double shippingAmount = OrderReadHelper
1811: .getAllOrderItemsAdjustmentsTotal(orderItems,
1812: orderAdjustments, false, false, true);
1813: shippingAmount += OrderReadHelper.calcOrderAdjustments(
1814: orderHeaderAdjustments, orderSubTotal, false,
1815: false, true);
1816: result
1817: .put("orderShippingTotal", new Double(
1818: shippingAmount));
1819:
1820: double taxAmount = OrderReadHelper
1821: .getAllOrderItemsAdjustmentsTotal(orderItems,
1822: orderAdjustments, false, true, false);
1823: taxAmount += OrderReadHelper.calcOrderAdjustments(
1824: orderHeaderAdjustments, orderSubTotal, false, true,
1825: false);
1826: result.put("orderTaxTotal", new Double(taxAmount));
1827: result.put("orderGrandTotal", new Double(OrderReadHelper
1828: .getOrderGrandTotal(orderItems, orderAdjustments)));
1829:
1830: List placingCustomerOrderRoles = delegator.findByAnd(
1831: "OrderRole", UtilMisc.toMap("orderId", orderId,
1832: "roleTypeId", "PLACING_CUSTOMER"));
1833: GenericValue placingCustomerOrderRole = EntityUtil
1834: .getFirst(placingCustomerOrderRoles);
1835: GenericValue placingCustomerPerson = placingCustomerOrderRole == null ? null
1836: : delegator.findByPrimaryKey("Person", UtilMisc
1837: .toMap("partyId", placingCustomerOrderRole
1838: .getString("partyId")));
1839: result.put("placingCustomerPerson", placingCustomerPerson);
1840:
1841: GenericValue shippingAddress = orh.getShippingAddress();
1842: result.put("shippingAddress", shippingAddress);
1843: GenericValue billingAccount = orderHeader
1844: .getRelatedOne("BillingAccount");
1845: result.put("billingAccount", billingAccount);
1846:
1847: Iterator orderPaymentPreferences = UtilMisc
1848: .toIterator(orderHeader
1849: .getRelated("OrderPaymentPreference"));
1850: if (orderPaymentPreferences != null) {
1851: List paymentMethods = new ArrayList();
1852: while (orderPaymentPreferences.hasNext()) {
1853: GenericValue opp = (GenericValue) orderPaymentPreferences
1854: .next();
1855: GenericValue paymentMethod = opp
1856: .getRelatedOne("PaymentMethod");
1857: if (paymentMethod != null) {
1858: paymentMethods.add(paymentMethod);
1859: } else {
1860: GenericValue paymentMethodType = opp
1861: .getRelatedOne("PaymentMethodType");
1862: if (paymentMethodType != null) {
1863: result.put("paymentMethodType",
1864: paymentMethodType);
1865: }
1866: }
1867: }
1868: result.put("paymentMethods", paymentMethods);
1869: }
1870:
1871: Iterator orderShipmentPreferences = UtilMisc
1872: .toIterator(orderHeader
1873: .getRelated("OrderShipmentPreference"));
1874: if (orderShipmentPreferences != null
1875: && orderShipmentPreferences.hasNext()) {
1876: GenericValue shipmentPreference = (GenericValue) orderShipmentPreferences
1877: .next();
1878: result.put("carrierPartyId", shipmentPreference
1879: .getString("carrierPartyId"));
1880: result.put("shipmentMethodTypeId", shipmentPreference
1881: .getString("shipmentMethodTypeId"));
1882: GenericValue shipmentMethodType = delegator
1883: .findByPrimaryKey(
1884: "ShipmentMethodType",
1885: UtilMisc
1886: .toMap(
1887: "shipmentMethodTypeId",
1888: shipmentPreference
1889: .getString("shipmentMethodTypeId")));
1890: result.put("shipMethDescription", shipmentMethodType
1891: .getString("description"));
1892: result.put("shippingInstructions", shipmentPreference
1893: .getString("shippingInstructions"));
1894: result.put("maySplit", shipmentPreference
1895: .getBoolean("maySplit"));
1896: result.put("giftMessage", shipmentPreference
1897: .getString("giftMessage"));
1898: result.put("isGift", shipmentPreference
1899: .getBoolean("isGift"));
1900: result.put("trackingNumber", shipmentPreference
1901: .getString("trackingNumber"));
1902: }
1903:
1904: Iterator orderItemPOIter = UtilMisc.toIterator(orderItems);
1905: if (orderItemPOIter != null && orderItemPOIter.hasNext()) {
1906: GenericValue orderItemPo = (GenericValue) orderItemPOIter
1907: .next();
1908: result.put("customerPoNumber", orderItemPo
1909: .getString("correspondingPoId"));
1910: }
1911:
1912: // get Shipment tracking info
1913: EntityCondition osisCond = new EntityFieldMap(UtilMisc
1914: .toMap("orderId", orderId), EntityOperator.AND);
1915: List osisOrder = UtilMisc.toList("shipmentId",
1916: "shipmentRouteSegmentId", "shipmentPackageSeqId");
1917: List osisFields = UtilMisc.toList("shipmentId",
1918: "shipmentRouteSegmentId", "carrierPartyId",
1919: "shipmentMethodTypeId");
1920: osisFields.add("shipmentPackageSeqId");
1921: osisFields.add("trackingCode");
1922: osisFields.add("boxNumber");
1923:
1924: EntityFindOptions osisFindOptions = new EntityFindOptions();
1925: osisFindOptions.setDistinct(true);
1926:
1927: List orderShipmentInfoSummaryList = null;
1928: EntityListIterator osisEli = delegator
1929: .findListIteratorByCondition(
1930: "OrderShipmentInfoSummary", osisCond, null,
1931: osisFields, osisOrder, osisFindOptions);
1932: if (osisEli != null) {
1933: orderShipmentInfoSummaryList = osisEli
1934: .getCompleteList();
1935: osisEli.close();
1936: }
1937: result.put("orderShipmentInfoSummaryList",
1938: orderShipmentInfoSummaryList);
1939:
1940: } catch (GenericEntityException e) {
1941: Debug.logError(e, "Entity read error", module);
1942: ServiceUtil
1943: .returnError("Problem with entity lookup, see error log");
1944: }
1945: return result;
1946: }
1947:
1948: /** Service to email a customer with initial order confirmation */
1949: public static Map prepareOrderConfirmation(DispatchContext ctx,
1950: Map context) {
1951: context.put("emailType", "PRDS_ODR_CONFIRM");
1952: return prepareOrderEmail(ctx, context);
1953: }
1954:
1955: /** Service to email a customer with order changes */
1956: public static Map prepareOrderComplete(DispatchContext ctx,
1957: Map context) {
1958: context.put("emailType", "PRDS_ODR_COMPLETE");
1959: return prepareOrderEmail(ctx, context);
1960: }
1961:
1962: /** Service to email a customer with order changes */
1963: public static Map prepareOrderBackorder(DispatchContext ctx,
1964: Map context) {
1965: context.put("emailType", "PRDS_ODR_BACKORDER");
1966: return prepareOrderEmail(ctx, context);
1967: }
1968:
1969: /** Service to email a customer with order changes */
1970: public static Map prepareOrderChange(DispatchContext ctx,
1971: Map context) {
1972: context.put("emailType", "PRDS_ODR_CHANGE");
1973: return prepareOrderEmail(ctx, context);
1974: }
1975:
1976: public static Map prepareOrderEmail(DispatchContext ctx, Map context) {
1977: Map result = new HashMap();
1978: GenericDelegator delegator = ctx.getDelegator();
1979: String orderId = (String) context.get("orderId");
1980: String emailType = (String) context.get("emailType");
1981: String ofbizHome = System.getProperty("ofbiz.home");
1982:
1983: // get the order header and store
1984: GenericValue orderHeader = null;
1985: try {
1986: orderHeader = delegator.findByPrimaryKey("OrderHeader",
1987: UtilMisc.toMap("orderId", orderId));
1988: } catch (GenericEntityException e) {
1989: Debug.logError(e, "Problem getting OrderHeader", module);
1990: }
1991:
1992: GenericValue productStoreEmail = null;
1993: if (orderHeader != null) {
1994: try {
1995: productStoreEmail = delegator.findByPrimaryKey(
1996: "ProductStoreEmailSetting", UtilMisc.toMap(
1997: "productStoreId", orderHeader
1998: .get("productStoreId"),
1999: "emailType", emailType));
2000: } catch (GenericEntityException e) {
2001: Debug.logError(e,
2002: "Problem getting the ProductStoreEmailSetting",
2003: module);
2004: }
2005: }
2006:
2007: if (productStoreEmail == null) {
2008: return ServiceUtil
2009: .returnError("No valid email setting for store");
2010: }
2011:
2012: OrderReadHelper orh = new OrderReadHelper(orderHeader);
2013: String emailString = orh.getOrderEmailString();
2014:
2015: // prepare the parsed subject
2016: Map orderEmailData = prepareOrderEmailData(ctx, UtilMisc.toMap(
2017: "orderId", orderId));
2018: String subjectString = productStoreEmail.getString("subject");
2019: subjectString = FlexibleStringExpander.expandString(
2020: subjectString, orderEmailData);
2021:
2022: result.put("templateName", ofbizHome
2023: + productStoreEmail.get("templatePath"));
2024: result.put("emailType", emailType);
2025: result.put("subject", subjectString);
2026: result.put("contentType", productStoreEmail.get("contentType"));
2027: result.put("sendFrom", productStoreEmail.get("fromAddress"));
2028: result.put("sendCc", productStoreEmail.get("ccAddress"));
2029: result.put("sendBcc", productStoreEmail.get("bccAddress"));
2030: result.put("sendTo", emailString);
2031: result.put(ModelService.RESPONSE_MESSAGE,
2032: ModelService.RESPOND_SUCCESS);
2033:
2034: return result;
2035: }
2036:
2037: /** Service to email order notifications for pending actions */
2038: public static Map sendProcessNotification(DispatchContext ctx,
2039: Map context) {
2040: //appears to not be used: Map result = new HashMap();
2041: GenericDelegator delegator = ctx.getDelegator();
2042: LocalDispatcher dispatcher = ctx.getDispatcher();
2043: String adminEmailList = (String) context.get("adminEmailList");
2044: String assignedToUser = (String) context.get("assignedPartyId");
2045: //appears to not be used: String assignedToRole = (String) context.get("assignedRoleTypeId");
2046: String workEffortId = (String) context.get("workEffortId");
2047:
2048: GenericValue workEffort = null;
2049: GenericValue orderHeader = null;
2050: //appears to not be used: String assignedEmail = null;
2051:
2052: // get the order/workflow info
2053: try {
2054: workEffort = delegator.findByPrimaryKey("WorkEffort",
2055: UtilMisc.toMap("workEffortId", workEffortId));
2056: String sourceReferenceId = workEffort
2057: .getString("sourceReferenceId");
2058: if (sourceReferenceId != null)
2059: orderHeader = delegator.findByPrimaryKey("OrderHeader",
2060: UtilMisc.toMap("orderId", sourceReferenceId));
2061: } catch (GenericEntityException e) {
2062: ServiceUtil.returnError("Problem with entity lookup");
2063: }
2064:
2065: // find the assigned user's email address(s)
2066: GenericValue party = null;
2067: Collection assignedToEmails = null;
2068: try {
2069: party = delegator.findByPrimaryKey("Party", UtilMisc.toMap(
2070: "partyId", assignedToUser));
2071: } catch (GenericEntityException e) {
2072: ServiceUtil.returnError("Problem with entity lookup");
2073: }
2074: if (party != null)
2075: assignedToEmails = ContactHelper.getContactMechByPurpose(
2076: party, "PRIMARY_EMAIL", false);
2077:
2078: Map templateData = new HashMap(context);
2079: String omgStatusId = WfUtil.getOMGStatus(workEffort
2080: .getString("currentStatusId"));
2081: templateData.putAll(orderHeader);
2082: templateData.putAll(workEffort);
2083: templateData.put("omgStatusId", omgStatusId);
2084:
2085: // get the assignments
2086: List assignments = null;
2087: if (workEffort != null) {
2088: try {
2089: assignments = workEffort
2090: .getRelated("WorkEffortPartyAssignment");
2091: } catch (GenericEntityException e1) {
2092: Debug.logError(e1, "Problems getting assignements",
2093: module);
2094: }
2095: }
2096: templateData.put("assignments", assignments);
2097:
2098: StringBuffer emailList = new StringBuffer();
2099: if (assignedToEmails != null) {
2100: Iterator aei = assignedToEmails.iterator();
2101: while (aei.hasNext()) {
2102: GenericValue ct = (GenericValue) aei.next();
2103: if (ct != null && ct.get("infoString") != null) {
2104: if (emailList.length() > 1)
2105: emailList.append(",");
2106: emailList.append(ct.getString("infoString"));
2107: }
2108: }
2109: }
2110: if (adminEmailList != null) {
2111: if (emailList.length() > 1)
2112: emailList.append(",");
2113: emailList.append(adminEmailList);
2114: }
2115:
2116: // prepare the mail info
2117: String ofbizHome = System.getProperty("ofbiz.home");
2118: String templateName = ofbizHome
2119: + "/components/order/email/default/emailprocessnotify.ftl";
2120:
2121: Map sendMailContext = new HashMap();
2122: sendMailContext.put("sendTo", emailList.toString());
2123: sendMailContext.put("sendFrom", "workflow@ofbiz.org"); // fixme
2124: sendMailContext.put("subject", "Workflow Notification");
2125: sendMailContext.put("templateName", templateName);
2126: sendMailContext.put("templateData", templateData);
2127:
2128: try {
2129: dispatcher.runAsync("sendGenericNotificationEmail",
2130: sendMailContext);
2131: } catch (GenericServiceException e) {
2132: ServiceUtil.returnError("SendMail service failed: "
2133: + e.getMessage());
2134: }
2135: return ServiceUtil.returnSuccess();
2136: }
2137:
2138: /** Service to create an order payment preference */
2139: public static Map createPaymentPreference(DispatchContext ctx,
2140: Map context) {
2141: Map result = new HashMap();
2142: GenericDelegator delegator = ctx.getDelegator();
2143: String orderId = (String) context.get("orderId");
2144: String paymentMethodTypeId = (String) context
2145: .get("paymentMethodTypeId");
2146: String paymentMethodId = (String) context
2147: .get("paymentMethodId");
2148: Double maxAmount = (Double) context.get("maxAmount");
2149:
2150: String prefId = null;
2151: Long newId = delegator.getNextSeqId("OrderPaymentPreference");
2152:
2153: if (newId == null) {
2154: return ServiceUtil
2155: .returnError("ERROR: Could not create OrderPaymentPreference (id generation failure)");
2156: } else {
2157: prefId = newId.toString();
2158: }
2159:
2160: Map fields = UtilMisc.toMap("orderPaymentPreferenceId", prefId,
2161: "orderId", orderId, "paymentMethodTypeId",
2162: paymentMethodTypeId, "paymentMethodId",
2163: paymentMethodId, "maxAmount", maxAmount);
2164:
2165: try {
2166: GenericValue v = delegator.makeValue(
2167: "OrderPaymentPreference", fields);
2168:
2169: delegator.create(v);
2170: } catch (GenericEntityException e) {
2171: result.put(ModelService.RESPONSE_MESSAGE,
2172: ModelService.RESPOND_ERROR);
2173: result.put(ModelService.ERROR_MESSAGE,
2174: "ERROR: Could not create OrderPaymentPreference ("
2175: + e.getMessage() + ").");
2176: return result;
2177: }
2178: result.put("orderPaymentPreferenceId", prefId);
2179: result.put(ModelService.RESPONSE_MESSAGE,
2180: ModelService.RESPOND_SUCCESS);
2181: return result;
2182: }
2183:
2184: /** Service to get order header information as standard results. */
2185: public static Map getOrderHeaderInformation(DispatchContext dctx,
2186: Map context) {
2187: GenericDelegator delegator = dctx.getDelegator();
2188: String orderId = (String) context.get("orderId");
2189:
2190: GenericValue orderHeader = null;
2191: try {
2192: orderHeader = delegator.findByPrimaryKey("OrderHeader",
2193: UtilMisc.toMap("orderId", orderId));
2194: } catch (GenericEntityException e) {
2195: Debug.logError(e, "Problem getting order header detial",
2196: module);
2197: return ServiceUtil.returnError("Cannot get order header : "
2198: + e.getMessage());
2199: }
2200: if (orderHeader != null) {
2201: Map result = ServiceUtil.returnSuccess();
2202: result.putAll(orderHeader);
2203: return result;
2204: }
2205: return ServiceUtil
2206: .returnError("Error getting order header information; null");
2207: }
2208:
2209: /** Service to get basic order information. */
2210: public static Map getOrderInformation(DispatchContext dctx,
2211: Map context) {
2212: Map result = new HashMap();
2213: GenericDelegator delegator = dctx.getDelegator();
2214: String orderId = (String) context.get("orderId");
2215:
2216: try {
2217: GenericValue orderHeader = delegator.findByPrimaryKeyCache(
2218: "OrderHeader", UtilMisc.toMap("orderId", orderId));
2219: Collection orderItems = orderHeader
2220: .getRelatedCache("OrderItem");
2221: OrderReadHelper orh = new OrderReadHelper(orderHeader);
2222: String statusString = orh.getStatusString();
2223: Double totalItems = new Double(orh
2224: .getTotalOrderItemsQuantity());
2225: Double totalPrice = new Double(orh.getOrderGrandTotal());
2226: GenericValue shipAddress = orh.getShippingAddress();
2227: GenericValue billAddress = orh.getBillingAddress();
2228: GenericValue billTo = orh.getBillToPerson();
2229: String affilId = orh.getAffiliateId();
2230: String distId = orh.getDistributorId();
2231:
2232: result.put("orderId", orderId);
2233: result.put("orderHeader", orderHeader);
2234: result.put("orderItems", orderItems);
2235: result.put("totalItems", totalItems);
2236: result.put("totalPrice", totalPrice);
2237: result.put("shippingAddress", shipAddress);
2238: result.put("billingAddress", billAddress);
2239: result.put("billToPerson", billTo);
2240: result.put("affiliateId", affilId);
2241: result.put("distributorId", distId);
2242: result.put("statusString", statusString);
2243: } catch (GenericEntityException e) {
2244: result.put(ModelService.RESPONSE_MESSAGE,
2245: ModelService.RESPOND_ERROR);
2246: result.put(ModelService.ERROR_MESSAGE,
2247: "ERROR: Could not get order information ("
2248: + e.getMessage() + ").");
2249: }
2250: return result;
2251: }
2252:
2253: /** Service to get the total shipping for an order. */
2254: public static Map getOrderShippingAmount(DispatchContext dctx,
2255: Map context) {
2256: GenericDelegator delegator = dctx.getDelegator();
2257: String orderId = (String) context.get("orderId");
2258:
2259: GenericValue orderHeader = null;
2260: try {
2261: orderHeader = delegator.findByPrimaryKey("OrderHeader",
2262: UtilMisc.toMap("orderId", orderId));
2263: } catch (GenericEntityException e) {
2264: Debug.logError(e, module);
2265: return ServiceUtil
2266: .returnError("ERROR: Could not get order information ("
2267: + e.getMessage() + ").");
2268: }
2269:
2270: Map result = null;
2271: if (orderHeader != null) {
2272: OrderReadHelper orh = new OrderReadHelper(orderHeader);
2273: List orderItems = orh.getValidOrderItems();
2274: List orderAdjustments = orh.getAdjustments();
2275: List orderHeaderAdjustments = orh
2276: .getOrderHeaderAdjustments();
2277: double orderSubTotal = orh.getOrderItemsSubTotal();
2278:
2279: double shippingAmount = OrderReadHelper
2280: .getAllOrderItemsAdjustmentsTotal(orderItems,
2281: orderAdjustments, false, false, true);
2282: shippingAmount += OrderReadHelper.calcOrderAdjustments(
2283: orderHeaderAdjustments, orderSubTotal, false,
2284: false, true);
2285:
2286: result = ServiceUtil.returnSuccess();
2287: result.put("shippingAmount", new Double(shippingAmount));
2288: } else {
2289: result = ServiceUtil
2290: .returnError("Unable to find OrderHeader; cannot get shipping amount");
2291: }
2292: return result;
2293: }
2294:
2295: /** Service to get an order contact mech. */
2296: public static Map getOrderAddress(DispatchContext dctx, Map context) {
2297: Map result = new HashMap();
2298: GenericDelegator delegator = dctx.getDelegator();
2299: String orderId = (String) context.get("orderId");
2300: //appears to not be used: GenericValue v = null;
2301: String purpose[] = { "BILLING_LOCATION", "SHIPPING_LOCATION" };
2302: String outKey[] = { "billingAddress", "shippingAddress" };
2303: GenericValue orderHeader = null;
2304:
2305: try {
2306: orderHeader = delegator.findByPrimaryKeyCache(
2307: "OrderHeader", UtilMisc.toMap("orderId", orderId));
2308: if (orderHeader != null)
2309: result.put("orderHeader", orderHeader);
2310: } catch (GenericEntityException e) {
2311: result.put(ModelService.RESPONSE_MESSAGE,
2312: ModelService.RESPOND_ERROR);
2313: result.put(ModelService.ERROR_MESSAGE,
2314: "ERROR: Could not get OrderHeader ("
2315: + e.getMessage() + ").");
2316: return result;
2317: }
2318: if (orderHeader == null) {
2319: result.put(ModelService.RESPONSE_MESSAGE,
2320: ModelService.RESPOND_ERROR);
2321: result.put(ModelService.ERROR_MESSAGE,
2322: "ERROR: Could get the OrderHeader.");
2323: return result;
2324: }
2325: for (int i = 0; i < purpose.length; i++) {
2326: try {
2327: GenericValue orderContactMech = EntityUtil
2328: .getFirst(orderHeader.getRelatedByAnd(
2329: "OrderContactMech", UtilMisc.toMap(
2330: "contactMechPurposeTypeId",
2331: purpose[i])));
2332: GenericValue contactMech = orderContactMech
2333: .getRelatedOne("ContactMech");
2334:
2335: if (contactMech != null) {
2336: result.put(outKey[i], contactMech
2337: .getRelatedOne("PostalAddress"));
2338: }
2339: } catch (GenericEntityException e) {
2340: result.put(ModelService.RESPONSE_MESSAGE,
2341: ModelService.RESPOND_ERROR);
2342: result.put(ModelService.ERROR_MESSAGE,
2343: "ERROR: Problems getting contact mech ("
2344: + e.getMessage() + ").");
2345: return result;
2346: }
2347: }
2348:
2349: result.put("orderId", orderId);
2350: return result;
2351: }
2352:
2353: /** Service to create a order header note. */
2354: public static Map createOrderNote(DispatchContext dctx, Map context) {
2355: Map result = new HashMap();
2356: GenericDelegator delegator = dctx.getDelegator();
2357: GenericValue userLogin = (GenericValue) context
2358: .get("userLogin");
2359: String noteString = (String) context.get("note");
2360: String orderId = (String) context.get("orderId");
2361: Map noteCtx = UtilMisc.toMap("note", noteString, "userLogin",
2362: userLogin);
2363:
2364: // Store the note.
2365: Map noteRes = org.ofbiz.common.CommonServices.createNote(dctx,
2366: noteCtx);
2367:
2368: if (noteRes.get(ModelService.RESPONSE_MESSAGE).equals(
2369: ModelService.RESPOND_ERROR))
2370: return noteRes;
2371:
2372: String noteId = (String) noteRes.get("noteId");
2373:
2374: if (noteId == null || noteId.length() == 0) {
2375: return ServiceUtil
2376: .returnError("Problem creating the note, no noteId returned.");
2377: }
2378:
2379: // Set the order info
2380: try {
2381: Map fields = UtilMisc.toMap("orderId", orderId, "noteId",
2382: noteId);
2383: GenericValue v = delegator.makeValue("OrderHeaderNote",
2384: fields);
2385:
2386: delegator.create(v);
2387: } catch (GenericEntityException ee) {
2388: Debug.logError(ee, module);
2389: result.put(ModelService.RESPONSE_MESSAGE,
2390: ModelService.RESPOND_ERROR);
2391: result.put(ModelService.ERROR_MESSAGE,
2392: "Problem associating note with order ("
2393: + ee.getMessage() + ").");
2394: }
2395:
2396: return result;
2397: }
2398:
2399: /** Null tax calc service. */
2400: public static Map nullTaxCalc(DispatchContext dctx, Map context) {
2401: return UtilMisc.toMap("orderAdjustments",
2402: UtilMisc.toList(null), "itemAdjustments", UtilMisc
2403: .toList(null));
2404: }
2405:
2406: /** Simple tax calc service. */
2407: public static Map simpleTaxCalc(DispatchContext dctx, Map context) {
2408: GenericDelegator delegator = dctx.getDelegator();
2409: String productStoreId = (String) context.get("productStoreId");
2410: List itemProductList = (List) context.get("itemProductList");
2411: List itemAmountList = (List) context.get("itemAmountList");
2412: List itemShippingList = (List) context.get("itemShippingList");
2413: Double orderShippingAmount = (Double) context
2414: .get("orderShippingAmount");
2415: GenericValue shippingAddress = (GenericValue) context
2416: .get("shippingAddress");
2417:
2418: // Simple Tax Calc only uses the state from the address and the SalesTaxLookup entity.
2419: String countryCode = shippingAddress.getString("countryGeoId");
2420: String stateCode = shippingAddress
2421: .getString("stateProvinceGeoId");
2422:
2423: // Setup the return lists.
2424: List orderAdjustments = new ArrayList();
2425: List itemAdjustments = new ArrayList();
2426:
2427: // Loop through the products; get the taxCategory; and lookup each in the cache.
2428: for (int i = 0; i < itemProductList.size(); i++) {
2429: GenericValue product = (GenericValue) itemProductList
2430: .get(i);
2431: Double itemAmount = (Double) itemAmountList.get(i);
2432: Double shippingAmount = (Double) itemShippingList.get(i);
2433: List taxList = getTaxAmount(delegator, product,
2434: productStoreId, countryCode, stateCode, itemAmount
2435: .doubleValue(), shippingAmount
2436: .doubleValue());
2437: itemAdjustments.add(taxList);
2438: }
2439: if (orderShippingAmount.doubleValue() > 0) {
2440: List taxList = getTaxAmount(delegator, null,
2441: productStoreId, countryCode, stateCode, 0.00,
2442: orderShippingAmount.doubleValue());
2443: orderAdjustments.addAll(taxList);
2444: }
2445:
2446: Map result = UtilMisc.toMap("orderAdjustments",
2447: orderAdjustments, "itemAdjustments", itemAdjustments);
2448:
2449: return result;
2450:
2451: }
2452:
2453: private static List getTaxAmount(GenericDelegator delegator,
2454: GenericValue item, String productStoreId,
2455: String countryCode, String stateCode, double itemAmount,
2456: double shippingAmount) {
2457: List adjustments = new ArrayList();
2458:
2459: // store expr
2460: EntityCondition storeCond = new EntityExpr("productStoreId",
2461: EntityOperator.EQUALS, productStoreId);
2462:
2463: // build the country expressions
2464: List countryExprs = UtilMisc.toList(new EntityExpr(
2465: "countryGeoId", EntityOperator.EQUALS, countryCode),
2466: new EntityExpr("countryGeoId", EntityOperator.EQUALS,
2467: "_NA_"));
2468: EntityCondition countryCond = new EntityConditionList(
2469: countryExprs, EntityOperator.OR);
2470:
2471: // build the state expression
2472: List stateExprs = UtilMisc.toList(
2473: new EntityExpr("stateProvinceGeoId",
2474: EntityOperator.EQUALS, stateCode),
2475: new EntityExpr("stateProvinceGeoId",
2476: EntityOperator.EQUALS, "_NA_"));
2477: EntityCondition stateCond = new EntityConditionList(stateExprs,
2478: EntityOperator.OR);
2479:
2480: // build the tax cat expression
2481: List taxCatExprs = UtilMisc.toList(new EntityExpr(
2482: "taxCategory", EntityOperator.EQUALS, "_NA_"));
2483: if (item != null && item.get("taxCategory") != null) {
2484: taxCatExprs.add(new EntityExpr("taxCategory",
2485: EntityOperator.EQUALS, item
2486: .getString("taxCategory")));
2487: }
2488: EntityCondition taxCatCond = new EntityConditionList(
2489: taxCatExprs, EntityOperator.OR);
2490:
2491: // build the main condition clause
2492: List mainExprs = UtilMisc.toList(storeCond, countryCond,
2493: stateCond);
2494: if (taxCatExprs.size() > 1) {
2495: mainExprs.add(taxCatCond);
2496: } else {
2497: mainExprs.add(taxCatExprs.get(0));
2498: }
2499: EntityCondition mainCondition = new EntityConditionList(
2500: mainExprs, EntityOperator.AND);
2501:
2502: // create the orderby clause
2503: List orderList = UtilMisc.toList("minPurchase", "fromDate");
2504:
2505: try {
2506: List lookupList = delegator.findByCondition(
2507: "SimpleSalesTaxLookup", mainCondition, null,
2508: orderList);
2509: List filteredList = EntityUtil.filterByDate(lookupList);
2510:
2511: if (filteredList.size() == 0) {
2512: Debug
2513: .logWarning(
2514: "SimpleTaxCalc: No State/TaxCategory pair found (with or without taxCat).",
2515: module);
2516: return adjustments;
2517: }
2518:
2519: // find the right entry(s) based on purchase amount
2520: Iterator flIt = filteredList.iterator();
2521: while (flIt.hasNext()) {
2522: GenericValue taxLookup = (GenericValue) flIt.next();
2523: //Debug.logInfo("Testing " + itemAmount + " with : " + taxLookup, module);
2524: if (itemAmount >= taxLookup.getDouble("minPurchase")
2525: .doubleValue()) {
2526: //Debug.logInfo("TaxLookup: " + taxLookup, module);
2527:
2528: double taxRate = taxLookup
2529: .get("salesTaxPercentage") != null ? taxLookup
2530: .getDouble("salesTaxPercentage")
2531: .doubleValue()
2532: : 0;
2533: double taxable = 0.00;
2534:
2535: if (item != null
2536: && (item.get("taxable") == null || (item
2537: .get("taxable") != null && item
2538: .getBoolean("taxable")
2539: .booleanValue()))) {
2540: taxable += itemAmount;
2541: }
2542: if (taxLookup != null
2543: && (taxLookup.get("taxShipping") == null || (taxLookup
2544: .get("taxShipping") != null && taxLookup
2545: .getBoolean("taxShipping")
2546: .booleanValue()))) {
2547: taxable += shippingAmount;
2548: }
2549:
2550: String currencyFormat = UtilProperties
2551: .getPropertyValue("general.properties",
2552: "currency.decimal.format", "##0.00");
2553: DecimalFormat formatter = new DecimalFormat(
2554: currencyFormat);
2555: double taxTotal = taxable * taxRate;
2556: String amountStr = formatter.format(taxTotal);
2557: Double taxAmount = null;
2558: try {
2559: taxAmount = new Double(formatter.parse(
2560: amountStr).doubleValue());
2561: } catch (ParseException e) {
2562: throw new GeneralException(
2563: "Problem getting parsed amount from string",
2564: e);
2565: }
2566:
2567: adjustments
2568: .add(delegator
2569: .makeValue(
2570: "OrderAdjustment",
2571: UtilMisc
2572: .toMap(
2573: "amount",
2574: taxAmount,
2575: "orderAdjustmentTypeId",
2576: "SALES_TAX",
2577: "comments",
2578: taxLookup
2579: .getString("description"))));
2580: }
2581: }
2582: } catch (GenericEntityException e) {
2583: Debug.logError(e, "Problems looking up tax rates", module);
2584: return new ArrayList();
2585: } catch (GeneralException e) {
2586: Debug.logError(e, "Problems looking up tax rates", module);
2587: return new ArrayList();
2588: }
2589:
2590: return adjustments;
2591: }
2592:
2593: // return / refund services
2594:
2595: // helper method for sending return notifications
2596: private static Map sendReturnNotification(DispatchContext ctx,
2597: Map context, String emailType) {
2598: GenericDelegator delegator = ctx.getDelegator();
2599: LocalDispatcher dispatcher = ctx.getDispatcher();
2600: GenericValue userLogin = (GenericValue) context
2601: .get("userLogin");
2602: String returnId = (String) context.get("returnId");
2603:
2604: // get the return header
2605: GenericValue returnHeader = null;
2606: try {
2607: returnHeader = delegator.findByPrimaryKey("ReturnHeader",
2608: UtilMisc.toMap("returnId", returnId));
2609: } catch (GenericEntityException e) {
2610: Debug.logError(e, module);
2611: return ServiceUtil
2612: .returnError("ERROR: Unable to get ReturnHeader for ID: "
2613: + returnId);
2614: }
2615:
2616: // get the return items
2617: List returnItems = null;
2618: try {
2619: returnItems = returnHeader.getRelated("ReturnItem");
2620: } catch (GenericEntityException e) {
2621: Debug.logError(e, module);
2622: return ServiceUtil
2623: .returnError("ERROR: Unable to get ReturnItem records from ReturnHeader");
2624: }
2625:
2626: // set the email template context
2627: Map templateContext = UtilMisc.toMap("returnHeader",
2628: returnHeader, "returnItems", returnItems);
2629:
2630: // get the order header -- the first item will determine which product store to use from the order
2631: String productStoreId = null;
2632: String emailAddress = null;
2633: if (returnItems != null) {
2634: GenericValue firstItem = EntityUtil.getFirst(returnItems);
2635: GenericValue orderHeader = null;
2636: try {
2637: orderHeader = firstItem.getRelatedOne("OrderHeader");
2638: } catch (GenericEntityException e) {
2639: Debug.logError(e, module);
2640: return ServiceUtil
2641: .returnError("ERROR: Unable to get OrderHeader from ReturnItem");
2642: }
2643:
2644: if (orderHeader != null
2645: && UtilValidate.isNotEmpty(orderHeader
2646: .getString("productStoreId"))) {
2647: OrderReadHelper orh = new OrderReadHelper(orderHeader);
2648: productStoreId = orh.getProductStoreId();
2649: emailAddress = orh.getOrderEmailString();
2650: }
2651: }
2652:
2653: // get the email setting and send the mail
2654: if (productStoreId != null && productStoreId.length() > 0) {
2655: GenericValue emailSetting = null;
2656: try {
2657: emailSetting = delegator.findByPrimaryKey(
2658: "ProductStoreEmailSetting", UtilMisc.toMap(
2659: "productStoreId", productStoreId,
2660: "emailType", emailType));
2661: } catch (GenericEntityException e) {
2662: Debug.logError(e, module);
2663: return ServiceUtil
2664: .returnError("ERROR: Unable to locate email setting : "
2665: + productStoreId + " / " + emailType);
2666: }
2667:
2668: if (emailSetting != null && emailAddress != null) {
2669: String subjectString = emailSetting
2670: .getString("subject");
2671: subjectString = FlexibleStringExpander.expandString(
2672: subjectString, templateContext);
2673:
2674: Map emailCtx = new HashMap();
2675: emailCtx.put("templateName", emailSetting
2676: .get("templatePath"));
2677: emailCtx.put("templateData", templateContext);
2678: emailCtx.put("sendTo", emailAddress);
2679: emailCtx.put("contentType", emailSetting
2680: .get("contentType"));
2681: emailCtx.put("sendFrom", emailSetting
2682: .get("fromAddress"));
2683: emailCtx.put("sendCc", emailSetting.get("ccAddress"));
2684: emailCtx.put("sendBcc", emailSetting.get("bccAddress"));
2685: emailCtx.put("subject", subjectString);
2686: emailCtx.put("userLogin", userLogin);
2687:
2688: // send off the email async so we will retry on failed attempts
2689: try {
2690: dispatcher.runAsync("sendGenericNotificationEmail",
2691: emailCtx);
2692: } catch (GenericServiceException e) {
2693: Debug.logError(e, "Problem sending mail", module);
2694: return ServiceUtil
2695: .returnError("Problem sending email");
2696: }
2697:
2698: // all done
2699: return ServiceUtil.returnSuccess();
2700: }
2701: }
2702:
2703: return ServiceUtil
2704: .returnError("ERROR: Problem with Product Store email setting : "
2705: + productStoreId + " / " + emailType);
2706: }
2707:
2708: // return request notification
2709: public static Map sendReturnAcceptNotification(DispatchContext ctx,
2710: Map context) {
2711: return sendReturnNotification(ctx, context, "PRDS_RTN_ACCEPT");
2712: }
2713:
2714: // return complete notification
2715: public static Map sendReturnCompleteNotification(
2716: DispatchContext ctx, Map context) {
2717: return sendReturnNotification(ctx, context, "PRDS_RTN_COMPLETE");
2718: }
2719:
2720: // return cancel notification
2721: public static Map sendReturnCancelNotification(DispatchContext ctx,
2722: Map context) {
2723: return sendReturnNotification(ctx, context, "PRDS_RTN_CANCEL");
2724: }
2725:
2726: // get the returnable quantiy for an order item
2727: public static Map getReturnableQuantity(DispatchContext ctx,
2728: Map context) {
2729: GenericDelegator delegator = ctx.getDelegator();
2730: GenericValue orderItem = (GenericValue) context
2731: .get("orderItem");
2732: GenericValue product = null;
2733: if (orderItem.get("productId") != null) {
2734: try {
2735: product = orderItem.getRelatedOne("Product");
2736: } catch (GenericEntityException e) {
2737: Debug.logError(e,
2738: "ERROR: Unable to get Product from OrderItem",
2739: module);
2740: }
2741: }
2742:
2743: // check returnable status
2744: boolean returnable = true;
2745:
2746: // first check returnable flag
2747: if (product != null
2748: && product.get("returnable") != null
2749: && "N"
2750: .equalsIgnoreCase(product
2751: .getString("returnable"))) {
2752: // the product is not returnable at all
2753: returnable = false;
2754: }
2755:
2756: // next check support discontinuation
2757: if (product != null
2758: && product.get("supportDiscontinuationDate") != null
2759: && !UtilDateTime
2760: .nowTimestamp()
2761: .before(
2762: product
2763: .getTimestamp("supportDiscontinuationDate"))) {
2764: // support discontinued either now or in the past
2765: returnable = false;
2766: }
2767:
2768: String itemStatus = orderItem.getString("statusId");
2769: double orderQty = orderItem.getDouble("quantity").doubleValue();
2770:
2771: // get the returnable quantity
2772: double returnableQuantity = 0.00;
2773: if (returnable && itemStatus.equals("ITEM_COMPLETED")) {
2774: List returnedItems = null;
2775: try {
2776: returnedItems = orderItem.getRelated("ReturnItem");
2777: } catch (GenericEntityException e) {
2778: Debug.logError(e, module);
2779: return ServiceUtil
2780: .returnError("ERROR: Unable to get return item information");
2781: }
2782: if (returnedItems == null || returnedItems.size() == 0) {
2783: returnableQuantity = orderQty;
2784: } else {
2785: double returnedQty = 0.00;
2786: Iterator ri = returnedItems.iterator();
2787: while (ri.hasNext()) {
2788: GenericValue returnItem = (GenericValue) ri.next();
2789: GenericValue returnHeader = null;
2790: try {
2791: returnHeader = returnItem
2792: .getRelatedOne("ReturnHeader");
2793: } catch (GenericEntityException e) {
2794: Debug.logError(e, module);
2795: return ServiceUtil
2796: .returnError("ERROR: Unable to get return header from item");
2797: }
2798: String returnStatus = returnHeader
2799: .getString("statusId");
2800: if (!returnStatus.equals("RETURN_CANCELLED")) {
2801: returnedQty += returnItem.getDouble(
2802: "returnQuantity").doubleValue();
2803: }
2804: }
2805: if (returnedQty < orderQty) {
2806: returnableQuantity = orderQty - returnedQty;
2807: }
2808: }
2809: }
2810:
2811: // get the returnable price
2812: double returnablePrice = 0.00;
2813: if (returnableQuantity > 0) {
2814: // get all order adjustments
2815: List orderAdjustments = null;
2816: try {
2817: orderAdjustments = delegator.findByAnd(
2818: "OrderAdjustment", UtilMisc.toMap("orderId",
2819: orderItem.get("orderId")));
2820: } catch (GenericEntityException e) {
2821: Debug.logError(e, module);
2822: return ServiceUtil
2823: .returnError("ERROR: Unable to get order adjustments from item");
2824: }
2825: returnablePrice = OrderReadHelper.getOrderItemTotal(
2826: orderItem, orderAdjustments);
2827: returnablePrice = (returnablePrice / orderQty);
2828: }
2829:
2830: Map result = ServiceUtil.returnSuccess();
2831: result
2832: .put("returnableQuantity", new Double(
2833: returnableQuantity));
2834: result.put("returnablePrice", new Double(returnablePrice));
2835: return result;
2836: }
2837:
2838: // get a map of returnable items (items not already returned) and quantities
2839: public static Map getReturnableItems(DispatchContext ctx,
2840: Map context) {
2841: LocalDispatcher dispatcher = ctx.getDispatcher();
2842: GenericDelegator delegator = ctx.getDelegator();
2843: String orderId = (String) context.get("orderId");
2844:
2845: GenericValue orderHeader = null;
2846: try {
2847: orderHeader = delegator.findByPrimaryKey("OrderHeader",
2848: UtilMisc.toMap("orderId", orderId));
2849: } catch (GenericEntityException e) {
2850: Debug.logError(e, module);
2851: return ServiceUtil
2852: .returnError("ERROR: Unable to get order information.");
2853: }
2854:
2855: Map returnable = new HashMap();
2856: if (orderHeader != null) {
2857: List orderItems = null;
2858: try {
2859: orderItems = orderHeader.getRelatedByAnd("OrderItem",
2860: UtilMisc.toMap("statusId", "ITEM_COMPLETED"));
2861: } catch (GenericEntityException e) {
2862: Debug.logError(e, module);
2863: return ServiceUtil
2864: .returnError("ERROR: Unable to get order item information.");
2865: }
2866: if (orderItems != null) {
2867: Iterator i = orderItems.iterator();
2868: while (i.hasNext()) {
2869: GenericValue item = (GenericValue) i.next();
2870: Map serviceResult = null;
2871: try {
2872: serviceResult = dispatcher.runSync(
2873: "getReturnableQuantity", UtilMisc
2874: .toMap("orderItem", item));
2875: } catch (GenericServiceException e) {
2876: Debug.logError(e, module);
2877: return ServiceUtil
2878: .returnError("ERROR: Unable to get the item returnable quantity.");
2879: }
2880: if (serviceResult
2881: .containsKey(ModelService.ERROR_MESSAGE)) {
2882: return ServiceUtil
2883: .returnError((String) serviceResult
2884: .get(ModelService.ERROR_MESSAGE));
2885: } else {
2886: Map returnInfo = new HashMap();
2887: returnInfo
2888: .put(
2889: "returnableQuantity",
2890: serviceResult
2891: .get("returnableQuantity"));
2892: returnInfo.put("returnablePrice", serviceResult
2893: .get("returnablePrice"));
2894: returnable.put(item, returnInfo);
2895: }
2896: }
2897: } else {
2898: return ServiceUtil
2899: .returnError("ERROR: No order items found.");
2900: }
2901: } else {
2902: return ServiceUtil
2903: .returnError("ERROR: Unable to find order header.");
2904: }
2905:
2906: Map result = ServiceUtil.returnSuccess();
2907: result.put("returnableItems", returnable);
2908: return result;
2909: }
2910:
2911: // check return items status and update return header status
2912: public static Map checkReturnComplete(DispatchContext ctx,
2913: Map context) {
2914: //appears to not be used: LocalDispatcher dispatcher = ctx.getDispatcher();
2915: GenericDelegator delegator = ctx.getDelegator();
2916: String returnId = (String) context.get("returnId");
2917:
2918: GenericValue returnHeader = null;
2919: List returnItems = null;
2920: try {
2921: returnHeader = delegator.findByPrimaryKey("ReturnHeader",
2922: UtilMisc.toMap("returnId", returnId));
2923: if (returnHeader != null) {
2924: returnItems = returnHeader.getRelated("ReturnItem");
2925: }
2926: } catch (GenericEntityException e) {
2927: Debug.logError(e, "Problems looking up return information",
2928: module);
2929: return ServiceUtil
2930: .returnError("Error getting ReturnHeader/Item information");
2931: }
2932:
2933: // if already completed just return
2934: if (returnHeader != null
2935: && returnHeader.get("statusId") != null) {
2936: String currentStatus = returnHeader.getString("statusId");
2937: if ("RETURN_COMPLETED".equals(currentStatus)
2938: || "RETURN_CANCELLED".equals(currentStatus)) {
2939: return ServiceUtil.returnSuccess();
2940: }
2941: }
2942:
2943: // now; to be used for all timestamps
2944: Timestamp now = UtilDateTime.nowTimestamp();
2945:
2946: List completedItems = new ArrayList();
2947: if (returnHeader != null && returnItems != null
2948: && returnItems.size() > 0) {
2949: Iterator itemsIter = returnItems.iterator();
2950: while (itemsIter.hasNext()) {
2951: GenericValue item = (GenericValue) itemsIter.next();
2952: String itemStatus = item != null ? item
2953: .getString("statusId") : null;
2954: if (itemStatus != null) {
2955: // both completed and cancelled items qualify for completed status change
2956: if ("RETURN_COMPLETED".equals(itemStatus)
2957: || "RETURN_CANCELLED".equals(itemStatus)) {
2958: completedItems.add(item);
2959: }
2960: }
2961: }
2962:
2963: // if all items are completed/cancelled these should match
2964: if (completedItems.size() == returnItems.size()) {
2965: List toStore = new LinkedList();
2966: returnHeader.set("statusId", "RETURN_COMPLETED");
2967: toStore.add(returnHeader);
2968:
2969: // create the status change history and set it to be stored
2970: String returnStatusId = delegator.getNextSeqId(
2971: "ReturnStatus").toString();
2972: GenericValue returnStatus = delegator.makeValue(
2973: "ReturnStatus", UtilMisc.toMap(
2974: "returnStatusId", returnStatusId));
2975: returnStatus.set("statusId", "RETURN_COMPLETED");
2976: returnStatus.set("returnId", returnId);
2977: returnStatus.set("statusDatetime", now);
2978: toStore.add(returnStatus);
2979: try {
2980: delegator.storeAll(toStore);
2981: } catch (GenericEntityException e) {
2982: Debug.logError(e, module);
2983: return ServiceUtil
2984: .returnError("ERROR: Unable to create ReturnStatus history");
2985: }
2986: }
2987:
2988: }
2989:
2990: Map result = ServiceUtil.returnSuccess();
2991: result.put("statusId", returnHeader.get("statusId"));
2992: return result;
2993: }
2994:
2995: // credit (billingAccount) return
2996: public static Map processCreditReturn(DispatchContext ctx,
2997: Map context) {
2998: LocalDispatcher dispatcher = ctx.getDispatcher();
2999: GenericDelegator delegator = ctx.getDelegator();
3000: String returnId = (String) context.get("returnId");
3001: GenericValue userLogin = (GenericValue) context
3002: .get("userLogin");
3003:
3004: GenericValue returnHeader = null;
3005: List returnItems = null;
3006: try {
3007: returnHeader = delegator.findByPrimaryKey("ReturnHeader",
3008: UtilMisc.toMap("returnId", returnId));
3009: if (returnHeader != null) {
3010: returnItems = returnHeader.getRelatedByAnd(
3011: "ReturnItem", UtilMisc.toMap("returnTypeId",
3012: "RTN_CREDIT"));
3013: }
3014: } catch (GenericEntityException e) {
3015: Debug.logError(e, "Problems looking up return information",
3016: module);
3017: return ServiceUtil
3018: .returnError("Error getting ReturnHeader/Item information");
3019: }
3020:
3021: if (returnHeader != null && returnItems != null
3022: && returnItems.size() > 0) {
3023: String billingAccountId = returnHeader
3024: .getString("billingAccountId");
3025: String fromPartyId = returnHeader.getString("fromPartyId");
3026: if (billingAccountId == null) {
3027: // create new BillingAccount w/ 0 balance
3028: try {
3029: Map newBa = dispatcher.runSync(
3030: "createBillingAccount", UtilMisc.toMap(
3031: "accountLimit", new Double(0.00),
3032: "description", "Credit Account",
3033: "userLogin", userLogin));
3034: if (!newBa.get(ModelService.RESPONSE_MESSAGE)
3035: .equals(ModelService.RESPOND_ERROR)) {
3036: billingAccountId = (String) newBa
3037: .get("billingAccountId");
3038: if (billingAccountId != null) {
3039: // set the role on the account
3040: Map newBaR = dispatcher.runSync(
3041: "createBillingAccountRole",
3042: UtilMisc.toMap("billingAccountId",
3043: billingAccountId,
3044: "partyId", fromPartyId,
3045: "roleTypeId",
3046: "BILL_TO_CUSTOMER",
3047: "userLogin", userLogin));
3048: if (newBaR.get(
3049: ModelService.RESPONSE_MESSAGE)
3050: .equals(ModelService.RESPOND_ERROR)) {
3051: Debug
3052: .logError(
3053: "Error with createBillingAccountRole: "
3054: + newBaR
3055: .get(ModelService.ERROR_MESSAGE),
3056: module);
3057: return ServiceUtil
3058: .returnError("Error with createBillingAccountRole: "
3059: + newBaR
3060: .get(ModelService.ERROR_MESSAGE));
3061: }
3062: }
3063: } else {
3064: Debug
3065: .logError(
3066: "Error with createBillingAccount: "
3067: + newBa
3068: .get(ModelService.ERROR_MESSAGE),
3069: module);
3070: return ServiceUtil
3071: .returnError("Error with createBillingAccount: "
3072: + newBa
3073: .get(ModelService.ERROR_MESSAGE));
3074: }
3075: } catch (GenericServiceException e) {
3076: Debug.logError(e,
3077: "Problems creating BillingAccount", module);
3078: return ServiceUtil
3079: .returnError("Problems creating billing account");
3080: }
3081: }
3082:
3083: // double check; make sure we have a billingAccount
3084: if (billingAccountId == null) {
3085: Debug
3086: .logError(
3087: "No available billing account, none was created",
3088: module);
3089: return ServiceUtil
3090: .returnError("No available billing account");
3091: }
3092:
3093: // now; to be used for all timestamps
3094: Timestamp now = UtilDateTime.nowTimestamp();
3095:
3096: // start the response creation
3097: String itemResponseId = delegator.getNextSeqId(
3098: "ReturnItemResponse").toString();
3099: GenericValue itemResponse = delegator.makeValue(
3100: "ReturnItemResponse", UtilMisc.toMap(
3101: "returnItemResponseId", itemResponseId));
3102:
3103: // need a total for the credit
3104: List toBeStored = new ArrayList();
3105: double creditTotal = 0.00;
3106: Iterator itemsIter = returnItems.iterator();
3107: while (itemsIter.hasNext()) {
3108: GenericValue item = (GenericValue) itemsIter.next();
3109: Double quantity = item.getDouble("returnQuantity");
3110: Double price = item.getDouble("returnPrice");
3111: if (quantity == null)
3112: quantity = new Double(0);
3113: if (price == null)
3114: price = new Double(0);
3115: creditTotal += price.doubleValue()
3116: * quantity.doubleValue();
3117:
3118: // set the response on the item and flag the item to be stored
3119: item.set("returnItemResponseId", itemResponseId);
3120: item.set("statusId", "RETURN_COMPLETED");
3121: toBeStored.add(item);
3122:
3123: // create the status change history and set it to be stored
3124: String returnStatusId = delegator.getNextSeqId(
3125: "ReturnStatus").toString();
3126: GenericValue returnStatus = delegator.makeValue(
3127: "ReturnStatus", UtilMisc.toMap(
3128: "returnStatusId", returnStatusId));
3129: returnStatus.set("statusId", item.get("statusId"));
3130: returnStatus.set("returnId", item.get("returnId"));
3131: returnStatus.set("returnItemSeqId", item
3132: .get("returnItemSeqId"));
3133: returnStatus.set("statusDatetime", now);
3134: toBeStored.add(returnStatus);
3135: }
3136:
3137: // create a Double object for the amount
3138: Double creditAmount = new Double(creditTotal);
3139:
3140: // create a Payment record for this credit; will look just like a normal payment
3141: String paymentId = delegator.getNextSeqId("Payment")
3142: .toString();
3143: GenericValue payment = delegator.makeValue("Payment",
3144: UtilMisc.toMap("paymentId", paymentId));
3145: payment.set("paymentTypeId", "RECEIPT");
3146: payment.set("paymentMethodTypeId", "EXT_BILLACT");
3147: payment.set("partyIdFrom", fromPartyId);
3148: payment.set("partyIdTo", "Company"); // TODO: need to fix this and find a partyId to use
3149: payment.set("effectiveDate", now);
3150: payment.set("amount", creditAmount);
3151: payment.set("comments", "Return Credit");
3152: try {
3153: delegator.create(payment);
3154: } catch (GenericEntityException e) {
3155: Debug.logError(e, "Problem creating Payment record",
3156: module);
3157: return ServiceUtil
3158: .returnError("Problem creating Payment record");
3159: }
3160:
3161: // create the PaymentApplication
3162: String paId = delegator.getNextSeqId("PaymentApplication")
3163: .toString();
3164: GenericValue pa = delegator.makeValue("PaymentApplication",
3165: UtilMisc.toMap("paymentApplicationId", paId));
3166: pa.set("paymentId", paymentId);
3167: pa.set("billingAccountId", billingAccountId);
3168: pa.set("amountApplied", creditAmount);
3169: try {
3170: delegator.create(pa);
3171: } catch (GenericEntityException e) {
3172: Debug.logError(e,
3173: "Problem creating PaymentApplication record",
3174: module);
3175: return ServiceUtil
3176: .returnError("Problem creating PaymentApplication record");
3177: }
3178:
3179: // fill in the response fields
3180: itemResponse.set("paymentId", paymentId);
3181: itemResponse.set("billingAccountId", billingAccountId);
3182: itemResponse.set("responseAmount", creditAmount);
3183: itemResponse.set("responseDate", now);
3184: try {
3185: delegator.create(itemResponse);
3186: } catch (GenericEntityException e) {
3187: Debug.logError(e,
3188: "Problem creating ReturnItemResponse record",
3189: module);
3190: return ServiceUtil
3191: .returnError("Problem creating ReturnItemResponse record");
3192: }
3193:
3194: // store the item changes (attached responseId)
3195: try {
3196: delegator.storeAll(toBeStored);
3197: } catch (GenericEntityException e) {
3198: Debug.logError(e, "Problem storing ReturnItem updates",
3199: module);
3200: return ServiceUtil
3201: .returnError("Problem storing ReturnItem updates");
3202: }
3203: }
3204:
3205: return ServiceUtil.returnSuccess();
3206: }
3207:
3208: // refund (cash/charge) return
3209: public static Map processRefundReturn(DispatchContext ctx,
3210: Map context) {
3211: LocalDispatcher dispatcher = ctx.getDispatcher();
3212: GenericDelegator delegator = ctx.getDelegator();
3213: String returnId = (String) context.get("returnId");
3214: GenericValue userLogin = (GenericValue) context
3215: .get("userLogin");
3216:
3217: GenericValue returnHeader = null;
3218: List returnItems = null;
3219: try {
3220: returnHeader = delegator.findByPrimaryKey("ReturnHeader",
3221: UtilMisc.toMap("returnId", returnId));
3222: if (returnHeader != null) {
3223: returnItems = returnHeader.getRelatedByAnd(
3224: "ReturnItem", UtilMisc.toMap("returnTypeId",
3225: "RTN_REFUND"));
3226: }
3227: } catch (GenericEntityException e) {
3228: Debug.logError(e, "Problems looking up return information",
3229: module);
3230: return ServiceUtil
3231: .returnError("Error getting ReturnHeader/Item information");
3232: }
3233:
3234: if (returnHeader != null && returnItems != null
3235: && returnItems.size() > 0) {
3236: Map itemsByOrder = new HashMap();
3237: Map totalByOrder = new HashMap();
3238: groupReturnItemsByOrder(returnItems, itemsByOrder,
3239: totalByOrder);
3240:
3241: // process each one by order
3242: Set itemSet = itemsByOrder.entrySet();
3243: Iterator itemByOrderIt = itemSet.iterator();
3244: while (itemByOrderIt.hasNext()) {
3245: Map.Entry entry = (Map.Entry) itemByOrderIt.next();
3246: String orderId = (String) entry.getKey();
3247: List items = (List) entry.getValue();
3248: Double orderTotal = (Double) totalByOrder.get(orderId);
3249:
3250: // get order header & payment prefs
3251: GenericValue orderHeader = null;
3252: List orderPayPrefs = null;
3253: try {
3254: orderHeader = delegator.findByPrimaryKey(
3255: "OrderHeader", UtilMisc.toMap("orderId",
3256: orderId));
3257: // sort these desending by maxAmount
3258: orderPayPrefs = orderHeader.getRelated(
3259: "OrderPaymentPreference", null, UtilMisc
3260: .toList("-maxAmount"));
3261: } catch (GenericEntityException e) {
3262: Debug.logError(e, "Cannot get Order details for #"
3263: + orderId, module);
3264: continue;
3265: }
3266:
3267: // get the payment prefs to use (will use them in order of amount charged)
3268: List prefsToUse = new ArrayList();
3269: Map prefsAmount = new HashMap();
3270: double neededAmount = orderTotal.doubleValue();
3271: if (orderPayPrefs != null && orderPayPrefs.size() > 0) {
3272: Iterator payPrefIter = orderPayPrefs.iterator();
3273: do {
3274: GenericValue pref = (GenericValue) payPrefIter
3275: .next();
3276: Double maxAmount = pref.getDouble("maxAmount");
3277: if (maxAmount == null
3278: || maxAmount.doubleValue() == 0.00) {
3279: prefsToUse.add(pref);
3280: prefsAmount.put(pref, orderTotal);
3281: neededAmount = 0.00;
3282: } else if (maxAmount.doubleValue() > orderTotal
3283: .doubleValue()) {
3284: prefsToUse.add(pref);
3285: prefsAmount.put(pref, orderTotal);
3286: neededAmount = 0.00;
3287: } else {
3288: prefsToUse.add(pref);
3289: if (maxAmount.doubleValue() > neededAmount) {
3290: prefsAmount.put(pref, new Double(
3291: maxAmount.doubleValue()
3292: - neededAmount));
3293: } else {
3294: prefsAmount.put(pref, maxAmount);
3295: }
3296: neededAmount -= maxAmount.doubleValue();
3297: }
3298: } while (neededAmount > 0 && payPrefIter.hasNext());
3299: }
3300:
3301: if (neededAmount != 0) {
3302: Debug.logError(
3303: "Was not able to find needed payment preferences for the order RTN: "
3304: + returnId + " ORD: " + orderId,
3305: module);
3306: continue;
3307: }
3308:
3309: Map prefSplitMap = new HashMap();
3310: if (prefsToUse == null || prefsToUse.size() == 0) {
3311: Debug.logError(
3312: "We didn't find any possible payment prefs to use for RTN: "
3313: + returnId + " ORD: " + orderId,
3314: module);
3315: continue;
3316: } else if (prefsToUse.size() > 1) {
3317: // we need to spit the items up to log which pref it was refunded to
3318: // TODO: add the split of items for multiple payment prefs
3319: } else {
3320: // single payment / single refund
3321: prefSplitMap.put(prefsToUse.get(0), items);
3322: }
3323:
3324: // now process all items for each preference
3325: Set prefItemSet = prefSplitMap.entrySet();
3326: Iterator prefItemIt = prefItemSet.iterator();
3327: while (prefItemIt.hasNext()) {
3328: Map.Entry prefItemEntry = (Map.Entry) prefItemIt
3329: .next();
3330: GenericValue orderPayPref = (GenericValue) prefItemEntry
3331: .getKey();
3332: List itemList = (List) prefItemEntry.getValue();
3333:
3334: Double this RefundAmount = (Double) prefsAmount
3335: .get(orderPayPref);
3336: String paymentId = null;
3337:
3338: // this can be extended to support additional electronic types
3339: List electronicTypes = UtilMisc.toList(
3340: "CREDIT_CARD", "EFT_ACCOUNT", "GIFT_CARD");
3341: //List electronicTypes = new ArrayList();
3342:
3343: if (electronicTypes.contains(orderPayPref
3344: .getString("paymentMethodTypeId"))) {
3345: // call the refund service to refund the payment
3346: try {
3347: Map serviceResult = dispatcher.runSync(
3348: "refundPayment", UtilMisc.toMap(
3349: "orderPaymentPreference",
3350: orderPayPref,
3351: "refundAmount",
3352: this RefundAmount,
3353: "userLogin", userLogin));
3354: paymentId = (String) serviceResult
3355: .get("paymentId");
3356: } catch (GenericServiceException e) {
3357: Debug
3358: .logError(
3359: e,
3360: "Problem running the refundPayment service",
3361: module);
3362: return ServiceUtil
3363: .returnError("Problems with the refund; see logs");
3364: }
3365: } else {
3366: // TODO: handle manual refunds (accounts payable)
3367: }
3368:
3369: //Debug.log("Finished handing refund payments", module);
3370:
3371: // now; for all timestamps
3372: Timestamp now = UtilDateTime.nowTimestamp();
3373:
3374: // create a new response entry
3375: String responseId = delegator.getNextSeqId(
3376: "ReturnItemResponse").toString();
3377: GenericValue response = delegator
3378: .makeValue("ReturnItemResponse", UtilMisc
3379: .toMap("returnItemResponseId",
3380: responseId));
3381: response
3382: .set(
3383: "orderPaymentPreferenceId",
3384: orderPayPref
3385: .getString("orderPaymentPreferenceId"));
3386: response.set("responseAmount", this RefundAmount);
3387: response.set("responseDate", now);
3388: if (paymentId != null) {
3389: // a null payment ID means no electronic refund was available; manual refund needed
3390: response.set("paymentId", paymentId);
3391: }
3392:
3393: //Debug.log("About to create return response", module);
3394:
3395: try {
3396: delegator.create(response);
3397: } catch (GenericEntityException e) {
3398: Debug
3399: .logError(
3400: e,
3401: "Problems creating new ReturnItemResponse entity",
3402: module);
3403: return ServiceUtil
3404: .returnError("Problems creating ReturnItemResponse entity");
3405: }
3406:
3407: //Debug.log("Return response created", module);
3408:
3409: // set the response on each item
3410: Iterator itemsIter = itemList.iterator();
3411: while (itemsIter.hasNext()) {
3412: GenericValue item = (GenericValue) itemsIter
3413: .next();
3414: item.set("returnItemResponseId", responseId);
3415: item.set("statusId", "RETURN_COMPLETED");
3416:
3417: // create the status history
3418: String returnStatusId = delegator.getNextSeqId(
3419: "ReturnStatus").toString();
3420: GenericValue returnStatus = delegator
3421: .makeValue("ReturnStatus", UtilMisc
3422: .toMap("returnStatusId",
3423: returnStatusId));
3424: returnStatus.set("statusId", item
3425: .get("statusId"));
3426: returnStatus.set("returnId", item
3427: .get("returnId"));
3428: returnStatus.set("returnItemSeqId", item
3429: .get("returnItemSeqId"));
3430: returnStatus.set("statusDatetime", now);
3431:
3432: //Debug.log("Updating item status", module);
3433: try {
3434: item.store();
3435: delegator.create(returnStatus);
3436: } catch (GenericEntityException e) {
3437: Debug
3438: .logError(
3439: "Problem updating the ReturnItem entity",
3440: module);
3441: return ServiceUtil
3442: .returnError("Problem updating ReturnItem (returnItemResponseId)");
3443: }
3444:
3445: //Debug.log("Item status and return status history created", module);
3446: }
3447: }
3448: }
3449: }
3450:
3451: //Debug.log("Finished refund process");
3452: return ServiceUtil.returnSuccess();
3453: }
3454:
3455: public static Map processReplacementReturn(DispatchContext ctx,
3456: Map context) {
3457: LocalDispatcher dispatcher = ctx.getDispatcher();
3458: GenericDelegator delegator = ctx.getDelegator();
3459: String returnId = (String) context.get("returnId");
3460: GenericValue userLogin = (GenericValue) context
3461: .get("userLogin");
3462:
3463: GenericValue returnHeader = null;
3464: List returnItems = null;
3465: try {
3466: returnHeader = delegator.findByPrimaryKey("ReturnHeader",
3467: UtilMisc.toMap("returnId", returnId));
3468: if (returnHeader != null) {
3469: returnItems = returnHeader.getRelatedByAnd(
3470: "ReturnItem", UtilMisc.toMap("returnTypeId",
3471: "RTN_REPLACE"));
3472: }
3473: } catch (GenericEntityException e) {
3474: Debug.logError(e, "Problems looking up return information",
3475: module);
3476: return ServiceUtil
3477: .returnError("Error getting ReturnHeader/Item information");
3478: }
3479:
3480: List createdOrderIds = new ArrayList();
3481: if (returnHeader != null && returnItems != null
3482: && returnItems.size() > 0) {
3483: Map itemsByOrder = new HashMap();
3484: Map totalByOrder = new HashMap();
3485: groupReturnItemsByOrder(returnItems, itemsByOrder,
3486: totalByOrder);
3487:
3488: // process each one by order
3489: Set itemSet = itemsByOrder.entrySet();
3490: Iterator itemByOrderIt = itemSet.iterator();
3491: while (itemByOrderIt.hasNext()) {
3492: Map.Entry entry = (Map.Entry) itemByOrderIt.next();
3493: String orderId = (String) entry.getKey();
3494: List items = (List) entry.getValue();
3495:
3496: // get order header & payment prefs
3497: GenericValue orderHeader = null;
3498: try {
3499: orderHeader = delegator.findByPrimaryKey(
3500: "OrderHeader", UtilMisc.toMap("orderId",
3501: orderId));
3502: } catch (GenericEntityException e) {
3503: Debug.logError(e, "Cannot get Order details for #"
3504: + orderId, module);
3505: continue;
3506: }
3507:
3508: OrderReadHelper orh = new OrderReadHelper(orderHeader);
3509:
3510: // create the replacement order
3511: Map orderMap = UtilMisc.toMap("userLogin", userLogin);
3512: GenericValue placingParty = orh.getPlacingParty();
3513: String placingPartyId = null;
3514: if (placingParty != null) {
3515: placingPartyId = placingParty.getString("partyId");
3516: }
3517:
3518: orderMap.put("orderTypeId", "SALES_ORDER");
3519: orderMap.put("partyId", placingPartyId);
3520: orderMap.put("productStoreId", orderHeader
3521: .get("productStoreId"));
3522: orderMap.put("webSiteId", orderHeader.get("webSiteId"));
3523: orderMap.put("visitId", orderHeader.get("visitId"));
3524: orderMap.put("currencyUom", orderHeader
3525: .get("currencyUom"));
3526: orderMap.put("grandTotal", new Double(0.00));
3527:
3528: // make the contact mechs
3529: List contactMechs = new ArrayList();
3530: List orderCm = null;
3531: try {
3532: orderCm = orderHeader
3533: .getRelated("OrderContactMech");
3534: } catch (GenericEntityException e) {
3535: Debug.logError(e, module);
3536: }
3537: if (orderCm != null) {
3538: Iterator orderCmi = orderCm.iterator();
3539: while (orderCmi.hasNext()) {
3540: GenericValue v = (GenericValue) orderCmi.next();
3541: contactMechs.add(new GenericValue(v));
3542: }
3543: orderMap.put("orderContactMechs", contactMechs);
3544: }
3545:
3546: // make the shipment prefs
3547: List shipmentPrefs = new ArrayList();
3548: List orderSp = null;
3549: try {
3550: orderSp = orderHeader
3551: .getRelated("OrderShipmentPreference");
3552: } catch (GenericEntityException e) {
3553: Debug.logError(e, module);
3554: }
3555: if (orderSp != null) {
3556: Iterator orderSpi = orderSp.iterator();
3557: while (orderSpi.hasNext()) {
3558: GenericValue v = (GenericValue) orderSpi.next();
3559: shipmentPrefs.add(new GenericValue(v));
3560: }
3561: orderMap.put("orderShipmentPreferences",
3562: shipmentPrefs);
3563: }
3564:
3565: // make the order items
3566: double itemTotal = 0.00;
3567: List orderItems = new ArrayList();
3568: if (items != null) {
3569: Iterator ri = items.iterator();
3570: int itemCount = 1;
3571: while (ri.hasNext()) {
3572: GenericValue returnItem = (GenericValue) ri
3573: .next();
3574: GenericValue orderItem = null;
3575: try {
3576: orderItem = returnItem
3577: .getRelatedOne("OrderItem");
3578: } catch (GenericEntityException e) {
3579: Debug.logError(e, module);
3580: continue;
3581: }
3582: if (orderItem != null) {
3583: Double quantity = returnItem
3584: .getDouble("returnQuantity");
3585: Double unitPrice = returnItem
3586: .getDouble("returnPrice");
3587: if (quantity != null && unitPrice != null) {
3588: itemTotal = (quantity.doubleValue() * unitPrice
3589: .doubleValue());
3590: GenericValue newItem = delegator
3591: .makeValue(
3592: "OrderItem",
3593: UtilMisc
3594: .toMap(
3595: "orderItemSeqId",
3596: new Integer(
3597: itemCount)
3598: .toString()));
3599:
3600: newItem.set("orderItemTypeId",
3601: "PRODUCT_ORDER_ITEM");
3602: newItem.set("productId", orderItem
3603: .get("productId"));
3604: newItem
3605: .set(
3606: "productFeatureId",
3607: orderItem
3608: .get("productFeatureId"));
3609: newItem.set("prodCatalogId", orderItem
3610: .get("prodCatalogId"));
3611: newItem
3612: .set(
3613: "productCategoryId",
3614: orderItem
3615: .get("productCategoryId"));
3616: newItem.set("quantity", quantity);
3617: newItem.set("unitPrice", unitPrice);
3618: newItem.set("unitListPrice", orderItem
3619: .get("unitListPrice"));
3620: newItem
3621: .set(
3622: "itemDescription",
3623: orderItem
3624: .get("itemDescription"));
3625: newItem.set("comments", orderItem
3626: .get("comments"));
3627: newItem
3628: .set(
3629: "correspondingPoId",
3630: orderItem
3631: .get("correspondingPoId"));
3632: newItem.set("statusId", "ITEM_CREATED");
3633: orderItems.add(newItem);
3634: }
3635: }
3636: }
3637: orderMap.put("orderItems", orderItems);
3638: } else {
3639: Debug.logError("No return items found??", module);
3640: continue;
3641: }
3642:
3643: // create the replacement adjustment
3644: GenericValue adj = delegator.makeValue(
3645: "OrderAdjustment", new HashMap());
3646: adj.set("orderAdjustmentTypeId", "REPLACE_ADJUSTMENT");
3647: adj.set("amount", new Double(itemTotal * -1));
3648: adj.set("comments", "Replacement Item Return #"
3649: + returnId);
3650: orderMap.put("orderAdjustments", UtilMisc.toList(adj));
3651:
3652: // create the order
3653: String createdOrderId = null;
3654: Map orderResult = null;
3655: try {
3656: orderResult = dispatcher.runSync("storeOrder",
3657: orderMap);
3658: } catch (GenericServiceException e) {
3659: Debug.logInfo(e, "Problem creating the order!",
3660: module);
3661: }
3662: if (orderResult != null) {
3663: createdOrderId = (String) orderResult
3664: .get("orderId");
3665: createdOrderIds.add(createdOrderId);
3666: }
3667:
3668: // since there is no payments required; order is ready for processing/shipment
3669: if (createdOrderId != null) {
3670: boolean ok = OrderChangeHelper.approveOrder(
3671: dispatcher, userLogin, createdOrderId);
3672: }
3673: }
3674: }
3675:
3676: StringBuffer successMessage = new StringBuffer();
3677: if (createdOrderIds.size() > 0) {
3678: successMessage
3679: .append("The following new orders have been created : ");
3680: Iterator i = createdOrderIds.iterator();
3681: while (i.hasNext()) {
3682: successMessage.append(i.next());
3683: if (i.hasNext()) {
3684: successMessage.append(", ");
3685: }
3686: }
3687: } else {
3688: successMessage.append("No orders were created.");
3689: }
3690:
3691: return ServiceUtil.returnSuccess(successMessage.toString());
3692: }
3693:
3694: public static void groupReturnItemsByOrder(List returnItems,
3695: Map itemsByOrder, Map totalByOrder) {
3696: Iterator itemIt = returnItems.iterator();
3697: while (itemIt.hasNext()) {
3698: GenericValue item = (GenericValue) itemIt.next();
3699: String orderId = item.getString("orderId");
3700: if (orderId != null) {
3701: if (itemsByOrder != null) {
3702: List orderList = (List) itemsByOrder.get(orderId);
3703: Double totalForOrder = null;
3704: if (totalByOrder != null) {
3705: totalForOrder = (Double) totalByOrder
3706: .get(orderId);
3707: }
3708: if (orderList == null) {
3709: orderList = new ArrayList();
3710: }
3711: if (totalForOrder == null) {
3712: totalForOrder = new Double(0.00);
3713: }
3714:
3715: // add to the items list
3716: orderList.add(item);
3717: itemsByOrder.put(orderId, orderList);
3718:
3719: if (totalByOrder != null) {
3720: // add on the total for this line
3721: Double quantity = item
3722: .getDouble("returnQuantity");
3723: Double amount = item.getDouble("returnPrice");
3724: if (quantity == null) {
3725: quantity = new Double(0);
3726: }
3727: if (amount == null) {
3728: amount = new Double(0.00);
3729: }
3730: double this Total = amount.doubleValue()
3731: * quantity.doubleValue();
3732: double existingTotal = totalForOrder
3733: .doubleValue();
3734: Double newTotal = new Double(existingTotal
3735: + this Total);
3736: totalByOrder.put(orderId, newTotal);
3737: }
3738: }
3739: }
3740: }
3741: }
3742:
3743: public static Map allowOrderSplit(DispatchContext ctx, Map context) {
3744: GenericDelegator delegator = ctx.getDelegator();
3745: GenericValue userLogin = (GenericValue) context
3746: .get("userLogin");
3747: String orderId = (String) context.get("orderId");
3748: String orderItemSeqId = (String) context.get("orderItemSeqId");
3749: if (orderItemSeqId == null) {
3750: orderItemSeqId = "_NA_";
3751: }
3752:
3753: // check and make sure we have permission to change the order
3754: Security security = ctx.getSecurity();
3755: if (!security.hasEntityPermission("ORDERMGR", "_UPDATE",
3756: userLogin)) {
3757: GenericValue placingCustomer = null;
3758: try {
3759: Map placingCustomerFields = UtilMisc.toMap("orderId",
3760: orderId, "partyId", userLogin
3761: .getString("partyId"), "roleTypeId",
3762: "PLACING_CUSTOMER");
3763: placingCustomer = delegator.findByPrimaryKey(
3764: "OrderRole", placingCustomerFields);
3765: } catch (GenericEntityException e) {
3766: return ServiceUtil
3767: .returnError("ERROR: Cannot get OrderRole entity: "
3768: + e.getMessage());
3769: }
3770: if (placingCustomer == null)
3771: return ServiceUtil
3772: .returnError("You do not have permission to change this order's status.");
3773: }
3774:
3775: GenericValue shipPref = null;
3776: try {
3777: Map fields = UtilMisc.toMap("orderId", orderId,
3778: "orderItemSeqId", orderItemSeqId);
3779: shipPref = delegator.findByPrimaryKey(
3780: "OrderShipmentPreference", fields);
3781: if (shipPref == null) {
3782: fields.put("orderItemSeqId", "_NA_");
3783: shipPref = delegator.findByPrimaryKey(
3784: "OrderShipmentPreference", fields);
3785: }
3786: } catch (GenericEntityException e) {
3787: Debug.logError(e,
3788: "Problems getting OrderShipmentPreference for : "
3789: + orderId + " / " + orderItemSeqId, module);
3790: return ServiceUtil
3791: .returnError("Cannot update; Problem getting OrderShipmentPreference");
3792: }
3793:
3794: if (shipPref != null) {
3795: shipPref.set("maySplit", "Y");
3796: try {
3797: shipPref.store();
3798: } catch (GenericEntityException e) {
3799: Debug.logError(
3800: "Problem saving OrdeShipmentPreference for : "
3801: + orderId + " / " + orderItemSeqId,
3802: module);
3803: return ServiceUtil
3804: .returnError("Cannot update; Problem setting OrderShipmentPreference");
3805: }
3806: } else {
3807: Debug.logError("ERROR: Got a NULL OrderShipmentPreference",
3808: module);
3809: return ServiceUtil
3810: .returnError("Cannot update; No available preference to change");
3811: }
3812: return ServiceUtil.returnSuccess();
3813: }
3814:
3815: public static Map cancelFlaggedSalesOrders(DispatchContext dctx,
3816: Map context) {
3817: GenericDelegator delegator = dctx.getDelegator();
3818: LocalDispatcher dispatcher = dctx.getDispatcher();
3819: GenericValue userLogin = (GenericValue) context
3820: .get("userLogin");
3821:
3822: List ordersToCheck = null;
3823: List exprs = new ArrayList();
3824:
3825: // create the query expressions
3826: exprs.add(new EntityExpr("orderTypeId", EntityOperator.EQUALS,
3827: "SALES_ORDER"));
3828: exprs.add(new EntityExpr("statusId", EntityOperator.NOT_EQUAL,
3829: "ORDER_COMPLETED"));
3830: exprs.add(new EntityExpr("statusId", EntityOperator.NOT_EQUAL,
3831: "ORDER_CANCELLED"));
3832: exprs.add(new EntityExpr("statusId", EntityOperator.NOT_EQUAL,
3833: "ORDER_REJECTED"));
3834:
3835: // get the orders
3836: try {
3837: ordersToCheck = delegator.findByAnd("OrderHeader", exprs,
3838: UtilMisc.toList("orderDate"));
3839: } catch (GenericEntityException e) {
3840: Debug.logError(e, "Problem getting order headers", module);
3841: }
3842:
3843: if (ordersToCheck == null || ordersToCheck.size() == 0) {
3844: Debug.logInfo("No orders to check, finished", module);
3845: return ServiceUtil.returnSuccess();
3846: }
3847:
3848: Iterator i = ordersToCheck.iterator();
3849: while (i.hasNext()) {
3850: GenericValue orderHeader = (GenericValue) i.next();
3851: String orderId = orderHeader.getString("orderId");
3852: String orderStatus = orderHeader.getString("statusId");
3853:
3854: if (orderStatus.equals("ORDER_CREATED")) {
3855: // first check for un-paid orders
3856: Timestamp orderDate = orderHeader
3857: .getTimestamp("entryDate");
3858: //appears to not be used: String webSiteId = orderHeader.getString("webSiteId");
3859:
3860: // name of the payment.properties file to use
3861: String propsFile = null;
3862:
3863: // need the payment.properties file for the website
3864: Map lookupFields = UtilMisc.toMap("productStoreId",
3865: orderHeader.getString("productStoreId"),
3866: "paymentMethodTypeId", "EXT_OFFLINE",
3867: "paymentServiceTypeEnumId", "_NA_");
3868: GenericValue paymentSettings = null;
3869: try {
3870: paymentSettings = delegator.findByPrimaryKey(
3871: "ProductStorePaymentSetting", lookupFields);
3872: } catch (GenericEntityException e) {
3873: Debug
3874: .logError(e,
3875: "Cannot get product store payment setting record");
3876: }
3877: if (paymentSettings == null
3878: || paymentSettings.get("paymentPropertiesPath") == null) {
3879: propsFile = "payment.properties";
3880: } else {
3881: propsFile = paymentSettings
3882: .getString("paymentPropertiesPath");
3883: }
3884:
3885: // need the store for the order
3886: GenericValue productStore = null;
3887: try {
3888: productStore = orderHeader
3889: .getRelatedOne("ProductStore");
3890: } catch (GenericEntityException e) {
3891: Debug
3892: .logError(
3893: e,
3894: "Unable to get ProductStore from OrderHeader",
3895: module);
3896: }
3897:
3898: // default days to cancel
3899: int daysTillCancel = 30;
3900:
3901: // get the value from the store
3902: if (productStore != null
3903: && productStore.get("daysToCancelNonPay") != null) {
3904: daysTillCancel = productStore.getLong(
3905: "daysToCancelNonPay").intValue();
3906: }
3907:
3908: if (daysTillCancel > 0) {
3909: // 0 days means do not auto-cancel
3910: Calendar cal = Calendar.getInstance();
3911: cal.setTimeInMillis(orderDate.getTime());
3912: cal.add(Calendar.DAY_OF_YEAR, daysTillCancel);
3913: Date cancelDate = cal.getTime();
3914: Date nowDate = new Date();
3915: //Debug.log("Cancel Date : " + cancelDate, module);
3916: //Debug.log("Current Date : " + nowDate, module);
3917: if (cancelDate.equals(nowDate)
3918: || nowDate.after(cancelDate)) {
3919: // cancel the order item(s)
3920: Map svcCtx = UtilMisc.toMap("orderId", orderId,
3921: "statusId", "ITEM_CANCELLED",
3922: "userLogin", userLogin);
3923: try {
3924: Map ores = dispatcher.runSync(
3925: "changeOrderItemStatus", svcCtx);
3926: } catch (GenericServiceException e) {
3927: Debug.logError(e,
3928: "Problem calling change item status service : "
3929: + svcCtx, module);
3930: }
3931: }
3932: }
3933: } else {
3934: // check for auto-cancel items
3935: List orderItems = null;
3936: try {
3937: orderItems = orderHeader.getRelated("OrderItem");
3938: } catch (GenericEntityException e) {
3939: Debug.logError(e,
3940: "Problem getting order item records",
3941: module);
3942: }
3943: if (orderItems != null && orderItems.size() > 0) {
3944: Iterator oii = orderItems.iterator();
3945: while (oii.hasNext()) {
3946: GenericValue orderItem = (GenericValue) oii
3947: .next();
3948: String orderItemSeqId = orderItem
3949: .getString("orderItemSeqId");
3950: Timestamp nowTimestamp = UtilDateTime
3951: .nowTimestamp();
3952: Timestamp autoCancelDate = orderItem
3953: .getTimestamp("autoCancelDate");
3954: Timestamp dontCancelDate = orderItem
3955: .getTimestamp("dontCancelSetDate");
3956: String dontCancelUserLogin = orderItem
3957: .getString("dontCancelSetUserLogin");
3958:
3959: if (dontCancelUserLogin == null
3960: && dontCancelDate == null
3961: && autoCancelDate != null) {
3962: if (autoCancelDate.equals(nowTimestamp)
3963: || autoCancelDate
3964: .after(nowTimestamp)) {
3965: // cancel the order item
3966: Map svcCtx = UtilMisc.toMap("orderId",
3967: orderId, "orderItemSeqId",
3968: orderItemSeqId, "statusId",
3969: "ITEM_CANCELLED", "userLogin",
3970: userLogin);
3971: try {
3972: Map res = dispatcher.runSync(
3973: "changeOrderItemStatus",
3974: svcCtx);
3975: } catch (GenericServiceException e) {
3976: Debug.logError(e,
3977: "Problem calling change item status service : "
3978: + svcCtx, module);
3979: }
3980: }
3981: }
3982: }
3983: }
3984: }
3985: }
3986: return ServiceUtil.returnSuccess();
3987: }
3988:
3989: public static Map checkDigitalItemFulfillment(DispatchContext dctx,
3990: Map context) {
3991: GenericDelegator delegator = dctx.getDelegator();
3992: LocalDispatcher dispatcher = dctx.getDispatcher();
3993: GenericValue userLogin = (GenericValue) context
3994: .get("userLogin");
3995: String orderId = (String) context.get("orderId");
3996:
3997: // need the order header
3998: GenericValue orderHeader = null;
3999: try {
4000: orderHeader = delegator.findByPrimaryKey("OrderHeader",
4001: UtilMisc.toMap("orderId", orderId));
4002: } catch (GenericEntityException e) {
4003: Debug.logError(e,
4004: "ERROR: Unable to get OrderHeader for orderId : "
4005: + orderId, module);
4006: return ServiceUtil
4007: .returnError("ERROR: Unable to get OrderHeader for orderId : "
4008: + orderId);
4009: }
4010:
4011: // get all the items for the order
4012: List orderItems = null;
4013: if (orderHeader != null) {
4014: try {
4015: orderItems = orderHeader.getRelated("OrderItem");
4016: } catch (GenericEntityException e) {
4017: Debug.logError(e,
4018: "ERROR: Unable to get OrderItem list for orderId : "
4019: + orderId, module);
4020: return ServiceUtil
4021: .returnError("ERROR: Unable to get OrderItem list for orderId : "
4022: + orderId);
4023: }
4024: }
4025:
4026: // find any digital goods
4027: Map digitalProducts = new HashMap();
4028: List digitalItems = new ArrayList();
4029: if (orderItems != null && orderItems.size() > 0) {
4030: Iterator i = orderItems.iterator();
4031: while (i.hasNext()) {
4032: GenericValue item = (GenericValue) i.next();
4033: GenericValue product = null;
4034: try {
4035: product = item.getRelatedOne("Product");
4036: } catch (GenericEntityException e) {
4037: Debug
4038: .logError(
4039: e,
4040: "ERROR: Unable to get Product from OrderItem",
4041: module);
4042: }
4043: if (product != null) {
4044: String productType = product
4045: .getString("productTypeId");
4046: // check for digital and finished/digital goods
4047: if ("DIGITAL_GOOD".equals(productType)
4048: || "FINDIG_GOOD".equals(productType)) {
4049: // we only invoice APPROVED items
4050: if ("ITEM_APPROVED".equals(item
4051: .getString("statusId"))) {
4052: digitalItems.add(item);
4053: }
4054: if ("DIGITAL_GOOD".equals(productType)) {
4055: // 100% digital goods need status change
4056: digitalProducts.put(item, product);
4057: }
4058: }
4059: }
4060: }
4061: }
4062:
4063: // now process the digital items
4064: if (digitalItems.size() > 0) {
4065: // invoice all APPROVED digital goods
4066: Map invoiceContext = UtilMisc.toMap("orderId", orderId,
4067: "billItems", digitalItems, "userLogin", userLogin);
4068: Map invoiceResult = null;
4069: try {
4070: invoiceResult = dispatcher.runSync(
4071: "createInvoiceForOrder", invoiceContext);
4072: } catch (GenericServiceException e) {
4073: Debug.logError(e,
4074: "ERROR: Unable to invoice digital items",
4075: module);
4076: return ServiceUtil
4077: .returnError("Problem with invoice creation; digital items not fulfilled.");
4078: }
4079: if (ModelService.RESPOND_ERROR.equals(invoiceResult
4080: .get(ModelService.RESPONSE_MESSAGE))) {
4081: return ServiceUtil.returnError((String) invoiceResult
4082: .get(ModelService.ERROR_MESSAGE));
4083: }
4084:
4085: // update the status of DIGITAL_GOOD to COMPLETED; leave FINDIG as APPROVED for pick/ship
4086: Iterator dii = digitalItems.iterator();
4087: while (dii.hasNext()) {
4088: GenericValue item = (GenericValue) dii.next();
4089: GenericValue product = (GenericValue) digitalProducts
4090: .get(item);
4091: if (product != null) {
4092: // we were set as a digital good; one more check and change status
4093: if ("DIGITAL_GOOD".equals(product
4094: .getString("productTypeId"))) {
4095: Map statusCtx = new HashMap();
4096: statusCtx.put("orderId", item
4097: .getString("orderId"));
4098: statusCtx.put("orderItemSeqId", item
4099: .getString("orderItemSeqId"));
4100: statusCtx.put("statusId", "ITEM_COMPLETED");
4101: statusCtx.put("userLogin", userLogin);
4102: try {
4103: dispatcher.runSyncIgnore(
4104: "changeOrderItemStatus", statusCtx);
4105: } catch (GenericServiceException e) {
4106: Debug.logError(e,
4107: "ERROR: Problem setting the status to COMPLETED : "
4108: + item, module);
4109: }
4110: }
4111: }
4112: }
4113:
4114: // fulfill the digital goods
4115: Map fulfillContext = UtilMisc.toMap("orderId", orderId,
4116: "orderItems", digitalItems, "userLogin", userLogin);
4117: Map fulfillResult = null;
4118: try {
4119: // will be running in an isolated transaction to prevent rollbacks
4120: fulfillResult = dispatcher.runSync(
4121: "fulfillDigitalItems", fulfillContext, 300,
4122: true);
4123: } catch (GenericServiceException e) {
4124: Debug.logError(e,
4125: "ERROR: Unable to fulfill digital items",
4126: module);
4127: }
4128: if (ModelService.RESPOND_ERROR.equals(fulfillResult
4129: .get(ModelService.RESPONSE_MESSAGE))) {
4130: // this service cannot return error at this point or we will roll back the invoice
4131: // since payments are already captured; errors should have been logged already.
4132: // the response message here will be passed as an error to the user.
4133: return ServiceUtil.returnSuccess((String) fulfillResult
4134: .get(ModelService.ERROR_MESSAGE));
4135: }
4136: }
4137:
4138: return ServiceUtil.returnSuccess();
4139: }
4140:
4141: public static Map fulfillDigitalItems(DispatchContext ctx,
4142: Map context) {
4143: //appears to not be used: GenericDelegator delegator = ctx.getDelegator();
4144: LocalDispatcher dispatcher = ctx.getDispatcher();
4145: //appears to not be used: String orderId = (String) context.get("orderId");
4146: List orderItems = (List) context.get("orderItems");
4147: GenericValue userLogin = (GenericValue) context
4148: .get("userLogin");
4149:
4150: if (orderItems != null && orderItems.size() > 0) {
4151: // loop through the digital items to fulfill
4152: Iterator itemsIterator = orderItems.iterator();
4153: while (itemsIterator.hasNext()) {
4154: GenericValue orderItem = (GenericValue) itemsIterator
4155: .next();
4156:
4157: // make sure we have a valid item
4158: if (orderItem == null) {
4159: ServiceUtil
4160: .returnError("ERROR: Cannot check for fulfillment; item not found.");
4161: }
4162:
4163: // locate the Product & ProductContent records
4164: GenericValue product = null;
4165: List productContent = null;
4166: try {
4167: product = orderItem.getRelatedOne("Product");
4168: if (product == null) {
4169: ServiceUtil
4170: .returnError("ERROR: Cannot check for fulfillment; product not found.");
4171: }
4172:
4173: List allProductContent = product
4174: .getRelated("ProductContent");
4175: if (allProductContent != null
4176: && allProductContent.size() > 0) {
4177: // only keep ones with valid dates
4178: productContent = EntityUtil.filterByDate(
4179: allProductContent, UtilDateTime
4180: .nowTimestamp(), "fromDate",
4181: "thruDate", true);
4182: Debug.logInfo("Product has "
4183: + allProductContent.size()
4184: + " associations, "
4185: + (productContent == null ? "0" : ""
4186: + productContent.size())
4187: + " has valid from/thru dates", module);
4188: }
4189: } catch (GenericEntityException e) {
4190: return ServiceUtil
4191: .returnError("ERROR: Cannot get Product entity: "
4192: + e.getMessage());
4193: }
4194:
4195: // now use the ProductContent to fulfill the item
4196: if (productContent != null && productContent.size() > 0) {
4197: Iterator prodcontentIterator = productContent
4198: .iterator();
4199: while (prodcontentIterator.hasNext()) {
4200: GenericValue productContentItem = (GenericValue) prodcontentIterator
4201: .next();
4202: GenericValue content = null;
4203: try {
4204: content = productContentItem
4205: .getRelatedOne("Content");
4206: } catch (GenericEntityException e) {
4207: Debug.logError(e,
4208: "ERROR: Cannot get Content entity: "
4209: + e.getMessage(), module);
4210: continue;
4211: }
4212:
4213: String fulfillmentType = productContentItem
4214: .getString("productContentTypeId");
4215: if ("FULFILLMENT_EXTASYNC"
4216: .equals(fulfillmentType)
4217: || "FULFILLMENT_EXTSYNC"
4218: .equals(fulfillmentType)) {
4219: // enternal service fulfillment
4220: String fulfillmentService = (String) content
4221: .get("serviceName");
4222: if (fulfillmentService == null) {
4223: Debug
4224: .logError(
4225: "ProductContent of type FULFILLMENT_EXTERNAL had Content with empty serviceName, can not run fulfillment",
4226: module);
4227: }
4228: Map serviceCtx = UtilMisc.toMap(
4229: "userLogin", userLogin,
4230: "orderItem", orderItem);
4231: serviceCtx.putAll(productContentItem
4232: .getPrimaryKey());
4233: try {
4234: Debug.logInfo(
4235: "Running external fulfillment '"
4236: + fulfillmentService
4237: + "'", module);
4238: if ("FULFILLMENT_EXTASYNC"
4239: .equals(fulfillmentType)) {
4240: dispatcher.runAsync(
4241: fulfillmentService,
4242: serviceCtx, true);
4243: } else if ("FULFILLMENT_EXTSYNC"
4244: .equals(fulfillmentType)) {
4245: Map resp = dispatcher.runSync(
4246: fulfillmentService,
4247: serviceCtx);
4248: if (ServiceUtil.isError(resp)) {
4249: return ServiceUtil
4250: .returnError(ServiceUtil
4251: .getErrorMessage(resp));
4252: }
4253: }
4254: } catch (GenericServiceException e) {
4255: Debug.logError(e,
4256: "ERROR: Could not run external fulfillment service '"
4257: + fulfillmentService
4258: + "'; "
4259: + e.getMessage(),
4260: module);
4261: }
4262: } else if ("FULFILLMENT_EMAIL"
4263: .equals(fulfillmentType)) {
4264: // digital email fulfillment
4265: // TODO: Add support for fulfillment email
4266: return ServiceUtil
4267: .returnError("Email Fulfillment type not yet implemented");
4268: } else if ("DIGITAL_DOWNLOAD"
4269: .equals(fulfillmentType)) {
4270: // digital download fulfillment
4271:
4272: // Nothing to do for here. Downloads are made available to the user
4273: // though a query of OrderItems with related ProductContent.
4274: } else {
4275: Debug
4276: .logError(
4277: "Invalid fulfillment type : "
4278: + fulfillmentType
4279: + " not supported.",
4280: module);
4281: }
4282: }
4283: }
4284: }
4285: }
4286: return ServiceUtil.returnSuccess();
4287: }
4288:
4289: }
|