0001: /*
0002: * $Id: CheckOutHelper.java,v 1.20 2004/02/28 19:49:47 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.shoppingcart;
0025:
0026: import java.text.DecimalFormat;
0027: import java.text.NumberFormat;
0028: import java.text.ParseException;
0029: import java.util.ArrayList;
0030: import java.util.HashMap;
0031: import java.util.Iterator;
0032: import java.util.LinkedList;
0033: import java.util.List;
0034: import java.util.Locale;
0035: import java.util.Map;
0036: import java.util.Set;
0037:
0038: import org.ofbiz.base.util.Debug;
0039: import org.ofbiz.base.util.GeneralException;
0040: import org.ofbiz.base.util.StringUtil;
0041: import org.ofbiz.base.util.UtilFormatOut;
0042: import org.ofbiz.base.util.UtilMisc;
0043: import org.ofbiz.base.util.UtilProperties;
0044: import org.ofbiz.base.util.UtilValidate;
0045: import org.ofbiz.entity.GenericDelegator;
0046: import org.ofbiz.entity.GenericEntityException;
0047: import org.ofbiz.entity.GenericValue;
0048: import org.ofbiz.entity.condition.EntityExpr;
0049: import org.ofbiz.entity.condition.EntityOperator;
0050: import org.ofbiz.entity.util.EntityUtil;
0051: import org.ofbiz.order.order.OrderChangeHelper;
0052: import org.ofbiz.order.order.OrderReadHelper;
0053: import org.ofbiz.party.contact.ContactHelper;
0054: import org.ofbiz.service.GenericServiceException;
0055: import org.ofbiz.service.LocalDispatcher;
0056: import org.ofbiz.service.ModelService;
0057: import org.ofbiz.service.ServiceUtil;
0058:
0059: /**
0060: * A facade over the ShoppingCart to simplify the relatively complex
0061: * processing required to create an order in the system.
0062: *
0063: * @author <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a>
0064: * @author <a href="mailto:cnelson@einnovation.com">Chris Nelson</a>
0065: * @author <a href="mailto:jonesde@ofbiz.org">David E. Jones</a>
0066: * @author <a href="mailto:tristana@twibble.org">Tristan Austin</a>
0067: * @version $Revision: 1.20 $
0068: * @since 2.0
0069: */
0070: public class CheckOutHelper {
0071:
0072: public static final String module = CheckOutHelper.class.getName();
0073: public static final String resource = "OrderUiLabels";
0074:
0075: private ShoppingCart cart;
0076: private GenericDelegator delegator;
0077: private LocalDispatcher dispatcher;
0078:
0079: public CheckOutHelper(LocalDispatcher dispatcher,
0080: GenericDelegator delegator, ShoppingCart cart) {
0081: this .delegator = delegator;
0082: this .dispatcher = dispatcher;
0083: this .cart = cart;
0084: }
0085:
0086: public Map setCheckOutShippingAddress(String shippingContactMechId) {
0087: List errorMessages = new ArrayList();
0088: Map result;
0089: String errMsg = null;
0090:
0091: if (this .cart != null && this .cart.size() > 0) {
0092: errorMessages
0093: .addAll(setCheckOutShippingAddressInternal(shippingContactMechId));
0094: } else {
0095: errMsg = UtilProperties.getMessage(resource,
0096: "checkhelper.no_items_in_cart",
0097: (cart != null ? cart.getLocale() : Locale
0098: .getDefault()));
0099: errorMessages.add(errMsg);
0100: }
0101: if (errorMessages.size() == 1) {
0102: result = ServiceUtil.returnError(errorMessages.get(0)
0103: .toString());
0104: } else if (errorMessages.size() > 0) {
0105: result = ServiceUtil.returnError(errorMessages);
0106: } else {
0107: result = ServiceUtil.returnSuccess();
0108: }
0109:
0110: return result;
0111: }
0112:
0113: private List setCheckOutShippingAddressInternal(
0114: String shippingContactMechId) {
0115: List errorMessages = new ArrayList();
0116: String errMsg = null;
0117:
0118: // set the shipping address
0119: if (UtilValidate.isNotEmpty(shippingContactMechId)) {
0120: this .cart.setShippingContactMechId(shippingContactMechId);
0121: } else {
0122: errMsg = UtilProperties.getMessage(resource,
0123: "checkhelper.select_shipping_destination",
0124: (cart != null ? cart.getLocale() : Locale
0125: .getDefault()));
0126: errorMessages.add(errMsg);
0127: }
0128:
0129: return errorMessages;
0130: }
0131:
0132: public Map setCheckOutShippingOptions(String shippingMethod,
0133: String correspondingPoId, String shippingInstructions,
0134: String orderAdditionalEmails, String maySplit,
0135: String giftMessage, String isGift) {
0136: List errorMessages = new ArrayList();
0137: Map result;
0138: String errMsg = null;
0139:
0140: if (this .cart != null && this .cart.size() > 0) {
0141: errorMessages.addAll(setCheckOutShippingOptionsInternal(
0142: shippingMethod, correspondingPoId,
0143: shippingInstructions, orderAdditionalEmails,
0144: maySplit, giftMessage, isGift));
0145: } else {
0146: errMsg = UtilProperties.getMessage(resource,
0147: "checkhelper.no_items_in_cart",
0148: (cart != null ? cart.getLocale() : Locale
0149: .getDefault()));
0150: errorMessages.add(errMsg);
0151: }
0152:
0153: if (errorMessages.size() == 1) {
0154: result = ServiceUtil.returnError(errorMessages.get(0)
0155: .toString());
0156: } else if (errorMessages.size() > 0) {
0157: result = ServiceUtil.returnError(errorMessages);
0158: } else {
0159: result = ServiceUtil.returnSuccess();
0160: }
0161:
0162: return result;
0163: }
0164:
0165: private List setCheckOutShippingOptionsInternal(
0166: String shippingMethod, String correspondingPoId,
0167: String shippingInstructions, String orderAdditionalEmails,
0168: String maySplit, String giftMessage, String isGift) {
0169: List errorMessages = new ArrayList();
0170: String errMsg = null;
0171:
0172: // set the general shipping options
0173: if (UtilValidate.isNotEmpty(shippingMethod)) {
0174: int delimiterPos = shippingMethod.indexOf('@');
0175: String shipmentMethodTypeId = null;
0176: String carrierPartyId = null;
0177:
0178: if (delimiterPos > 0) {
0179: shipmentMethodTypeId = shippingMethod.substring(0,
0180: delimiterPos);
0181: carrierPartyId = shippingMethod
0182: .substring(delimiterPos + 1);
0183: }
0184:
0185: this .cart.setShipmentMethodTypeId(shipmentMethodTypeId);
0186: this .cart.setCarrierPartyId(carrierPartyId);
0187: } else {
0188: errMsg = UtilProperties.getMessage(resource,
0189: "checkhelper.select_shipping_method",
0190: (cart != null ? cart.getLocale() : Locale
0191: .getDefault()));
0192: errorMessages.add(errMsg);
0193: }
0194: this .cart.setShippingInstructions(shippingInstructions);
0195: if (UtilValidate.isNotEmpty(maySplit)) {
0196: cart.setMaySplit(Boolean.valueOf(maySplit));
0197: } else {
0198: errMsg = UtilProperties.getMessage(resource,
0199: "checkhelper.select_splitting_preference",
0200: (cart != null ? cart.getLocale() : Locale
0201: .getDefault()));
0202: errorMessages.add(errMsg);
0203: }
0204: this .cart.setGiftMessage(giftMessage);
0205: if (UtilValidate.isNotEmpty(isGift)) {
0206: cart.setIsGift(Boolean.valueOf(isGift));
0207: } else {
0208: errMsg = UtilProperties.getMessage(resource,
0209: "checkhelper.specify_if_order_is_gift",
0210: (cart != null ? cart.getLocale() : Locale
0211: .getDefault()));
0212: errorMessages.add(errMsg);
0213: }
0214:
0215: this .cart.setOrderAdditionalEmails(orderAdditionalEmails);
0216:
0217: // set the PO number
0218: if (UtilValidate.isNotEmpty(correspondingPoId)) {
0219: this .cart.setPoNumber(correspondingPoId);
0220: } else {
0221: this .cart.setPoNumber("(none)");
0222: }
0223:
0224: return errorMessages;
0225: }
0226:
0227: public Map setCheckOutPayment(Map selectedPaymentMethods,
0228: List singleUsePayments, String billingAccountId,
0229: Double billingAccountAmt) {
0230: List errorMessages = new ArrayList();
0231: Map result;
0232: String errMsg = null;
0233:
0234: if (this .cart != null && this .cart.size() > 0) {
0235: errorMessages.addAll(setCheckOutPaymentInternal(
0236: selectedPaymentMethods, singleUsePayments,
0237: billingAccountId, billingAccountAmt));
0238: } else {
0239: errMsg = UtilProperties.getMessage(resource,
0240: "checkhelper.no_items_in_cart",
0241: (cart != null ? cart.getLocale() : Locale
0242: .getDefault()));
0243: errorMessages.add(errMsg);
0244: }
0245:
0246: if (errorMessages.size() == 1) {
0247: result = ServiceUtil.returnError(errorMessages.get(0)
0248: .toString());
0249: } else if (errorMessages.size() > 0) {
0250: result = ServiceUtil.returnError(errorMessages);
0251: } else {
0252: result = ServiceUtil.returnSuccess();
0253: }
0254:
0255: return result;
0256: }
0257:
0258: private List setCheckOutPaymentInternal(Map selectedPaymentMethods,
0259: List singleUsePayments, String billingAccountId,
0260: Double billingAccountAmt) {
0261: List errorMessages = new ArrayList();
0262: String errMsg = null;
0263:
0264: if (singleUsePayments == null) {
0265: singleUsePayments = new ArrayList();
0266: }
0267:
0268: // set the billing account amount
0269: if (billingAccountId != null && billingAccountAmt != null
0270: && !billingAccountId.equals("_NA_")) {
0271: cart.setBillingAccount(billingAccountId, billingAccountAmt
0272: .doubleValue());
0273: } else {
0274: cart.setBillingAccount(null, 0.00);
0275: }
0276:
0277: // set the payment method option
0278: if (selectedPaymentMethods != null
0279: && selectedPaymentMethods.size() > 0) {
0280: // clear out the old payments
0281: this .cart.clearPaymentMethodTypeIds();
0282: this .cart.clearPaymentMethodIds();
0283:
0284: // if we are EXT_BILLACT (billing account only) then we need to make sure we have enough credit
0285: if (selectedPaymentMethods.containsKey("EXT_BILLACT")) {
0286: double accountCredit = this
0287: .availableAccountBalance(cart
0288: .getBillingAccountId());
0289: // make sure we have enough to cover; if this is selected we don't have other payment methods
0290: if (cart.getGrandTotal() > accountCredit) {
0291: errMsg = UtilProperties
0292: .getMessage(
0293: resource,
0294: "checkhelper.insufficient_credit_available_on_account",
0295: (cart != null ? cart.getLocale()
0296: : Locale.getDefault()));
0297: errorMessages.add(errMsg);
0298: }
0299: }
0300:
0301: Set paymentMethods = selectedPaymentMethods.keySet();
0302: Iterator i = paymentMethods.iterator();
0303: while (i.hasNext()) {
0304: String checkOutPaymentId = (String) i.next();
0305:
0306: // get the selected amount to use
0307: Double paymentAmount = null;
0308: if (selectedPaymentMethods.get(checkOutPaymentId) != null) {
0309: paymentAmount = (Double) selectedPaymentMethods
0310: .get(checkOutPaymentId);
0311: }
0312:
0313: // all payment method ids will be numeric, type ids will start with letter
0314: if (Character.isLetter(checkOutPaymentId.charAt(0))) {
0315: this .cart.addPaymentMethodTypeId(checkOutPaymentId);
0316: } else {
0317: boolean singleUse = singleUsePayments
0318: .contains(checkOutPaymentId);
0319: this .cart.setPaymentMethodAmount(checkOutPaymentId,
0320: paymentAmount, singleUse);
0321: //Debug.logInfo("Set Payment Method : " + checkOutPaymentId + " @ " + paymentAmount, module);
0322: }
0323: }
0324: } else {
0325: errMsg = UtilProperties.getMessage(resource,
0326: "checkhelper.select_method_of_payment",
0327: (cart != null ? cart.getLocale() : Locale
0328: .getDefault()));
0329: errorMessages.add(errMsg);
0330: }
0331:
0332: return errorMessages;
0333: }
0334:
0335: public Map setCheckOutOptions(String shippingMethod,
0336: String shippingContactMechId, Map selectedPaymentMethods,
0337: List singleUsePayments, String billingAccountId,
0338: Double billingAccountAmt, String correspondingPoId,
0339: String shippingInstructions, String orderAdditionalEmails,
0340: String maySplit, String giftMessage, String isGift) {
0341: List errorMessages = new ArrayList();
0342: Map result = null;
0343: String errMsg = null;
0344:
0345: if (this .cart != null && this .cart.size() > 0) {
0346: // set the general shipping options and method
0347: errorMessages.addAll(setCheckOutShippingOptionsInternal(
0348: shippingMethod, correspondingPoId,
0349: shippingInstructions, orderAdditionalEmails,
0350: maySplit, giftMessage, isGift));
0351:
0352: // set the shipping address
0353: errorMessages
0354: .addAll(setCheckOutShippingAddressInternal(shippingContactMechId));
0355:
0356: // set the payment method(s) option
0357: errorMessages.addAll(setCheckOutPaymentInternal(
0358: selectedPaymentMethods, singleUsePayments,
0359: billingAccountId, billingAccountAmt));
0360:
0361: } else {
0362: errMsg = UtilProperties.getMessage(resource,
0363: "checkhelper.no_items_in_cart",
0364: (cart != null ? cart.getLocale() : Locale
0365: .getDefault()));
0366: errorMessages.add(errMsg);
0367: }
0368:
0369: if (errorMessages.size() == 1) {
0370: result = ServiceUtil.returnError(errorMessages.get(0)
0371: .toString());
0372: } else if (errorMessages.size() > 0) {
0373: result = ServiceUtil.returnError(errorMessages);
0374: } else {
0375: result = ServiceUtil.returnSuccess();
0376: }
0377:
0378: return result;
0379: }
0380:
0381: public Map checkGiftCard(Map params, Map selectedPaymentMethods) {
0382: List errorMessages = new ArrayList();
0383: Map errorMaps = new HashMap();
0384: Map result = new HashMap();
0385: String errMsg = null;
0386: // handle gift card payment
0387: if (params.get("addGiftCard") != null) {
0388: String gcNum = (String) params.get("giftCardNumber");
0389: String gcPin = (String) params.get("giftCardPin");
0390: String gcAmt = (String) params.get("giftCardAmount");
0391: double gcAmount = -1;
0392:
0393: boolean gcFieldsOkay = true;
0394: if (gcNum == null || gcNum.length() == 0) {
0395: errMsg = UtilProperties.getMessage(resource,
0396: "checkhelper.enter_gift_card_number",
0397: (cart != null ? cart.getLocale() : Locale
0398: .getDefault()));
0399: errorMessages.add(errMsg);
0400: gcFieldsOkay = false;
0401: }
0402: if (gcPin == null || gcPin.length() == 0) {
0403: errMsg = UtilProperties.getMessage(resource,
0404: "checkhelper.enter_gift_card_pin_number",
0405: (cart != null ? cart.getLocale() : Locale
0406: .getDefault()));
0407: errorMessages.add(errMsg);
0408: gcFieldsOkay = false;
0409: }
0410: if (selectedPaymentMethods != null
0411: && selectedPaymentMethods.size() > 0) {
0412: if (gcAmt == null || gcAmt.length() == 0) {
0413: errMsg = UtilProperties
0414: .getMessage(
0415: resource,
0416: "checkhelper.enter_amount_to_place_on_gift_card",
0417: (cart != null ? cart.getLocale()
0418: : Locale.getDefault()));
0419: errorMessages.add(errMsg);
0420: gcFieldsOkay = false;
0421: }
0422: }
0423: if (gcAmt != null && gcAmt.length() > 0) {
0424: try {
0425: gcAmount = Double.parseDouble(gcAmt);
0426: } catch (NumberFormatException e) {
0427: Debug.logError(e, module);
0428: errMsg = UtilProperties.getMessage(resource,
0429: "checkhelper.invalid_amount_for_gift_card",
0430: (cart != null ? cart.getLocale() : Locale
0431: .getDefault()));
0432: errorMessages.add(errMsg);
0433: gcFieldsOkay = false;
0434: }
0435: }
0436:
0437: if (gcFieldsOkay) {
0438: // store the gift card
0439: Map gcCtx = new HashMap();
0440: gcCtx.put("partyId", params.get("partyId"));
0441: gcCtx.put("cardNumber", gcNum);
0442: gcCtx.put("pinNumber", gcPin);
0443: gcCtx.put("userLogin", cart.getUserLogin());
0444: Map gcResult = null;
0445: try {
0446: gcResult = dispatcher.runSync("createGiftCard",
0447: gcCtx);
0448: } catch (GenericServiceException e) {
0449: Debug.logError(e, module);
0450: errorMessages.add(e.getMessage());
0451: }
0452: if (gcResult != null) {
0453: this .addErrors(errorMessages, errorMaps, gcResult);
0454:
0455: if (errorMessages.size() == 0
0456: && errorMaps.size() == 0) {
0457: // set the GC payment method
0458: Double giftCardAmount = null;
0459: if (gcAmount > 0) {
0460: giftCardAmount = new Double(gcAmount);
0461: }
0462: String gcPaymentMethodId = (String) gcResult
0463: .get("paymentMethodId");
0464: result = ServiceUtil.returnSuccess();
0465: result
0466: .put("paymentMethodId",
0467: gcPaymentMethodId);
0468: result.put("amount", giftCardAmount);
0469: }
0470: } else {
0471: errMsg = UtilProperties
0472: .getMessage(
0473: resource,
0474: "checkhelper.problem_with_gift_card_information",
0475: (cart != null ? cart.getLocale()
0476: : Locale.getDefault()));
0477: errorMessages.add(errMsg);
0478: }
0479: }
0480: } else {
0481: result = ServiceUtil.returnSuccess();
0482: }
0483:
0484: // see whether we need to return an error or not
0485: if (errorMessages.size() > 0) {
0486: result.put(ModelService.ERROR_MESSAGE_LIST, errorMessages);
0487: result.put(ModelService.RESPONSE_MESSAGE,
0488: ModelService.RESPOND_ERROR);
0489: }
0490: if (errorMaps.size() > 0) {
0491: result.put(ModelService.ERROR_MESSAGE_MAP, errorMaps);
0492: result.put(ModelService.RESPONSE_MESSAGE,
0493: ModelService.RESPOND_ERROR);
0494: }
0495:
0496: return result;
0497: }
0498:
0499: // Create order event - uses createOrder service for processing
0500: public Map createOrder(GenericValue userLogin,
0501: String distributorId, String affiliateId,
0502: List trackingCodeOrders, boolean areOrderItemsExploded,
0503: String visitId, String webSiteId) {
0504: String errMsg = null;
0505: if (this .cart == null) {
0506: return null;
0507: }
0508: String orderId = this .cart.getOrderId();
0509: Map result;
0510:
0511: // format the grandTotal
0512: String currencyFormat = UtilProperties.getPropertyValue(
0513: "general.properties", "currency.decimal.format",
0514: "##0.00");
0515: DecimalFormat formatter = new DecimalFormat(currencyFormat);
0516: double cartTotal = this .cart.getGrandTotal();
0517: String grandTotalString = formatter.format(cartTotal);
0518: Double grandTotal = null;
0519: try {
0520: grandTotal = new Double(formatter.parse(grandTotalString)
0521: .doubleValue());
0522: } catch (ParseException e) {
0523: Debug
0524: .logError(
0525: e,
0526: "Problem getting parsed currency amount from DecimalFormat",
0527: module);
0528: errMsg = UtilProperties
0529: .getMessage(
0530: resource,
0531: "checkhelper.could_not_create_order_parsing_totals",
0532: (cart != null ? cart.getLocale() : Locale
0533: .getDefault()));
0534: result = ServiceUtil.returnError(errMsg);
0535: return result;
0536: }
0537:
0538: // store the order - build the context
0539: Map context = this .cart.makeCartMap(this .dispatcher,
0540: areOrderItemsExploded);
0541:
0542: //get the TrackingCodeOrder List
0543: context.put("trackingCodeOrders", trackingCodeOrders);
0544:
0545: if (distributorId != null)
0546: context.put("distributorId", distributorId);
0547: if (affiliateId != null)
0548: context.put("affiliateId", affiliateId);
0549:
0550: // need the partyId; don't use userLogin in case of an order via order mgr
0551: String partyId = this .cart.getPartyId();
0552: String productStoreId = cart.getProductStoreId();
0553:
0554: context.put("grandTotal", grandTotal);
0555: context.put("userLogin", userLogin);
0556: context.put("partyId", partyId);
0557: context.put("productStoreId", productStoreId);
0558: context.put("visitId", visitId);
0559: context.put("webSiteId", webSiteId);
0560:
0561: // store the order - invoke the service
0562: Map storeResult = null;
0563:
0564: try {
0565: storeResult = dispatcher.runSync("storeOrder", context);
0566: orderId = (String) storeResult.get("orderId");
0567: if (orderId != null && orderId.length() > 0) {
0568: this .cart.setOrderId(orderId);
0569: if (this .cart.getFirstAttemptOrderId() == null) {
0570: this .cart.setFirstAttemptOrderId(orderId);
0571: }
0572: }
0573: } catch (GenericServiceException e) {
0574: String service = e.getMessage();
0575: Map messageMap = UtilMisc.toMap("service", service);
0576: errMsg = UtilProperties
0577: .getMessage(
0578: resource,
0579: "checkhelper.could_not_create_order_invoking_service",
0580: messageMap, (cart != null ? cart
0581: .getLocale() : Locale.getDefault()));
0582: result = ServiceUtil.returnError(errMsg);
0583: Debug.logError(e, module);
0584: return result;
0585: }
0586:
0587: // check for error message(s)
0588: if (ModelService.RESPOND_ERROR.equals(storeResult
0589: .get(ModelService.RESPONSE_MESSAGE))
0590: || storeResult.containsKey(ModelService.ERROR_MESSAGE)
0591: || storeResult.containsKey(ModelService.ERROR_MESSAGE)) {
0592: errMsg = UtilProperties
0593: .getMessage(
0594: resource,
0595: "checkhelper.did_not_complete_order_following_occurred",
0596: (cart != null ? cart.getLocale() : Locale
0597: .getDefault()));
0598: result = ServiceUtil.returnError(errMsg);
0599: return result;
0600: }
0601:
0602: // set the orderId for use by chained events
0603: result = ServiceUtil.returnSuccess();
0604: result.put("order_id", orderId);
0605: result.put("orderId", orderId);
0606: result.put("orderAdditionalEmails", this .cart
0607: .getOrderAdditionalEmails());
0608:
0609: // save the emails to the order
0610: List toBeStored = new LinkedList();
0611:
0612: GenericValue party = null;
0613: try {
0614: party = this .delegator.findByPrimaryKey("Party", UtilMisc
0615: .toMap("partyId", partyId));
0616: } catch (GenericEntityException e) {
0617: Debug
0618: .logWarning(e, "Problems getting Party record",
0619: module);
0620: party = null;
0621: }
0622:
0623: // create order contact mechs for the email address(s)
0624: if (party != null) {
0625: Iterator emailIter = UtilMisc
0626: .toIterator(ContactHelper.getContactMechByType(
0627: party, "EMAIL_ADDRESS", false));
0628: while (emailIter != null && emailIter.hasNext()) {
0629: GenericValue email = (GenericValue) emailIter.next();
0630: GenericValue orderContactMech = this .delegator
0631: .makeValue("OrderContactMech", UtilMisc.toMap(
0632: "orderId", orderId, "contactMechId",
0633: email.getString("contactMechId"),
0634: "contactMechPurposeTypeId",
0635: "ORDER_EMAIL"));
0636: toBeStored.add(orderContactMech);
0637: }
0638: }
0639:
0640: // create dummy contact mechs and order contact mechs for the additional emails
0641: String additionalEmails = this .cart.getOrderAdditionalEmails();
0642: List emailList = StringUtil.split(additionalEmails, ",");
0643: if (emailList == null)
0644: emailList = new ArrayList();
0645: Iterator eli = emailList.iterator();
0646: while (eli.hasNext()) {
0647: String email = (String) eli.next();
0648: String contactMechId = this .delegator.getNextSeqId(
0649: "ContactMech").toString();
0650: GenericValue contactMech = this .delegator.makeValue(
0651: "ContactMech", UtilMisc.toMap("contactMechId",
0652: contactMechId, "contactMechTypeId",
0653: "EMAIL_ADDRESS", "infoString", email));
0654:
0655: GenericValue orderContactMech = this .delegator.makeValue(
0656: "OrderContactMech", UtilMisc.toMap("orderId",
0657: orderId, "contactMechId", contactMechId,
0658: "contactMechPurposeTypeId", "ORDER_EMAIL"));
0659: toBeStored.add(contactMech);
0660: toBeStored.add(orderContactMech);
0661: }
0662:
0663: if (toBeStored.size() > 0) {
0664: try {
0665: if (Debug.verboseOn())
0666: Debug.logVerbose("To Be Stored: " + toBeStored,
0667: module);
0668: this .delegator.storeAll(toBeStored);
0669: /* Why is this here?
0670: try {
0671: Thread.sleep(2000);
0672: } catch (Exception e) {}
0673: */
0674: } catch (GenericEntityException e) {
0675: // not a fatal error; so just print a message
0676: Debug
0677: .logWarning(
0678: e,
0679: "Problems storing order email contact information",
0680: module);
0681: }
0682: }
0683:
0684: return result;
0685: }
0686:
0687: public void calcAndAddTax() throws GeneralException {
0688: if (!"SALES_ORDER".equals(cart.getOrderType())) {
0689: return;
0690: }
0691: List items = this .cart.makeOrderItems();
0692: List adjs = this .cart.makeAllAdjustments();
0693: GenericValue shipAddress = this .cart.getShippingAddress();
0694: String productStoreId = cart.getProductStoreId();
0695:
0696: if (shipAddress == null) {
0697: throw new GeneralException(
0698: "Shipping address is not set in the shopping cart.");
0699: }
0700:
0701: // remove old tax adjustments
0702: this .cart.removeAdjustmentByType("SALES_TAX");
0703:
0704: // get the tax adjustments
0705: List taxReturn = getTaxAdjustments(dispatcher, "calcTax",
0706: productStoreId, items, adjs, shipAddress);
0707:
0708: if (Debug.verboseOn())
0709: Debug.logVerbose("ReturnList: " + taxReturn, module);
0710:
0711: List orderAdj = (List) taxReturn.get(0);
0712: List itemAdj = (List) taxReturn.get(1);
0713:
0714: // pass the order adjustments back
0715: if (orderAdj != null && orderAdj.size() > 0) {
0716: Iterator oai = orderAdj.iterator();
0717:
0718: while (oai.hasNext())
0719: this .cart.addAdjustment((GenericValue) oai.next());
0720: }
0721:
0722: // return the order item adjustments
0723: if (itemAdj != null && itemAdj.size() > 0) {
0724: List cartItems = this .cart.items();
0725:
0726: for (int i = 0; i < cartItems.size(); i++) {
0727: ShoppingCartItem item = (ShoppingCartItem) cartItems
0728: .get(i);
0729: List itemAdjustments = (List) itemAdj.get(i);
0730: Iterator ida = itemAdjustments.iterator();
0731:
0732: while (ida.hasNext())
0733: item.addAdjustment((GenericValue) ida.next());
0734: }
0735: }
0736: }
0737:
0738: // Calc the tax adjustments.
0739: private List getTaxAdjustments(LocalDispatcher dispatcher,
0740: String taxService, String productStoreId, List orderItems,
0741: List allAdjustments, GenericValue shipAddress)
0742: throws GeneralException {
0743: List products = new ArrayList(orderItems.size());
0744: List amounts = new ArrayList(orderItems.size());
0745: List shipAmts = new ArrayList(orderItems.size());
0746:
0747: double orderSubTotal = OrderReadHelper.getOrderItemsSubTotal(
0748: orderItems, allAdjustments);
0749: List orderHeaderAdjustments = OrderReadHelper
0750: .getOrderHeaderAdjustments(allAdjustments);
0751: Double cartShipping = new Double(OrderReadHelper
0752: .calcOrderAdjustments(orderHeaderAdjustments,
0753: orderSubTotal, false, false, true));
0754:
0755: // build up the list of tax calc service parameters
0756: for (int i = 0; i < orderItems.size(); i++) {
0757: GenericValue orderItem = (GenericValue) orderItems.get(i);
0758:
0759: try {
0760: products.add(i, orderItem.getRelatedOne("Product")); // get the product entity
0761: amounts.add(i, new Double(OrderReadHelper
0762: .getOrderItemSubTotal(orderItem,
0763: allAdjustments, true, false))); // get the item amount
0764: shipAmts.add(i, new Double(OrderReadHelper
0765: .getOrderItemAdjustmentsTotal(orderItem,
0766: allAdjustments, false, false, true))); // get the shipping amount
0767: } catch (GenericEntityException e) {
0768: Debug.logError(e, "Cannot read order item entity ("
0769: + e.getMessage() + ")", module);
0770: throw new GeneralException(
0771: "Cannot read the order item entity", e);
0772: }
0773: }
0774: Map serviceContext = UtilMisc.toMap("productStoreId",
0775: productStoreId, "itemProductList", products,
0776: "itemAmountList", amounts, "itemShippingList",
0777: shipAmts, "orderShippingAmount", cartShipping,
0778: "shippingAddress", shipAddress);
0779:
0780: Map serviceResult = null;
0781:
0782: try {
0783: serviceResult = dispatcher.runSync(taxService,
0784: serviceContext);
0785: } catch (GenericServiceException e) {
0786: Debug.logError(e, module);
0787: throw new GeneralException(
0788: "Problem occurred in tax service ("
0789: + e.getMessage() + ")", e);
0790: }
0791:
0792: if (ServiceUtil.isError(serviceResult)) {
0793: throw new GeneralException(ServiceUtil
0794: .getErrorMessage(serviceResult));
0795: }
0796:
0797: // the adjustments (returned in order) from taxware.
0798: List orderAdj = (List) serviceResult.get("orderAdjustments");
0799: List itemAdj = (List) serviceResult.get("itemAdjustments");
0800:
0801: return UtilMisc.toList(orderAdj, itemAdj);
0802: }
0803:
0804: public Map processPayment(GenericValue productStore,
0805: GenericValue userLogin) throws GeneralException {
0806: // Get some payment related strings
0807: String DECLINE_MESSAGE = productStore
0808: .getString("authDeclinedMessage");
0809: String ERROR_MESSAGE = productStore
0810: .getString("authErrorMessage");
0811: String RETRY_ON_ERROR = productStore
0812: .getString("retryFailedAuths");
0813: if (RETRY_ON_ERROR == null) {
0814: RETRY_ON_ERROR = "Y";
0815: }
0816:
0817: // Get the orderId from the cart.
0818: String orderId = this .cart.getOrderId();
0819:
0820: // Get the paymentMethodTypeIds - this will need to change when ecom supports multiple payments
0821: List paymentMethodTypeIds = this .cart.getPaymentMethodTypeIds();
0822:
0823: // Check the payment preferences; if we have ANY w/ status PAYMENT_NOT_AUTH invoke payment service.
0824: boolean requireAuth = false;
0825: List allPaymentPreferences = null;
0826: try {
0827: allPaymentPreferences = this .delegator.findByAnd(
0828: "OrderPaymentPreference", UtilMisc.toMap("orderId",
0829: orderId));
0830: } catch (GenericEntityException e) {
0831: throw new GeneralException(
0832: "Problems getting payment preferences", e);
0833: }
0834:
0835: Map paymentFields = UtilMisc.toMap("statusId",
0836: "PAYMENT_NOT_AUTH");
0837: List paymentPreferences = EntityUtil.filterByAnd(
0838: allPaymentPreferences, paymentFields);
0839:
0840: if (paymentPreferences != null && paymentPreferences.size() > 0) {
0841: requireAuth = true;
0842: }
0843:
0844: // Invoke payment processing.
0845: if (requireAuth) {
0846: Map paymentResult = null;
0847: try {
0848: // invoke the payment gateway service.
0849: paymentResult = dispatcher.runSync("authOrderPayments",
0850: UtilMisc.toMap("orderId", orderId, "userLogin",
0851: userLogin));
0852: } catch (GenericServiceException e) {
0853: Debug.logWarning(e, module);
0854: }
0855: if (Debug.verboseOn())
0856: Debug
0857: .logVerbose("Finsished w/ Payment Service",
0858: module);
0859: if (paymentResult != null
0860: && paymentResult.containsKey("processResult")) {
0861: String authResp = (String) paymentResult
0862: .get("processResult");
0863:
0864: if (authResp.equals("FAILED")) {
0865: // order was NOT approved
0866: if (Debug.verboseOn())
0867: Debug.logVerbose(
0868: "Payment auth was NOT a success!",
0869: module);
0870:
0871: boolean ok = OrderChangeHelper.rejectOrder(
0872: dispatcher, userLogin, orderId);
0873: if (!ok) {
0874: throw new GeneralException(
0875: "Problem with order change; see above error");
0876: }
0877:
0878: // null out the orderId for next pass.
0879: cart.setOrderId(null);
0880: return ServiceUtil.returnError(DECLINE_MESSAGE);
0881: } else if (authResp.equals("APPROVED")) {
0882: // order WAS approved
0883: if (Debug.verboseOn())
0884: Debug.logVerbose("Payment auth was a success!",
0885: module);
0886:
0887: // set the order and item status to approved
0888: boolean ok = OrderChangeHelper.approveOrder(
0889: dispatcher, userLogin, orderId);
0890: if (!ok) {
0891: throw new GeneralException(
0892: "Problem with order change; see above error");
0893: }
0894:
0895: return ServiceUtil.returnSuccess();
0896: } else if (authResp.equals("ERROR")) {
0897: // service failed
0898: if (Debug.verboseOn())
0899: Debug
0900: .logVerbose(
0901: "Payment auth failed due to processor trouble.",
0902: module);
0903: if ("Y".equalsIgnoreCase(RETRY_ON_ERROR)) {
0904: return ServiceUtil.returnSuccess(ERROR_MESSAGE);
0905: } else {
0906: boolean ok = OrderChangeHelper.cancelOrder(
0907: dispatcher, userLogin, orderId);
0908: if (!ok) {
0909: throw new GeneralException(
0910: "Problem with order change; see above error");
0911: }
0912: // null out orderId for next pass
0913: this .cart.setOrderId(null);
0914: return ServiceUtil.returnError(ERROR_MESSAGE);
0915: }
0916: } else {
0917: // should never happen
0918: return ServiceUtil
0919: .returnError("Please contact customer service; payment return code unknown.");
0920: }
0921: } else {
0922: // result returned null == service failed
0923: if (Debug.verboseOn())
0924: Debug
0925: .logVerbose(
0926: "Payment auth failed due to processor trouble.",
0927: module);
0928: if ("Y".equalsIgnoreCase(RETRY_ON_ERROR)) {
0929: return ServiceUtil.returnSuccess(ERROR_MESSAGE);
0930: } else {
0931: boolean ok = OrderChangeHelper.cancelOrder(
0932: dispatcher, userLogin, orderId);
0933: if (!ok) {
0934: throw new GeneralException(
0935: "Problem with order change; see above error");
0936: }
0937: // null out orderId for next pass
0938: this .cart.setOrderId(null);
0939: return ServiceUtil.returnError(ERROR_MESSAGE);
0940: }
0941: }
0942: } else if (paymentMethodTypeIds.contains("EXT_COD")
0943: || paymentMethodTypeIds.contains("EXT_BILLACT")) {
0944: boolean hasOther = false;
0945: boolean validAmount = false;
0946:
0947: Iterator pmti = paymentMethodTypeIds.iterator();
0948: while (pmti.hasNext()) {
0949: String type = (String) pmti.next();
0950: if (!"EXT_COD".equals(type)
0951: && !"EXT_BILLACT".equals(type)) {
0952: hasOther = true;
0953: break;
0954: }
0955: }
0956:
0957: if (!hasOther) {
0958: if (!paymentMethodTypeIds.contains("EXT_COD")) {
0959: // only billing account, make sure we have enough to cover
0960: String billingAccountId = cart
0961: .getBillingAccountId();
0962: double billAcctCredit = this
0963: .availableAccountBalance(billingAccountId);
0964: double billingAcctAmt = cart
0965: .getBillingAccountAmount();
0966: if (billAcctCredit >= billingAcctAmt) {
0967: if (cart.getGrandTotal() > billAcctCredit) {
0968: validAmount = false;
0969: } else {
0970: validAmount = true;
0971: }
0972: }
0973: }
0974:
0975: // approve this as long as there are only COD and Billing Account types
0976: boolean ok = OrderChangeHelper.approveOrder(dispatcher,
0977: userLogin, orderId);
0978: if (!ok) {
0979: throw new GeneralException(
0980: "Problem with order change; see above error");
0981: }
0982: }
0983: return ServiceUtil.returnSuccess();
0984: } else {
0985: // Handle NO payment gateway as a success.
0986: return ServiceUtil.returnSuccess();
0987: }
0988: }
0989:
0990: public Map checkOrderBlacklist(GenericValue userLogin) {
0991: if (cart == null) {
0992: return ServiceUtil.returnSuccess("success");
0993: }
0994: GenericValue shippingAddressObj = this .cart
0995: .getShippingAddress();
0996: if (shippingAddressObj == null) {
0997: return ServiceUtil.returnSuccess("success");
0998: }
0999: String shippingAddress = UtilFormatOut.checkNull(
1000: shippingAddressObj.getString("address1")).toUpperCase();
1001: List exprs = UtilMisc.toList(new EntityExpr(new EntityExpr(
1002: "blacklistString", true, EntityOperator.EQUALS,
1003: shippingAddress, true), EntityOperator.AND,
1004: new EntityExpr("orderBlacklistTypeId",
1005: EntityOperator.EQUALS, "BLACKLIST_ADDRESS")));
1006: String errMsg = null;
1007:
1008: List paymentMethods = this .cart.getPaymentMethods();
1009: Iterator i = paymentMethods.iterator();
1010: while (i.hasNext()) {
1011: GenericValue paymentMethod = (GenericValue) i.next();
1012: if (paymentMethod.getString("paymentMethodTypeId").equals(
1013: "CREDIT_CARD")) {
1014: GenericValue creditCard = null;
1015: GenericValue billingAddress = null;
1016: try {
1017: creditCard = paymentMethod
1018: .getRelatedOne("CreditCard");
1019: if (creditCard != null)
1020: billingAddress = creditCard
1021: .getRelatedOne("PostalAddress");
1022: } catch (GenericEntityException e) {
1023: Debug
1024: .logError(
1025: e,
1026: "Problems getting credit card from payment method",
1027: module);
1028: errMsg = UtilProperties.getMessage(resource,
1029: "checkhelper.problems_reading_database",
1030: (cart != null ? cart.getLocale() : Locale
1031: .getDefault()));
1032: return ServiceUtil.returnError(errMsg);
1033: }
1034: if (creditCard != null) {
1035: String creditCardNumber = UtilFormatOut
1036: .checkNull(creditCard
1037: .getString("cardNumber"));
1038: exprs.add(new EntityExpr(new EntityExpr(
1039: "blacklistString", EntityOperator.EQUALS,
1040: creditCardNumber), EntityOperator.AND,
1041: new EntityExpr("orderBlacklistTypeId",
1042: EntityOperator.EQUALS,
1043: "BLACKLIST_CREDITCARD")));
1044: }
1045: if (billingAddress != null) {
1046: String address = UtilFormatOut
1047: .checkNull(billingAddress.getString(
1048: "address1").toUpperCase());
1049: exprs.add(new EntityExpr(new EntityExpr(
1050: "blacklistString", true,
1051: EntityOperator.EQUALS, address, true),
1052: EntityOperator.AND, new EntityExpr(
1053: "orderBlacklistTypeId",
1054: EntityOperator.EQUALS,
1055: "BLACKLIST_ADDRESS")));
1056: }
1057: }
1058: }
1059:
1060: List blacklistFound = null;
1061: if (exprs.size() > 0) {
1062: try {
1063: blacklistFound = this .delegator.findByOr(
1064: "OrderBlacklist", exprs);
1065: } catch (GenericEntityException e) {
1066: Debug.logError(e,
1067: "Problems with OrderBlacklist lookup.", module);
1068: errMsg = UtilProperties.getMessage(resource,
1069: "checkhelper.problems_reading_database",
1070: (cart != null ? cart.getLocale() : Locale
1071: .getDefault()));
1072: return ServiceUtil.returnError(errMsg);
1073: }
1074: }
1075:
1076: if (blacklistFound != null && blacklistFound.size() > 0) {
1077: return ServiceUtil.returnError("failed");
1078: } else {
1079: return ServiceUtil.returnSuccess("success");
1080: }
1081: }
1082:
1083: public Map failedBlacklistCheck(GenericValue userLogin,
1084: GenericValue productStore) {
1085: Map result;
1086: String errMsg = null;
1087:
1088: String REJECT_MESSAGE = productStore
1089: .getString("authFraudMessage");
1090:
1091: // Get the orderId from the cart.
1092: String orderId = this .cart.getOrderId();
1093:
1094: // set the order/item status - reverse inv
1095: OrderChangeHelper.rejectOrder(dispatcher, userLogin, orderId);
1096:
1097: // nuke the userlogin
1098: userLogin.set("enabled", "N");
1099: try {
1100: userLogin.store();
1101: } catch (GenericEntityException e) {
1102: Debug.logError(e, "Problems de-activating userLogin.",
1103: module);
1104: errMsg = UtilProperties.getMessage(resource,
1105: "checkhelper.database_error", (cart != null ? cart
1106: .getLocale() : Locale.getDefault()));
1107: result = ServiceUtil.returnError(errMsg);
1108: return result;
1109: }
1110: result = ServiceUtil.returnSuccess();
1111: result.put(ModelService.ERROR_MESSAGE, REJECT_MESSAGE);
1112:
1113: // wipe the cart and session
1114: this .cart.clear();
1115: return result;
1116: }
1117:
1118: public Map checkExternalPayment(String orderId) {
1119: Map result;
1120: String errMsg = null;
1121: // warning there can only be ONE payment preference for this to work
1122: // you cannot accept multiple payment type when using an external gateway
1123: GenericValue orderHeader = null;
1124: try {
1125: orderHeader = this .delegator.findByPrimaryKey(
1126: "OrderHeader", UtilMisc.toMap("orderId", orderId));
1127: } catch (GenericEntityException e) {
1128: Debug.logError(e, "Problems getting order header", module);
1129: errMsg = UtilProperties.getMessage(resource,
1130: "checkhelper.problems_getting_order_header",
1131: (cart != null ? cart.getLocale() : Locale
1132: .getDefault()));
1133: result = ServiceUtil.returnError(errMsg);
1134: return result;
1135: }
1136: if (orderHeader != null) {
1137: List paymentPrefs = null;
1138: try {
1139: paymentPrefs = orderHeader
1140: .getRelated("OrderPaymentPreference");
1141: } catch (GenericEntityException e) {
1142: Debug.logError(e, "Problems getting order payments",
1143: module);
1144: errMsg = UtilProperties
1145: .getMessage(
1146: resource,
1147: "checkhelper.problems_getting_payment_preference",
1148: (cart != null ? cart.getLocale()
1149: : Locale.getDefault()));
1150: result = ServiceUtil.returnError(errMsg);
1151: return result;
1152: }
1153: if (paymentPrefs != null && paymentPrefs.size() > 0) {
1154: if (paymentPrefs.size() > 1) {
1155: Debug
1156: .logError(
1157: "Too many payment preferences, you cannot have more then one when using external gateways",
1158: module);
1159: }
1160: GenericValue paymentPreference = EntityUtil
1161: .getFirst(paymentPrefs);
1162: String paymentMethodTypeId = paymentPreference
1163: .getString("paymentMethodTypeId");
1164: if (paymentMethodTypeId.startsWith("EXT_")) {
1165: String type = paymentMethodTypeId.substring(4);
1166: result = ServiceUtil.returnSuccess();
1167: result.put("type", type.toLowerCase());
1168: return result;
1169: }
1170: }
1171: result = ServiceUtil.returnSuccess();
1172: result.put("type", "none");
1173: return result;
1174: } else {
1175: errMsg = UtilProperties.getMessage(resource,
1176: "checkhelper.problems_getting_order_header",
1177: (cart != null ? cart.getLocale() : Locale
1178: .getDefault()));
1179: result = ServiceUtil.returnError(errMsg);
1180: result.put("type", "error");
1181: return result;
1182: }
1183: }
1184:
1185: /**
1186: * Sets the shipping contact mechanism on the cart
1187: *
1188: * @param shippingContactMechId The identifier of the contact
1189: * @return A Map conforming to the OFBiz Service conventions containing
1190: * any error messages
1191: */
1192: public Map finalizeOrderEntryShip(String shippingContactMechId) {
1193: Map result;
1194: String errMsg = null;
1195: //Verify the field is valid
1196: if (UtilValidate.isNotEmpty(shippingContactMechId)) {
1197: this .cart.setShippingContactMechId(shippingContactMechId);
1198: result = ServiceUtil.returnSuccess();
1199: } else {
1200: errMsg = UtilProperties.getMessage(resource,
1201: "checkhelper.enter_shipping_address",
1202: (cart != null ? cart.getLocale() : Locale
1203: .getDefault()));
1204: result = ServiceUtil.returnError(errMsg);
1205: }
1206:
1207: return result;
1208: }
1209:
1210: /**
1211: * Sets the options associated with the order
1212: *
1213: * @param shippingMethod The shipping method indicating the carrier and
1214: * shipment type to use
1215: * @param shippingInstructions Any additional handling instructions
1216: * @param maySplit "true" or anything else for <code>false</code>
1217: * @param giftMessage A message to have included for the recipient
1218: * @param isGift "true" or anything else for <code>false</code>
1219: * @return A Map conforming to the OFBiz Service conventions containing
1220: * any error messages
1221: */
1222: public Map finalizeOrderEntryOptions(String shippingMethod,
1223: String shippingInstructions, String maySplit,
1224: String giftMessage, String isGift) {
1225: Map result;
1226: String errMsg = null;
1227: //Verify the shipping method is valid
1228: if (UtilValidate.isNotEmpty(shippingMethod)) {
1229: int delimiterPos = shippingMethod.indexOf('@');
1230: String shipmentMethodTypeId = null;
1231: String carrierPartyId = null;
1232:
1233: if (delimiterPos > 0) {
1234: shipmentMethodTypeId = shippingMethod.substring(0,
1235: delimiterPos);
1236: carrierPartyId = shippingMethod
1237: .substring(delimiterPos + 1);
1238: }
1239:
1240: this .cart.setShipmentMethodTypeId(shipmentMethodTypeId);
1241: this .cart.setCarrierPartyId(carrierPartyId);
1242: } else {
1243: errMsg = UtilProperties.getMessage(resource,
1244: "checkhelper.select_shipping_method",
1245: (cart != null ? cart.getLocale() : Locale
1246: .getDefault()));
1247: result = ServiceUtil.returnError(errMsg);
1248: }
1249:
1250: //Set the remaining order options
1251: this .cart.setShippingInstructions(shippingInstructions);
1252: this .cart.setGiftMessage(giftMessage);
1253: this .cart.setMaySplit(Boolean.valueOf(maySplit));
1254: this .cart.setIsGift(Boolean.valueOf(isGift));
1255:
1256: result = ServiceUtil.returnSuccess();
1257: return result;
1258: }
1259:
1260: /**
1261: * Indicates whether the payment should be made offline or
1262: * whether further settings will be given for the electronic
1263: * payment method.
1264: *
1265: * @param paymentMthodType "offline" to indicate that is to be paid
1266: * offline, <code>null</code> or anything else for online.
1267: * @return A Map conforming to the OFBiz Service conventions containing
1268: * any error messages
1269: */
1270: public Map finalizeOrderEntryMethodType(String paymentMthodType) {
1271: Map result;
1272:
1273: this .cart.clearPaymentMethodTypeIds();
1274: this .cart.clearPaymentMethodIds();
1275: if (paymentMthodType != null
1276: && paymentMthodType.equals("offline")) {
1277: this .cart.addPaymentMethodTypeId("EXT_OFFLINE");
1278: }
1279:
1280: result = ServiceUtil.returnSuccess();
1281: return result;
1282: }
1283:
1284: /**
1285: * Sets the payment ID to use during the checkout process
1286: *
1287: * @param checkOutPaymentId The type of payment to use, should
1288: * be "OFFLINE_PAYMENT" to indicate offlinem otherwise the payment ID
1289: * will be associated with the cart
1290: * @return A Map conforming to the OFBiz Service conventions containing
1291: * any error messages. Includes the field "OFFLINE_PAYMENT"
1292: * containing a <code>Boolean</code> indicating whether it's an offline
1293: * payment or not.
1294: */
1295: public Map finalizeOrderEntryPayment(String checkOutPaymentId,
1296: Double amount, boolean singleUse, boolean append) {
1297: Map result = ServiceUtil.returnSuccess();
1298:
1299: if (UtilValidate.isNotEmpty(checkOutPaymentId)) {
1300: if (!checkOutPaymentId.equals("OFFLINE_PAYMENT")) {
1301: // clear out the old payments
1302: if (!append) {
1303: this .cart.clearPaymentMethodTypeIds();
1304: this .cart.clearPaymentMethodIds();
1305: }
1306: // all payment method ids will be numeric, type ids will start with letter
1307: if (Character.isLetter(checkOutPaymentId.charAt(0))) {
1308: this .cart.addPaymentMethodTypeId(checkOutPaymentId);
1309: } else {
1310: this .cart.setPaymentMethodAmount(checkOutPaymentId,
1311: amount, singleUse);
1312: }
1313: } else {
1314: this .cart.clearPaymentMethodIds();
1315: this .cart.clearPaymentMethodTypeIds();
1316: result.put("OFFLINE_PAYMENT", new Boolean(true));
1317: }
1318: }
1319:
1320: return result;
1321: }
1322:
1323: /**
1324: * Defines the payment options for an order.
1325: *
1326: * @param params Contains the amount associated with
1327: * each <code>paymentMethodTypeId</code>.
1328: * @return A Map conforming to the OFBiz Service conventions containing
1329: * any error messages. Includes the field "OFFLINE_PAYMENTS"
1330: * containing a <code>Boolean</code> indicating whether it's an offline
1331: * payment or not.
1332: */
1333: public Map finalizeOrderEntryOfflinePayments(Map params) {
1334: Map result = ServiceUtil.returnSuccess();
1335: List errorMessages = new ArrayList();
1336: String errMsg = null;
1337:
1338: // get a list of payment types
1339: List paymentTypes = null;
1340: try {
1341: paymentTypes = delegator.findAll("PaymentMethodType");
1342: } catch (GenericEntityException e) {
1343: Debug.logError(e,
1344: "Cannot get payment method types from datasource",
1345: module);
1346: }
1347: if (paymentTypes != null) {
1348: Map paymentPrefs = new HashMap();
1349: double paymentTally = 0.00;
1350: Iterator pi = paymentTypes.iterator();
1351: while (pi.hasNext()) {
1352: GenericValue paymentMethodType = (GenericValue) pi
1353: .next();
1354: String paymentType = null;
1355: if (paymentMethodType != null
1356: && paymentMethodType.get("paymentMethodTypeId") != null) {
1357: paymentType = paymentMethodType
1358: .getString("paymentMethodTypeId");
1359: }
1360:
1361: // get the amount by type
1362: double paymentAmount = 0.00;
1363: if (paymentType != null
1364: && !paymentType.equals("OFFLINE")) {
1365: String amount = (String) params
1366: .get(paymentMethodType
1367: .getString("paymentMethodTypeId"));
1368: if (amount != null && amount.length() > 0) {
1369: try {
1370: paymentAmount = NumberFormat
1371: .getNumberInstance().parse(amount)
1372: .doubleValue();
1373: } catch (java.text.ParseException pe) {
1374: errMsg = UtilProperties
1375: .getMessage(
1376: resource,
1377: "checkhelper.problems_parsing_amount",
1378: (cart != null ? cart
1379: .getLocale()
1380: : Locale
1381: .getDefault()));
1382: result = ServiceUtil.returnError(errMsg);
1383: return result;
1384: }
1385: }
1386: }
1387:
1388: // only worry about types w/ an amount
1389: if (paymentAmount > 0.00) {
1390: paymentPrefs.put(paymentType, new Double(
1391: paymentAmount));
1392: paymentTally += paymentAmount;
1393: }
1394: }
1395:
1396: double cartTotal = cart.getGrandTotal();
1397: if (cartTotal != paymentTally) {
1398: errMsg = UtilProperties.getMessage(resource,
1399: "checkhelper.totals_do_not_match_order_total",
1400: (cart != null ? cart.getLocale() : Locale
1401: .getDefault()));
1402: result = ServiceUtil.returnError(errMsg);
1403: return result;
1404: } else {
1405: Set keySet = paymentPrefs.keySet();
1406: Iterator i = keySet.iterator();
1407: while (i.hasNext()) {
1408: String type = (String) i.next();
1409: Double amt = (Double) paymentPrefs.get(type);
1410: cart.addPaymentMethodTypeId(type, amt);
1411: }
1412: result.put("OFFLINE_PAYMENTS", new Boolean(true));
1413: }
1414: }
1415:
1416: return result;
1417: }
1418:
1419: /**
1420: * Performs all the finalization settings and combines all the results.
1421: * This is a convenience method, primarily to match the original
1422: * code structure of the adapter class <code>CheckOutEvents</code>.
1423: * <p>
1424: * I would prefer to remove this altogether and move the method
1425: * {@link #addErrors(List, Map, Map) addErrors} to the utility
1426: * class {@link ServiceUtil ServiceUtil}
1427: *
1428: * @see CheckOutHelper#finalizeOrderEntryMethodType(String)
1429: * @see CheckOutHelper#finalizeOrderEntryOfflinePayments(Map)
1430: * @see CheckOutHelper#finalizeOrderEntryOptions(String, String, String, String, String)
1431: * @see CheckOutHelper#finalizeOrderEntryPayment(String, Double, boolean, boolean)
1432: * @see CheckOutHelper#finalizeOrderEntryShip(String)
1433: */
1434: public Map finalizeOrderEntry(String finalizeMode,
1435: String shippingContactMechId, String shippingMethod,
1436: String shippingInstructions, String maySplit,
1437: String giftMessage, String isGift, String methodType,
1438: String checkOutPaymentId, boolean isSingleUsePayment,
1439: boolean appendPayment, Map params) {
1440: Map result = ServiceUtil.returnSuccess();
1441: Map errorMaps = new HashMap();
1442: Map callResult;
1443: List errorMessages = new ArrayList();
1444:
1445: // set the shipping method
1446: if (finalizeMode != null && finalizeMode.equals("ship")) {
1447: callResult = this
1448: .finalizeOrderEntryShip(shippingContactMechId);
1449: this .addErrors(errorMessages, errorMaps, callResult);
1450: }
1451:
1452: // set the options
1453: if (finalizeMode != null && finalizeMode.equals("options")) {
1454: callResult = this
1455: .finalizeOrderEntryOptions(shippingMethod,
1456: shippingInstructions, maySplit,
1457: giftMessage, isGift);
1458: this .addErrors(errorMessages, errorMaps, callResult);
1459: }
1460:
1461: // payment option; if offline we skip the payment screen
1462: if (finalizeMode != null && finalizeMode.equals("payoption")) {
1463: callResult = this .finalizeOrderEntryMethodType(methodType);
1464: this .addErrors(errorMessages, errorMaps, callResult);
1465: }
1466:
1467: // set the payment
1468: if (finalizeMode != null && finalizeMode.equals("payment")) {
1469: Map selectedPaymentMethods = null;
1470: if (checkOutPaymentId != null) {
1471: callResult = this .finalizeOrderEntryPayment(
1472: checkOutPaymentId, null, isSingleUsePayment,
1473: appendPayment);
1474: this .addErrors(errorMessages, errorMaps, callResult);
1475: selectedPaymentMethods = UtilMisc.toMap(
1476: checkOutPaymentId, null);
1477: }
1478: callResult = checkGiftCard(params, selectedPaymentMethods);
1479: this .addErrors(errorMessages, errorMaps, callResult);
1480: if (errorMessages.size() == 0 && errorMaps.size() == 0) {
1481: String gcPaymentMethodId = (String) callResult
1482: .get("paymentMethodId");
1483: Double giftCardAmount = (Double) callResult
1484: .get("amount");
1485: Map gcCallRes = this .finalizeOrderEntryPayment(
1486: gcPaymentMethodId, giftCardAmount, true, true);
1487: this .addErrors(errorMessages, errorMaps, gcCallRes);
1488: }
1489: }
1490:
1491: // create offline payments
1492: if (finalizeMode != null
1493: && finalizeMode.equals("offline_payments")) {
1494: callResult = this .finalizeOrderEntryOfflinePayments(params);
1495: this .addErrors(errorMessages, errorMaps, callResult);
1496: }
1497:
1498: //See whether we need to return an error or not
1499: if (errorMessages.size() > 0) {
1500: result.put(ModelService.ERROR_MESSAGE_LIST, errorMessages);
1501: result.put(ModelService.RESPONSE_MESSAGE,
1502: ModelService.RESPOND_ERROR);
1503: }
1504: if (errorMaps.size() > 0) {
1505: result.put(ModelService.ERROR_MESSAGE_MAP, errorMaps);
1506: result.put(ModelService.RESPONSE_MESSAGE,
1507: ModelService.RESPOND_ERROR);
1508: }
1509:
1510: return result;
1511: }
1512:
1513: /**
1514: * Takes the result of an invocation and extracts any error messages
1515: * and adds them to the targetList. This will handle both List and String
1516: * error messags.
1517: *
1518: * @param targetList The List to add the error messages to
1519: * @param targetMap The Map to add any Map error messages to
1520: * @param callResult The result from an invocation
1521: */
1522: private void addErrors(List targetList, Map targetMap,
1523: Map callResult) {
1524: List newList;
1525: Map.Entry entry;
1526: Iterator mapIter;
1527: Map errorMsgMap;
1528: StringBuffer outMsg;
1529:
1530: //See if there is a single message
1531: if (callResult.containsKey(ModelService.ERROR_MESSAGE)) {
1532: targetList.add(callResult.get(ModelService.ERROR_MESSAGE));
1533: }
1534:
1535: //See if there is a message list
1536: if (callResult.containsKey(ModelService.ERROR_MESSAGE_LIST)) {
1537: newList = (List) callResult
1538: .get(ModelService.ERROR_MESSAGE_LIST);
1539: targetList.addAll(newList);
1540: }
1541:
1542: //See if there are an error message map
1543: if (callResult.containsKey(ModelService.ERROR_MESSAGE_MAP)) {
1544: errorMsgMap = (Map) callResult
1545: .get(ModelService.ERROR_MESSAGE_MAP);
1546: targetMap.putAll(errorMsgMap);
1547: }
1548: }
1549:
1550: public double availableAccountBalance(String billingAccountId) {
1551: GenericValue billingAccount = null;
1552: Double accountBalance = new Double(0.00);
1553: Double accountLimit = new Double(0.00);
1554:
1555: if (billingAccountId != null) {
1556: try {
1557: Map res = dispatcher.runSync(
1558: "calcBillingAccountBalance", UtilMisc.toMap(
1559: "billingAccountId", billingAccountId));
1560: billingAccount = (GenericValue) res
1561: .get("billingAccount");
1562: accountBalance = (Double) res.get("accountBalance");
1563: } catch (GenericServiceException e) {
1564: Debug.logError(e, module);
1565: }
1566: if (billingAccount != null) {
1567: accountLimit = billingAccount.getDouble("accountLimit");
1568: }
1569:
1570: if (accountLimit == null) {
1571: accountLimit = new Double(0.00);
1572: }
1573: if (accountBalance == null) {
1574: accountBalance = new Double(0.00);
1575: }
1576: }
1577:
1578: double availableBalance = (accountLimit.doubleValue() - accountBalance
1579: .doubleValue());
1580: String currencyFormat = UtilProperties.getPropertyValue(
1581: "general.properties", "currency.decimal.format",
1582: "##0.00");
1583: DecimalFormat formatter = new DecimalFormat(currencyFormat);
1584: String availableString = formatter.format(availableBalance);
1585: Double available = null;
1586: try {
1587: available = new Double(formatter.parse(availableString)
1588: .doubleValue());
1589: } catch (ParseException e) {
1590: Debug.logError(e,
1591: "Problem getting parsed available amount", module);
1592: }
1593: //Debug.logInfo("Billing Account : " + billingAccountId + " - " + available, module);
1594: return available.doubleValue();
1595: }
1596:
1597: public Map makeBillingAccountMap(List paymentPrefs) {
1598: Map accountMap = new HashMap();
1599: if (paymentPrefs != null) {
1600: Iterator i = accountMap.keySet().iterator();
1601: while (i.hasNext()) {
1602: GenericValue pp = (GenericValue) i.next();
1603: if (pp.get("billingAccountId") != null) {
1604: accountMap.put(pp.getString("billingAccountId"), pp
1605: .getDouble("maxAmount"));
1606: }
1607: }
1608: }
1609: return accountMap;
1610: }
1611: }
|