com.salesmanager.core.module.impl.integration.shipping.CanadaPostQuotesImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.salesmanager.core.module.impl.integration.shipping.CanadaPostQuotesImpl.java

Source

/*
 * Licensed to csti consulting 
 * You may obtain a copy of the License at
 *
 * http://www.csticonsulting.com
 * Copyright (c) 2006-Aug 24, 2010 Consultation CS-TI inc. 
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package com.salesmanager.core.module.impl.integration.shipping;

import java.io.Reader;
import java.io.StringReader;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.digester.Digester;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.salesmanager.core.constants.Constants;
import com.salesmanager.core.constants.ShippingConstants;
import com.salesmanager.core.entity.customer.Customer;
import com.salesmanager.core.entity.merchant.MerchantConfiguration;
import com.salesmanager.core.entity.merchant.MerchantStore;
import com.salesmanager.core.entity.reference.CoreModuleService;
import com.salesmanager.core.entity.reference.Country;
import com.salesmanager.core.entity.shipping.PackageDetail;
import com.salesmanager.core.entity.shipping.ShippingOption;
import com.salesmanager.core.module.model.integration.ShippingQuotesModule;
import com.salesmanager.core.service.ServiceFactory;
import com.salesmanager.core.service.cache.RefCache;
import com.salesmanager.core.service.common.model.IntegrationKeys;
import com.salesmanager.core.service.common.model.IntegrationProperties;
import com.salesmanager.core.service.merchant.ConfigurationResponse;
import com.salesmanager.core.service.shipping.ShippingService;
import com.salesmanager.core.util.CountryUtil;
import com.salesmanager.core.util.CurrencyUtil;
import com.salesmanager.core.util.LabelUtil;
import com.salesmanager.core.util.LanguageUtil;
import com.salesmanager.core.util.LogMerchantUtil;

public class CanadaPostQuotesImpl implements ShippingQuotesModule {

    private Logger log = Logger.getLogger(CanadaPostQuotesImpl.class);

    public String getShippingMethodDescription(Locale locale) {
        return LabelUtil.getInstance().getText(locale, "module.canadapost");
    }

    public Collection<ShippingOption> getShippingQuote(ConfigurationResponse config, BigDecimal orderTotal,
            Collection<PackageDetail> packages, Customer customer, MerchantStore store, Locale locale) {

        BigDecimal total = orderTotal;

        if (packages == null) {
            return null;
        }

        // only applies to Canada and US
        if (customer.getCustomerCountryId() != 38 && customer.getCustomerCountryId() != 223) {
            return null;
        }

        // supports en and fr
        String language = locale.getLanguage();
        if (!language.equals(Constants.FRENCH_CODE) && !language.equals(Constants.ENGLISH_CODE)) {
            language = Constants.ENGLISH_CODE;
        }

        // get canadapost credentials
        if (config == null) {
            log.error("CanadaPostQuotesImp.getShippingQuote requires ConfigurationVO for key SHP_RT_CRED");
            return null;
        }

        // if store is not CAD
        if (!store.getCurrency().equals(Constants.CURRENCY_CODE_CAD)) {
            total = CurrencyUtil.convertToCurrency(total, store.getCurrency(), Constants.CURRENCY_CODE_CAD);
        }

        PostMethod httppost = null;

        CanadaPostParsedElements canadaPost = null;

        try {

            int icountry = store.getCountry();
            String country = CountryUtil.getCountryIsoCodeById(icountry);

            ShippingService sservice = (ShippingService) ServiceFactory.getService(ServiceFactory.ShippingService);
            CoreModuleService cms = sservice.getRealTimeQuoteShippingService(country, "canadapost");

            IntegrationKeys keys = (IntegrationKeys) config.getConfiguration("canadapost-keys");
            IntegrationProperties props = (IntegrationProperties) config.getConfiguration("canadapost-properties");

            if (cms == null) {
                // throw new
                // Exception("Central integration services not configured for "
                // + PaymentConstants.PAYMENT_PSIGATENAME + " and country id " +
                // origincountryid);
                log.error("CoreModuleService not configured for  canadapost and country id " + icountry);
                return null;
            }

            String host = cms.getCoreModuleServiceProdDomain();
            String protocol = cms.getCoreModuleServiceProdProtocol();
            String port = cms.getCoreModuleServiceProdPort();
            String url = cms.getCoreModuleServiceProdEnv();
            if (props.getProperties1().equals(String.valueOf(ShippingConstants.TEST_ENVIRONMENT))) {
                host = cms.getCoreModuleServiceDevDomain();
                protocol = cms.getCoreModuleServiceDevProtocol();
                port = cms.getCoreModuleServiceDevPort();
                url = cms.getCoreModuleServiceDevEnv();
            }

            // accept KG and CM

            StringBuffer request = new StringBuffer();

            request.append("<?xml version=\"1.0\" ?>");
            request.append("<eparcel>");
            request.append("<language>").append(language).append("</language>");

            request.append("<ratesAndServicesRequest>");
            request.append("<merchantCPCID>").append(keys.getUserid()).append("</merchantCPCID>");
            request.append("<fromPostalCode>")
                    .append(com.salesmanager.core.util.ShippingUtil.trimPostalCode(store.getStorepostalcode()))
                    .append("</fromPostalCode>");
            request.append("<turnAroundTime>").append("24").append("</turnAroundTime>");
            request.append("<itemsPrice>").append(CurrencyUtil.displayFormatedAmountNoCurrency(total, "CAD"))
                    .append("</itemsPrice>");
            request.append("<lineItems>");

            Iterator packageIterator = packages.iterator();
            while (packageIterator.hasNext()) {
                PackageDetail pack = (PackageDetail) packageIterator.next();
                request.append("<item>");
                request.append("<quantity>").append(pack.getShippingQuantity()).append("</quantity>");
                request.append("<weight>")
                        .append(String.valueOf(
                                CurrencyUtil.getWeight(pack.getShippingWeight(), store, Constants.KG_WEIGHT_UNIT)))
                        .append("</weight>");
                request.append("<length>")
                        .append(String.valueOf(
                                CurrencyUtil.getMeasure(pack.getShippingLength(), store, Constants.CM_SIZE_UNIT)))
                        .append("</length>");
                request.append("<width>")
                        .append(String.valueOf(
                                CurrencyUtil.getMeasure(pack.getShippingWidth(), store, Constants.CM_SIZE_UNIT)))
                        .append("</width>");
                request.append("<height>")
                        .append(String.valueOf(
                                CurrencyUtil.getMeasure(pack.getShippingHeight(), store, Constants.CM_SIZE_UNIT)))
                        .append("</height>");
                request.append("<description>").append(pack.getProductName()).append("</description>");
                request.append("<readyToShip/>");
                request.append("</item>");
            }

            Country c = null;
            Map countries = (Map) RefCache
                    .getAllcountriesmap(LanguageUtil.getLanguageNumberCode(locale.getLanguage()));
            c = (Country) countries.get(store.getCountry());

            request.append("</lineItems>");
            request.append("<city>").append(customer.getCustomerCity()).append("</city>");

            request.append("<provOrState>").append(customer.getShippingSate()).append("</provOrState>");
            Map cs = (Map) RefCache.getAllcountriesmap(LanguageUtil.getLanguageNumberCode(locale.getLanguage()));
            Country customerCountry = (Country) cs.get(customer.getCustomerCountryId());
            request.append("<country>").append(customerCountry.getCountryName()).append("</country>");
            request.append("<postalCode>").append(
                    com.salesmanager.core.util.ShippingUtil.trimPostalCode(customer.getCustomerPostalCode()))
                    .append("</postalCode>");
            request.append("</ratesAndServicesRequest>");
            request.append("</eparcel>");

            /**
             * <?xml version="1.0" ?> <eparcel>
             * <!--********************************--> <!-- Prefered language
             * for the --> <!-- response (FR/EN) (optional) -->
             * <!--********************************--> <language>en</language>
             * 
             * <ratesAndServicesRequest>
             * <!--**********************************--> <!-- Merchant
             * Identification assigned --> <!-- by Canada Post --> <!-- --> <!--
             * Note: Use 'CPC_DEMO_HTML' or ask --> <!-- our Help Desk to change
             * your --> <!-- profile if you want HTML to be --> <!-- returned to
             * you --> <!--**********************************--> <merchantCPCID>
             * CPC_DEMO_XML </merchantCPCID>
             * 
             * <!--*********************************--> <!--Origin Postal Code
             * --> <!--This parameter is optional -->
             * <!--*********************************-->
             * <fromPostalCode>m1p1c0</fromPostalCode>
             * 
             * <!--**********************************--> <!-- Turn Around Time
             * (hours) --> <!-- This parameter is optional -->
             * <!--**********************************--> <turnAroundTime> 24
             * </turnAroundTime>
             * 
             * <!--**********************************--> <!-- Total amount in $
             * of the items --> <!-- for insurance calculation --> <!-- This
             * parameter is optional -->
             * <!--**********************************-->
             * <itemsPrice>0.00</itemsPrice>
             * 
             * <!--**********************************--> <!-- List of items in
             * the shopping --> <!-- cart --> <!-- Each item is defined by : -->
             * <!-- - quantity (mandatory) --> <!-- - size (mandatory) --> <!--
             * - weight (mandatory) --> <!-- - description (mandatory) --> <!--
             * - ready to ship (optional) -->
             * <!--**********************************--> <lineItems> <item>
             * <quantity> 1 </quantity> <weight> 1.491 </weight> <length> 1
             * </length> <width> 1 </width> <height> 1 </height> <description>
             * KAO Diskettes </description> </item>
             * 
             * <item> <quantity> 1 </quantity> <weight> 1.5 </weight> <length>
             * 20 </length> <width> 30 </width> <height> 20 </height>
             * <description> My Ready To Ship Item</description>
             * <!--**********************************************--> <!-- By
             * adding the 'readyToShip' tag, Sell Online --> <!-- will not pack
             * this item in the boxes --> <!-- defined in the merchant profile.
             * --> <!-- Instead, this item will be shipped in its --> <!--
             * original box: 1.5 kg and 20x30x20 cm -->
             * <!--**********************************************-->
             * <readyToShip/> </item> </lineItems>
             * 
             * <!--********************************--> <!-- City where the
             * parcel will be --> <!-- shipped to -->
             * <!--********************************--> <city> </city>
             * 
             * <!--********************************--> <!-- Province (Canada) or
             * State (US)--> <!-- where the parcel will be --> <!-- shipped to
             * --> <!--********************************--> <provOrState>
             * Wisconsin </provOrState>
             * 
             * <!--********************************--> <!-- Country or ISO
             * Country code --> <!-- where the parcel will be --> <!-- shipped
             * to --> <!--********************************--> <country> CANADA
             * </country>
             * 
             * <!--********************************--> <!-- Postal Code (or ZIP)
             * where the --> <!-- parcel will be shipped to -->
             * <!--********************************--> <postalCode>
             * H3K1E5</postalCode> </ratesAndServicesRequest> </eparcel>
             **/

            log.debug("canadapost request " + request.toString());

            HttpClient client = new HttpClient();

            StringBuilder u = new StringBuilder().append(protocol).append("://").append(host).append(":")
                    .append(port);
            if (!StringUtils.isBlank(url)) {
                u.append(url);
            }

            log.debug("Canadapost URL " + u.toString());

            httppost = new PostMethod(u.toString());
            RequestEntity entity = new StringRequestEntity(request.toString(), "text/plain", "UTF-8");
            httppost.setRequestEntity(entity);

            int result = client.executeMethod(httppost);

            if (result != 200) {
                log.error("Communication Error with canadapost " + protocol + "://" + host + ":" + port + url);
                throw new Exception(
                        "Communication Error with canadapost " + protocol + "://" + host + ":" + port + url);
            }
            String stringresult = httppost.getResponseBodyAsString();
            log.debug("canadapost response " + stringresult);

            canadaPost = new CanadaPostParsedElements();
            Digester digester = new Digester();
            digester.push(canadaPost);

            digester.addCallMethod("eparcel/ratesAndServicesResponse/statusCode", "setStatusCode", 0);
            digester.addCallMethod("eparcel/ratesAndServicesResponse/statusMessage", "setStatusMessage", 0);
            digester.addObjectCreate("eparcel/ratesAndServicesResponse/product",
                    com.salesmanager.core.entity.shipping.ShippingOption.class);
            digester.addSetProperties("eparcel/ratesAndServicesResponse/product", "sequence", "optionId");
            digester.addCallMethod("eparcel/ratesAndServicesResponse/product/shippingDate", "setShippingDate", 0);
            digester.addCallMethod("eparcel/ratesAndServicesResponse/product/deliveryDate", "setDeliveryDate", 0);
            digester.addCallMethod("eparcel/ratesAndServicesResponse/product/name", "setOptionName", 0);
            digester.addCallMethod("eparcel/ratesAndServicesResponse/product/rate", "setOptionPriceText", 0);
            digester.addSetNext("eparcel/ratesAndServicesResponse/product", "addOption");

            /**
             * response
             * 
             * <?xml version="1.0" ?> <!DOCTYPE eparcel (View Source for full
             * doctype...)> - <eparcel> - <ratesAndServicesResponse>
             * <statusCode>1</statusCode> <statusMessage>OK</statusMessage>
             * <requestID>1769506</requestID> <handling>0.0</handling>
             * <language>0</language> - <product id="1040" sequence="1">
             * <name>Priority Courier</name> <rate>38.44</rate>
             * <shippingDate>2008-12-22</shippingDate>
             * <deliveryDate>2008-12-23</deliveryDate>
             * <deliveryDayOfWeek>3</deliveryDayOfWeek>
             * <nextDayAM>true</nextDayAM> <packingID>P_0</packingID> </product>
             * - <product id="1020" sequence="2"> <name>Expedited</name>
             * <rate>16.08</rate> <shippingDate>2008-12-22</shippingDate>
             * <deliveryDate>2008-12-23</deliveryDate>
             * <deliveryDayOfWeek>3</deliveryDayOfWeek>
             * <nextDayAM>false</nextDayAM> <packingID>P_0</packingID>
             * </product> - <product id="1010" sequence="3">
             * <name>Regular</name> <rate>16.08</rate>
             * <shippingDate>2008-12-22</shippingDate>
             * <deliveryDate>2008-12-29</deliveryDate>
             * <deliveryDayOfWeek>2</deliveryDayOfWeek>
             * <nextDayAM>false</nextDayAM> <packingID>P_0</packingID>
             * </product> - <packing> <packingID>P_0</packingID> - <box>
             * <name>Small Box</name> <weight>1.691</weight>
             * <expediterWeight>1.691</expediterWeight> <length>25.0</length>
             * <width>17.0</width> <height>16.0</height> - <packedItem>
             * <quantity>1</quantity> <description>KAO Diskettes</description>
             * </packedItem> </box> - <box> <name>My Ready To Ship Item</name>
             * <weight>2.0</weight> <expediterWeight>1.5</expediterWeight>
             * <length>30.0</length> <width>20.0</width> <height>20.0</height> -
             * <packedItem> <quantity>1</quantity> <description>My Ready To Ship
             * Item</description> </packedItem> </box> </packing> -
             * <shippingOptions> <insurance>No</insurance>
             * <deliveryConfirmation>Yes</deliveryConfirmation>
             * <signature>No</signature> </shippingOptions> <comment />
             * </ratesAndServicesResponse> </eparcel> - <!-- END_OF_EPARCEL -->
             */

            Reader reader = new StringReader(stringresult);

            digester.parse(reader);

        } catch (Exception e) {
            log.error(e);
        } finally {
            if (httppost != null) {
                httppost.releaseConnection();
            }
        }

        if (canadaPost == null || canadaPost.getStatusCode() == null) {
            return null;
        }

        if (canadaPost.getStatusCode().equals("-6") || canadaPost.getStatusCode().equals("-7")) {
            LogMerchantUtil.log(store.getMerchantId(), "Can't process CanadaPost statusCode="
                    + canadaPost.getStatusCode() + " message= " + canadaPost.getStatusMessage());
        }

        if (!canadaPost.getStatusCode().equals("1")) {
            log.error("An error occured with canadapost request (code-> " + canadaPost.getStatusCode()
                    + " message-> " + canadaPost.getStatusMessage() + ")");
            return null;
        }

        String carrier = getShippingMethodDescription(locale);
        // cost is in CAD, need to do conversion

        boolean requiresCurrencyConversion = false;
        String storeCurrency = store.getCurrency();
        if (!storeCurrency.equals(Constants.CURRENCY_CODE_CAD)) {
            requiresCurrencyConversion = true;
        }

        /** Details on whit RT quote information to display **/
        MerchantConfiguration rtdetails = config
                .getMerchantConfiguration(ShippingConstants.MODULE_SHIPPING_DISPLAY_REALTIME_QUOTES);
        int displayQuoteDeliveryTime = ShippingConstants.NO_DISPLAY_RT_QUOTE_TIME;
        if (rtdetails != null) {

            if (!StringUtils.isBlank(rtdetails.getConfigurationValue1())) {// display
                // or
                // not
                // quotes
                try {
                    displayQuoteDeliveryTime = Integer.parseInt(rtdetails.getConfigurationValue1());

                } catch (Exception e) {
                    log.error("Display quote is not an integer value [" + rtdetails.getConfigurationValue1() + "]");
                }
            }
        }
        /**/

        List options = canadaPost.getOptions();
        if (options != null) {
            Iterator i = options.iterator();
            while (i.hasNext()) {
                ShippingOption option = (ShippingOption) i.next();
                option.setCurrency(store.getCurrency());
                StringBuffer description = new StringBuffer();
                description.append(option.getOptionName());
                if (displayQuoteDeliveryTime == ShippingConstants.DISPLAY_RT_QUOTE_TIME) {
                    description.append(" (").append(option.getDeliveryDate()).append(")");
                }
                option.setDescription(description.toString());
                if (requiresCurrencyConversion) {
                    option.setOptionPrice(CurrencyUtil.convertToCurrency(option.getOptionPrice(),
                            Constants.CURRENCY_CODE_CAD, store.getCurrency()));
                }
                // System.out.println(option.getOptionPrice().toString());

            }
        }

        return options;
    }

    public ConfigurationResponse getConfiguration(MerchantConfiguration configurations, ConfigurationResponse vo)
            throws Exception {
        if (configurations.getConfigurationKey().equals(ShippingConstants.MODULE_SHIPPING_RT_CRED)) {// handle
            // credentials

            if (!StringUtils.isBlank(configurations.getConfigurationValue2())) {

                IntegrationKeys keys = ShippingUtil.getKeys(configurations.getConfigurationValue1());
                vo.addConfiguration("canadapost-keys", keys);

            }

            if (!StringUtils.isBlank(configurations.getConfigurationValue2())) {
                IntegrationProperties props = ShippingUtil.getProperties(configurations.getConfigurationValue2());
                vo.addConfiguration("canadapost-properties", props);
            }

        }

        if (configurations.getConfigurationKey().equals(ShippingConstants.MODULE_SHIPPING_RT_PKG_DOM_INT)) {// handle
            // packages
            // &
            // services
            Map domesticmap = null;
            Map globalmap = null;
            // PKGOPTIONS
            if (!StringUtils.isBlank(configurations.getConfigurationValue())) {
                vo.addConfiguration("package-canadapost", configurations.getConfigurationValue());
            }
        }

        vo.addMerchantConfiguration(configurations);
        return vo;
    }

    public void storeConfiguration(int merchantid, ConfigurationResponse vo, HttpServletRequest request)
            throws Exception {
        // TODO Auto-generated method stub

    }

}

class CanadaPostParsedElements {

    private String statusCode;
    private String statusMessage;
    private List options = new ArrayList();

    public void addOption(ShippingOption option) {
        options.add(option);
    }

    public List getOptions() {
        return options;
    }

    public String getStatusCode() {
        return statusCode;
    }

    public void setStatusCode(String statusCode) {
        this.statusCode = statusCode;
    }

    public String getStatusMessage() {
        return statusMessage;
    }

    public void setStatusMessage(String statusMessage) {
        this.statusMessage = statusMessage;
    }

}