Author: sichen
Date: Mon Apr 16 15:39:18 2007 New Revision: 529422 URL: http://svn.apache.org/viewvc?view=rev&rev=529422 Log: UPS Support for: Insured package value; Third-party shipper payment; COD - Insured package value controlled by a new ShipmentPackage.insuredValue field and UI in EditShipmentPackages screen - Third-party shipper payment controlled by new ShipmentRouteSegment.thirdPartyAccountNumber and ShipmentRouteSegment.thirdPartyContactMechId fields, and UI in EditShipmentRouteSegments screen - COD controlled by properties in shipment.properties and this assumption: If all items in a shipment package come from orders which were paid ONLY with EXT_COD, then the package is a COD package - COD surcharge amount defined in shipment.properties and split (or not) between packages, and converted to the shipment currency if necessary - Package value for COD is calculated using the getShipmentPackageValueFromOrders service, which calculates the value of each shipment package item by prorating the value of the order item (as determined by the getOrderItemValue service) via packed quantity vs. ordered quantity, for each item of the shipment - converting to the shipment currency if necessary - Providing a 'Residential Delivery' checkbox in the EditShipmentRouteSegments screen for UPS shipments so that UPS Voice Notification service will be requested automatically if checked (and a destination telecom contactMechId is provided) Modified: ofbiz/trunk/applications/product/config/ProductUiLabels.properties ofbiz/trunk/applications/product/config/shipment.properties ofbiz/trunk/applications/product/entitydef/entitygroup.xml ofbiz/trunk/applications/product/entitydef/entitymodel_shipment.xml ofbiz/trunk/applications/product/servicedef/services_shipment.xml ofbiz/trunk/applications/product/src/org/ofbiz/shipment/shipment/ShipmentServices.java ofbiz/trunk/applications/product/src/org/ofbiz/shipment/thirdparty/ups/UpsServices.java ofbiz/trunk/applications/product/webapp/facility/WEB-INF/actions/shipment/EditShipmentRouteSegments.bsh ofbiz/trunk/applications/product/webapp/facility/shipment/EditShipmentPackages.ftl ofbiz/trunk/applications/product/webapp/facility/shipment/EditShipmentRouteSegments.ftl Modified: ofbiz/trunk/applications/product/config/ProductUiLabels.properties URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/config/ProductUiLabels.properties?view=diff&rev=529422&r1=529421&r2=529422 ============================================================================== --- ofbiz/trunk/applications/product/config/ProductUiLabels.properties (original) +++ ofbiz/trunk/applications/product/config/ProductUiLabels.properties Mon Apr 16 15:39:18 2007 @@ -1203,6 +1203,7 @@ ProductShipmentFedexHomeEvening=Evening ProductShipmentFedexHomeAppointment=Appointment ProductShipmentId=Shipment Id +ProductShipmentInsuredValuePackage=Insured Value ProductShipmentItemSeqId=Shipment Item Seq Id ProductShipmentManifest=Manifest for Shipment ProductShipmentMethod=Shipment Method @@ -1210,15 +1211,19 @@ ProductShipmentMethodTypes=Shipment Method Types ProductShipmentNone=None ProductShipmentNotFoundId=The Shipment was not found with ID +ProductShipmentPackageNotFound=shipmentPackageSeqId [${shipmentPackageSeqId}] was not found in shipment with ID [${shipmentId}] ProductShipmentPlan=Shipment Plan ProductShipmentPlanToOrderItems=Shipment Plan --> Order Items ProductShipmentQuickComplete=Quick Complete Drop Shipment +ProductShipmentThirdPartyAccountNumber=Third Party Account Number +ProductShipmentThirdPartyAddress=Third Party Account Address ID ProductShipmentTotalWeight=Total Weight ProductShipmentTotalVolume=Total Volume ProductShipmentType=Shipment Type ProductShipmentTypeId=Shipment type Id ProductShipmentUomAbbreviation_WT_lb=lbs ProductShipmentUomAbbreviation_WT_kg=kg +ProductShipmentUpsResidential=Residential Delivery ProductShipments=Shipments ProductShipmentsFound=Shipments Found ProductShipping=Shipping Modified: ofbiz/trunk/applications/product/config/shipment.properties URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/config/shipment.properties?view=diff&rev=529422&r1=529421&r2=529422 ============================================================================== --- ofbiz/trunk/applications/product/config/shipment.properties (original) +++ ofbiz/trunk/applications/product/config/shipment.properties Mon Apr 16 15:39:18 2007 @@ -72,6 +72,28 @@ # minimum be equal to the value below. shipment.ups.min.estimate.weight=.1 +#ÊCOD Surcharge +#ÊWill be applied if shipment.ups.cod.applyCODSurcharge is true and all shipment package items +#Êare from orders which have been fully paid via EXT_COD +shipment.ups.cod.applyCODSurcharge=true +shipment.ups.cod.surcharge.amount=9 +shipment.ups.cod.surcharge.currencyUomId=USD + +#Êshipment.ups.cod.surcharge.applyToPackages: +#Êall - surcharge amount will be applied to each shipment package +#Êfirst - surcharge amount will be applied to the first package in the shipment +#Êsplit - surcharge amount will be split between shipment packages (fractional cents are rounded +#Ê via symmetric arithmetic rounding) +shipment.ups.cod.surcharge.applyToPackages=first + +#ÊCODFundsCode +#ÊThe code that indicates the type of funds used for the COD payment. +#ÊFor package-level COD: +#Ê0 = Unsecured funds allowed (check, cashier's check or money order - no cash allowed) +#Ê8 = Secured Funds only (cashier's check or money order - no cash allowed) +#ÊShipment-level COD: Not supported +shipment.ups.cod.codFundsCode=0 + ############################################ # USPS Webtools API Configuration ############################################ Modified: ofbiz/trunk/applications/product/entitydef/entitygroup.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/entitydef/entitygroup.xml?view=diff&rev=529422&r1=529421&r2=529422 ============================================================================== --- ofbiz/trunk/applications/product/entitydef/entitygroup.xml (original) +++ ofbiz/trunk/applications/product/entitydef/entitygroup.xml Mon Apr 16 15:39:18 2007 @@ -324,5 +324,6 @@ <entity-group group="org.ofbiz" entity="ShipmentType" /> <entity-group group="org.ofbiz" entity="ShipmentTypeAttr" /> <entity-group group="org.ofbiz" entity="ShippingDocument" /> + <entity-group group="org.ofbiz" entity="PackedQtyVsOrderItemQuantity" /> </entitygroup> Modified: ofbiz/trunk/applications/product/entitydef/entitymodel_shipment.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/entitydef/entitymodel_shipment.xml?view=diff&rev=529422&r1=529421&r2=529422 ============================================================================== --- ofbiz/trunk/applications/product/entitydef/entitymodel_shipment.xml (original) +++ ofbiz/trunk/applications/product/entitydef/entitymodel_shipment.xml Mon Apr 16 15:39:18 2007 @@ -997,6 +997,7 @@ <field name="dateCreated" type="date-time"></field> <field name="weight" type="floating-point"></field> <field name="weightUomId" type="id"></field> + <field name="insuredValue" type="currency-amount"></field> <prim-key field="shipmentId"/> <prim-key field="shipmentPackageSeqId"/> <relation type="one" fk-name="SHPKG_SHPMNT" rel-entity-name="Shipment"> @@ -1110,6 +1111,8 @@ <field name="lastUpdatedDate" type="date-time"></field> <field name="homeDeliveryType" type="id"></field> <field name="homeDeliveryDate" type="date-time"></field> + <field name="thirdPartyAccountNumber" type="id"></field> + <field name="thirdPartyContactMechId" type="id"></field> <prim-key field="shipmentId"/> <prim-key field="shipmentRouteSegmentId"/> <relation type="one" fk-name="SHPMT_RTSEG_SHPMT" rel-entity-name="Shipment"> @@ -1163,6 +1166,9 @@ <relation type="one" fk-name="SHPKRTSG_BWUOM" title="BillingWeight" rel-entity-name="Uom"> <key-map field-name="billingWeightUomId" rel-field-name="uomId"/> </relation> + <relation type="one" fk-name="SHPMT_RTSEG_TPPAD" title="ThirdParty" rel-entity-name="PostalAddress"> + <key-map field-name="thirdPartyContactMechId" rel-field-name="contactMechId"/> + </relation> </entity> <view-entity entity-name="ShipmentPackageRouteDetail" package-name="org.ofbiz.shipment.shipment" @@ -1274,5 +1280,32 @@ <key-map field-name="shipmentPackageSeqId"/> </relation> </entity> + + <view-entity entity-name="PackedQtyVsOrderItemQuantity" + package-name="org.ofbiz.shipment.shipment" + title="Shipment Route Segment Detail View Entity"> + <description>View to report ShipmentPackageContent quantity vs. OrderItem quantity via + ItemIssuance</description> + <member-entity entity-alias="SPC" entity-name="ShipmentPackageContent"/> + <member-entity entity-alias="II" entity-name="ItemIssuance"/> + <member-entity entity-alias="OI" entity-name="OrderItem"/> + <alias entity-alias="SPC" name="shipmentId"/> + <alias entity-alias="SPC" name="shipmentPackageSeqId"/> + <alias entity-alias="SPC" name="packedQuantity" field="quantity"/> + <alias entity-alias="OI" name="orderId"/> + <alias entity-alias="OI" name="orderItemSeqId"/> + <alias entity-alias="OI" name="orderedQuantity" field="quantity"/> + <view-link entity-alias="SPC" rel-entity-alias="II"> + <key-map field-name="shipmentId"/> + <key-map field-name="shipmentItemSeqId"/> + </view-link> + <view-link entity-alias="II" rel-entity-alias="OI"> + <key-map field-name="orderId"/> + <key-map field-name="orderItemSeqId"/> + </view-link> + <relation type="one" rel-entity-name="OrderHeader"> + <key-map field-name="orderId"/> + </relation> + </view-entity> </entitymodel> Modified: ofbiz/trunk/applications/product/servicedef/services_shipment.xml URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/servicedef/services_shipment.xml?view=diff&rev=529422&r1=529421&r2=529422 ============================================================================== --- ofbiz/trunk/applications/product/servicedef/services_shipment.xml (original) +++ ofbiz/trunk/applications/product/servicedef/services_shipment.xml Mon Apr 16 15:39:18 2007 @@ -645,4 +645,16 @@ <description>Delete a QuantityBreak</description> <auto-attributes entity-name="QuantityBreak" include="pk" mode="IN" optional="false"/> </service> + + <service name="getShipmentPackageValueFromOrders" engine="java" + location="org.ofbiz.shipment.shipment.ShipmentServices" invoke="getShipmentPackageValueFromOrders" auth="true"> + <description>Calculates the total value of a shipment package by totalling the results of the getOrderItemValue service + for the orderItem related to each ShipmentPackageContent, prorated by the quantity of the orderItem packed in the + ShipmentPackageContent. Value is converted according to the incoming currencyUomId.</description> + <attribute name="shipmentId" type="String" mode="IN" optional="false"/> + <attribute name="shipmentPackageSeqId" type="String" mode="IN" optional="false"/> + <attribute name="currencyUomId" type="String" mode="IN" optional="false"/> + <attribute name="packageValue" type="BigDecimal" mode="OUT" optional="true"/> + </service> + </services> Modified: ofbiz/trunk/applications/product/src/org/ofbiz/shipment/shipment/ShipmentServices.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/src/org/ofbiz/shipment/shipment/ShipmentServices.java?view=diff&rev=529422&r1=529421&r2=529422 ============================================================================== --- ofbiz/trunk/applications/product/src/org/ofbiz/shipment/shipment/ShipmentServices.java (original) +++ ofbiz/trunk/applications/product/src/org/ofbiz/shipment/shipment/ShipmentServices.java Mon Apr 16 15:39:18 2007 @@ -19,13 +19,11 @@ package org.ofbiz.shipment.shipment; import java.util.*; +import java.math.BigDecimal; import javolution.util.FastMap; -import org.ofbiz.base.util.Debug; -import org.ofbiz.base.util.StringUtil; -import org.ofbiz.base.util.UtilMisc; -import org.ofbiz.base.util.UtilValidate; +import org.ofbiz.base.util.*; import org.ofbiz.common.geo.GeoWorker; import org.ofbiz.entity.GenericDelegator; import org.ofbiz.entity.GenericEntityException; @@ -45,6 +43,11 @@ public static final String module = ShipmentServices.class.getName(); + public static final String resource = "ProductUiLabels"; + public static final int decimals = UtilNumber.getBigDecimalScale("order.decimals"); + public static final int rounding = UtilNumber.getBigDecimalRoundingMode("order.rounding"); + public static final BigDecimal ZERO = (new BigDecimal("0")).setScale(decimals, rounding); + public static Map createShipmentEstimate(DispatchContext dctx, Map context) { Map result = new HashMap(); GenericDelegator delegator = dctx.getDelegator(); @@ -943,5 +946,87 @@ // don't return an error return ServiceUtil.returnSuccess(); + } + + /** + * Calculates the total value of a shipment package by totalling the results of the getOrderItemValue service + * for the orderItem related to each ShipmentPackageContent, prorated by the quantity of the orderItem packed in the + * ShipmentPackageContent. Value is converted according to the incoming currencyUomId. + * @param dctx DispatchContext + * @param context Map + * @return Map + */ + public static Map getShipmentPackageValueFromOrders(DispatchContext dctx, Map context) { + LocalDispatcher dispatcher = dctx.getDispatcher(); + GenericDelegator delegator = dctx.getDelegator(); + GenericValue userLogin = (GenericValue) context.get("userLogin"); + Locale locale = (Locale) context.get("locale"); + + String shipmentId = (String) context.get("shipmentId"); + String shipmentPackageSeqId = (String) context.get("shipmentPackageSeqId"); + String currencyUomId = (String) context.get("currencyUomId"); + + BigDecimal packageTotalValue = ZERO; + + GenericValue shipment = null; + GenericValue shipmentPackage = null; + try { + + shipment = delegator.findByPrimaryKey("Shipment", UtilMisc.toMap("shipmentId", shipmentId)); + if (UtilValidate.isEmpty(shipment)) { + String errorMessage = UtilProperties.getMessage(resource, "ProductShipmentNotFoundId", locale); + Debug.logError(errorMessage, module); + return ServiceUtil.returnError(errorMessage); + } + + shipmentPackage = delegator.findByPrimaryKey("ShipmentPackage", UtilMisc.toMap("shipmentId", shipmentId, "shipmentPackageSeqId", shipmentPackageSeqId)); + if (UtilValidate.isEmpty(shipmentPackage)) { + String errorMessage = UtilProperties.getMessage(resource, "ProductShipmentPackageNotFound", context, locale); + Debug.logError(errorMessage, module); + return ServiceUtil.returnError(errorMessage); + } + + List packageContents = delegator.findByAnd("PackedQtyVsOrderItemQuantity", UtilMisc.toMap("shipmentId", shipmentId, "shipmentPackageSeqId", shipmentPackageSeqId)); + Iterator packageContentsIt = packageContents.iterator(); + while (packageContentsIt.hasNext()) { + GenericValue packageContent = (GenericValue) packageContentsIt.next(); + String orderId = packageContent.getString("orderId"); + String orderItemSeqId = packageContent.getString("orderItemSeqId"); + + // Get the value of the orderItem by calling the getOrderItemValue service + Map getOrderItemValueResult = dispatcher.runSync("getOrderItemValue", UtilMisc.toMap("orderId", orderId, "orderItemSeqId", orderItemSeqId, "userLogin", userLogin, "locale", locale)); + if (ServiceUtil.isError(getOrderItemValueResult)) return getOrderItemValueResult; + BigDecimal orderItemTotalValue = (BigDecimal) getOrderItemValueResult.get("orderItemValue"); + + // How much of the orderItem does the packed item represent? + BigDecimal packedQuantity = packageContent.getBigDecimal("packedQuantity"); + BigDecimal orderedQuantity = packageContent.getBigDecimal("orderedQuantity"); + BigDecimal proportionOfOrderedQuantity = packedQuantity.divide(orderedQuantity, 10, rounding); + + // Prorate the orderItem's value by that proportion + BigDecimal packageContentValue = proportionOfOrderedQuantity.multiply(orderItemTotalValue).setScale(decimals, rounding); + + // Convert the value to the shipment currency, if necessary + GenericValue orderHeader = packageContent.getRelatedOne("OrderHeader"); + Map convertUomResult = dispatcher.runSync("convertUom", UtilMisc.toMap("uomId", orderHeader.getString("currencyUom"), "uomIdTo", currencyUomId, "originalValue", new Double(packageContentValue.doubleValue()))); + if (ServiceUtil.isError(convertUomResult)) return convertUomResult; + if (convertUomResult.containsKey("convertedValue")) { + packageContentValue = new BigDecimal(((Double) convertUomResult.get("convertedValue")).doubleValue()).setScale(decimals, rounding); + } + + // Add the value of the packed item to the package's total value + packageTotalValue = packageTotalValue.add(packageContentValue); + } + + } catch (GenericEntityException e) { + Debug.logError(e, module); + return ServiceUtil.returnError(e.getMessage()); + } catch (GenericServiceException e) { + Debug.logError(e, module); + return ServiceUtil.returnError(e.getMessage()); + } + Map result = ServiceUtil.returnSuccess(); + result.put("packageValue", packageTotalValue); + return result; } } Modified: ofbiz/trunk/applications/product/src/org/ofbiz/shipment/thirdparty/ups/UpsServices.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/src/org/ofbiz/shipment/thirdparty/ups/UpsServices.java?view=diff&rev=529422&r1=529421&r2=529422 ============================================================================== --- ofbiz/trunk/applications/product/src/org/ofbiz/shipment/thirdparty/ups/UpsServices.java (original) +++ ofbiz/trunk/applications/product/src/org/ofbiz/shipment/thirdparty/ups/UpsServices.java Mon Apr 16 15:39:18 2007 @@ -21,35 +21,20 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; +import java.util.*; +import java.math.BigDecimal; import javax.xml.parsers.ParserConfigurationException; import org.apache.velocity.test.MiscTestCase; -import org.ofbiz.base.util.Base64; -import org.ofbiz.base.util.Debug; -import org.ofbiz.base.util.GeneralException; -import org.ofbiz.base.util.HttpClient; -import org.ofbiz.base.util.HttpClientException; -import org.ofbiz.base.util.StringUtil; -import org.ofbiz.base.util.UtilMisc; -import org.ofbiz.base.util.UtilProperties; -import org.ofbiz.base.util.UtilValidate; -import org.ofbiz.base.util.UtilXml; +import org.ofbiz.base.util.*; import org.ofbiz.entity.GenericDelegator; import org.ofbiz.entity.GenericEntityException; import org.ofbiz.entity.GenericValue; +import org.ofbiz.entity.condition.EntityExpr; +import org.ofbiz.entity.condition.EntityOperator; import org.ofbiz.entity.util.EntityUtil; -import org.ofbiz.service.DispatchContext; -import org.ofbiz.service.GenericServiceException; -import org.ofbiz.service.ServiceDispatcher; -import org.ofbiz.service.ServiceUtil; +import org.ofbiz.service.*; import org.ofbiz.product.store.ProductStoreWorker; import org.w3c.dom.Document; @@ -75,11 +60,15 @@ unitsOfbizToUps.put(entry.getValue(), entry.getKey()); } } - + public static final int decimals = UtilNumber.getBigDecimalScale("order.decimals"); + public static final int rounding = UtilNumber.getBigDecimalRoundingMode("order.rounding"); public static Map upsShipmentConfirm(DispatchContext dctx, Map context) { Map result = new HashMap(); GenericDelegator delegator = dctx.getDelegator(); + LocalDispatcher dispatcher = dctx.getDispatcher(); + GenericValue userLogin = (GenericValue) context.get("userLogin"); + Locale locale = (Locale) context.get("locale"); String shipmentId = (String) context.get("shipmentId"); String shipmentRouteSegmentId = (String) context.get("shipmentRouteSegmentId"); @@ -200,6 +189,67 @@ ordersDescription = "Order " + (String) orderIdSet.iterator().next(); } + // COD Support + boolean applyCODSurcharge = "true".equalsIgnoreCase(UtilProperties.getPropertyValue("shipment", "shipment.ups.cod.applyCODSurcharge")); + + // COD only applies if all orders involved with the shipment were paid only with EXT_COD - anything else becomes too complicated + if (applyCODSurcharge) { + + // Get the paymentMethodTypeIds of all the orderPaymentPreferences involved with the shipment + List opps = delegator.findByCondition("OrderPaymentPreference", new EntityExpr("orderId", EntityOperator.IN, orderIdSet), null, null); + List paymentMethodTypeIds = EntityUtil.getFieldListFromEntityList(opps, "paymentMethodTypeId", true); + + if (paymentMethodTypeIds.size() > 1 || ! paymentMethodTypeIds.contains("EXT_COD")) { + applyCODSurcharge = false; + } + } + + String codSurchargeAmount = null; + String codSurchargeCurrencyUomId = null; + String codFundsCode = null; + + boolean codSurchargeApplyToFirstPackage = false; + boolean codSurchargeApplyToAllPackages = false; + boolean codSurchargeSplitBetweenPackages = false; + + BigDecimal codSurchargePackageAmount = null; + + if (applyCODSurcharge) { + + codSurchargeAmount = UtilProperties.getPropertyValue("shipment", "shipment.ups.cod.surcharge.amount"); + if (UtilValidate.isEmpty(codSurchargeAmount)) { + return ServiceUtil.returnError("shipment.ups.cod.surcharge.amount is not configured in shipment.properties"); + } + codSurchargeCurrencyUomId = UtilProperties.getPropertyValue("shipment", "shipment.ups.cod.surcharge.currencyUomId"); + if (UtilValidate.isEmpty(codSurchargeCurrencyUomId)) { + return ServiceUtil.returnError("shipment.ups.cod.surcharge.currencyUomId is not configured in shipment.properties"); + } + String codSurchargeApplyToPackages = UtilProperties.getPropertyValue("shipment", "shipment.ups.cod.surcharge.applyToPackages"); + if (UtilValidate.isEmpty(codSurchargeApplyToPackages)) { + return ServiceUtil.returnError("shipment.ups.cod.surcharge.applyToPackages is not configured in shipment.properties"); + } + codFundsCode = UtilProperties.getPropertyValue("shipment", "shipment.ups.cod.codFundsCode"); + if (UtilValidate.isEmpty(codFundsCode)) { + return ServiceUtil.returnError("shipment.ups.cod.codFundsCode is not configured in shipment.properties"); + } + + codSurchargeApplyToFirstPackage = "first".equalsIgnoreCase(codSurchargeApplyToPackages); + codSurchargeApplyToAllPackages = "all".equalsIgnoreCase(codSurchargeApplyToPackages); + codSurchargeSplitBetweenPackages = "split".equalsIgnoreCase(codSurchargeApplyToPackages); + + codSurchargePackageAmount = new BigDecimal(codSurchargeAmount).setScale(decimals, rounding); + if (codSurchargeSplitBetweenPackages) { + codSurchargePackageAmount = codSurchargePackageAmount.divide(new BigDecimal(shipmentPackageRouteSegs.size()), decimals, rounding); + } + + if (UtilValidate.isEmpty(destTelecomNumber)) { + Debug.logInfo("Voice notification service will not be requested for COD shipmentId " + shipmentId + ", shipmentRouteSegmentId " + shipmentRouteSegmentId + " - missing destination phone number", module); + } + if (UtilValidate.isEmpty(shipmentRouteSegment.get("homeDeliveryType"))) { + Debug.logInfo("Voice notification service will not be requested for COD shipmentId " + shipmentId + ", shipmentRouteSegmentId " + shipmentRouteSegmentId + " - destination address is not residential", module); + } + } + // Okay, start putting the XML together... Document shipmentConfirmRequestDoc = UtilXml.makeEmptyXmlDocument("ShipmentConfirmRequest"); Element shipmentConfirmRequestElement = shipmentConfirmRequestDoc.getDocumentElement(); @@ -267,6 +317,9 @@ UtilXml.addChildElementValue(shipToAddressElement, "StateProvinceCode", destPostalAddress.getString("stateProvinceGeoId"), shipmentConfirmRequestDoc); UtilXml.addChildElementValue(shipToAddressElement, "PostalCode", destPostalAddress.getString("postalCode"), shipmentConfirmRequestDoc); UtilXml.addChildElementValue(shipToAddressElement, "CountryCode", destCountryGeo.getString("geoCode"), shipmentConfirmRequestDoc); + if (UtilValidate.isNotEmpty(shipmentRouteSegment.getString("homeDeliveryType"))) { + UtilXml.addChildElement(shipToAddressElement, "ResidentialAddress", shipmentConfirmRequestDoc); + } // Child of Shipment: ShipFrom Element shipFromElement = UtilXml.addChildElement(shipmentElement, "ShipFrom", shipmentConfirmRequestDoc); @@ -286,17 +339,46 @@ // Child of Shipment: PaymentInformation Element paymentInformationElement = UtilXml.addChildElement(shipmentElement, "PaymentInformation", shipmentConfirmRequestDoc); - Element prepaidElement = UtilXml.addChildElement(paymentInformationElement, "Prepaid", shipmentConfirmRequestDoc); - Element billShipperElement = UtilXml.addChildElement(prepaidElement, "BillShipper", shipmentConfirmRequestDoc); - // fill in BillShipper AccountNumber element from properties file - UtilXml.addChildElementValue(billShipperElement, "AccountNumber", UtilProperties.getPropertyValue("shipment", "shipment.ups.bill.shipper.account.number"), shipmentConfirmRequestDoc); + + String thirdPartyAccountNumber = shipmentRouteSegment.getString("thirdPartyAccountNumber"); + + if (UtilValidate.isEmpty(thirdPartyAccountNumber)) { + + // Paid by shipper + Element prepaidElement = UtilXml.addChildElement(paymentInformationElement, "Prepaid", shipmentConfirmRequestDoc); + Element billShipperElement = UtilXml.addChildElement(prepaidElement, "BillShipper", shipmentConfirmRequestDoc); + + // fill in BillShipper AccountNumber element from properties file + UtilXml.addChildElementValue(billShipperElement, "AccountNumber", UtilProperties.getPropertyValue("shipment", "shipment.ups.bill.shipper.account.number"), shipmentConfirmRequestDoc); + } else { + + // Paid by another shipper (may be receiver or not) + GenericValue thirdPartyPostalAddress = shipmentRouteSegment.getRelatedOne("ThirdPartyPostalAddress"); + + // UPS requires the postal code and country code of the third party + if (UtilValidate.isEmpty(thirdPartyPostalAddress)) { + return ServiceUtil.returnError("ThirdPartyPostalAddress not found for ShipmentRouteSegment with shipmentId " + shipmentId + " and shipmentRouteSegmentId " + shipmentRouteSegmentId); + } + GenericValue thirdPartyCountryGeo = thirdPartyPostalAddress.getRelatedOne("CountryGeo"); + if (UtilValidate.isEmpty(thirdPartyCountryGeo)) { + return ServiceUtil.returnError("ThirdPartyCountryGeo not found for ShipmentRouteSegment with shipmentId " + shipmentId + " and shipmentRouteSegmentId " + shipmentRouteSegmentId); + } + + Element billThirdPartyElement = UtilXml.addChildElement(paymentInformationElement, "BillThirdParty", shipmentConfirmRequestDoc); + Element billThirdPartyShipperElement = UtilXml.addChildElement(billThirdPartyElement, "BillThirdPartyShipper", shipmentConfirmRequestDoc); + UtilXml.addChildElementValue(billThirdPartyShipperElement, "AccountNumber", thirdPartyAccountNumber, shipmentConfirmRequestDoc); + Element thirdPartyElement = UtilXml.addChildElement(billThirdPartyShipperElement, "ThirdParty", shipmentConfirmRequestDoc); + Element addressElement = UtilXml.addChildElement(thirdPartyElement, "Address", shipmentConfirmRequestDoc); + UtilXml.addChildElementValue(addressElement, "PostalCode", thirdPartyPostalAddress.getString("postalCode"), shipmentConfirmRequestDoc); + UtilXml.addChildElementValue(addressElement, "CountryCode", thirdPartyCountryGeo.getString("geoCode"), shipmentConfirmRequestDoc); + } // Child of Shipment: Service Element serviceElement = UtilXml.addChildElement(shipmentElement, "Service", shipmentConfirmRequestDoc); UtilXml.addChildElementValue(serviceElement, "Code", carrierShipmentMethod.getString("carrierServiceCode"), shipmentConfirmRequestDoc); // Child of Shipment: Package - Iterator shipmentPackageRouteSegIter = shipmentPackageRouteSegs.iterator(); + ListIterator shipmentPackageRouteSegIter = shipmentPackageRouteSegs.listIterator(); while (shipmentPackageRouteSegIter.hasNext()) { GenericValue shipmentPackageRouteSeg = (GenericValue) shipmentPackageRouteSegIter.next(); GenericValue shipmentPackage = shipmentPackageRouteSeg.getRelatedOne("ShipmentPackage"); @@ -352,6 +434,54 @@ if (carrierShipmentBoxType != null && carrierShipmentBoxType.get("oversizeCode") != null) { UtilXml.addChildElementValue(packageElement, "OversizePackage", carrierShipmentBoxType.getString("oversizeCode"), shipmentConfirmRequestDoc); } + + Element packageServiceOptionsElement = UtilXml.addChildElement(packageElement, "PackageServiceOptions", shipmentConfirmRequestDoc); + + // Determine the currency by trying the shipmentRouteSegment, then the Shipment, then the framework's default currency, and finally default to USD + String currencyCode = null; + if (UtilValidate.isNotEmpty(shipmentRouteSegment.getString("currencyUomId"))) { + currencyCode = shipmentRouteSegment.getString("currencyUomId"); + } else if (UtilValidate.isNotEmpty(shipmentRouteSegment.getString("currencyUomId"))) { + currencyCode = shipment.getString("currencyUomId"); + } else { + currencyCode = UtilProperties.getPropertyValue("general.properties", "currency.uom.id.default", "USD"); + } + + // Package insured value + BigDecimal insuredValue = shipmentPackage.getBigDecimal("insuredValue"); + if (! UtilValidate.isEmpty(insuredValue)) { + + Element insuredValueElement = UtilXml.addChildElement(packageServiceOptionsElement, "InsuredValue", shipmentConfirmRequestDoc); + UtilXml.addChildElementValue(insuredValueElement, "MonetaryValue", insuredValue.setScale(2, BigDecimal.ROUND_HALF_UP).toString(), shipmentConfirmRequestDoc); + UtilXml.addChildElementValue(insuredValueElement, "CurrencyCode", currencyCode, shipmentConfirmRequestDoc); + } + + if (applyCODSurcharge) { + Element codElement = UtilXml.addChildElement(packageServiceOptionsElement, "COD", shipmentConfirmRequestDoc); + UtilXml.addChildElementValue(codElement, "CODCode", "3", shipmentConfirmRequestDoc); // "3" is the only valid value for package-level COD + UtilXml.addChildElementValue(codElement, "CODFundsCode", codFundsCode, shipmentConfirmRequestDoc); + Element codAmountElement = UtilXml.addChildElement(codElement, "CODAmount", shipmentConfirmRequestDoc); + UtilXml.addChildElementValue(codAmountElement, "CurrencyCode", currencyCode, shipmentConfirmRequestDoc); + + // Get the value of the package by going back to the orderItems + Map getPackageValueResult = dispatcher.runSync("getShipmentPackageValueFromOrders", UtilMisc.toMap("shipmentId", shipmentId, "shipmentPackageSeqId", shipmentPackage.get("shipmentPackageSeqId"), "currencyUomId", currencyCode, "userLogin", userLogin, "locale", locale)); + if (ServiceUtil.isError(getPackageValueResult)) return getPackageValueResult; + BigDecimal packageValue = (BigDecimal) getPackageValueResult.get("packageValue"); + + // Convert the value of the COD surcharge to the shipment currency, if necessary + Map convertUomResult = dispatcher.runSync("convertUom", UtilMisc.toMap("uomId", codSurchargeCurrencyUomId, "uomIdTo", currencyCode, "originalValue", new Double(codSurchargePackageAmount.doubleValue()))); + if (ServiceUtil.isError(convertUomResult)) return convertUomResult; + if (convertUomResult.containsKey("convertedValue")) { + codSurchargePackageAmount = new BigDecimal(((Double) convertUomResult.get("convertedValue")).doubleValue()).setScale(decimals, rounding); + } + + // Add the amount of the surcharge for the package, if the surcharge should be on all packages or the first and this is the first package + if (codSurchargeApplyToAllPackages || codSurchargeSplitBetweenPackages || (codSurchargeApplyToFirstPackage && shipmentPackageRouteSegIter.previousIndex() <= 0)) { + packageValue = packageValue.add(codSurchargePackageAmount); + } + + UtilXml.addChildElementValue(codAmountElement, "MonetaryValue", packageValue.setScale(decimals, rounding).toString(), shipmentConfirmRequestDoc); + } } String shipmentConfirmRequestString = null; @@ -432,6 +562,9 @@ } return handleUpsShipmentConfirmResponse(shipmentConfirmResponseDocument, shipmentRouteSegment); + } catch (GenericServiceException e) { + Debug.logError(e, module); + return ServiceUtil.returnError("Error reading or writing Shipment data for UPS Shipment Confirm: " + e.toString()); } catch (GenericEntityException e) { Debug.logError(e, module); if (shipmentConfirmResponseString != null) { Modified: ofbiz/trunk/applications/product/webapp/facility/WEB-INF/actions/shipment/EditShipmentRouteSegments.bsh URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/webapp/facility/WEB-INF/actions/shipment/EditShipmentRouteSegments.bsh?view=diff&rev=529422&r1=529421&r2=529422 ============================================================================== --- ofbiz/trunk/applications/product/webapp/facility/WEB-INF/actions/shipment/EditShipmentRouteSegments.bsh (original) +++ ofbiz/trunk/applications/product/webapp/facility/WEB-INF/actions/shipment/EditShipmentRouteSegments.bsh Mon Apr 16 15:39:18 2007 @@ -60,6 +60,7 @@ } else { shipmentRouteSegmentData.put("carrierServiceStatusValidChangeToDetails", delegator.findByAnd("StatusValidChangeToDetail", UtilMisc.toMap("statusId", "SHRSCS_NOT_STARTED"), UtilMisc.toList("sequenceId"))); } + shipmentRouteSegmentData.put("thirdPartyPostalAddress", shipmentRouteSegment.getRelatedOne("ThirdPartyPostalAddress")); shipmentRouteSegmentDatas.add(shipmentRouteSegmentData); } } Modified: ofbiz/trunk/applications/product/webapp/facility/shipment/EditShipmentPackages.ftl URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/webapp/facility/shipment/EditShipmentPackages.ftl?view=diff&rev=529422&r1=529421&r2=529422 ============================================================================== --- ofbiz/trunk/applications/product/webapp/facility/shipment/EditShipmentPackages.ftl (original) +++ ofbiz/trunk/applications/product/webapp/facility/shipment/EditShipmentPackages.ftl Mon Apr 16 15:39:18 2007 @@ -58,6 +58,9 @@ <option value="${boxType.shipmentBoxTypeId}" <#if shipmentPackage.shipmentBoxTypeId?exists && shipmentPackage.shipmentBoxTypeId == boxType.shipmentBoxTypeId>selected</#if>>${boxType.get("description",locale)}</option> </#list> </select> + <br /> + <span class="tabletext">${uiLabelMap.ProductShipmentInsuredValuePackage}:</span> + <input type="text" size="5" name="insuredValue" value="${shipmentPackage.insuredValue?if_exists}" class="inputBox"/> </td> <td><a href="javascript:document.updateShipmentPackageForm${shipmentPackageData_index}.submit();" class="buttontext">${uiLabelMap.CommonUpdate}</a></td> <td><div class="tabletext"><a href="<@ofbizUrl>deleteShipmentPackage?shipmentId=${shipmentId}&shipmentPackageSeqId=${shipmentPackage.shipmentPackageSeqId}</@ofbizUrl>" class="buttontext">${uiLabelMap.CommonDelete}</a></div></td> Modified: ofbiz/trunk/applications/product/webapp/facility/shipment/EditShipmentRouteSegments.ftl URL: http://svn.apache.org/viewvc/ofbiz/trunk/applications/product/webapp/facility/shipment/EditShipmentRouteSegments.ftl?view=diff&rev=529422&r1=529421&r2=529422 ============================================================================== --- ofbiz/trunk/applications/product/webapp/facility/shipment/EditShipmentRouteSegments.ftl (original) +++ ofbiz/trunk/applications/product/webapp/facility/shipment/EditShipmentRouteSegments.ftl Mon Apr 16 15:39:18 2007 @@ -25,6 +25,8 @@ <div class="tableheadtext">${uiLabelMap.ProductOriginDestinationFacility}</div> <div class="tableheadtext">${uiLabelMap.ProductOriginDestinationAddressId}</div> <div class="tableheadtext">${uiLabelMap.ProductOriginDestinationPhoneId}</div> + <div class="tableheadtext">${uiLabelMap.ProductShipmentThirdPartyAccountNumber}</div> + <div class="tableheadtext">${uiLabelMap.ProductShipmentThirdPartyAddress}</div> </td> <td> <div class="tableheadtext">${uiLabelMap.ProductShipmentFedexHomeDeliveryTypeDate}</div> @@ -60,6 +62,7 @@ <#assign currencyUom = shipmentRouteSegmentData.currencyUom?if_exists> <#assign billingWeightUom = shipmentRouteSegmentData.billingWeightUom?if_exists> <#assign carrierServiceStatusValidChangeToDetails = shipmentRouteSegmentData.carrierServiceStatusValidChangeToDetails?if_exists> + <#assign thirdPartyPostalAddress = shipmentRouteSegmentData.thirdPartyPostalAddress?if_exists> <form action="<@ofbizUrl>updateShipmentRouteSegment</@ofbizUrl>" name="updateShipmentRouteSegmentForm${shipmentRouteSegmentData_index}"> <input type="hidden" name="shipmentId" value="${shipmentId}"/> <input type="hidden" name="shipmentRouteSegmentId" value="${shipmentRouteSegment.shipmentRouteSegmentId}"/> @@ -128,11 +131,21 @@ <input type="text" size="15" name="destTelecomNumberId" value="${shipmentRouteSegment.destTelecomNumberId?if_exists}" class="inputBox"/> <#if destTelecomNumber?has_content>[${destTelecomNumber.countryCode?if_exists} ${destTelecomNumber.areaCode?if_exists} ${destTelecomNumber.contactNumber?if_exists}]</#if> </div> + <div class="tabletext"> + <input type="text" size="15" name="thirdPartyAccountNumber" value="${shipmentRouteSegment.thirdPartyAccountNumber?if_exists}" class="inputBox"/> + </div> + <div class="tabletext"> + <input type="text" size="15" name="thirdPartyContactMechId" value="${shipmentRouteSegment.thirdPartyContactMechId?if_exists}" class="inputBox"/> + <#if thirdPartyPostalAddress?has_content>[${uiLabelMap.CommonTo}: ${thirdPartyPostalAddress.toName?if_exists}, ${uiLabelMap.CommonAttn}: ${thirdPartyPostalAddress.attnName?if_exists}, ${thirdPartyPostalAddress.address1?if_exists}, ${thirdPartyPostalAddress.address2?if_exists}, ${thirdPartyPostalAddress.city?if_exists}, ${thirdPartyPostalAddress.stateProvinceGeoId?if_exists}, ${thirdPartyPostalAddress.postalCode?if_exists}, ${thirdPartyPostalAddress.countryGeoId?if_exists}]</#if> + </div> </td> <td> <#if "UPS" == shipmentRouteSegment.carrierPartyId?if_exists> <#if !shipmentRouteSegment.carrierServiceStatusId?has_content || "SHRSCS_NOT_STARTED" == shipmentRouteSegment.carrierServiceStatusId?if_exists> <a href="<@ofbizUrl>upsShipmentConfirm?shipmentId=${shipmentRouteSegment.shipmentId}&shipmentRouteSegmentId=${shipmentRouteSegment.shipmentRouteSegmentId}</@ofbizUrl>" class="buttontext">${uiLabelMap.ProductConfirmShipmentUps}</a> + <br/> + ${uiLabelMap.ProductShipmentUpsResidential}: + <input type="checkbox" name="homeDeliveryType" class="checkBox" value="Y" ${(shipmentRouteSegment.homeDeliveryType?has_content)?string("checked=\"checked\"","")}> <#elseif "SHRSCS_CONFIRMED" == shipmentRouteSegment.carrierServiceStatusId?if_exists> <a href="<@ofbizUrl>upsShipmentAccept?shipmentId=${shipmentRouteSegment.shipmentId}&shipmentRouteSegmentId=${shipmentRouteSegment.shipmentRouteSegmentId}</@ofbizUrl>" class="buttontext">${uiLabelMap.ProductAcceptUpsShipmentConfirmation}</a> <br/> |
Free forum by Nabble | Edit this page |