/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * 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 org.apache.ofbiz.ebay;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;

import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.GeneralException;
import org.apache.ofbiz.base.util.UtilDateTime;
import org.apache.ofbiz.base.util.UtilGenerics;
import org.apache.ofbiz.base.util.UtilMisc;
import org.apache.ofbiz.base.util.UtilNumber;
import org.apache.ofbiz.base.util.UtilProperties;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.base.util.UtilXml;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericEntityException;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.entity.condition.EntityComparisonOperator;
import org.apache.ofbiz.entity.condition.EntityCondition;
import org.apache.ofbiz.entity.util.EntityQuery;
import org.apache.ofbiz.entity.util.EntityUtil;
import org.apache.ofbiz.order.order.OrderChangeHelper;
import org.apache.ofbiz.order.shoppingcart.CheckOutHelper;
import org.apache.ofbiz.order.shoppingcart.ShoppingCart;
import org.apache.ofbiz.order.shoppingcart.ShoppingCartItem;
import org.apache.ofbiz.party.party.PartyWorker;
import org.apache.ofbiz.service.DispatchContext;
import org.apache.ofbiz.service.LocalDispatcher;
import org.apache.ofbiz.service.ModelService;
import org.apache.ofbiz.service.ServiceUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

public class EbayOrderServices {

    private static final String RESOURCE = "EbayUiLabels";
    private static final String MODULE = EbayOrderServices.class.getName();

    private static final int DECIMALS = UtilNumber.getBigDecimalScale("order.decimals");
    private static final RoundingMode ROUNDING = UtilNumber.getRoundingMode("order.rounding");
    private static boolean isGetSellerTransactionsCall = false;
    private static boolean isGetOrdersCall = false;
    private static boolean isGetMyeBaySellingCall = false;
    private static List<Map<String, Object>> orderList = new LinkedList<>();
    private static List<String> getSellerTransactionsContainingOrderList = new LinkedList<>();
    private static List<String> orderImportSuccessMessageList = new LinkedList<>();
    private static List<String> orderImportFailureMessageList = new LinkedList<>();

    public static Map<String, Object> getEbayOrders(DispatchContext dctx, Map<String, Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Locale locale = (Locale) context.get("locale");
        orderImportSuccessMessageList.clear();
        orderImportFailureMessageList.clear();
        getSellerTransactionsContainingOrderList.clear();
        orderList.clear();
        Map<String, Object> result = new HashMap<>();
        try {
            Map<String, Object> eBayConfigResult = EbayHelper.buildEbayConfig(context, delegator);
            if (UtilValidate.isEmpty(eBayConfigResult)) {
                String eBayConfigErrorMsg = UtilProperties.getMessage(RESOURCE, "EbayConfigurationSettingsAreMissingForConnectingToEbayServer",
                        locale);
                return ServiceUtil.returnError(eBayConfigErrorMsg);
            }

            StringBuffer sellerTransactionsItemsXml = new StringBuffer();
            if (!ServiceUtil.isFailure(buildGetSellerTransactionsRequest(context, sellerTransactionsItemsXml,
                    eBayConfigResult.get("token").toString()))) {
                result = EbayHelper.postItem(eBayConfigResult.get("xmlGatewayUri").toString(), sellerTransactionsItemsXml, eBayConfigResult.get(
                        "devID").toString(), eBayConfigResult.get("appID").toString(), eBayConfigResult.get("certID").toString(),
                        "GetSellerTransactions", eBayConfigResult.get("compatibilityLevel").toString(), eBayConfigResult.get("siteID").toString());
                String getSellerTransactionSuccessMsg = (String) result.get(ModelService.SUCCESS_MESSAGE);
                if (getSellerTransactionSuccessMsg != null) {
                    isGetSellerTransactionsCall = true;
                    result = checkOrders(delegator, dispatcher, locale, context, getSellerTransactionSuccessMsg);
                }
            }

            StringBuffer getOrdersXml = new StringBuffer();
            if (!ServiceUtil.isFailure(buildGetOrdersRequest(context, getOrdersXml, eBayConfigResult.get("token").toString()))) {
                result = EbayHelper.postItem(eBayConfigResult.get("xmlGatewayUri").toString(), getOrdersXml,
                        eBayConfigResult.get("devID").toString(), eBayConfigResult.get("appID").toString(), eBayConfigResult.get("certID").toString(),
                        "GetOrders", eBayConfigResult.get("compatibilityLevel").toString(), eBayConfigResult.get("siteID").toString());
                String getOrdersSuccessMsg = (String) result.get(ModelService.SUCCESS_MESSAGE);
                if (getOrdersSuccessMsg != null) {
                    isGetOrdersCall = true;
                    result = checkOrders(delegator, dispatcher, locale, context, getOrdersSuccessMsg);
                }
            }

            StringBuffer getMyeBaySellingXml = new StringBuffer();
            if (!ServiceUtil.isFailure(buildGetMyeBaySellingRequest(context, getMyeBaySellingXml, eBayConfigResult.get("token").toString()))) {
                result = EbayHelper.postItem(eBayConfigResult.get("xmlGatewayUri").toString(), getMyeBaySellingXml,
                        eBayConfigResult.get("devID").toString(), eBayConfigResult.get("appID").toString(), eBayConfigResult.get("certID").toString(),
                        "GetMyeBaySelling", eBayConfigResult.get("compatibilityLevel").toString(), eBayConfigResult.get("siteID").toString());
                String getMyeBaySellingSuccessMsg = (String) result.get(ModelService.SUCCESS_MESSAGE);
                if (getMyeBaySellingSuccessMsg != null) {
                    isGetMyeBaySellingCall = true;
                    result = checkOrders(delegator, dispatcher, locale, context, getMyeBaySellingSuccessMsg);
                }
            }
        } catch (Exception e) {
            String errMsg = UtilProperties.getMessage(RESOURCE, "buildEbayConfig.exceptionInGetOrdersFromEbay" + e.getMessage(), locale);
            return ServiceUtil.returnError(errMsg);
        }
        return result;
    }

    public static Map<String, Object> importEbayOrders(DispatchContext dctx, Map<String, Object> context) {
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Locale locale = (Locale) context.get("locale");
        Map<String, Object> result = new HashMap<>();
        String externalId = (String) context.get("externalId");
        List<Map<String, Object>> orderList = UtilGenerics.cast(context.get("orderList"));
        try {
            if (UtilValidate.isNotEmpty(orderList)) {
                Iterator<Map<String, Object>> orderListIter = orderList.iterator();
                while (orderListIter.hasNext()) {
                    Map<String, Object> orderMapCtx = orderListIter.next();
                    if (externalId.equals(orderMapCtx.get("externalId").toString())) {
                        context.clear();
                        context.putAll(orderMapCtx);
                        break;
                    }
                }
            }
            result = createShoppingCart(delegator, dispatcher, locale, context, true);
        } catch (Exception e) {
            Debug.logError("Exception in importOrderFromEbay " + e, MODULE);
            return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "ordersImportFromEbay.exceptionInImportOrderFromEbay", locale));
        }
        if (UtilValidate.isNotEmpty(orderImportSuccessMessageList)) {
            result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS);
            result.put(ModelService.SUCCESS_MESSAGE_LIST, orderImportSuccessMessageList);
        }

        if (UtilValidate.isNotEmpty(orderImportSuccessMessageList)) {
            result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_FAIL);
            result.put(ModelService.ERROR_MESSAGE_LIST, orderImportFailureMessageList);
        }
        return result;
    }

    private static Map<String, Object> buildGetOrdersRequest(Map<String, Object> context, StringBuffer dataItemsXml, String token) {
        Locale locale = (Locale) context.get("locale");
        String fromDate = (String) context.get("fromDate");
        String thruDate = (String) context.get("thruDate");
        try {
            Document transDoc = UtilXml.makeEmptyXmlDocument("GetOrdersRequest");
            Element transElem = transDoc.getDocumentElement();
            transElem.setAttribute("xmlns", "urn:ebay:apis:eBLBaseComponents");
            UtilXml.addChildElementValue(transElem, "DetailLevel", "ReturnAll", transDoc);

            EbayHelper.appendRequesterCredentials(transElem, transDoc, token);

            if (UtilValidate.isNotEmpty(getSellerTransactionsContainingOrderList)) {
                Element orderIdArrayElem = UtilXml.addChildElement(transElem, "OrderIDArray", transDoc);
                Iterator<String> orderIdListIter = getSellerTransactionsContainingOrderList.iterator();
                while (orderIdListIter.hasNext()) {
                    String orderId = orderIdListIter.next();
                    UtilXml.addChildElementValue(orderIdArrayElem, "OrderID", orderId, transDoc);
                }
            } else {
                UtilXml.addChildElementValue(transElem, "OrderRole", "Seller", transDoc);
                UtilXml.addChildElementValue(transElem, "OrderStatus", "Completed", transDoc);

                String fromDateOut = EbayHelper.convertDate(fromDate, "yyyy-MM-dd HH:mm:ss.SSS", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
                if (fromDateOut != null) {
                    UtilXml.addChildElementValue(transElem, "CreateTimeFrom", fromDateOut, transDoc);
                } else {
                    Debug.logError("Cannot convert from date from yyyy-MM-dd HH:mm:ss.SSS date format to yyyy-MM-dd'T'HH:mm:ss.SSS'Z' date format",
                            MODULE);
                    return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "ordersImportFromEbay.cannotConvertFromDate", locale));
                }
                fromDateOut = EbayHelper.convertDate(thruDate, "yyyy-MM-dd HH:mm:ss.SSS", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
                if (fromDateOut != null) {
                    UtilXml.addChildElementValue(transElem, "CreateTimeTo", fromDateOut, transDoc);
                } else {
                    Debug.logError("Cannot convert thru date from yyyy-MM-dd HH:mm:ss.SSS date format to yyyy-MM-dd'T'HH:mm:ss.SSS'Z' date format",
                            MODULE);
                    return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "ordersImportFromEbay.cannotConvertThruDate", locale));
                }
            }
            dataItemsXml.append(UtilXml.writeXmlDocument(transDoc));
        } catch (Exception e) {
            Debug.logError("Exception during building get seller transactions request", MODULE);
            return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "ordersImportFromEbay"
                    + ".exceptionDuringBuildingGetSellerTransactionRequest", locale));
        }
        return ServiceUtil.returnSuccess();
    }

    private static Map<String, Object> buildGetSellerTransactionsRequest(Map<String, Object> context, StringBuffer sellerTransactionsItemsXml,
            String token) {
        Locale locale = (Locale) context.get("locale");
        String fromDate = (String) context.get("fromDate");
        String thruDate = (String) context.get("thruDate");
        try {
            Document transDoc = UtilXml.makeEmptyXmlDocument("GetSellerTransactionsRequest");
            Element transElem = transDoc.getDocumentElement();
            transElem.setAttribute("xmlns", "urn:ebay:apis:eBLBaseComponents");

            EbayHelper.appendRequesterCredentials(transElem, transDoc, token);
            UtilXml.addChildElementValue(transElem, "DetailLevel", "ReturnAll", transDoc);
            UtilXml.addChildElementValue(transElem, "IncludeContainingOrder", "true", transDoc);

            String fromDateOut = EbayHelper.convertDate(fromDate, "yyyy-MM-dd HH:mm:ss.SSS", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
            if (fromDateOut != null) {
                UtilXml.addChildElementValue(transElem, "ModTimeFrom", fromDateOut, transDoc);
            } else {
                Debug.logError("Cannot convert from date from yyyy-MM-dd HH:mm:ss.SSS date format to yyyy-MM-dd'T'HH:mm:ss.SSS'Z' date format",
                        MODULE);
                return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "ordersImportFromEbay.cannotConvertFromDate", locale));
            }

            fromDateOut = EbayHelper.convertDate(thruDate, "yyyy-MM-dd HH:mm:ss.SSS", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
            if (fromDateOut != null) {
                UtilXml.addChildElementValue(transElem, "ModTimeTo", fromDateOut, transDoc);
            } else {
                Debug.logError("Cannot convert thru date from yyyy-MM-dd HH:mm:ss.SSS date format to yyyy-MM-dd'T'HH:mm:ss.SSS'Z' date format",
                        MODULE);
                return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "ordersImportFromEbay.cannotConvertThruDate", locale));
            }
            sellerTransactionsItemsXml.append(UtilXml.writeXmlDocument(transDoc));
        } catch (Exception e) {
            Debug.logError("Exception during building get seller transactions request", MODULE);
            return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "ordersImportFromEbay"
                    + ".exceptionDuringBuildingGetSellerTransactionRequest", locale));
        }
        return ServiceUtil.returnSuccess();
    }

    private static Map<String, Object> buildGetMyeBaySellingRequest(Map<String, Object> context, StringBuffer getMyeBaySellingXml, String token) {
        Locale locale = (Locale) context.get("locale");
        try {
            Document transDoc = UtilXml.makeEmptyXmlDocument("GetMyeBaySellingRequest");
            Element transElem = transDoc.getDocumentElement();
            transElem.setAttribute("xmlns", "urn:ebay:apis:eBLBaseComponents");

            EbayHelper.appendRequesterCredentials(transElem, transDoc, token);

            Element deletedFromSoldListElem = UtilXml.addChildElement(transElem, "DeletedFromSoldList", transDoc);
            UtilXml.addChildElementValue(deletedFromSoldListElem, "Sort", "ItemID", transDoc);
            getMyeBaySellingXml.append(UtilXml.writeXmlDocument(transDoc));
        } catch (Exception e) {
            Debug.logError("Exception during building MyeBaySelling request", MODULE);
            return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "ordersImportFromEbay.exceptionDuringBuildingMyeBaySellingRequest",
                    locale));
        }
        return ServiceUtil.returnSuccess();
    }

    private static Map<String, Object> checkOrders(Delegator delegator, LocalDispatcher dispatcher, Locale locale, Map<String, Object> context,
            String responseMsg) {
        StringBuffer errorMessage = new StringBuffer();
        Map<String, Object> result = new HashMap<>();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        if (isGetSellerTransactionsCall) {
            List<Map<String, Object>> getSellerTransactionList = readGetSellerTransactionResponse(responseMsg, locale, (String) context.get(
                    "productStoreId"), delegator, dispatcher, errorMessage, userLogin);
            if (UtilValidate.isNotEmpty(getSellerTransactionList)) {
                orderList.addAll(getSellerTransactionList);
            }
            isGetSellerTransactionsCall = false;
            return ServiceUtil.returnSuccess();
        } else if (isGetOrdersCall) {
            List<Map<String, Object>> getOrdersList = readGetOrdersResponse(responseMsg, locale, (String) context.get("productStoreId"), delegator,
                    dispatcher, errorMessage, userLogin);
            if (UtilValidate.isNotEmpty(getOrdersList)) {
                orderList.addAll(getOrdersList);
            }
            isGetOrdersCall = false;
            return ServiceUtil.returnSuccess();
        } else if (isGetMyeBaySellingCall) {
            // for now fetching only deleted transaction & orders value from the sold list.
            List<String> eBayDeletedOrdersAndTransactionList = readGetMyeBaySellingResponse(responseMsg, locale, (String) context.get(
                    "productStoreId"), delegator, dispatcher, errorMessage, userLogin);
            if (UtilValidate.isNotEmpty(eBayDeletedOrdersAndTransactionList)) {
                Debug.logInfo("The value of getMyeBaySellingList" + eBayDeletedOrdersAndTransactionList, MODULE);
                Iterator<Map<String, Object>> orderListIter = orderList.iterator();
                while (orderListIter.hasNext()) {
                    Map<String, Object> orderCtx = orderListIter.next();
                    if (eBayDeletedOrdersAndTransactionList.contains(orderCtx.get("externalId"))) {
                        // Now finally exclude orders & transaction that has been deleted from sold list.
                        orderList.remove(orderCtx);
                    }
                }
            }
        }
        if (UtilValidate.isEmpty(orderList)) {
            Debug.logError("No orders found", MODULE);
            return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "ordersImportFromEbay.noOrdersFound", locale));
        }
        if (UtilValidate.isNotEmpty(orderList)) {
            result.put("orderList", orderList);
        }
        return result;
    }

// Sample xml data that is being generated from GetOrders request
//
//    <?xml version="1.0" encoding="UTF-8"?><GetOrdersResponse xmlns="urn:ebay:apis:eBLBaseComponents">
//    <Timestamp>2009-09-10T11:17:53.529Z</Timestamp>
//    <Ack>Success</Ack>
//    <Version>631</Version>
//    <Build>E631_CORE_BUNDLED_9942930_R1</Build>
//    <OrderArray>
//        <Order>
//            <OrderID>116583010</OrderID>
//            <OrderStatus>Completed</OrderStatus>
//            <AdjustmentAmount currencyID="USD">0.0</AdjustmentAmount>
//            <AmountSaved currencyID="USD">0.0</AmountSaved>
//            <CheckoutStatus>
//                <eBayPaymentStatus>NoPaymentFailure</eBayPaymentStatus>
//                <LastModifiedTime>2009-09-08T14:07:10.000Z</LastModifiedTime>
//                <PaymentMethod>CCAccepted</PaymentMethod>
//                <Status>Complete</Status>
//                <IntegratedMerchantCreditCardEnabled>false</IntegratedMerchantCreditCardEnabled>
//            </CheckoutStatus>
//            <ShippingDetails>
//                <InsuranceFee currencyID="USD">0.0</InsuranceFee>
//                <InsuranceOption>NotOffered</InsuranceOption>
//                <InsuranceWanted>false</InsuranceWanted>
//                <SalesTax>
//                    <SalesTaxPercent>0.0</SalesTaxPercent>
//                    <SalesTaxState/>
//                    <ShippingIncludedInTax>false</ShippingIncludedInTax>
//                    <SalesTaxAmount currencyID="USD">0.0</SalesTaxAmount>
//                </SalesTax>
//                <ShippingServiceOptions>
//                    <ShippingService>UPS2ndDay</ShippingService>
//                    <ShippingServiceCost currencyID="USD">10.0</ShippingServiceCost>
//                    <ShippingServicePriority>1</ShippingServicePriority>
//                    <ExpeditedService>false</ExpeditedService>
//                    <ShippingTimeMin>1</ShippingTimeMin>
//                    <ShippingTimeMax>2</ShippingTimeMax>
//                </ShippingServiceOptions>
//                <SellingManagerSalesRecordNumber>103</SellingManagerSalesRecordNumber>
//                <GetItFast>false</GetItFast>
//            </ShippingDetails>
//            <CreatingUserRole>Buyer</CreatingUserRole>
//            <CreatedTime>2009-09-08T08:53:23.000Z</CreatedTime>
//            <PaymentMethods>AmEx</PaymentMethods>
//            <PaymentMethods>Discover</PaymentMethods>
//            <PaymentMethods>VisaMC</PaymentMethods>
//            <ShippingAddress>
//                <Name>Apache OFBiz</Name>
//                <Street1>Apache Software Foundation</Street1>
//                <Street2/>
//                <CityName>Salt Lake City</CityName>
//                <StateOrProvince>UT</StateOrProvince>
//                <Country>US</Country>
//                <CountryName>United States</CountryName>
//                <Phone>888 887 9876</Phone>
//                <PostalCode>84101</PostalCode>
//                <AddressID>5149770</AddressID>
//                <AddressOwner>eBay</AddressOwner>
//                <ExternalAddressID/>
//            </ShippingAddress>
//            <ShippingServiceSelected>
//                <ShippingInsuranceCost currencyID="USD">0.0</ShippingInsuranceCost>
//                <ShippingService>UPS2ndDay</ShippingService>
//                <ShippingServiceCost currencyID="USD">10.0</ShippingServiceCost>
//            </ShippingServiceSelected>
//            <Subtotal currencyID="USD">132.0</Subtotal>
//            <Total currencyID="USD">142.0</Total>
//            <ExternalTransaction>
//                <ExternalTransactionID>SIS</ExternalTransactionID>
//                <ExternalTransactionTime>2009-09-08T08:53:32.000Z</ExternalTransactionTime>
//                <FeeOrCreditAmount currencyID="USD">0.0</FeeOrCreditAmount>
//                <PaymentOrRefundAmount currencyID="USD">142.0</PaymentOrRefundAmount>
//            </ExternalTransaction>
//            <TransactionArray>
//                <Transaction>
//                    <Buyer>
//                        <Email>apache.ofbiz@gmail.com</Email>
//                    </Buyer>
//                    <ShippingDetails>
//                        <SellingManagerSalesRecordNumber>101</SellingManagerSalesRecordNumber>
//                    </ShippingDetails>
//                    <Item>
//                        <ItemID>110040779968</ItemID>
//                        <SKU>GZ-9290</SKU>
//                    </Item>
//                    <QuantityPurchased>1</QuantityPurchased>
//                    <Status>
//                        <PaymentHoldStatus>None</PaymentHoldStatus>
//                    </Status>
//                    <TransactionID>0</TransactionID>
//                    <TransactionPrice currencyID="USD">102.0</TransactionPrice>
//                </Transaction>
//                <Transaction>
//                    <Buyer>
//                        <Email>apache.ofbiz@gmail.com</Email>
//                    </Buyer>
//                    <ShippingDetails>
//                        <SellingManagerSalesRecordNumber>102</SellingManagerSalesRecordNumber>
//                    </ShippingDetails>
//                    <Item>
//                        <ItemID>110040780249</ItemID>
//                        <SKU>GZ-1001</SKU>
//                    </Item>
//                    <QuantityPurchased>1</QuantityPurchased>
//                    <Status>
//                        <PaymentHoldStatus>None</PaymentHoldStatus>
//                    </Status>
//                    <TransactionID>0</TransactionID>
//                    <TransactionPrice currencyID="USD">30.0</TransactionPrice>
//                </Transaction>
//            </TransactionArray>
//            <BuyerUserID>apacheofbiz</BuyerUserID>
//            <PaidTime>2009-09-08T14:04:17.000Z</PaidTime>
//            <ShippedTime>2009-09-08T14:07:09.000Z</ShippedTime>
//            <IntegratedMerchantCreditCardEnabled>false</IntegratedMerchantCreditCardEnabled>
//        </Order>
//    </OrderArray>
//</GetOrdersResponse>


    private static List<Map<String, Object>> readGetOrdersResponse(String responseMsg, Locale locale, String productStoreId, Delegator delegator,
            LocalDispatcher dispatcher, StringBuffer errorMessage, GenericValue userLogin) {
        List<Map<String, Object>> fetchedOrders = new LinkedList<>();
        Document docResponse = null;
        Element elemResponse = null;
        try {
            docResponse = UtilXml.readXmlDocument(responseMsg, true);
            elemResponse = docResponse.getDocumentElement();
        } catch (SAXException | ParserConfigurationException | IOException e) {
            Debug.logError("Exception during read response from Ebay: " + e.getMessage(), MODULE);
            return fetchedOrders;
        }
        String ack = UtilXml.childElementValue(elemResponse, "Ack", "Failure");
        int totalOrders = 0;
        if (ack != null && "Success".equals(ack)) {
            List<? extends Element> orderArrays = UtilXml.childElementList(elemResponse, "OrderArray");
            if (UtilValidate.isNotEmpty(orderArrays)) {
                totalOrders = orderArrays.size();
            }
            if (totalOrders > 0) {
                // retrieve transaction array
                Iterator<? extends Element> orderArraysElemIter = orderArrays.iterator();
                while (orderArraysElemIter.hasNext()) {
                    Element orderArraysElement = orderArraysElemIter.next();

                    // retrieve transaction
                    List<? extends Element> orders = UtilXml.childElementList(orderArraysElement, "Order");
                    Iterator<? extends Element> ordersElemIter = orders.iterator();

                    while (ordersElemIter.hasNext()) {
                        Map<String, Object> orderCtx = new HashMap<>();
                        Element ordersElement = ordersElemIter.next();
                        String externalOrderId = UtilXml.childElementValue(ordersElement, "OrderID");
                        orderCtx.put("externalId", "EBO_" + externalOrderId);
                        GenericValue orderExist = null;
                        try {
                            orderExist = externalOrderExists(delegator, (String) orderCtx.get("externalId"));
                        } catch (GenericEntityException e) {
                            Debug.logError("Exception during read response from Ebay: " + e.getMessage(), MODULE);
                        }
                        if (orderExist != null) {
                            orderCtx.put("orderId", orderExist.get("orderId"));
                        } else {
                            orderCtx.put("orderId", "");
                        }

                        orderCtx.put("amountPaid", UtilXml.childElementValue(ordersElement, "Total", "0"));
                        String createdDate = UtilXml.childElementValue(ordersElement, "CreatedTime");
                        if (UtilValidate.isNotEmpty(createdDate)) {
                            createdDate = EbayHelper.convertDate(createdDate, "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "yyyy-MM-dd HH:mm:ss.SSS");
                            orderCtx.put("createdDate", createdDate);
                        }
                        orderCtx.put("paidTime", UtilXml.childElementValue(ordersElement, "PaidTime"));
                        orderCtx.put("shippedTime", UtilXml.childElementValue(ordersElement, "ShippedTime"));
                        orderCtx.put("ebayUserIdBuyer", UtilXml.childElementValue(ordersElement, "BuyerUserID"));
                        orderCtx.put("productStoreId", productStoreId);

                        // Retrieve shipping address
                        Map<String, Object> shippingAddressCtx = new HashMap<>();
                        List<? extends Element> shippingAddressList = UtilXml.childElementList(ordersElement, "ShippingAddress");
                        Iterator<? extends Element> shippingAddressElemIter = shippingAddressList.iterator();
                        while (shippingAddressElemIter.hasNext()) {
                            Element shippingAddressElement = shippingAddressElemIter.next();
                            shippingAddressCtx.put("buyerName", UtilXml.childElementValue(shippingAddressElement, "Name"));
                            shippingAddressCtx.put("shippingAddressStreet1", UtilXml.childElementValue(shippingAddressElement, "Street1"));
                            shippingAddressCtx.put("shippingAddressStreet2", UtilXml.childElementValue(shippingAddressElement, "Street2"));
                            shippingAddressCtx.put("shippingAddressCityName", UtilXml.childElementValue(shippingAddressElement, "CityName"));
                            shippingAddressCtx.put("shippingAddressStateOrProvince", UtilXml.childElementValue(shippingAddressElement,
                                    "StateOrProvince"));
                            shippingAddressCtx.put("shippingAddressCountry", UtilXml.childElementValue(shippingAddressElement, "Country"));
                            shippingAddressCtx.put("shippingAddressCountryName", UtilXml.childElementValue(shippingAddressElement,
                                    "CountryName"));
                            shippingAddressCtx.put("shippingAddressPhone", UtilXml.childElementValue(shippingAddressElement, "Phone"));
                            shippingAddressCtx.put("shippingAddressPostalCode", UtilXml.childElementValue(shippingAddressElement, "PostalCode"));
                        }
                        orderCtx.put("shippingAddressCtx", shippingAddressCtx);

                        if (UtilValidate.isEmpty(shippingAddressCtx)) {
                            String shippingAddressMissingMsg = "Shipping Address is missing for eBay Order ID (" + externalOrderId + ")";
                            orderImportFailureMessageList.add(shippingAddressMissingMsg);
                        }

                        // Retrieve shipping service selected
                        Map<String, Object> shippingServiceSelectedCtx = new HashMap<>();
                        List<? extends Element> shippingServiceSelectedList = UtilXml.childElementList(ordersElement, "ShippingServiceSelected");
                        Iterator<? extends Element> shippingServiceSelectedElemIter = shippingServiceSelectedList.iterator();
                        while (shippingServiceSelectedElemIter.hasNext()) {
                            Element shippingServiceSelectedElement = shippingServiceSelectedElemIter.next();
                            shippingServiceSelectedCtx.put("shippingService", UtilXml.childElementValue(shippingServiceSelectedElement,
                                    "ShippingService"));
                            shippingServiceSelectedCtx.put("shippingServiceCost", UtilXml.childElementValue(shippingServiceSelectedElement,
                                    "ShippingServiceCost", "0"));
                            String insuranceCost = UtilXml.childElementValue(shippingServiceSelectedElement, "ShippingInsuranceCost", "0");
                            if (UtilValidate.isNotEmpty(insuranceCost)) {
                                shippingServiceSelectedCtx.put("shippingTotalAdditionalCost", insuranceCost);
                            }
                        }
                        orderCtx.put("shippingServiceSelectedCtx", shippingServiceSelectedCtx);

                        if (UtilValidate.isEmpty(shippingServiceSelectedCtx.get("shippingService").toString())) {
                            String shippingServiceMissingMsg = "Shipping Method is missing for eBay Order ID (" + externalOrderId + ")";
                            orderImportFailureMessageList.add(shippingServiceMissingMsg);
                        }

                        // Retrieve shipping details
                        Map<String, Object> shippingDetailsCtx = new HashMap<>();
                        List<? extends Element> shippingDetailsList = UtilXml.childElementList(ordersElement, "ShippingDetails");
                        Iterator<? extends Element> shippingDetailsElemIter = shippingDetailsList.iterator();
                        while (shippingDetailsElemIter.hasNext()) {
                            Element shippingDetailsElement = shippingDetailsElemIter.next();
                            shippingDetailsCtx.put("insuranceFee", UtilXml.childElementValue(shippingDetailsElement, "InsuranceFee", "0"));
                            shippingDetailsCtx.put("insuranceOption", UtilXml.childElementValue(shippingDetailsElement, "InsuranceOption"));
                            shippingDetailsCtx.put("insuranceWanted", UtilXml.childElementValue(shippingDetailsElement, "InsuranceWanted",
                                    "false"));

                            // Retrieve sales Tax
                            List<? extends Element> salesTaxList = UtilXml.childElementList(shippingDetailsElement, "SalesTax");
                            Iterator<? extends Element> salesTaxElemIter = salesTaxList.iterator();
                            while (salesTaxElemIter.hasNext()) {
                                Element salesTaxElement = salesTaxElemIter.next();
                                shippingDetailsCtx.put("salesTaxAmount", UtilXml.childElementValue(salesTaxElement, "SalesTaxAmount", "0"));
                                shippingDetailsCtx.put("salesTaxPercent", UtilXml.childElementValue(salesTaxElement, "SalesTaxPercent", "0"));
                                shippingDetailsCtx.put("salesTaxState", UtilXml.childElementValue(salesTaxElement, "SalesTaxState", "0"));
                                shippingDetailsCtx.put("shippingIncludedInTax", UtilXml.childElementValue(salesTaxElement,
                                        "ShippingIncludedInTax", "false"));
                            }
                        }
                        orderCtx.put("shippingDetailsCtx", shippingDetailsCtx);

                        // Retrieve checkout status
                        Map<String, Object> checkoutStatusCtx = new HashMap<>();
                        List<? extends Element> checkoutStatusList = UtilXml.childElementList(ordersElement, "CheckoutStatus");
                        Iterator<? extends Element> checkoutStatusElemIter = checkoutStatusList.iterator();
                        while (checkoutStatusElemIter.hasNext()) {
                            Element statusElement = checkoutStatusElemIter.next();
                            checkoutStatusCtx.put("eBayPaymentStatus", UtilXml.childElementValue(statusElement, "eBayPaymentStatus"));
                            checkoutStatusCtx.put("paymentMethodUsed", UtilXml.childElementValue(statusElement, "PaymentMethod"));
                            checkoutStatusCtx.put("completeStatus", UtilXml.childElementValue(statusElement, "Status"));
                        }
                        orderCtx.put("checkoutStatusCtx", checkoutStatusCtx);

                        // Retrieve external transaction
                        Map<String, Object> externalTransactionCtx = new HashMap<>();
                        List<? extends Element> externalTransactionList = UtilXml.childElementList(ordersElement, "ExternalTransaction");
                        Iterator<? extends Element> externalTransactionElemIter = externalTransactionList.iterator();
                        while (externalTransactionElemIter.hasNext()) {
                            Element externalTransactionElement = externalTransactionElemIter.next();
                            externalTransactionCtx.put("externalTransactionID", UtilXml.childElementValue(externalTransactionElement,
                                    "ExternalTransactionID"));
                            externalTransactionCtx.put("externalTransactionTime", UtilXml.childElementValue(externalTransactionElement,
                                    "ExternalTransactionTime"));
                            externalTransactionCtx.put("feeOrCreditAmount", UtilXml.childElementValue(externalTransactionElement,
                                    "FeeOrCreditAmount", "0"));
                            externalTransactionCtx.put("paymentOrRefundAmount", UtilXml.childElementValue(externalTransactionElement,
                                    "PaymentOrRefundAmount", "0"));
                        }
                        orderCtx.put("externalTransactionCtx", externalTransactionCtx);

                        // Retrieve Transactions Array --> Transactions | Order Items
                        List<Map<String, Object>> orderItemList = new LinkedList<>();
                        String buyersEmailId = null;
                        List<? extends Element> transactionArrayList = UtilXml.childElementList(ordersElement, "TransactionArray");
                        Iterator<? extends Element> transactionArrayElemIter = transactionArrayList.iterator();
                        while (transactionArrayElemIter.hasNext()) {
                            Element transactionArrayElement = transactionArrayElemIter.next();

                            boolean buyerEmailExists = false;
                            List<? extends Element> transactionList = UtilXml.childElementList(transactionArrayElement, "Transaction");
                            Iterator<? extends Element> transactionElemIter = transactionList.iterator();
                            while (transactionElemIter.hasNext()) {
                                Map<String, Object> transactionCtx = new HashMap<>();
                                Element transactionElement = transactionElemIter.next();

                                // Retrieve Buyer email
                                if (!buyerEmailExists) {
                                    List<? extends Element> buyerList = UtilXml.childElementList(transactionElement, "Buyer");
                                    Iterator<? extends Element> buyerElemIter = buyerList.iterator();
                                    while (buyerElemIter.hasNext()) {
                                        Element buyerElement = buyerElemIter.next();
                                        buyersEmailId = UtilXml.childElementValue(buyerElement, "Email");
                                        if (UtilValidate.isNotEmpty(buyersEmailId)) {
                                            buyerEmailExists = true;
                                        }
                                    }
                                }

                                // Retrieve Order Item info
                                List<? extends Element> itemList = UtilXml.childElementList(transactionElement, "Item");
                                Iterator<? extends Element> itemElemIter = itemList.iterator();
                                while (itemElemIter.hasNext()) {
                                    Element itemElement = itemElemIter.next();
                                    transactionCtx.put("goodIdentificationIdValue", UtilXml.childElementValue(itemElement, "ItemID"));
                                    transactionCtx.put("productId", UtilXml.childElementValue(itemElement, "SKU"));
                                }
                                transactionCtx.put("quantity", UtilXml.childElementValue(transactionElement, "QuantityPurchased"));
                                transactionCtx.put("transactionId", UtilXml.childElementValue(transactionElement, "TransactionID"));
                                transactionCtx.put("transactionPrice", UtilXml.childElementValue(transactionElement, "TransactionPrice"));
                                orderItemList.add(transactionCtx);
                            }
                        }
                        orderCtx.put("orderItemList", orderItemList);
                        if (UtilValidate.isNotEmpty(buyersEmailId)) {
                            orderCtx.put("emailBuyer", buyersEmailId);
                        }
                        orderCtx.put("userLogin", userLogin);
                        orderCtx.put("isEbayOrder", "Y");
                        orderCtx.put("isEbayTransaction", "");

                        // Map<String, Object> result = dispatcher.runSync("importEbayOrders", orderCtx);
                        fetchedOrders.add(orderCtx);
                    }
                }
            }
            // Debug.logInfo("The generated string is ======= " + fetchedOrders.toString(), MODULE);
        } else {
            List<? extends Element> errorList = UtilXml.childElementList(elemResponse, "Errors");
            Iterator<? extends Element> errorElemIter = errorList.iterator();
            while (errorElemIter.hasNext()) {
                Element errorElement = errorElemIter.next();
                errorMessage.append(UtilXml.childElementValue(errorElement, "ShortMessage", ""));
            }
        }
        return fetchedOrders;
    }

    private static List<Map<String, Object>> readGetSellerTransactionResponse(String responseMsg, Locale locale, String productStoreId,
            Delegator delegator, LocalDispatcher dispatcher,
            StringBuffer errorMessage, GenericValue userLogin) {
        List<Map<String, Object>> fetchedOrders = new LinkedList<>();

        Document docResponse = null;
        Element elemResponse = null;
        try {
            docResponse = UtilXml.readXmlDocument(responseMsg, true);
            elemResponse = docResponse.getDocumentElement();
        } catch (SAXException | ParserConfigurationException | IOException e) {
            Debug.logError("Exception during read response from Ebay: " + e.getMessage(), MODULE);
            return fetchedOrders;
        }
        String ack = UtilXml.childElementValue(elemResponse, "Ack", "Failure");
        List<? extends Element> paginationList = UtilXml.childElementList(elemResponse, "PaginationResult");
        int totalOrders = 0;
        Iterator<? extends Element> paginationElemIter = paginationList.iterator();
        while (paginationElemIter.hasNext()) {
            Element paginationElement = paginationElemIter.next();
            String totalNumberOfEntries = UtilXml.childElementValue(paginationElement, "TotalNumberOfEntries", "0");
            totalOrders = Integer.valueOf(totalNumberOfEntries);
        }

        if (ack != null && "Success".equals(ack)) {
            if (totalOrders > 0) {
                // retrieve transaction array
                List<? extends Element> transactions = UtilXml.childElementList(elemResponse, "TransactionArray");
                Iterator<? extends Element> transactionsElemIter = transactions.iterator();
                while (transactionsElemIter.hasNext()) {
                    Element transactionsElement = transactionsElemIter.next();

                    // retrieve transaction
                    List<? extends Element> transaction = UtilXml.childElementList(transactionsElement, "Transaction");
                    Iterator<? extends Element> transactionElemIter = transaction.iterator();
                    while (transactionElemIter.hasNext()) {
                        Element transactionElement = transactionElemIter.next();
                        Map<String, Object> orderCtx = new HashMap<>();

                        orderCtx.put("amountPaid", UtilXml.childElementValue(transactionElement, "AmountPaid", "0"));
                        String createdDate = UtilXml.childElementValue(transactionElement, "CreatedDate");
                        if (UtilValidate.isNotEmpty(createdDate)) {
                            createdDate = EbayHelper.convertDate(createdDate, "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "yyyy-MM-dd HH:mm:ss.SSS");
                            orderCtx.put("createdDate", createdDate);
                        }
                        orderCtx.put("paidTime", UtilXml.childElementValue(transactionElement, "PaidTime"));
                        orderCtx.put("shippedTime", UtilXml.childElementValue(transactionElement, "ShippedTime"));
                        orderCtx.put("productStoreId", productStoreId);

                        // if any transaction contains order then add it in the list and give it to GetOrders request.
                        List<? extends Element> containingOrders = UtilXml.childElementList(transactionElement, "ContainingOrder");
                        Iterator<? extends Element> containingOrdersIter = containingOrders.iterator();
                        while (containingOrdersIter.hasNext()) {
                            Element containingOrdersElement = containingOrdersIter.next();
                            String orderId = UtilXml.childElementValue(containingOrdersElement, "OrderID");
                            if (getSellerTransactionsContainingOrderList != null && !getSellerTransactionsContainingOrderList.contains(orderId)) {
                                getSellerTransactionsContainingOrderList.add(orderId);
                            }
                        }
                        if (UtilValidate.isNotEmpty(containingOrders)) {
                            continue;
                        }

                        // retrieve buyer
                        Map<String, Object> shippingAddressCtx = new HashMap<>();
                        Map<String, Object> buyerCtx = new HashMap<>();
                        List<? extends Element> buyer = UtilXml.childElementList(transactionElement, "Buyer");
                        Iterator<? extends Element> buyerElemIter = buyer.iterator();
                        while (buyerElemIter.hasNext()) {
                            Element buyerElement = buyerElemIter.next();
                            buyerCtx.put("emailBuyer", UtilXml.childElementValue(buyerElement, "Email", ""));
                            buyerCtx.put("eiasTokenBuyer", UtilXml.childElementValue(buyerElement, "EIASToken", ""));
                            buyerCtx.put("ebayUserIdBuyer", UtilXml.childElementValue(buyerElement, "UserID", ""));

                            // retrieve buyer information
                            List<? extends Element> buyerInfo = UtilXml.childElementList(buyerElement, "BuyerInfo");
                            Iterator<? extends Element> buyerInfoElemIter = buyerInfo.iterator();
                            while (buyerInfoElemIter.hasNext()) {
                                Element buyerInfoElement = buyerInfoElemIter.next();

                                // retrieve shipping address
                                List<? extends Element> shippingAddressInfo = UtilXml.childElementList(buyerInfoElement, "ShippingAddress");
                                Iterator<? extends Element> shippingAddressElemIter = shippingAddressInfo.iterator();
                                while (shippingAddressElemIter.hasNext()) {
                                    Element shippingAddressElement = shippingAddressElemIter.next();
                                    shippingAddressCtx.put("buyerName", UtilXml.childElementValue(shippingAddressElement, "Name", ""));
                                    shippingAddressCtx.put("shippingAddressStreet", UtilXml.childElementValue(shippingAddressElement, "Street",
                                            ""));
                                    shippingAddressCtx.put("shippingAddressStreet1", UtilXml.childElementValue(shippingAddressElement,
                                            "Street1", ""));
                                    shippingAddressCtx.put("shippingAddressStreet2", UtilXml.childElementValue(shippingAddressElement,
                                            "Street2", ""));
                                    shippingAddressCtx.put("shippingAddressCityName", UtilXml.childElementValue(shippingAddressElement,
                                            "CityName", ""));
                                    shippingAddressCtx.put("shippingAddressStateOrProvince", UtilXml.childElementValue(shippingAddressElement,
                                            "StateOrProvince", ""));
                                    shippingAddressCtx.put("shippingAddressCountry", UtilXml.childElementValue(shippingAddressElement,
                                            "Country", ""));
                                    shippingAddressCtx.put("shippingAddressCountryName", UtilXml.childElementValue(shippingAddressElement,
                                            "CountryName", ""));
                                    shippingAddressCtx.put("shippingAddressPhone", UtilXml.childElementValue(shippingAddressElement, "Phone",
                                            ""));
                                    shippingAddressCtx.put("shippingAddressPostalCode", UtilXml.childElementValue(shippingAddressElement,
                                            "PostalCode", ""));
                                }
                            }
                        }
                        orderCtx.put("buyerCtx", buyerCtx);
                        orderCtx.put("shippingAddressCtx", shippingAddressCtx);

                        // retrieve shipping service selected
                        Map<String, Object> shippingServiceSelectedCtx = new HashMap<>();
                        List<? extends Element> shippingServiceSelected = UtilXml.childElementList(transactionElement, "ShippingServiceSelected");
                        Iterator<? extends Element> shippingServiceSelectedElemIter = shippingServiceSelected.iterator();
                        while (shippingServiceSelectedElemIter.hasNext()) {
                            Element shippingServiceSelectedElement = shippingServiceSelectedElemIter.next();
                            shippingServiceSelectedCtx.put("shippingService", UtilXml.childElementValue(shippingServiceSelectedElement,
                                    "ShippingService", ""));
                            shippingServiceSelectedCtx.put("shippingServiceCost", UtilXml.childElementValue(shippingServiceSelectedElement,
                                    "ShippingServiceCost", "0"));

                            String incuranceCost = UtilXml.childElementValue(shippingServiceSelectedElement, "ShippingInsuranceCost", "0");
                            String additionalCost = UtilXml.childElementValue(shippingServiceSelectedElement, "ShippingServiceAdditionalCost",
                                    "0");
                            String surchargeCost = UtilXml.childElementValue(shippingServiceSelectedElement, "ShippingSurcharge", "0");

                            double shippingInsuranceCost = 0;
                            double shippingServiceAdditionalCost = 0;
                            double shippingSurcharge = 0;

                            if (UtilValidate.isNotEmpty(incuranceCost)) {
                                shippingInsuranceCost = Double.parseDouble(incuranceCost);
                            }
                            if (UtilValidate.isNotEmpty(additionalCost)) {
                                shippingServiceAdditionalCost = Double.parseDouble(additionalCost);
                            }
                            if (UtilValidate.isNotEmpty(surchargeCost)) {
                                shippingSurcharge = Double.parseDouble(surchargeCost);
                            }
                            double shippingTotalAdditionalCost = shippingInsuranceCost + shippingServiceAdditionalCost + shippingSurcharge;
                            String totalAdditionalCost = Double.toString(shippingTotalAdditionalCost);
                            shippingServiceSelectedCtx.put("shippingTotalAdditionalCost", totalAdditionalCost);
                        }
                        orderCtx.put("shippingServiceSelectedCtx", shippingServiceSelectedCtx);

                        // retrieve shipping details
                        Map<String, Object> shippingDetailsCtx = new HashMap<>();
                        List<? extends Element> shippingDetails = UtilXml.childElementList(transactionElement, "ShippingDetails");
                        Iterator<? extends Element> shippingDetailsElemIter = shippingDetails.iterator();
                        while (shippingDetailsElemIter.hasNext()) {
                            Element shippingDetailsElement = shippingDetailsElemIter.next();
                            shippingDetailsCtx.put("insuranceFee", UtilXml.childElementValue(shippingDetailsElement, "InsuranceFee", "0"));
                            shippingDetailsCtx.put("insuranceOption", UtilXml.childElementValue(shippingDetailsElement, "InsuranceOption", ""));
                            shippingDetailsCtx.put("insuranceWanted", UtilXml.childElementValue(shippingDetailsElement, "InsuranceWanted",
                                    "false"));

                            // retrieve sales Tax
                            List<? extends Element> salesTax = UtilXml.childElementList(shippingDetailsElement, "SalesTax");
                            Iterator<? extends Element> salesTaxElemIter = salesTax.iterator();
                            while (salesTaxElemIter.hasNext()) {
                                Element salesTaxElement = salesTaxElemIter.next();
                                shippingDetailsCtx.put("salesTaxAmount", UtilXml.childElementValue(salesTaxElement, "SalesTaxAmount", "0"));
                                shippingDetailsCtx.put("salesTaxPercent", UtilXml.childElementValue(salesTaxElement, "SalesTaxPercent", "0"));
                                shippingDetailsCtx.put("salesTaxState", UtilXml.childElementValue(salesTaxElement, "SalesTaxState", "0"));
                                shippingDetailsCtx.put("shippingIncludedInTax", UtilXml.childElementValue(salesTaxElement,
                                        "ShippingIncludedInTax", "false"));
                            }

                            // retrieve tax table
                            List<? extends Element> taxTable = UtilXml.childElementList(shippingDetailsElement, "TaxTable");
                            Iterator<? extends Element> taxTableElemIter = taxTable.iterator();
                            while (taxTableElemIter.hasNext()) {
                                Element taxTableElement = taxTableElemIter.next();

                                List<? extends Element> taxJurisdiction = UtilXml.childElementList(taxTableElement, "TaxJurisdiction");
                                Iterator<? extends Element> taxJurisdictionElemIter = taxJurisdiction.iterator();
                                while (taxJurisdictionElemIter.hasNext()) {
                                    Element taxJurisdictionElement = taxJurisdictionElemIter.next();

                                    shippingDetailsCtx.put("jurisdictionID", UtilXml.childElementValue(taxJurisdictionElement,
                                            "JurisdictionID", ""));
                                    shippingDetailsCtx.put("jurisdictionSalesTaxPercent", UtilXml.childElementValue(taxJurisdictionElement,
                                            "SalesTaxPercent", "0"));
                                    shippingDetailsCtx.put("jurisdictionShippingIncludedInTax",
                                            UtilXml.childElementValue(taxJurisdictionElement, "ShippingIncludedInTax", "0"));
                                }
                            }
                        }
                        orderCtx.put("shippingDetailsCtx", shippingDetailsCtx);

                        // retrieve status
                        Map<String, Object> checkoutStatusCtx = new HashMap<>();
                        List<? extends Element> status = UtilXml.childElementList(transactionElement, "Status");
                        Iterator<? extends Element> statusElemIter = status.iterator();
                        while (statusElemIter.hasNext()) {
                            Element statusElement = statusElemIter.next();
                            checkoutStatusCtx.put("eBayPaymentStatus", UtilXml.childElementValue(statusElement, "eBayPaymentStatus", ""));
                            checkoutStatusCtx.put("checkoutStatus", UtilXml.childElementValue(statusElement, "CheckoutStatus", ""));
                            checkoutStatusCtx.put("paymentMethodUsed", UtilXml.childElementValue(statusElement, "PaymentMethodUsed", ""));
                            checkoutStatusCtx.put("completeStatus", UtilXml.childElementValue(statusElement, "CompleteStatus", ""));
                            checkoutStatusCtx.put("buyerSelectedShipping", UtilXml.childElementValue(statusElement, "BuyerSelectedShipping", ""));
                        }
                        orderCtx.put("checkoutStatusCtx", checkoutStatusCtx);

                        // retrieve external transaction
                        Map<String, Object> externalTransactionCtx = new HashMap<>();
                        List<? extends Element> externalTransaction = UtilXml.childElementList(transactionElement, "ExternalTransaction");
                        Iterator<? extends Element> externalTransactionElemIter = externalTransaction.iterator();
                        while (externalTransactionElemIter.hasNext()) {
                            Element externalTransactionElement = externalTransactionElemIter.next();
                            externalTransactionCtx.put("externalTransactionID", UtilXml.childElementValue(externalTransactionElement,
                                    "ExternalTransactionID", ""));
                            externalTransactionCtx.put("externalTransactionTime", UtilXml.childElementValue(externalTransactionElement,
                                    "ExternalTransactionTime", ""));
                            externalTransactionCtx.put("feeOrCreditAmount", UtilXml.childElementValue(externalTransactionElement,
                                    "FeeOrCreditAmount", "0"));
                            externalTransactionCtx.put("paymentOrRefundAmount", UtilXml.childElementValue(externalTransactionElement,
                                    "PaymentOrRefundAmount", "0"));
                        }
                        orderCtx.put("externalTransactionCtx", externalTransactionCtx);

                        String quantityPurchased = UtilXml.childElementValue(transactionElement, "QuantityPurchased", "");
                        // retrieve item
                        List<Map<String, Object>> orderItemList = new LinkedList<>();
                        String itemId = "";
                        List<? extends Element> item = UtilXml.childElementList(transactionElement, "Item");
                        Iterator<? extends Element> itemElemIter = item.iterator();
                        while (itemElemIter.hasNext()) {
                            Map<String, Object> orderItemCtx = new HashMap<>();
                            Element itemElement = itemElemIter.next();
                            itemId = UtilXml.childElementValue(itemElement, "ItemID", "");
                            orderItemCtx.put("paymentMethods", UtilXml.childElementValue(itemElement, "PaymentMethods", ""));
                            orderItemCtx.put("quantity", quantityPurchased);
                            orderItemCtx.put("startPrice", UtilXml.childElementValue(itemElement, "StartPrice", "0"));
                            orderItemCtx.put("title", UtilXml.childElementValue(itemElement, "Title", ""));

                            String productId = UtilXml.childElementValue(itemElement, "SKU", "");
                            if (UtilValidate.isEmpty(productId)) {
                                productId = UtilXml.childElementValue(itemElement, "ApplicationData", "");
                                if (UtilValidate.isEmpty(productId)) {
                                    productId = EbayHelper.retrieveProductIdFromTitle(delegator, (String) orderItemCtx.get("title"));
                                }
                            }
                            orderItemCtx.put("productId", productId);
                            // retrieve selling status
                            List<? extends Element> sellingStatus = UtilXml.childElementList(itemElement, "SellingStatus");
                            Iterator<? extends Element> sellingStatusitemElemIter = sellingStatus.iterator();
                            while (sellingStatusitemElemIter.hasNext()) {
                                Element sellingStatusElement = sellingStatusitemElemIter.next();
                                orderItemCtx.put("amount", UtilXml.childElementValue(sellingStatusElement, "CurrentPrice", "0"));
                                orderItemCtx.put("quantitySold", UtilXml.childElementValue(sellingStatusElement, "QuantitySold", "0"));
                                orderItemCtx.put("listingStatus", UtilXml.childElementValue(sellingStatusElement, "ListingStatus", ""));
                            }
                            orderItemList.add(orderItemCtx);
                        }
                        orderCtx.put("orderItemList", orderItemList);

                        // retrieve transactionId
                        String transactionId = UtilXml.childElementValue(transactionElement, "TransactionID", "");

                        // set the externalId
                        if ("0".equals(transactionId)) {
                            // this is a Chinese Auction: ItemID is used to uniquely identify the transaction
                            orderCtx.put("externalId", "EBI_" + itemId);
                        } else {
                            orderCtx.put("externalId", "EBT_" + transactionId);
                        }
                        orderCtx.put("transactionId", "EBI_" + itemId);

                        GenericValue orderExist = null;
                        try {
                            orderExist = externalOrderExists(delegator, (String) orderCtx.get("externalId"));
                        } catch (GenericEntityException e) {
                            Debug.logError("Exception during read response from Ebay: " + e.getMessage(), MODULE);
                        }
                        if (orderExist != null) {
                            orderCtx.put("orderId", orderExist.get("orderId"));
                        } else {
                            orderCtx.put("orderId", "");
                        }

                        // retrieve transaction price
                        orderCtx.put("transactionPrice", UtilXml.childElementValue(transactionElement, "TransactionPrice", "0"));

                        if (UtilValidate.isEmpty(shippingServiceSelectedCtx.get("shippingService").toString())) {
                            String shippingServiceMissingMsg = "Shipping Method is missing for eBay Order ID (" + orderCtx.get("externalId")
                                    .toString() + ")";
                            orderImportFailureMessageList.add(shippingServiceMissingMsg);
                        }

                        // Lets put emailAddress & userId on the root similiar to that of GetOrders request
                        orderCtx.put("emailBuyer", buyerCtx.get("emailBuyer").toString());
                        orderCtx.put("ebayUserIdBuyer", buyerCtx.get("ebayUserIdBuyer").toString());

                        orderCtx.put("userLogin", userLogin);
                        orderCtx.put("isEbayTransaction", "Y");
                        orderCtx.put("isEbayOrder", "");

                        // Now finally put the root map in the fetched orders list.
                        fetchedOrders.add(orderCtx);
                    }
                }
            }
        } else {
            List<? extends Element> errorList = UtilXml.childElementList(elemResponse, "Errors");
            Iterator<? extends Element> errorElemIter = errorList.iterator();
            while (errorElemIter.hasNext()) {
                Element errorElement = errorElemIter.next();
                errorMessage.append(UtilXml.childElementValue(errorElement, "ShortMessage", ""));
            }
        }
        return fetchedOrders;
    }

    private static List<String> readGetMyeBaySellingResponse(String responseMsg, Locale locale, String productStoreId, Delegator delegator,
            LocalDispatcher dispatcher, StringBuffer errorMessage, GenericValue userLogin) {
        List<String> fetchDeletedOrdersAndTransactions = new LinkedList<>();
        Document docResponse = null;
        try {
            docResponse = UtilXml.readXmlDocument(responseMsg, true);
        } catch (SAXException | ParserConfigurationException | IOException e) {
            Debug.logError("Exception during read response from Ebay: " + e.getMessage(), MODULE);
            return fetchDeletedOrdersAndTransactions;
        }
        Element elemResponse = docResponse.getDocumentElement();
        String ack = UtilXml.childElementValue(elemResponse, "Ack", "Failure");
        if (ack != null && "Success".equals(ack)) {
            // retrieve transaction array
            List<? extends Element> deletedFromSoldList = UtilXml.childElementList(elemResponse, "DeletedFromSoldList");
            Iterator<? extends Element> deletedFromSoldElemIter = deletedFromSoldList.iterator();
            while (deletedFromSoldElemIter.hasNext()) {
                Element deletedFromSoldElement = deletedFromSoldElemIter.next();
                // retrieve transaction
                List<? extends Element> orderTransactionArrayList = UtilXml.childElementList(deletedFromSoldElement, "OrderTransactionArray");
                Iterator<? extends Element> orderTransactionArrayElemIter = orderTransactionArrayList.iterator();
                while (orderTransactionArrayElemIter.hasNext()) {
                    Element orderTransactionArrayElement = orderTransactionArrayElemIter.next();
                    List<? extends Element> orderTransactionList = UtilXml.childElementList(orderTransactionArrayElement, "OrderTransaction");
                    Iterator<? extends Element> orderTransactionElemIter = orderTransactionList.iterator();
                    while (orderTransactionElemIter.hasNext()) {
                        Element orderTransactionElement = orderTransactionElemIter.next();

                        List<? extends Element> sellerOrderList = UtilXml.childElementList(orderTransactionElement, "Order");
                        Iterator<? extends Element> sellerOrderElemIter = sellerOrderList.iterator();
                        while (sellerOrderElemIter.hasNext()) {
                            Element sellerOrderElement = sellerOrderElemIter.next();
                            String orderId = UtilXml.childElementValue(sellerOrderElement, "OrderID");
                            if (UtilValidate.isNotEmpty(orderId)) {
                                fetchDeletedOrdersAndTransactions.add(orderId);
                            }
                        }
                        List<? extends Element> transactionList = UtilXml.childElementList(orderTransactionElement, "Transaction");
                        Iterator<? extends Element> transactionElemIter = transactionList.iterator();
                        while (transactionElemIter.hasNext()) {
                            Element transactionElement = transactionElemIter.next();

                            List<? extends Element> itemList = UtilXml.childElementList(transactionElement, "Item");
                            Iterator<? extends Element> itemElemIter = itemList.iterator();
                            while (itemElemIter.hasNext()) {
                                Element itemElement = itemElemIter.next();
                                String itemId = UtilXml.childElementValue(itemElement, "ItemID");
                                if (UtilValidate.isNotEmpty(itemId)) {
                                    fetchDeletedOrdersAndTransactions.add(itemId);
                                }
                            }
                        }
                    }
                }
            }
        } else {
            List<? extends Element> errorList = UtilXml.childElementList(elemResponse, "Errors");
            Iterator<? extends Element> errorElemIter = errorList.iterator();
            while (errorElemIter.hasNext()) {
                Element errorElement = errorElemIter.next();
                errorMessage.append(UtilXml.childElementValue(errorElement, "ShortMessage", ""));
            }
        }
        return fetchDeletedOrdersAndTransactions;
    }

    private static Map<String, Object> createShoppingCart(Delegator delegator, LocalDispatcher dispatcher, Locale locale,
            Map<String, Object> context, boolean create) {
        try {
            String productStoreId = (String) context.get("productStoreId");
            GenericValue userLogin = (GenericValue) context.get("userLogin");
            String defaultCurrencyUomId = null;
            String payToPartyId = null;
            String facilityId = null;

            // Product Store is mandatory
            if (productStoreId == null) {
                return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "ordersImportFromEbay.productStoreIdIsMandatory", locale));
            } else {
                GenericValue productStore = EntityQuery.use(delegator).from("ProductStore").where("productStoreId", productStoreId).queryOne();
                if (productStore != null) {
                    defaultCurrencyUomId = productStore.getString("defaultCurrencyUomId");
                    payToPartyId = productStore.getString("payToPartyId");
                    facilityId = productStore.getString("inventoryFacilityId");
                } else {
                    return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "ordersImportFromEbay.productStoreIdIsMandatory", locale));
                }
            }

            // create a new shopping cart
            ShoppingCart cart = new ShoppingCart(delegator, productStoreId, locale, defaultCurrencyUomId);

            // set the external id with the eBay Item Id
            String externalId = (String) context.get("externalId");
            String transactionId = (String) context.get("transactionId");

            if (UtilValidate.isNotEmpty(externalId)) {
                if (externalOrderExists(delegator, externalId) != null && create) {
                    return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "ordersImportFromEbay.externalIdAlreadyExist", locale));
                }
                cart.setExternalId(externalId);
                cart.setTransactionId(transactionId);
            } else {
                return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "ordersImportFromEbay.externalIdNotAvailable", locale));
            }

            cart.setOrderType("SALES_ORDER");
            cart.setChannelType("EBAY_SALES_CHANNEL");
            cart.setUserLogin(userLogin, dispatcher);
            cart.setProductStoreId(productStoreId);

            if (UtilValidate.isNotEmpty(facilityId)) {
                cart.setFacilityId(facilityId);
            }
            String amountStr = (String) context.get("amountPaid");
            BigDecimal amountPaid = BigDecimal.ZERO;

            if (UtilValidate.isNotEmpty(amountStr)) {
                amountPaid = new BigDecimal(amountStr);
            }
            // add the payment EXT_BAY for the paid amount
            cart.addPaymentAmount("EXT_EBAY", amountPaid, externalId, null, true, false, false);

            // set the order date with the eBay created date
            Timestamp orderDate = UtilDateTime.nowTimestamp();
            if (UtilValidate.isNotEmpty(context.get("createdDate"))) {
                orderDate = UtilDateTime.toTimestamp((String) context.get("createdDate"));
            }
            cart.setOrderDate(orderDate);
            // Before import the order from eBay to OFBiz is mandatory that the payment has be received
            String paidTime = (String) context.get("paidTime");
            if (UtilValidate.isEmpty(paidTime)) {
                return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "ordersImportFromEbay.paymentIsStillNotReceived", locale));
            }

            List<Map<String, Object>> orderItemList = UtilGenerics.cast(context.get("orderItemList"));
            Iterator<Map<String, Object>> orderItemIter = orderItemList.iterator();
            while (orderItemIter.hasNext()) {
                Map<String, Object> orderItem = orderItemIter.next();
                addItem(cart, orderItem, dispatcher, delegator, 0);
            }

            // set partyId from
            if (UtilValidate.isNotEmpty(payToPartyId)) {
                cart.setBillFromVendorPartyId(payToPartyId);
            }
            // Apply shipping costs as order adjustment
            Map<String, Object> shippingServiceSelectedCtx = UtilGenerics.cast(context.get("shippingServiceSelectedCtx"));

            String shippingCost = (String) shippingServiceSelectedCtx.get("shippingServiceCost");
            if (UtilValidate.isNotEmpty(shippingCost)) {
                double shippingAmount = Double.parseDouble(shippingCost);
                if (shippingAmount > 0) {
                    GenericValue shippingAdjustment = EbayHelper.makeOrderAdjustment(delegator, "SHIPPING_CHARGES", cart.getOrderId(), null, null,
                            shippingAmount, 0.0);
                    if (shippingAdjustment != null) {
                        cart.addAdjustment(shippingAdjustment);
                    }
                }
            }
            // Apply additional shipping costs as order adjustment
            String shippingTotalAdditionalCost = (String) shippingServiceSelectedCtx.get("shippingTotalAdditionalCost");
            if (UtilValidate.isNotEmpty(shippingTotalAdditionalCost)) {
                double shippingAdditionalCost = Double.parseDouble(shippingTotalAdditionalCost);
                if (shippingAdditionalCost > 0) {
                    GenericValue shippingAdjustment = EbayHelper.makeOrderAdjustment(delegator, "MISCELLANEOUS_CHARGE", cart.getOrderId(), null,
                            null, shippingAdditionalCost, 0.0);
                    if (shippingAdjustment != null) {
                        cart.addAdjustment(shippingAdjustment);
                    }
                }
            }
            // Apply sales tax as order adjustment
            Map<String, Object> shippingDetailsCtx = UtilGenerics.cast(context.get("shippingDetailsCtx"));
            String salesTaxAmount = (String) shippingDetailsCtx.get("salesTaxAmount");
            String salesTaxPercent = (String) shippingDetailsCtx.get("salesTaxPercent");
            if (UtilValidate.isNotEmpty(salesTaxAmount)) {
                double salesTaxAmountTotal = Double.parseDouble(salesTaxAmount);
                if (salesTaxAmountTotal > 0) {
                    double salesPercent = 0.0;
                    if (UtilValidate.isNotEmpty(salesTaxPercent)) {
                        salesPercent = Double.parseDouble(salesTaxPercent);
                    }
                    GenericValue salesTaxAdjustment = EbayHelper.makeOrderAdjustment(delegator, "SALES_TAX", cart.getOrderId(), null, null,
                            salesTaxAmountTotal, salesPercent);
                    if (salesTaxAdjustment != null) {
                        cart.addAdjustment(salesTaxAdjustment);
                    }
                }
            }
            // order has to be created ?
            if (create) {
                Debug.logInfo("Importing new order from eBay", MODULE);
                // set partyId to
                String partyId = null;
                String contactMechId = null;

                Map<String, Object> shippingAddressCtx = UtilGenerics.cast(context.get("shippingAddressCtx"));
                if (UtilValidate.isNotEmpty(shippingAddressCtx)) {
                    String buyerName = (String) shippingAddressCtx.get("buyerName");
                    String firstName = buyerName.substring(0, buyerName.indexOf(" "));
                    String lastName = buyerName.substring(buyerName.indexOf(" ") + 1);

                    String country = (String) shippingAddressCtx.get("shippingAddressCountry");
                    String state = (String) shippingAddressCtx.get("shippingAddressStateOrProvince");
                    String city = (String) shippingAddressCtx.get("shippingAddressCityName");
                    EbayHelper.correctCityStateCountry(dispatcher, shippingAddressCtx, city, state, country);

                    List<GenericValue> shipInfo =
                            PartyWorker.findMatchingPersonPostalAddresses(delegator,
                                shippingAddressCtx.get("shippingAddressStreet1").toString(), (
                                UtilValidate.isEmpty(shippingAddressCtx.get("shippingAddressStreet2")) ? null : shippingAddressCtx.get(
                                            "shippingAddressStreet2").toString()),
                                shippingAddressCtx.get("city").toString(), (
                                UtilValidate.isEmpty(shippingAddressCtx.get("stateProvinceGeoId")) ? null : shippingAddressCtx.get(
                                        "stateProvinceGeoId").toString()),
                            shippingAddressCtx.get("shippingAddressPostalCode").toString(),
                            null, shippingAddressCtx.get("countryGeoId").toString(), firstName, null, lastName);
                    if (UtilValidate.isNotEmpty(shipInfo)) {
                        GenericValue first = EntityUtil.getFirst(shipInfo);
                        partyId = first.getString("partyId");
                        Debug.logInfo("Existing shipping address found for : (party: " + partyId + ")", MODULE);
                    }
                }

                // If matching party not found then try to find partyId from PartyAttribute entity.
                GenericValue partyAttribute = null;
                if (UtilValidate.isNotEmpty(context.get("eiasTokenBuyer"))) {
                    partyAttribute = EntityQuery.use(delegator).from("PartyAttribute").where("attrValue", context.get("eiasTokenBuyer")).queryFirst();
                    if (UtilValidate.isNotEmpty(partyAttribute)) {
                        partyId = (String) partyAttribute.get("partyId");
                    }
                }

                // if we get a party, check its contact information.
                if (UtilValidate.isNotEmpty(partyId)) {
                    Debug.logInfo("Found existing party associated to the eBay buyer: " + partyId, MODULE);
                    GenericValue party = EntityQuery.use(delegator).from("Party").where("partyId", partyId).queryOne();

                    contactMechId = EbayHelper.setShippingAddressContactMech(dispatcher, delegator, party, userLogin, shippingAddressCtx);
                    String emailBuyer = (String) context.get("emailBuyer");
                    if (!("".equals(emailBuyer) || "Invalid Request".equalsIgnoreCase(emailBuyer))) {
                        EbayHelper.setEmailContactMech(dispatcher, delegator, party, userLogin, context);
                    }
                    EbayHelper.setPhoneContactMech(dispatcher, delegator, party, userLogin, shippingAddressCtx);
                }

                // create party if none exists already
                if (UtilValidate.isEmpty(partyId)) {
                    Debug.logInfo("Creating new party for the eBay buyer.", MODULE);
                    partyId = EbayHelper.createCustomerParty(dispatcher, (String) shippingAddressCtx.get("buyerName"), userLogin);
                    if (UtilValidate.isEmpty(partyId)) {
                        Debug.logWarning("Using admin party for the eBay buyer.", MODULE);
                        partyId = "admin";
                    }
                }

                // create new party's contact information
                if (UtilValidate.isEmpty(contactMechId)) {
                    Map<String, Object> buyerCtx = UtilGenerics.cast(context.get("buyerCtx"));
                    String eiasTokenBuyer = null;
                    if (UtilValidate.isNotEmpty(buyerCtx)) {
                        eiasTokenBuyer = (String) buyerCtx.get("eiasTokenBuyer");
                    }
                    Debug.logInfo("Creating new postal address for party: " + partyId, MODULE);
                    contactMechId = EbayHelper.createAddress(dispatcher, partyId, userLogin, "SHIPPING_LOCATION", shippingAddressCtx);
                    if (UtilValidate.isEmpty(contactMechId)) {
                        return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "EbayStoreUnableToCreatePostalAddress", locale)
                                + shippingAddressCtx);
                    }
                    Debug.logInfo("Created postal address: " + contactMechId, MODULE);
                    Debug.logInfo("Creating new phone number for party: " + partyId, MODULE);
                    EbayHelper.createPartyPhone(dispatcher, partyId, (String) shippingAddressCtx.get("shippingAddressPhone"), userLogin);
                    Debug.logInfo("Creating association to eBay buyer for party: " + partyId, MODULE);
                    EbayHelper.createEbayCustomer(dispatcher, partyId, (String) context.get("ebayUserIdBuyer"), eiasTokenBuyer, userLogin);
                    String emailBuyer = (String) context.get("emailBuyer");
                    if (UtilValidate.isNotEmpty(emailBuyer) && !"Invalid Request".equalsIgnoreCase(emailBuyer)) {
                        Debug.logInfo("Creating new email for party: " + partyId, MODULE);
                        EbayHelper.createPartyEmail(dispatcher, partyId, emailBuyer, userLogin);
                    }
                }

                Debug.logInfo("Setting cart roles for party: " + partyId, MODULE);
                cart.setBillToCustomerPartyId(partyId);
                cart.setPlacingCustomerPartyId(partyId);
                cart.setShipToCustomerPartyId(partyId);
                cart.setEndUserCustomerPartyId(partyId);

                Debug.logInfo("Setting contact mech in cart: " + contactMechId, MODULE);
                cart.setAllShippingContactMechId(contactMechId);
                cart.setAllMaySplit(Boolean.FALSE);

                Debug.logInfo("Setting shipment method: " + (String) shippingServiceSelectedCtx.get("shippingService"), MODULE);
                EbayHelper.setShipmentMethodType(cart, (String) shippingServiceSelectedCtx.get("shippingService"), productStoreId, delegator);
                cart.makeAllShipGroupInfos(dispatcher);

                // create the order
                Debug.logInfo("Creating CheckOutHelper.", MODULE);
                CheckOutHelper checkout = new CheckOutHelper(dispatcher, delegator, cart);
                Debug.logInfo("Creating order.", MODULE);
                Map<?, ?> orderCreate = checkout.createOrder(userLogin);

                if ("error".equals(orderCreate.get("responseMessage"))) {
                    List<String> errorMessageList = UtilGenerics.checkCollection(orderCreate.get("errorMessageList"), String.class);
                    return ServiceUtil.returnError(errorMessageList);
                }
                String orderId = (String) orderCreate.get("orderId");
                Debug.logInfo("Created order with id: " + orderId, MODULE);

                if (UtilValidate.isNotEmpty(orderId)) {
                    String orderCreatedMsg = "Order created successfully with ID (" + orderId + ") & eBay Order ID associated with this order is ("
                            + externalId + ").";
                    orderImportSuccessMessageList.add(orderCreatedMsg);
                }

                // approve the order
                if (UtilValidate.isNotEmpty(orderId)) {
                    Debug.logInfo("Approving order with id: " + orderId, MODULE);
                    boolean approved = OrderChangeHelper.approveOrder(dispatcher, userLogin, orderId);
                    Debug.logInfo("Order approved with result: " + approved, MODULE);

                    // create the payment from the preference
                    if (approved) {
                        Debug.logInfo("Creating payment for approved order.", MODULE);
                        EbayHelper.createPaymentFromPaymentPreferences(delegator, dispatcher, userLogin, orderId, externalId, cart.getOrderDate(),
                                amountPaid, partyId);
                        Debug.logInfo("Payment created.", MODULE);
                    }
                }
            }
        } catch (Exception e) {
            Debug.logError("Exception in createShoppingCart: " + e.getMessage(), MODULE);
            return ServiceUtil.returnFailure(UtilProperties.getMessage(RESOURCE, "ordersImportFromEbay.exceptionInCreateShoppingCart", locale) + ":"
                    + " " + e.getMessage());
        }
        return ServiceUtil.returnSuccess();
    }

    // Made some changes transactionId removed.
    private static GenericValue externalOrderExists(Delegator delegator, String externalId) throws GenericEntityException {
        Debug.logInfo("Checking for existing externalId: " + externalId, MODULE);
        EntityCondition condition = EntityCondition.makeCondition(UtilMisc.toList(EntityCondition.makeCondition("externalId",
                EntityComparisonOperator.EQUALS, externalId), EntityCondition.makeCondition("statusId", EntityComparisonOperator.NOT_EQUAL,
                        "ORDER_CANCELLED")), EntityComparisonOperator.AND);
        GenericValue orderHeader = EntityQuery.use(delegator).from("OrderHeader").where(condition).cache(true).queryFirst();
        return orderHeader;
    }

    private static void addItem(ShoppingCart cart, Map<String, Object> orderItem, LocalDispatcher dispatcher, Delegator delegator, int groupIdx)
            throws GeneralException {
        String productId = (String) orderItem.get("productId");
        GenericValue product = EntityQuery.use(delegator).from("Product").where("productId", productId).queryOne();
        if (UtilValidate.isEmpty(product)) {
            String productMissingMsg = "The product having ID (" + productId + ") is misssing in the system.";
            orderImportFailureMessageList.add(productMissingMsg);
        }
        BigDecimal qty = new BigDecimal(orderItem.get("quantity").toString());
        String itemPrice = (String) orderItem.get("transactionPrice");
        if (UtilValidate.isEmpty(itemPrice)) {
            itemPrice = (String) orderItem.get("amount");
        }
        BigDecimal price = new BigDecimal(itemPrice);
        price = price.setScale(DECIMALS, ROUNDING);

        HashMap<String, Object> attrs = new HashMap<>();
        attrs.put("shipGroup", groupIdx);

        // Checking if previously added same product exists in the cart
        ShoppingCartItem previouslyAddedItemInCart = null;
        if (cart.size() != 0) {
            Iterator<ShoppingCartItem> cartiter = cart.iterator();
            while (cartiter != null && cartiter.hasNext()) {
                ShoppingCartItem cartItem = cartiter.next();
                if (cartItem.getProductId().equals(productId)) {
                    previouslyAddedItemInCart = cartItem;
                }
            }
        }
        if (previouslyAddedItemInCart != null) {
            BigDecimal newQuantity = previouslyAddedItemInCart.getQuantity().add(qty);
            previouslyAddedItemInCart.setQuantity(newQuantity, dispatcher, cart);
        } else {
            int idx = cart.addItemToEnd(productId, null, qty, null, null, attrs, null, null, dispatcher, Boolean.FALSE, Boolean.TRUE, Boolean.TRUE,
                    Boolean.TRUE);
            ShoppingCartItem cartItem = cart.findCartItem(idx);
            cartItem.setQuantity(qty, dispatcher, cart, true, false);
            // locate the price verify it matches the expected price
            BigDecimal cartPrice = cartItem.getBasePrice();
            cartPrice = cartPrice.setScale(DECIMALS, ROUNDING);
            if (price.doubleValue() != cartPrice.doubleValue()) {
                // does not match; honor the price but hold the order for manual review
                cartItem.setIsModifiedPrice(true);
                cartItem.setBasePrice(price);
                cart.setHoldOrder(true);
                cart.addInternalOrderNote("Price received [" + price + "] (for item # " + productId
                        + ") from eBay Checkout does not match the price in the database [" + cartPrice + "]. Order is held for manual review.");
            }
            // assign the item to its ship group
            cart.setItemShipGroupQty(cartItem, qty, groupIdx);
        }
    }
}
