Author: jleroux
Date: Fri Oct  6 00:02:41 2006
New Revision: 453515

URL: http://svn.apache.org/viewvc?view=rev&rev=453515
Log:
This commit resolves "Percentage item and sale discounts not working" 
(https://issues.apache.org/jira/browse/OFBIZ-289)



Thanks to Ray Barlow for reporting and Si Chen/Iain Fogg for their clues. I 
have tested it quite thourougly it seems to work well. 

IMHO there is still work to be done for the receipt that does not show clearly 
the sale adjustment. But that's another story...

Added:
    incubator/ofbiz/trunk/framework/base/lib/plugin.jar   (with props)
Modified:
    
incubator/ofbiz/trunk/applications/accounting/src/org/ofbiz/accounting/invoice/InvoiceServices.java
    
incubator/ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderReadHelper.java
    incubator/ofbiz/trunk/applications/pos/src/org/ofbiz/pos/PosTransaction.java
    
incubator/ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductWorker.java

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=453515&r1=453514&r2=453515
==============================================================================
--- 
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
 Fri Oct  6 00:02:41 2006
@@ -105,6 +105,7 @@
     private static int rounding = 
UtilNumber.getBigDecimalRoundingMode("invoice.rounding");
     private static int taxDecimals = 
UtilNumber.getBigDecimalScale("salestax.calc.decimals");
     private static int taxRounding = 
UtilNumber.getBigDecimalScale("salestax.rounding");
+    public static final int taxCalcScale = 
UtilNumber.getBigDecimalScale("salestax.calc.decimals");
 
     public static final String resource = "AccountingUiLabels";
 
@@ -477,61 +478,73 @@
                     Iterator itemAdjIter = itemAdjustments.iterator();
                     while (itemAdjIter.hasNext()) {
                         GenericValue adj = (GenericValue) itemAdjIter.next();
-                        if (adj.get("amount") != null) {
+                        
+                        BigDecimal amount = new BigDecimal(0);
+                        if (adj.get("amount") != null) { 
                             // pro-rate the amount
-
                             // set decimals = 100 means we don't round this 
intermediate value, which is very important
-                            BigDecimal amount = 
adj.getBigDecimal("amount").divide(orderItem.getBigDecimal("quantity"), 100, 
rounding);
+                            amount = 
adj.getBigDecimal("amount").divide(orderItem.getBigDecimal("quantity"), 100, 
rounding);
                             amount = amount.multiply(billingQuantity);
                             amount = amount.setScale(decimals, rounding);
-
-                            Map createInvoiceItemAdjContext = 
FastMap.newInstance();
-                            createInvoiceItemAdjContext.put("invoiceId", 
invoiceId);
-                            
createInvoiceItemAdjContext.put("invoiceItemSeqId", invoiceItemSeqId);
-                            
createInvoiceItemAdjContext.put("invoiceItemTypeId", 
getInvoiceItemType(delegator, adj.getString("orderAdjustmentTypeId"), null, 
invoiceType, "INVOICE_ITM_ADJ"));
-                            createInvoiceItemAdjContext.put("description", 
adj.get("description"));
-                            createInvoiceItemAdjContext.put("quantity", new 
Double(1));
-                            createInvoiceItemAdjContext.put("amount", new 
Double(amount.doubleValue()));
-                            createInvoiceItemAdjContext.put("productId", 
orderItem.get("productId"));
-                            
createInvoiceItemAdjContext.put("productFeatureId", 
orderItem.get("productFeatureId"));
-                            
createInvoiceItemAdjContext.put("overrideGlAccountId", 
adj.get("overrideGlAccountId"));
-                            createInvoiceItemAdjContext.put("parentInvoiceId", 
invoiceId);
-                            
createInvoiceItemAdjContext.put("parentInvoiceItemSeqId", 
parentInvoiceItemSeqId);
-                            //createInvoiceItemAdjContext.put("uomId", "");
-                            createInvoiceItemAdjContext.put("userLogin", 
userLogin);
-                            createInvoiceItemAdjContext.put("taxAuthPartyId", 
adj.get("taxAuthPartyId"));
-                            createInvoiceItemAdjContext.put("taxAuthGeoId", 
adj.get("taxAuthGeoId"));
-                            
createInvoiceItemAdjContext.put("taxAuthorityRateSeqId", 
adj.get("taxAuthorityRateSeqId"));
-        
-                            // invoice items for sales tax are not taxable 
themselves
-                            // TODO: This is not an ideal solution. Instead, 
we need to use OrderAdjustment.includeInTax when it is implemented
-                            if 
(!(adj.getString("orderAdjustmentTypeId").equals("SALES_TAX"))) {
-                                createInvoiceItemAdjContext.put("taxableFlag", 
product.get("taxable"));    
-                            }
-        
-                            Map createInvoiceItemAdjResult = 
dispatcher.runSync("createInvoiceItem", createInvoiceItemAdjContext);
-                            if 
(ServiceUtil.isError(createInvoiceItemAdjResult)) {
-                                return 
ServiceUtil.returnError(UtilProperties.getMessage(resource,"AccountingErrorCreatingInvoiceItemFromOrder",locale),
 null, null, createInvoiceItemAdjResult);
-                            }
-
-                            // this adjustment amount
-                            BigDecimal thisAdjAmount = new 
BigDecimal(amount.doubleValue()).setScale(decimals, rounding);
-
-                            // adjustments only apply to totals when they are 
not tax or shipping adjustments
-                            if 
(!"SALES_TAX".equals(adj.getString("orderAdjustmentTypeId")) &&
-                                    
!"SHIPPING_ADJUSTMENT".equals(adj.getString("orderAdjustmentTypeId"))) {
-                                // increment the invoice subtotal
-                                invoiceSubTotal = 
invoiceSubTotal.add(thisAdjAmount).setScale(decimals, rounding);
-
-                                // add to the ship amount only if it applies 
to this item
-                                if (shippingApplies) {
-                                    invoiceShipProRateAmount = 
invoiceShipProRateAmount.add(thisAdjAmount).setScale(decimals, rounding);
-                                }
-                            }
-
-                            // increment the counter
-                            invoiceItemSeqNum++;
-                            invoiceItemSeqId = 
UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum, 2);
+                        }
+                        else if (adj.get("sourcePercentage") != null) { 
+                            // pro-rate the amount
+                            // set decimals = 100 means we don't round this 
intermediate value, which is very important
+                            BigDecimal percent = 
adj.getBigDecimal("sourcePercentage");
+                            percent = percent.divide(new BigDecimal(100), 100, 
rounding);
+                            amount = billingAmount.multiply(percent); 
+                            amount = 
amount.divide(orderItem.getBigDecimal("quantity"), 100, rounding);
+                            amount = amount.multiply(billingQuantity);
+                            amount = amount.setScale(decimals, rounding);
+                        }
+                        if (amount.signum() != 0) {                      
+                               Map createInvoiceItemAdjContext = 
FastMap.newInstance();
+                               createInvoiceItemAdjContext.put("invoiceId", 
invoiceId);
+                               
createInvoiceItemAdjContext.put("invoiceItemSeqId", invoiceItemSeqId);
+                               
createInvoiceItemAdjContext.put("invoiceItemTypeId", 
getInvoiceItemType(delegator, adj.getString("orderAdjustmentTypeId"), null, 
invoiceType, "INVOICE_ITM_ADJ"));
+                               createInvoiceItemAdjContext.put("description", 
adj.get("description"));
+                               createInvoiceItemAdjContext.put("quantity", new 
Double(1));
+                               createInvoiceItemAdjContext.put("amount", new 
Double(amount.doubleValue()));
+                               createInvoiceItemAdjContext.put("productId", 
orderItem.get("productId"));
+                               
createInvoiceItemAdjContext.put("productFeatureId", 
orderItem.get("productFeatureId"));
+                               
createInvoiceItemAdjContext.put("overrideGlAccountId", 
adj.get("overrideGlAccountId"));
+                               
createInvoiceItemAdjContext.put("parentInvoiceId", invoiceId);
+                               
createInvoiceItemAdjContext.put("parentInvoiceItemSeqId", 
parentInvoiceItemSeqId);
+                               //createInvoiceItemAdjContext.put("uomId", "");
+                               createInvoiceItemAdjContext.put("userLogin", 
userLogin);
+                               
createInvoiceItemAdjContext.put("taxAuthPartyId", adj.get("taxAuthPartyId"));
+                               createInvoiceItemAdjContext.put("taxAuthGeoId", 
adj.get("taxAuthGeoId"));
+                               
createInvoiceItemAdjContext.put("taxAuthorityRateSeqId", 
adj.get("taxAuthorityRateSeqId"));
+           
+                               // invoice items for sales tax are not taxable 
themselves
+                               // TODO: This is not an ideal solution. 
Instead, we need to use OrderAdjustment.includeInTax when it is implemented
+                               if 
(!(adj.getString("orderAdjustmentTypeId").equals("SALES_TAX"))) {
+                                   
createInvoiceItemAdjContext.put("taxableFlag", product.get("taxable"));    
+                               }
+           
+                               Map createInvoiceItemAdjResult = 
dispatcher.runSync("createInvoiceItem", createInvoiceItemAdjContext);
+                               if 
(ServiceUtil.isError(createInvoiceItemAdjResult)) {
+                                   return 
ServiceUtil.returnError(UtilProperties.getMessage(resource,"AccountingErrorCreatingInvoiceItemFromOrder",locale),
 null, null, createInvoiceItemAdjResult);
+                               }
+       
+                               // this adjustment amount
+                               BigDecimal thisAdjAmount = new 
BigDecimal(amount.doubleValue()).setScale(decimals, rounding);
+       
+                               // adjustments only apply to totals when they 
are not tax or shipping adjustments
+                               if 
(!"SALES_TAX".equals(adj.getString("orderAdjustmentTypeId")) &&
+                                       
!"SHIPPING_ADJUSTMENT".equals(adj.getString("orderAdjustmentTypeId"))) {
+                                   // increment the invoice subtotal
+                                   invoiceSubTotal = 
invoiceSubTotal.add(thisAdjAmount).setScale(decimals, rounding);
+       
+                                   // add to the ship amount only if it 
applies to this item
+                                   if (shippingApplies) {
+                                       invoiceShipProRateAmount = 
invoiceShipProRateAmount.add(thisAdjAmount).setScale(decimals, rounding);
+                                   }
+                               }
+       
+                               // increment the counter
+                               invoiceItemSeqNum++;
+                               invoiceItemSeqId = 
UtilFormatOut.formatPaddedNumber(invoiceItemSeqNum, 2);
                         }
                     }
                 }
@@ -605,7 +618,7 @@
                 BigDecimal adjAmount = calcHeaderAdj(delegator, adj, 
invoiceType, invoiceId, invoiceItemSeqId, 
                         orderSubTotal, invoiceSubTotal, invoiceQuantity, 
taxDecimals, taxRounding, userLogin, dispatcher, locale);
                 // this doesn't really effect anything; but just for our totals
-                invoiceSubTotal = 
invoiceSubTotal.add(adjAmount).setScale(decimals, rounding);
+                invoiceSubTotal = 
invoiceSubTotal.add(adjAmount).setScale(decimals, rounding);                
             }
 
             // check for previous order payments
@@ -1495,6 +1508,49 @@
             if (divisor.signum() != 0) {
                 // multiply first then divide to avoid rounding errors
                 amount = baseAdjAmount.multiply(multiplier).divide(divisor, 
decimals, rounding);
+            }
+            if (amount.signum() != 0) {
+                Map createInvoiceItemContext = FastMap.newInstance();
+                createInvoiceItemContext.put("invoiceId", invoiceId);
+                createInvoiceItemContext.put("invoiceItemSeqId", 
invoiceItemSeqId);
+                createInvoiceItemContext.put("invoiceItemTypeId", 
getInvoiceItemType(delegator, adj.getString("orderAdjustmentTypeId"), null, 
invoiceTypeId, "INVOICE_ADJ"));
+                createInvoiceItemContext.put("description", 
adj.get("description"));
+                createInvoiceItemContext.put("quantity", new Double(1));
+                createInvoiceItemContext.put("amount", new 
Double(amount.doubleValue()));
+                createInvoiceItemContext.put("overrideGlAccountId", 
adj.get("overrideGlAccountId"));
+                //createInvoiceItemContext.put("productId", 
orderItem.get("productId"));
+                //createInvoiceItemContext.put("productFeatureId", 
orderItem.get("productFeatureId"));
+                //createInvoiceItemContext.put("uomId", "");
+                //createInvoiceItemContext.put("taxableFlag", 
product.get("taxable"));
+                createInvoiceItemContext.put("taxAuthPartyId", 
adj.get("taxAuthPartyId"));
+                createInvoiceItemContext.put("taxAuthGeoId", 
adj.get("taxAuthGeoId"));
+                createInvoiceItemContext.put("taxAuthorityRateSeqId", 
adj.get("taxAuthorityRateSeqId"));
+                createInvoiceItemContext.put("userLogin", userLogin);
+
+                Map createInvoiceItemResult = null;
+                try {
+                    createInvoiceItemResult = 
dispatcher.runSync("createInvoiceItem", createInvoiceItemContext);
+                } catch( GenericServiceException e ) {
+                    String errMsg = 
UtilProperties.getMessage(resource,"AccountingServiceErrorCreatingInvoiceItemFromOrder",locale)
 + ": " + e.toString();
+                    Debug.logError(e, errMsg, module);
+                    ServiceUtil.returnError(errMsg);
+                }
+                if (ServiceUtil.isError(createInvoiceItemResult)) {
+                    
ServiceUtil.returnError(UtilProperties.getMessage(resource,"AccountingErrorCreatingInvoiceItemFromOrder",locale),
 null, null, createInvoiceItemResult);
+                }
+            }
+            amount.setScale(decimals, rounding);
+            adjAmount = amount;
+        }
+        else if (adj.get("sourcePercentage") != null) {
+            // pro-rate the amount
+            BigDecimal percent = adj.getBigDecimal("sourcePercentage");
+            percent = percent.divide(new BigDecimal(100), 100, rounding);      
        
+            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 = percent.multiply(divisor);
             }
             if (amount.signum() != 0) {
                 Map createInvoiceItemContext = FastMap.newInstance();

Modified: 
incubator/ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderReadHelper.java
URL: 
http://svn.apache.org/viewvc/incubator/ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderReadHelper.java?view=diff&rev=453515&r1=453514&r2=453515
==============================================================================
--- 
incubator/ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderReadHelper.java
 (original)
+++ 
incubator/ofbiz/trunk/applications/order/src/org/ofbiz/order/order/OrderReadHelper.java
 Fri Oct  6 00:02:41 2006
@@ -73,7 +73,8 @@
     public static final int taxCalcScale = 
UtilNumber.getBigDecimalScale("salestax.calc.decimals");
     public static final int taxFinalScale = 
UtilNumber.getBigDecimalRoundingMode("salestax.final.decimals");
     public static final int taxRounding = 
UtilNumber.getBigDecimalRoundingMode("salestax.rounding");
-    public static final BigDecimal ZERO = (new 
BigDecimal("0")).setScale(scale, rounding);
+    public static final BigDecimal ZERO = (new 
BigDecimal("0")).setScale(scale, rounding);    
+    public static final BigDecimal percentage = (new 
BigDecimal("0.01")).setScale(scale, rounding);    
 
     protected GenericValue orderHeader = null;
     protected List orderItemAndShipGrp = null;
@@ -2349,6 +2350,12 @@
             BigDecimal amount = 
orderAdjustment.getBigDecimal("amount").setScale(taxCalcScale, taxRounding); 
             adjustment = adjustment.add(amount);
         }
+        else if (orderAdjustment.get("sourcePercentage") != null) {
+            // round amount to best precision (taxCalcScale) because db value 
of 0.825 is pulled as 0.8249999...
+            BigDecimal percent = 
orderAdjustment.getBigDecimal("sourcePercentage").setScale(taxCalcScale,taxRounding);
+            BigDecimal amount = 
orderSubTotal.multiply(percent).multiply(percentage).setScale(taxCalcScale, 
taxRounding);
+            adjustment = adjustment.add(amount);
+        }        
         return adjustment.setScale(scale, rounding);
     }
 
@@ -2609,6 +2616,9 @@
         BigDecimal adjustment = ZERO;
         if (itemAdjustment.get("amount") != null) {
             adjustment = 
adjustment.add(setScaleByType("SALES_TAX".equals(itemAdjustment.get("orderAdjustmentTypeId")),
 itemAdjustment.getBigDecimal("amount")));
+        }
+        else if (itemAdjustment.get("sourcePercentage") != null) {
+            adjustment = 
adjustment.add(setScaleByType("SALES_TAX".equals(itemAdjustment.get("orderAdjustmentTypeId")),
 
itemAdjustment.getBigDecimal("sourcePercentage").multiply(quantity).multiply(unitPrice).multiply(percentage)));
         }
         if (Debug.verboseOn()) Debug.logVerbose("calcItemAdjustment: " + 
itemAdjustment + ", quantity=" + quantity + ", unitPrice=" + unitPrice + ", 
adjustment=" + adjustment, module);
         return adjustment.setScale(scale, rounding);

Modified: 
incubator/ofbiz/trunk/applications/pos/src/org/ofbiz/pos/PosTransaction.java
URL: 
http://svn.apache.org/viewvc/incubator/ofbiz/trunk/applications/pos/src/org/ofbiz/pos/PosTransaction.java?view=diff&rev=453515&r1=453514&r2=453515
==============================================================================
--- 
incubator/ofbiz/trunk/applications/pos/src/org/ofbiz/pos/PosTransaction.java 
(original)
+++ 
incubator/ofbiz/trunk/applications/pos/src/org/ofbiz/pos/PosTransaction.java 
Fri Oct  6 00:02:41 2006
@@ -393,7 +393,7 @@
         GenericValue adjustment = 
session.getDelegator().makeValue("OrderAdjustment", null);
         adjustment.set("orderAdjustmentTypeId", "DISCOUNT_ADJUSTMENT");
         if (percent) {
-            adjustment.set("percentage", new Double(discount));
+            adjustment.set("sourcePercentage", new Double(discount * 100));
         } else {
             adjustment.set("amount", new Double(discount));
         }
@@ -405,7 +405,7 @@
             if (itemAdj != null) {
                 item.removeAdjustment(itemAdj.intValue());
             }
-            int idx = item.addAdjustment(adjustment);
+               int idx = item.addAdjustment(adjustment);    
             skuDiscounts.put(productId, new Integer(idx));
         } else {
             trace("add sale adjustment");

Modified: 
incubator/ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductWorker.java
URL: 
http://svn.apache.org/viewvc/incubator/ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductWorker.java?view=diff&rev=453515&r1=453514&r2=453515
==============================================================================
--- 
incubator/ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductWorker.java
 (original)
+++ 
incubator/ofbiz/trunk/applications/product/src/org/ofbiz/product/product/ProductWorker.java
 Fri Oct  6 00:02:41 2006
@@ -441,8 +441,8 @@
         if (orderAdjustment.get("amount") != null) {
             adjustment += orderAdjustment.getDouble("amount").doubleValue();
         }
-        if (orderAdjustment.get("percentage") != null) {
-            adjustment += 
(orderAdjustment.getDouble("percentage").doubleValue() * orderSubTotal);
+        else if (orderAdjustment.get("sourcePercentage") != null) {
+            adjustment += 
(orderAdjustment.getDouble("sourcePercentage").doubleValue() * orderSubTotal);
         }
         return adjustment;
     }    

Added: incubator/ofbiz/trunk/framework/base/lib/plugin.jar
URL: 
http://svn.apache.org/viewvc/incubator/ofbiz/trunk/framework/base/lib/plugin.jar?view=auto&rev=453515
==============================================================================
Binary file - no diff available.

Propchange: incubator/ofbiz/trunk/framework/base/lib/plugin.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream


Reply via email to