Author: sichen
Date: Wed Nov  1 17:31:40 2006
New Revision: 470173

URL: http://svn.apache.org/viewvc?view=rev&rev=470173
Log:
Invoicing services now support pro-rating of taxes based on product store 
settings and invoicing of additional shipping charges from the Shipment entity

Modified:
    
incubator/ofbiz/trunk/applications/accounting/config/AccountingUiLabels.properties
    
incubator/ofbiz/trunk/applications/accounting/servicedef/services_invoice.xml
    
incubator/ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceServices.java

Modified: 
incubator/ofbiz/trunk/applications/accounting/config/AccountingUiLabels.properties
URL: 
http://svn.apache.org/viewvc/incubator/ofbiz/trunk/applications/accounting/config/AccountingUiLabels.properties?view=diff&rev=470173&r1=470172&r2=470173
==============================================================================
--- 
incubator/ofbiz/trunk/applications/accounting/config/AccountingUiLabels.properties
 (original)
+++ 
incubator/ofbiz/trunk/applications/accounting/config/AccountingUiLabels.properties
 Wed Nov  1 17:31:40 2006
@@ -538,7 +538,6 @@
 AccountingErrorCreatingInvoiceFromOrderCheckPaymentAppl=Error creating invoice 
from order while checking payment applications
 AccountingEntityDataProblemCreatingInvoiceFromOrderItems=Entity/data problem 
creating invoice from order items: ${reason} 
 AccountingServiceOtherProblemCreatingInvoiceFromOrderItems=Service/other 
problem creating invoice from order items: ${reason} 
-AccountingTroubleCreateInvoicesFromShipmentsService=Trouble calling 
createInvoicesFromShipments service; invoice not created for shipment 
[${shipmentId}]
 AccountingShipmentsOfDifferentTypes=Shipments of different types found; 
shipment [${tmpShipmentId}] of type [${shipmentTypeId}] is of different type 
from the previous ones.
 AccountingTroubleGettingShipmentEntity=Trouble getting Shipment entity for 
shipment [${tmpShipmentId}]
 AccountingProblemGettingItemsFromShipments=Problem getting issued items from 
shipments
@@ -599,6 +598,18 @@
 AccountingInvoiceCommissionNoItems=No order or return items, not creating 
commission invoice
 AccountingInvoiceCommissionEntityDataProblem=Entity/data problem creating 
commission invoice: ${reason} 
 AccountingPageTitleAgreementPriceList=Agreement Price List
+AccountingAdditionalShippingChargeForShipment=Additional Shipping Charge For 
Shipment
+AccountingUnableToAuthAdditionalShipCharges=Unable to authorize additional 
shipping charges for shipmentId ${shipmentId} to paymentMethodId 
${paymentMethodId} (orderPaymentPreferenceId ${orderPaymentPreferenceId})
+AccountingTroubleCallingAuthOrderPaymentPreferenceService=Trouble calling 
authOrderPaymentPreference service
+AccountingTroubleCallingCreateInvoicesFromShipmentService=Trouble calling 
createInvoicesFromShipment service; invoice not created for shipment 
[${shipmentId}]
+AccountingTroubleCallingCreateInvoicesFromShipmentsService=Trouble calling 
createInvoicesFromShipments service
+AccountingTroubleCallingCreateOrderAdjustmentService=Trouble calling 
createOrderAdjustment service
+AccountingProblemGettingOrderPaymentPreferences=Problem getting 
OrderPaymentPreference records
+AccountingTroubleCallingCreateOrderPaymentPreferenceService=Trouble calling 
createOrderPaymentPreference service
+AccountingTroubleCallingCalcTaxService=Trouble calling calcTaxService
+AccountingProblemStoringOrderAdjustments=Problem storing OrderAdjustments: 
${orderAdjustments}
+AccountingErrorCreatingOrderAdjustmentBillingFromOrder=Error creating 
OrderAdjustmentBilling from order
+AccountingTroubleCallingCalculateInvoicedAdjustmentTotalService=Accounting 
trouble calling calculateInvoicedAdjustmentTotal service
 
 #Potentional Common definitions
 FormFieldTitle_emailAddressFrom=From Emailadress

Modified: 
incubator/ofbiz/trunk/applications/accounting/servicedef/services_invoice.xml
URL: 
http://svn.apache.org/viewvc/incubator/ofbiz/trunk/applications/accounting/servicedef/services_invoice.xml?view=diff&rev=470173&r1=470172&r2=470173
==============================================================================
--- 
incubator/ofbiz/trunk/applications/accounting/servicedef/services_invoice.xml 
(original)
+++ 
incubator/ofbiz/trunk/applications/accounting/servicedef/services_invoice.xml 
Wed Nov  1 17:31:40 2006
@@ -254,4 +254,10 @@
         <auto-attributes entity-name="InvoiceContactMech" include="pk" 
mode="IN" optional="false"/>
         <attribute name="contactMechId" type="String" mode="OUT" 
optional="true"/>
     </service>
+    <service name="calculateInvoicedAdjustmentTotal" engine="java"
+            location="org.ofbiz.accounting.invoice.InvoiceServices" 
invoke="calculateInvoicedAdjustmentTotalBd">
+        <description>Calculate the previously invoiced amount for an 
OrderAdjustment</description>
+        <attribute name="orderAdjustment" type="GenericValue" mode="IN" 
optional="false"/>
+        <attribute name="invoicedTotal" type="BigDecimal" mode="OUT" 
optional="false"/>
+    </service>
 </services>

Modified: 
incubator/ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceServices.java
URL: 
http://svn.apache.org/viewvc/incubator/ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceServices.java?view=diff&rev=470173&r1=470172&r2=470173
==============================================================================
--- 
incubator/ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceServices.java
 (original)
+++ 
incubator/ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceServices.java
 Wed Nov  1 17:31:40 2006
@@ -41,6 +41,7 @@
 import org.ofbiz.entity.GenericDelegator;
 import org.ofbiz.entity.GenericEntityException;
 import org.ofbiz.entity.GenericValue;
+import org.ofbiz.entity.util.EntityUtil;
 import org.ofbiz.entity.condition.EntityCondition;
 import org.ofbiz.entity.condition.EntityOperator;
 import org.ofbiz.entity.condition.EntityExpr;
@@ -473,6 +474,23 @@
                     while (itemAdjIter.hasNext()) {
                         GenericValue adj = (GenericValue) itemAdjIter.next();
                         
+                        // Check against OrderAdjustmentBilling to see how 
much of this adjustment has already been invoiced
+                        BigDecimal adjAlreadyInvoicedAmount = null;
+                        try {
+                            Map checkResult = 
dispatcher.runSync("calculateInvoicedAdjustmentTotal", 
UtilMisc.toMap("orderAdjustment", adj));
+                            adjAlreadyInvoicedAmount = (BigDecimal) 
checkResult.get("invoicedTotal");
+                        } catch (GenericServiceException e) {
+                            String errMsg = 
UtilProperties.getMessage(resource, 
"AccountingTroubleCallingCalculateInvoicedAdjustmentTotalService", locale);
+                            Debug.logError(e, errMsg, module);
+                            return ServiceUtil.returnError(errMsg);
+                        }
+        
+                        // If the absolute invoiced amount >= the abs of the 
adjustment amount, the full amount has already been invoiced,
+                        //  so skip this adjustment
+                        if 
(adjAlreadyInvoicedAmount.abs().compareTo(adj.getBigDecimal("amount").setScale(decimals,
 rounding).abs()) > 0) {
+                            continue;
+                        }
+        
                         BigDecimal amount = new BigDecimal(0);
                         if (adj.get("amount") != null) { 
                             // pro-rate the amount
@@ -520,7 +538,20 @@
                                if 
(ServiceUtil.isError(createInvoiceItemAdjResult)) {
                                    return 
ServiceUtil.returnError(UtilProperties.getMessage(resource,"AccountingErrorCreatingInvoiceItemFromOrder",locale),
 null, null, createInvoiceItemAdjResult);
                                }
-       
+
+                            // Create the OrderAdjustmentBilling record
+                            Map createOrderAdjustmentBillingContext = 
FastMap.newInstance();
+                            
createOrderAdjustmentBillingContext.put("orderAdjustmentId", 
adj.getString("orderAdjustmentId"));
+                            
createOrderAdjustmentBillingContext.put("invoiceId", invoiceId);
+                            
createOrderAdjustmentBillingContext.put("invoiceItemSeqId", invoiceItemSeqId);
+                            createOrderAdjustmentBillingContext.put("amount", 
new Double(amount.doubleValue()));
+                            
createOrderAdjustmentBillingContext.put("userLogin", userLogin);
+
+                            Map createOrderAdjustmentBillingResult = 
dispatcher.runSync("createOrderAdjustmentBilling", 
createOrderAdjustmentBillingContext);
+                            if 
(ServiceUtil.isError(createOrderAdjustmentBillingResult)) {
+                                return 
ServiceUtil.returnError(UtilProperties.getMessage(resource,"AccountingErrorCreatingOrderAdjustmentBillingFromOrder",locale),
 null, null, createOrderAdjustmentBillingContext);
+                            }
+
                                // this adjustment amount
                                BigDecimal thisAdjAmount = new 
BigDecimal(amount.doubleValue()).setScale(decimals, rounding);
        
@@ -545,22 +576,40 @@
             }
 
             // create header adjustments as line items -- always to 
tax/shipping last
-            List shipAdjustments = new ArrayList();
-            List taxAdjustments = new ArrayList();
+            Map shipAdjustments = new HashMap();
+            Map taxAdjustments = new HashMap();
 
             List headerAdjustments = orh.getOrderHeaderAdjustments();
             Iterator headerAdjIter = headerAdjustments.iterator();
             while (headerAdjIter.hasNext()) {
                 GenericValue adj = (GenericValue) headerAdjIter.next();
+
+                // Check against OrderAdjustmentBilling to see how much of 
this adjustment has already been invoiced
+                BigDecimal adjAlreadyInvoicedAmount = null;
+                try {
+                    Map checkResult = 
dispatcher.runSync("calculateInvoicedAdjustmentTotal", 
UtilMisc.toMap("orderAdjustment", adj));
+                    adjAlreadyInvoicedAmount = ((BigDecimal) 
checkResult.get("invoicedTotal")).setScale(decimals, rounding);
+                } catch (GenericServiceException e) {
+                    String errMsg = UtilProperties.getMessage(resource, 
"AccountingTroubleCallingCalculateInvoicedAdjustmentTotalService", locale);
+                    Debug.logError(e, errMsg, module);
+                    return ServiceUtil.returnError(errMsg);
+                }
+
+                // If the absolute invoiced amount >= the abs of the 
adjustment amount, the full amount has already been invoiced,
+                //  so skip this adjustment
+                if 
(adjAlreadyInvoicedAmount.abs().compareTo(adj.getBigDecimal("amount").setScale(decimals,
 rounding).abs()) > 0) {
+                    continue;
+                }
+
                 if 
("SHIPPING_CHARGES".equals(adj.getString("orderAdjustmentTypeId"))) {
-                    shipAdjustments.add(adj);
+                    shipAdjustments.put(adj, adjAlreadyInvoicedAmount);
                 } else if 
("SALES_TAX".equals(adj.getString("orderAdjustmentTypeId"))) {
-                    taxAdjustments.add(adj);
+                    taxAdjustments.put(adj, adjAlreadyInvoicedAmount);
                 } else {
                     // these will effect the shipping pro-rate (unless 
commented)
                     // other adjustment type
                     BigDecimal adjAmount = calcHeaderAdj(delegator, adj, 
invoiceType, invoiceId, invoiceItemSeqId, 
-                            orderSubTotal, invoiceSubTotal, invoiceQuantity, 
decimals, rounding, userLogin, dispatcher, locale);
+                            orderSubTotal, invoiceSubTotal, 
adj.getBigDecimal("amount").setScale(decimals, rounding), decimals, rounding, 
userLogin, dispatcher, locale);
                     // invoiceShipProRateAmount += adjAmount;
                     // do adjustments compound or are they based off subtotal? 
Here we will (unless commented)
                     // invoiceSubTotal += adjAmount;
@@ -573,41 +622,79 @@
 
             // next do the shipping adjustments.  Note that we do not want to 
add these to the invoiceSubTotal or orderSubTotal for pro-rating tax later, as 
that would cause
             // numerator/denominator problems when the shipping is not 
pro-rated but rather charged all on the first invoice
-            Iterator shipAdjIter = shipAdjustments.iterator();
+            Iterator shipAdjIter = shipAdjustments.keySet().iterator();
             while (shipAdjIter.hasNext()) {
                 GenericValue adj = (GenericValue) shipAdjIter.next();
+                BigDecimal adjAlreadyInvoicedAmount = (BigDecimal) 
shipAdjustments.get(adj);
+                
                 if ("N".equalsIgnoreCase(prorateShipping)) {
-                    if (previousInvoiceFound) {
-                        Debug.logInfo("Previous invoice found for this order 
[" + orderId + "]; shipping already billed", module);
-                        continue;
-                    } else {
-                        // this is the first invoice; bill it all now
-                        BigDecimal adjAmount = calcHeaderAdj(delegator, adj, 
invoiceType, invoiceId, invoiceItemSeqId, 
-                                new BigDecimal("1"), new BigDecimal("1"), 
totalItemsInOrder, decimals, rounding, userLogin, dispatcher, locale);
-                        // increment the counter
-                        invoiceItemSeqNum++;
-                        invoiceItemSeqId = 
UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum, 2);
-                    }
+
+                    // Set the divisor and multiplier to 1 to avoid prorating
+                    BigDecimal divisor = new BigDecimal("1");
+                    BigDecimal multiplier = new BigDecimal("1");
+                    
+                    // The base amount in this case is the adjustment amount 
minus the total already invoiced for that adjustment, since
+                    //  it won't be prorated
+                    BigDecimal baseAmount = 
adj.getBigDecimal("amount").setScale(decimals, 
rounding).subtract(adjAlreadyInvoicedAmount);
+                    BigDecimal adjAmount = calcHeaderAdj(delegator, adj, 
invoiceType, invoiceId, invoiceItemSeqId, 
+                            divisor, multiplier, baseAmount, decimals, 
rounding, userLogin, dispatcher, locale);
                 } else {
-                    // pro-rate the shipping amount based on shippable 
information
+
+                    // Pro-rate the shipping amount based on shippable 
information
+                    BigDecimal divisor = shippableAmount;
+                    BigDecimal multiplier = invoiceShipProRateAmount;
+                    
+                    // The base amount in this case is the adjustment amount, 
since we want to prorate based on the full amount
+                    BigDecimal baseAmount = 
adj.getBigDecimal("amount").setScale(decimals, rounding);
                     BigDecimal adjAmount = calcHeaderAdj(delegator, adj, 
invoiceType, invoiceId, invoiceItemSeqId, 
-                            shippableAmount, invoiceShipProRateAmount, 
invoiceQuantity, decimals, rounding, userLogin, dispatcher, locale);
-                    // increment the counter
-                    invoiceItemSeqNum++;
-                    invoiceItemSeqId = 
UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum, 2);
+                            divisor, multiplier, baseAmount, decimals, 
rounding, userLogin, dispatcher, locale);
                 }
+
+                // Increment the counter
+                invoiceItemSeqNum++;
+                invoiceItemSeqId = 
UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum, 2);
             }
 
             // last do the tax adjustments
-            Iterator taxAdjIter = taxAdjustments.iterator();
+            String prorateTaxes = productStore.getString("prorateTaxes");
+            if (prorateTaxes == null) {
+                prorateTaxes = "Y";
+            }            
+            Iterator taxAdjIter = taxAdjustments.keySet().iterator();
             while (taxAdjIter.hasNext()) {
                 GenericValue adj = (GenericValue) taxAdjIter.next();
-                // note this should use invoice decimals & rounding instead of 
taxDecimals and taxRounding, because it will be added to the invoice 
-                BigDecimal adjAmount = calcHeaderAdj(delegator, adj, 
invoiceType, invoiceId, invoiceItemSeqId, 
-                        orderSubTotal, invoiceSubTotal, invoiceQuantity, 
decimals, rounding, userLogin, dispatcher, locale);
-                // this doesn't really effect anything; but just for our totals
-                // since it will no longer be used in pro-rating, we can just 
round off now
+                BigDecimal adjAlreadyInvoicedAmount = (BigDecimal) 
taxAdjustments.get(adj);
+                BigDecimal adjAmount = null;
+                
+                if ("N".equalsIgnoreCase(prorateTaxes)) {
+
+                    // Set the divisor and multiplier to 1 to avoid prorating
+                    BigDecimal divisor = new BigDecimal("1");
+                    BigDecimal multiplier = new BigDecimal("1");
+                    
+                    // The base amount in this case is the adjustment amount 
minus the total already invoiced for that adjustment, since
+                    //  it won't be prorated
+                    //  Note this should use invoice decimals & rounding 
instead of taxDecimals and taxRounding for tax adjustments, because it will be 
added to the invoice 
+                    BigDecimal baseAmount = 
adj.getBigDecimal("amount").setScale(decimals, 
rounding).subtract(adjAlreadyInvoicedAmount);
+                    adjAmount = calcHeaderAdj(delegator, adj, invoiceType, 
invoiceId, invoiceItemSeqId, 
+                             divisor, multiplier, baseAmount, decimals, 
rounding, userLogin, dispatcher, locale);
+                } else {
+
+                    // Pro-rate the tax amount based on shippable information
+                    BigDecimal divisor = orderSubTotal;
+                    BigDecimal multiplier = invoiceSubTotal;
+                    
+                    // The base amount in this case is the adjustment amount, 
since we want to prorate based on the full amount
+                    //  Note this should use invoice decimals & rounding 
instead of taxDecimals and taxRounding for tax adjustments, because it will be 
added to the invoice 
+                    BigDecimal baseAmount = 
adj.getBigDecimal("amount").setScale(decimals, rounding);
+                    adjAmount = calcHeaderAdj(delegator, adj, invoiceType, 
invoiceId, invoiceItemSeqId, 
+                            divisor, multiplier, baseAmount, decimals, 
rounding, userLogin, dispatcher, locale);
+                }
                 invoiceSubTotal = 
invoiceSubTotal.add(adjAmount).setScale(decimals, rounding);                
+
+                // Increment the counter
+                invoiceItemSeqNum++;
+                invoiceItemSeqId = 
UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum, 2);
             }
 
             // check for previous order payments
@@ -889,8 +976,8 @@
             Map result = dispatcher.runSync("createInvoicesFromShipments", 
serviceContext);
             invoicesCreated = (List) result.get("invoicesCreated");
         } catch (GenericServiceException e) {
-            Debug.logError(e, "Trouble calling createInvoicesFromShipments 
service; invoice not created for shipment [" + shipmentId + "]", module);
-            return 
ServiceUtil.returnError(UtilProperties.getMessage(resource,"AccountingTroubleCreateInvoicesFromShipmentsService",UtilMisc.toMap("shipmentId",shipmentId),locale));
+            Debug.logError(e, "Trouble calling createInvoicesFromShipment 
service; invoice not created for shipment [" + shipmentId + "]", module);
+            return 
ServiceUtil.returnError(UtilProperties.getMessage(resource,"AccountingTroubleCallingCreateInvoicesFromShipmentService",UtilMisc.toMap("shipmentId",shipmentId),locale));
         }
         Map response = ServiceUtil.returnSuccess();
         response.put("invoicesCreated", invoicesCreated);
@@ -1066,6 +1153,180 @@
                 itemQtyAvail.put(issue.getString("orderItemSeqId"), billAvail);
             }
 
+            OrderReadHelper orh = new OrderReadHelper(delegator, orderId);
+            GenericValue productStore = orh.getProductStore();
+
+            // If shipping charges are not prorated, the shipments need to be 
examined for additional shipping charges
+            if (productStore.getString("prorateShipping").equals("N")) {
+    
+                // Get the set of filtered shipments
+                List invoiceableShipmentIds = 
EntityUtil.getFieldListFromEntityList(toBillItems, "shipmentId", true);
+                List invoiceableShipments = null;
+                try {
+                    invoiceableShipments = 
delegator.findByCondition("Shipment", new EntityExpr("shipmentId", 
EntityOperator.IN, invoiceableShipmentIds), null, null);
+                } catch( GenericEntityException e ) {
+                    String errMsg = UtilProperties.getMessage(resource, 
"AccountingTroubleCallingCreateInvoicesFromShipmentsService", locale);
+                    Debug.logError(e, errMsg, module);
+                    return ServiceUtil.returnError(errMsg);
+                }
+                
+                // Total the additional shipping charges for the shipments
+                Map additionalShippingCharges = new HashMap();
+                BigDecimal totalAdditionalShippingCharges = ZERO;
+                Iterator isit = invoiceableShipments.iterator();
+                while(isit.hasNext()) {
+                    GenericValue shipment = (GenericValue) isit.next();
+                    if (shipment.get("additionalShippingCharge") == null) 
continue;
+                    BigDecimal shipmentAdditionalShippingCharges = 
shipment.getBigDecimal("additionalShippingCharge").setScale(decimals, rounding);
+                    additionalShippingCharges.put(shipment, 
shipmentAdditionalShippingCharges);
+                    totalAdditionalShippingCharges = 
totalAdditionalShippingCharges.add(shipmentAdditionalShippingCharges);
+                }
+                
+                // If the additional shipping charges are greater than zero, 
process them
+                if (totalAdditionalShippingCharges.signum() == 1) {
+
+                    // Add an OrderAdjustment to the order for each additional 
shipping charge
+                    Iterator ascit = 
additionalShippingCharges.keySet().iterator();
+                    while (ascit.hasNext()) {
+                        GenericValue shipment = (GenericValue) ascit.next();
+                        String shipmentId = shipment.getString("shipmentId");
+                        BigDecimal additionalShippingCharge = (BigDecimal) 
additionalShippingCharges.get(shipment);
+                        Map createOrderAdjustmentContext = new HashMap();
+                        createOrderAdjustmentContext.put("orderId", orderId);
+                        
createOrderAdjustmentContext.put("orderAdjustmentTypeId", "SHIPPING_CHARGES");
+                        createOrderAdjustmentContext.put("description", 
UtilProperties.getMessage(resource, 
"AccountingAdditionalShippingChargeForShipment", locale) + " #" + shipmentId);
+                        createOrderAdjustmentContext.put("sourceReferenceId", 
shipmentId);
+                        createOrderAdjustmentContext.put("amount", new 
Double(additionalShippingCharge.doubleValue()));
+                        createOrderAdjustmentContext.put("userLogin", 
context.get("userLogin"));
+                        String shippingOrderAdjustmentId = null;
+                        try {
+                            Map createOrderAdjustmentResult = 
dispatcher.runSync("createOrderAdjustment", createOrderAdjustmentContext);
+                            shippingOrderAdjustmentId = (String) 
createOrderAdjustmentResult.get("orderAdjustmentId");
+                        } catch (GenericServiceException e) {
+                            String errMsg = 
UtilProperties.getMessage(resource, 
"AccountingTroubleCallingCreateOrderAdjustmentService", locale);
+                            Debug.logError(e, errMsg, module);
+                            return ServiceUtil.returnError(errMsg);
+                        }
+
+                        // Obtain a list of OrderAdjustments due to tax on the 
shipping charges, if any
+                        GenericValue billToParty = orh.getBillToParty();
+                        GenericValue payToParty = orh.getBillFromParty();
+                        GenericValue destinationContactMech = null;
+                        try {
+                            destinationContactMech = 
shipment.getRelatedOne("DestinationPostalAddress");
+                        } catch( GenericEntityException e ) {
+                            String errMsg = 
UtilProperties.getMessage(resource, 
"AccountingTroubleCallingCreateInvoicesFromShipmentService", locale);
+                            Debug.logError(e, errMsg, module);
+                            return ServiceUtil.returnError(errMsg);
+                        }
+                        
+                        List emptyList = new ArrayList();
+                        Map calcTaxContext = new HashMap();
+                        calcTaxContext.put("productStoreId", 
orh.getProductStoreId());
+                        calcTaxContext.put("payToPartyId", 
payToParty.getString("partyId"));
+                        calcTaxContext.put("billToPartyId", 
billToParty.getString("partyId"));
+                        calcTaxContext.put("orderShippingAmount", 
totalAdditionalShippingCharges);
+                        calcTaxContext.put("shippingAddress", 
destinationContactMech);
+
+                        // These parameters don't matter if we're only worried 
about adjustments on the shipping charges
+                        calcTaxContext.put("itemProductList", emptyList);
+                        calcTaxContext.put("itemAmountList", emptyList);
+                        calcTaxContext.put("itemPriceList", emptyList);
+                        calcTaxContext.put("itemShippingList", emptyList);
+
+                        List orderAdjustments = null;
+                        Map calcTaxResult = null;
+                        try {
+                            calcTaxResult = dispatcher.runSync("calcTax", 
calcTaxContext);
+                        } catch (GenericServiceException e) {
+                            String errMsg = 
UtilProperties.getMessage(resource, "AccountingTroubleCallingCalcTaxService", 
locale);
+                            Debug.logError(e, errMsg, module);
+                            return ServiceUtil.returnError(errMsg);
+                        }
+                        orderAdjustments = (List) 
calcTaxResult.get("orderAdjustments");
+
+                        // If we have any OrderAdjustments due to tax on 
shipping, store them and add them to the total
+                        if (calcTaxResult != null && orderAdjustments != null) 
{
+                            Iterator oait = orderAdjustments.iterator();
+                            while (oait.hasNext()) {
+                                GenericValue orderAdjustment = (GenericValue) 
oait.next();
+                                totalAdditionalShippingCharges = 
totalAdditionalShippingCharges.add(orderAdjustment.getBigDecimal("amount").setScale(decimals,
 rounding));
+                                orderAdjustment.set("orderAdjustmentId", 
delegator.getNextSeqId("OrderAdjustment"));
+                                orderAdjustment.set("orderId", orderId);
+                                orderAdjustment.set("orderItemSeqId", "_NA_");
+                                orderAdjustment.set("shipGroupSeqId", 
shipment.getString("primaryShipGroupSeqId"));
+                                orderAdjustment.set("originalAdjustmentId", 
shippingOrderAdjustmentId);                                
+                            }
+                            try {
+                                delegator.storeAll(orderAdjustments);
+                            } catch( GenericEntityException e ) {
+                                String errMsg = 
UtilProperties.getMessage(resource, "AccountingProblemStoringOrderAdjustments", 
UtilMisc.toMap("orderAdjustments", orderAdjustments), locale);
+                                Debug.logError(e, errMsg, module);
+                                return ServiceUtil.returnError(errMsg);
+                            }
+                        }
+
+                        // If part of the order was paid via credit card, try 
to charge it for the additional shipping
+                        List orderPaymentPreferences = new ArrayList();
+                        try {
+                            orderPaymentPreferences = 
delegator.findByAnd("OrderPaymentPreference", UtilMisc.toMap("orderId", 
orderId));
+                        } catch( GenericEntityException e ) {
+                            String errMsg = 
UtilProperties.getMessage(resource, 
"AccountingProblemGettingOrderPaymentPreferences", locale);
+                            Debug.logError(e, errMsg, module);
+                            return ServiceUtil.returnError(errMsg);
+                        }
+
+                        //  Use the first credit card we find, for the sake of 
simplicity
+                        String paymentMethodId = null;
+                        Iterator oppit = orderPaymentPreferences.iterator();
+                        while (oppit.hasNext()) {
+                            GenericValue orderPaymentPreference = 
(GenericValue) oppit.next();
+                            if 
(orderPaymentPreference.getString("paymentMethodTypeId").equals("CREDIT_CARD")) 
{
+                                paymentMethodId = 
orderPaymentPreference.getString("paymentMethodId");
+                                break;
+                            }
+                        }
+                        
+                        if (paymentMethodId != null ) {
+                            
+                            // Create a new OrderPaymentPreference for the 
order to handle the additional charge. Don't
+                            //  set the maxAmount so that it doesn't interfere 
with other authorizations
+                            Map serviceContext = UtilMisc.toMap("orderId", 
orderId, "paymentMethodId", paymentMethodId, "paymentMethodTypeId", 
"CREDIT_CARD", "userLogin", context.get("userLogin"));
+                            String orderPaymentPreferenceId = null;
+                            try {
+                                Map result = 
dispatcher.runSync("createOrderPaymentPreference", serviceContext);
+                                orderPaymentPreferenceId = (String) 
result.get("orderPaymentPreferenceId");
+                            } catch (GenericServiceException e) {
+                                String errMsg = 
UtilProperties.getMessage(resource, 
"AccountingTroubleCallingCreateOrderPaymentPreferenceService", locale);
+                                Debug.logError(e, errMsg, module);
+                                return ServiceUtil.returnError(errMsg);
+                            }
+
+                            // Attempt to authorize the new 
orderPaymentPreference
+                            Map authResult = null;
+                            try {
+
+                                // Use an overrideAmount because the maxAmount 
wasn't set on the OrderPaymentPreference
+                                authResult = 
dispatcher.runSync("authOrderPaymentPreference", 
UtilMisc.toMap("orderPaymentPreferenceId", orderPaymentPreferenceId, 
"overrideAmount", new Double(totalAdditionalShippingCharges.doubleValue()), 
"userLogin", context.get("userLogin")));
+                            } catch (GenericServiceException e) {
+                                String errMsg = 
UtilProperties.getMessage(resource, 
"AccountingTroubleCallingAuthOrderPaymentPreferenceService", locale);
+                                Debug.logError(e, errMsg, module);
+                                return ServiceUtil.returnError(errMsg);
+                            }
+
+                            // If the authorization fails, create the invoice 
anyway, but make a note of it
+                            boolean authFinished = ( (Boolean) 
authResult.get("finished") ).booleanValue();
+                            boolean authErrors = ( (Boolean) 
authResult.get("errors") ).booleanValue();
+                            if (authErrors || ! authFinished) {
+                                String errMsg = 
UtilProperties.getMessage(resource, 
"AccountingUnableToAuthAdditionalShipCharges", UtilMisc.toMap("shipmentId", 
shipmentId, "paymentMethodId", paymentMethodId, "orderPaymentPreferenceId", 
orderPaymentPreferenceId), locale);
+                                Debug.logError(errMsg, module);
+                            }
+                            
+                        } 
+                    } 
+                }
+            }
+
             // call the createInvoiceForOrder service for each order
             Map serviceContext = UtilMisc.toMap("orderId", orderId, 
"billItems", toBillItems, "userLogin", context.get("userLogin"));
             try {
@@ -1490,16 +1751,16 @@
     }
 
     private static BigDecimal calcHeaderAdj(GenericDelegator delegator, 
GenericValue adj, String invoiceTypeId, String invoiceId, String 
invoiceItemSeqId, 
-            BigDecimal divisor, BigDecimal multiplier, BigDecimal 
invoiceQuantity, int decimals, int rounding, GenericValue userLogin, 
LocalDispatcher dispatcher, Locale locale) {
+            BigDecimal divisor, BigDecimal multiplier, BigDecimal baseAmount, 
int decimals, int rounding, GenericValue userLogin, LocalDispatcher dispatcher, 
Locale locale) {
         BigDecimal adjAmount = ZERO;
         if (adj.get("amount") != null) {
+
             // pro-rate the amount
-            BigDecimal baseAdjAmount = adj.getBigDecimal("amount");
             BigDecimal amount = ZERO;
             // make sure the divisor is not 0 to avoid NaN problems; just 
leave the amount as 0 and skip it in essense
             if (divisor.signum() != 0) {
                 // multiply first then divide to avoid rounding errors
-                amount = baseAdjAmount.multiply(multiplier).divide(divisor, 
decimals, rounding);
+                amount = baseAmount.multiply(multiplier).divide(divisor, 
decimals, rounding);
             }
             if (amount.signum() != 0) {
                 Map createInvoiceItemContext = FastMap.newInstance();
@@ -1530,6 +1791,21 @@
                 if (ServiceUtil.isError(createInvoiceItemResult)) {
                     
ServiceUtil.returnError(UtilProperties.getMessage(resource,"AccountingErrorCreatingInvoiceItemFromOrder",locale),
 null, null, createInvoiceItemResult);
                 }
+
+                // Create the OrderAdjustmentBilling record
+                Map createOrderAdjustmentBillingContext = 
FastMap.newInstance();
+                createOrderAdjustmentBillingContext.put("orderAdjustmentId", 
adj.getString("orderAdjustmentId"));
+                createOrderAdjustmentBillingContext.put("invoiceId", 
invoiceId);
+                createOrderAdjustmentBillingContext.put("invoiceItemSeqId", 
invoiceItemSeqId);
+                createOrderAdjustmentBillingContext.put("amount", new 
Double(amount.doubleValue()));
+                createOrderAdjustmentBillingContext.put("userLogin", 
userLogin);
+
+                try {
+                    Map createOrderAdjustmentBillingResult = 
dispatcher.runSync("createOrderAdjustmentBilling", 
createOrderAdjustmentBillingContext);
+                } catch( GenericServiceException e ) {
+                    
ServiceUtil.returnError(UtilProperties.getMessage(resource,"AccountingErrorCreatingOrderAdjustmentBillingFromOrder",locale),
 null, null, createOrderAdjustmentBillingContext);
+                }
+
             }
             amount.setScale(decimals, rounding);
             adjAmount = amount;
@@ -1573,6 +1849,21 @@
                 if (ServiceUtil.isError(createInvoiceItemResult)) {
                     
ServiceUtil.returnError(UtilProperties.getMessage(resource,"AccountingErrorCreatingInvoiceItemFromOrder",locale),
 null, null, createInvoiceItemResult);
                 }
+
+                // Create the OrderAdjustmentBilling record
+                Map createOrderAdjustmentBillingContext = 
FastMap.newInstance();
+                createOrderAdjustmentBillingContext.put("orderAdjustmentId", 
adj.getString("orderAdjustmentId"));
+                createOrderAdjustmentBillingContext.put("invoiceId", 
invoiceId);
+                createOrderAdjustmentBillingContext.put("invoiceItemSeqId", 
invoiceItemSeqId);
+                createOrderAdjustmentBillingContext.put("amount", new 
Double(amount.doubleValue()));
+                createOrderAdjustmentBillingContext.put("userLogin", 
userLogin);
+
+                try {
+                    Map createOrderAdjustmentBillingResult = 
dispatcher.runSync("createOrderAdjustmentBilling", 
createOrderAdjustmentBillingContext);
+                } catch( GenericServiceException e ) {
+                    
ServiceUtil.returnError(UtilProperties.getMessage(resource,"AccountingErrorCreatingOrderAdjustmentBillingFromOrder",locale),
 null, null, createOrderAdjustmentBillingContext);
+                }
+
             }
             amount.setScale(decimals, rounding);
             adjAmount = amount;
@@ -2381,6 +2672,30 @@
         errorMessageList.add("??unsuitable parameters passed...?? This 
message.... should never be shown\n");
         errorMessageList.add("--Input parameters...InvoiceId:" + invoiceId + " 
invoiceItemSeqId:" + invoiceItemSeqId + " PaymentId:" + paymentId + " 
toPaymentId:" + toPaymentId + "\n  paymentApplicationId:" + 
paymentApplicationId + " amountApplied:" + amountApplied);
         return ServiceUtil.returnError(errorMessageList);
+    }
+
+    public static Map calculateInvoicedAdjustmentTotalBd(DispatchContext dctx, 
Map context) {
+        GenericDelegator delegator = dctx.getDelegator();
+        Locale locale = (Locale) context.get("locale");
+        GenericValue orderAdjustment = (GenericValue) 
context.get("orderAdjustment");
+        Map result = ServiceUtil.returnSuccess();
+        
+        BigDecimal invoicedTotal = ZERO;
+        List invoicedAdjustments = null;
+        try {
+            invoicedAdjustments = 
delegator.findByAnd("OrderAdjustmentBilling", 
UtilMisc.toMap("orderAdjustmentId", 
orderAdjustment.getString("orderAdjustmentId")));
+        } catch( GenericEntityException e ) {
+            String errMsg = UtilProperties.getMessage(resource, 
"AccountingTroubleCallingCalculateInvoicedAdjustmentTotalService" + ": " + 
e.getMessage(), locale);
+            Debug.logError(e, errMsg, module);
+            return ServiceUtil.returnError(errMsg);
+        }
+        Iterator iait = invoicedAdjustments.iterator();
+        while (iait.hasNext()) {
+            GenericValue invoicedAdjustment = (GenericValue) iait.next();
+            invoicedTotal = 
invoicedTotal.add(invoicedAdjustment.getBigDecimal("amount").setScale(decimals, 
rounding));
+        }
+        result.put("invoicedTotal", invoicedTotal);
+        return result;
     }
 
     /**


Reply via email to