# HG changeset patch
# User Adrián Romero <adrianromero@openbravo.com>
# Date 1455817806 -3600
#      Thu Feb 18 18:50:06 2016 +0100
# Node ID e634410377a01df022af7c4415f531a3a1238d00
# Parent  d2efce7ba4a72ebc7da5a6dae0f54d7457557c04
Fixes issue 0032264: Taxes at document level are not properly calculated in some cases

diff --git a/web/org.openbravo.retail.posterminal/js/data/dataordertaxes.js b/web/org.openbravo.retail.posterminal/js/data/dataordertaxes.js
--- a/web/org.openbravo.retail.posterminal/js/data/dataordertaxes.js
+++ b/web/org.openbravo.retail.posterminal/js/data/dataordertaxes.js
@@ -66,7 +66,7 @@
 
   var getTaxRateNumber = function (taxRate) {
 
-      var rate = new BigDecimal(String(taxRate.get('rate'))); // 10
+      var rate = new BigDecimal(String(taxRate)); // 10
       return rate.divide(new BigDecimal('100'), 20, BigDecimal.prototype.ROUND_HALF_UP); // 0.10
       };
 
@@ -186,7 +186,7 @@
             if (!taxRate.get('summaryLevel')) {
 
               var taxId = taxRate.get('id');
-              var rate = getTaxRateNumber(taxRate);
+              var rate = getTaxRateNumber(taxRate.get('rate'));
               if (taxRate.get('cascade')) {
                 linerate = linerate.multiply(rate.add(BigDecimal.prototype.ONE));
                 taxamt = taxamt.multiply(new BigDecimal(String(OB.DEC.add(1, rate))));
@@ -257,10 +257,6 @@
           'pricenet': OB.DEC.add(line.get('pricenet'), roundedLinePriceNet)
         });
 
-        receipt.set('net', OB.DEC.add(receipt.get('net'), linenet), {
-          silent: true
-        });
-
         //We follow the same formula of function c_get_net_price_from_gross to compute the discounted net
         if (!(_.isNull(discountedGross) || _.isUndefined(discountedGross))) {
           if (taxamtdc && OB.DEC.toNumber(taxamtdc) !== 0) {
@@ -386,17 +382,14 @@
 
               if (taxes[taxId]) {
                 taxes[taxId].net = OB.DEC.add(taxes[taxId].net, taxLines[taxId].net);
-                taxes[taxId].amount = (taxRate.get('docTaxAmount') === 'D') //
-                ? OB.DEC.mul(taxes[taxId].net, getTaxRateNumber(taxRate)) // Calculate taxes At Document Level
-                : OB.DEC.add(taxes[taxId].amount, taxLines[taxId].amount); // Calculate taxes At Line Level
+                taxes[taxId].amount = OB.DEC.add(taxes[taxId].amount, taxLines[taxId].amount); // Calculate taxes At Line Level. If At Doc Level, adjustment is done at the end.
               } else {
                 taxes[taxId] = {};
                 taxes[taxId].name = taxRate.get('name');
+                taxes[taxId].docTaxAmount = taxRate.get('docTaxAmount');
                 taxes[taxId].rate = taxRate.get('rate');
                 taxes[taxId].net = taxLines[taxId].net;
-                taxes[taxId].amount = (taxRate.get('docTaxAmount') === 'D') //
-                ? OB.DEC.mul(taxes[taxId].net, getTaxRateNumber(taxRate)) // Initialize taxes At Document Level
-                : taxLines[taxId].amount; // Initialize taxes At Line Level
+                taxes[taxId].amount = taxLines[taxId].amount; // Initialize taxes At Line Level. If At Doc Level, adjustment is done at the end.
               }
             }
           });
@@ -495,40 +488,59 @@
       return Promise.all(_.map(receipt.get('lines').models, function (line) {
         return calcLineTaxesIncPrice(receipt, line);
       })).then(function () {
-        // Ajust receipt taxes if net + taxes !== gross
+
+        var taxFinal;
+        var newTotalNet;
+        var newNet;
+        var newAmount;
+        var totalTaxAmount = OB.DEC.Zero;
+        var totalGross = OB.DEC.Zero;
         var totalNet = OB.DEC.Zero;
-        var totalGross = OB.DEC.Zero;
-        var totalTaxAmount = OB.DEC.Zero;
-        var taxToAdjust = null;
-        var taxToAdjustMax = OB.DEC.Zero;
-        var adjustment;
+        var lineToAdjust = null;
+        var netToAdjust = OB.DEC.Zero;
 
         // Calculate taxes
         _.forEach(receipt.get('taxes'), function (tax, taxid) {
+          if (tax.docTaxAmount === 'D') {
+            // Adjust taxes in case of taxes at doc level...
+            taxFinal = OB.DEC.add(tax.net, tax.amount);
+            newNet = OB.DEC.div(taxFinal, OB.DEC.add(OB.DEC.One, getTaxRateNumber(tax.rate)));
+            newAmount = OB.DEC.sub(taxFinal, newNet);
+            tax.net = newNet;
+            tax.amount = newAmount;
+          }
           totalTaxAmount = OB.DEC.add(totalTaxAmount, tax.amount);
-          if (OB.DEC.abs(tax.amount) > taxToAdjustMax) {
-            taxToAdjust = tax;
-            taxToAdjustMax = OB.DEC.abs(tax.amount);
+        });
+
+        // And now Total Net = Total Gross - Sum(Tax Amounts)
+        // And adjust a line net if needed
+        receipt.get('lines').forEach(function (line) {
+          if (!_.isUndefined(line.get('discountedNet'))) {
+            // Include in the calculation only the lines that have a 'discountedNet' attribute
+            // because has been processed by calcLineTaxesIncPrice()
+            totalNet = OB.DEC.add(totalNet, line.get('discountedNet'));
+            totalGross = OB.DEC.add(totalGross, calculateDiscountedGross(line));
+
+            if (OB.DEC.abs(line.get('discountedNet')) > netToAdjust) {
+              lineToAdjust = line;
+              netToAdjust = OB.DEC.abs(line.get('discountedNet'));
+            }
+
           }
         });
 
-        if (taxToAdjust) {
-          // Adjust can be performed
-          // Calculate receipt net and gross
-          receipt.get('lines').forEach(function (line) {
-            if (!_.isUndefined(line.get('discountedNet'))) {
-              // Include in the calculation only the lines that have a 'discountedNet' attribute
-              // because has been processed by calcLineTaxesIncPrice()
-              totalNet = OB.DEC.add(totalNet, line.get('discountedNet'));
-              totalGross = OB.DEC.add(totalGross, calculateDiscountedGross(line));
-            }
+        // Adjust the selected line to verify: sum(linenets) = receiptnet
+        newTotalNet = OB.DEC.sub(totalGross, totalTaxAmount);
+        if (lineToAdjust && newTotalNet !== totalNet) {
+          lineToAdjust.set('discountedNet', OB.DEC.sub(OB.DEC.add(lineToAdjust.get('discountedNet'), newTotalNet), totalNet), {
+            silent: true
           });
+        }
 
-          adjustment = OB.DEC.sub(totalGross, OB.DEC.add(totalNet, totalTaxAmount));
-          if (adjustment !== OB.DEC.Zero) {
-            taxToAdjust.amount = OB.DEC.add(taxToAdjust.amount, adjustment);
-          }
-        }
+        // Sets the receipt Net
+        receipt.set('net', newTotalNet, {
+          silent: true
+        });
       });
       };
 
@@ -560,7 +572,7 @@
             if (!taxRate.get('summaryLevel')) {
 
               var taxId = taxRate.get('id');
-              var rate = getTaxRateNumber(taxRate);
+              var rate = getTaxRateNumber(taxRate.get('rate'));
               var net = OB.DEC.mul(pricenetAux, line.get('qty')); //=== discountedNet
               if (taxRate.get('cascade')) {
 
@@ -603,7 +615,7 @@
                   }
                 }
                 taxes[taxId].amount = (taxRate.get('docTaxAmount') === 'D') //
-                ? OB.DEC.mul(taxes[taxId].net, getTaxRateNumber(taxRate)) // Calculate taxes At Document Level
+                ? OB.DEC.mul(taxes[taxId].net, getTaxRateNumber(taxRate.get('rate'))) // Calculate taxes At Document Level
                 : OB.DEC.add(taxes[taxId].amount, amount); // Calculate taxes At Line Level
               } else {
                 taxes[taxId] = {};
@@ -620,7 +632,7 @@
                   }
                 }
                 taxes[taxId].amount = (taxRate.get('docTaxAmount') === 'D') //
-                ? OB.DEC.mul(taxes[taxId].net, getTaxRateNumber(taxRate)) // Calculate taxes At Document Level
+                ? OB.DEC.mul(taxes[taxId].net, getTaxRateNumber(taxRate.get('rate'))) // Calculate taxes At Document Level
                 : amount; // Calculate taxes At Line Level
               }
             } else {
@@ -829,6 +841,10 @@
             });
           }
         }
+
+        receipt.set('net', totalNet, {
+          silent: true
+        });
       });
       };
 
diff --git a/web/org.openbravo.retail.posterminal/js/model/order.js b/web/org.openbravo.retail.posterminal/js/model/order.js
--- a/web/org.openbravo.retail.posterminal/js/model/order.js
+++ b/web/org.openbravo.retail.posterminal/js/model/order.js
@@ -502,17 +502,6 @@
           });
         }
       }, this);
-
-      var totalnet = this.get('lines').reduce(function (memo, e) {
-        if (e.get('net')) {
-          return memo.add(new BigDecimal(String(e.get('net'))));
-        } else {
-          return memo.add(new BigDecimal('0'));
-        }
-      }, new BigDecimal(String(OB.DEC.Zero)));
-      totalnet = OB.DEC.toNumber(totalnet);
-
-      this.set('net', totalnet);
     },
     getTotal: function () {
       return this.getGross();
@@ -588,14 +577,6 @@
         silent: true
       });
       var saveAndTriggerEvents = function (gross) {
-          var net = me.get('lines').reduce(function (memo, e) {
-            var netLine = e.get('discountedNet');
-            if (netLine) {
-              return OB.DEC.add(memo, netLine);
-            } else {
-              return memo;
-            }
-          }, OB.DEC.Zero);
           //total qty
           var qty = me.get('lines').reduce(function (memo, e) {
             var qtyLine = e.getQty();
@@ -608,7 +589,6 @@
 
           // all attributes are set at once, preventing the change event of each attribute to be fired until all values are set
           me.set({
-            'net': net,
             'gross': gross,
             'qty': qty
           });
# HG changeset patch
# User Adrián Romero <adrianromero@openbravo.com>
# Date 1456390117 -3600
#      Thu Feb 25 09:48:37 2016 +0100
# Node ID 06d6c580eae939ff50b3bdaeecc16716fb9bba1c
# Parent  e634410377a01df022af7c4415f531a3a1238d00
Fixes issue 0032264: Taxes at document level are not properly calculated in some cases
Implementing taxes at document adjustments in price not including taxes

diff --git a/web/org.openbravo.retail.posterminal/js/data/dataordertaxes.js b/web/org.openbravo.retail.posterminal/js/data/dataordertaxes.js
--- a/web/org.openbravo.retail.posterminal/js/data/dataordertaxes.js
+++ b/web/org.openbravo.retail.posterminal/js/data/dataordertaxes.js
@@ -490,14 +490,15 @@
       })).then(function () {
 
         var taxFinal;
-        var newTotalNet;
         var newNet;
         var newAmount;
-        var totalTaxAmount = OB.DEC.Zero;
+        var adjustAmount;
+        var candidateLine = null;
+        var candidateTaxLineAmount = OB.DEC.Zero;
+        
         var totalGross = OB.DEC.Zero;
-        var totalNet = OB.DEC.Zero;
-        var lineToAdjust = null;
-        var netToAdjust = OB.DEC.Zero;
+        var newTotalTaxAmount = OB.DEC.Zero;
+        var newTotalNet = OB.DEC.Zero;
 
         // Calculate taxes
         _.forEach(receipt.get('taxes'), function (tax, taxid) {
@@ -506,11 +507,41 @@
             taxFinal = OB.DEC.add(tax.net, tax.amount);
             newNet = OB.DEC.div(taxFinal, OB.DEC.add(OB.DEC.One, getTaxRateNumber(tax.rate)));
             newAmount = OB.DEC.sub(taxFinal, newNet);
+            adjustAmount = OB.DEC.sub(tax.amount, newAmount);
             tax.net = newNet;
             tax.amount = newAmount;
+            
+            if (adjustAmount !== 0) {
+              // move te adjustment to a net line...
+              receipt.get('lines').forEach(function (line) {
+                if (!_.isUndefined(line.get('discountedNet'))) {
+                  // Include in the calculation only the lines that have a 'discountedNet' attribute
+                  // because has been processed by calcLineTaxesIncPrice()
+                  _.each(line.get('taxLines'), function (taxline, taxlineid) {
+                    if (taxid === taxlineid && Math.sign(newAmount) === Math.sign(taxline.amount)) {
+                      // Candidate for applying the adjustment
+                      if (OB.DEC.abs(taxline.amount) > candidateTaxLineAmount) {
+                        candidateTaxLineAmount = OB.DEC.abs(candidateTaxLineAmount);
+                        candidateLine = line;
+                      }
+                    }
+                  });
+                }
+              });  
+              // if line found to make adjustments, apply.
+              if (candidateLine) {
+                candidateLine.set('discountedNet', OB.DEC.add(candidateLine.get('discountedNet'), adjustAmount), {
+                  silent: true
+                });
+              }
+            }
           }
-          totalTaxAmount = OB.DEC.add(totalTaxAmount, tax.amount);
+          
+          // Accummulate the total tax amount in this loop too.
+          newTotalTaxAmount = OB.DEC.add(newTotalTaxAmount, tax.amount);
         });
+        
+        
 
         // And now Total Net = Total Gross - Sum(Tax Amounts)
         // And adjust a line net if needed
@@ -518,27 +549,17 @@
           if (!_.isUndefined(line.get('discountedNet'))) {
             // Include in the calculation only the lines that have a 'discountedNet' attribute
             // because has been processed by calcLineTaxesIncPrice()
-            totalNet = OB.DEC.add(totalNet, line.get('discountedNet'));
             totalGross = OB.DEC.add(totalGross, calculateDiscountedGross(line));
-
-            if (OB.DEC.abs(line.get('discountedNet')) > netToAdjust) {
-              lineToAdjust = line;
-              netToAdjust = OB.DEC.abs(line.get('discountedNet'));
-            }
-
           }
         });
 
         // Adjust the selected line to verify: sum(linenets) = receiptnet
-        newTotalNet = OB.DEC.sub(totalGross, totalTaxAmount);
-        if (lineToAdjust && newTotalNet !== totalNet) {
-          lineToAdjust.set('discountedNet', OB.DEC.sub(OB.DEC.add(lineToAdjust.get('discountedNet'), newTotalNet), totalNet), {
-            silent: true
-          });
-        }
+        newTotalNet = OB.DEC.sub(totalGross, newTotalTaxAmount);
 
         // Sets the receipt Net
-        receipt.set('net', newTotalNet, {
+        receipt.set(
+            'net', newTotalNet, 
+            'taxAmount', newTotalTaxAmount, {
           silent: true
         });
       });
@@ -614,13 +635,12 @@
                     taxes[taxId].net = OB.DEC.add(taxes[taxId].net, roundingLoses);
                   }
                 }
-                taxes[taxId].amount = (taxRate.get('docTaxAmount') === 'D') //
-                ? OB.DEC.mul(taxes[taxId].net, getTaxRateNumber(taxRate.get('rate'))) // Calculate taxes At Document Level
-                : OB.DEC.add(taxes[taxId].amount, amount); // Calculate taxes At Line Level
+                taxes[taxId].amount = OB.DEC.add(taxes[taxId].amount, amount);
               } else {
                 taxes[taxId] = {};
                 taxes[taxId].name = taxRate.get('name');
                 taxes[taxId].rate = taxRate.get('rate');
+                taxes[taxId].docTaxAmount = taxRate.get('docTaxAmount');
                 taxes[taxId].net = net;
                 if (discountedNet !== linenet) {
                   //If we lost precision because the price that we are showing is not the real one
@@ -631,9 +651,7 @@
                     taxes[taxId].net = OB.DEC.add(taxes[taxId].net, roundingLoses);
                   }
                 }
-                taxes[taxId].amount = (taxRate.get('docTaxAmount') === 'D') //
-                ? OB.DEC.mul(taxes[taxId].net, getTaxRateNumber(taxRate.get('rate'))) // Calculate taxes At Document Level
-                : amount; // Calculate taxes At Line Level
+                taxes[taxId].amount = amount;
               }
             } else {
               linetaxid = taxRate.get('id');
@@ -815,6 +833,10 @@
 
         var adjustment;
 
+//        taxes[taxId].amount = (taxRate.get('docTaxAmount') === 'D') //
+//        ? OB.DEC.mul(taxes[taxId].net, getTaxRateNumber(taxRate.get('rate'))) // Calculate taxes At Document Level
+//        : OB.DEC.add(taxes[taxId].amount, amount); // Calculate taxes At Line Level
+        
         receipt.get('lines').forEach(function (line) {
           totalNet = OB.DEC.add(totalNet, line.get('discountedNet'));
           gross = line.get('discountedGross');
# HG changeset patch
# User Adrián Romero <adrianromero@openbravo.com>
# Date 1456401667 -3600
#      Thu Feb 25 13:01:07 2016 +0100
# Node ID 61a6ee3c9cbc7ce563c244a5c9848dd5074d9f47
# Parent  06d6c580eae939ff50b3bdaeecc16716fb9bba1c
Fixes issue 0032264: Taxes at document level are not properly calculated in some cases
* Complete implementation of adjustments in taxes not including taxes

diff --git a/web/org.openbravo.retail.posterminal/js/data/dataordertaxes.js b/web/org.openbravo.retail.posterminal/js/data/dataordertaxes.js
--- a/web/org.openbravo.retail.posterminal/js/data/dataordertaxes.js
+++ b/web/org.openbravo.retail.posterminal/js/data/dataordertaxes.js
@@ -495,7 +495,7 @@
         var adjustAmount;
         var candidateLine = null;
         var candidateTaxLineAmount = OB.DEC.Zero;
-        
+
         var totalGross = OB.DEC.Zero;
         var newTotalTaxAmount = OB.DEC.Zero;
         var newTotalNet = OB.DEC.Zero;
@@ -510,7 +510,7 @@
             adjustAmount = OB.DEC.sub(tax.amount, newAmount);
             tax.net = newNet;
             tax.amount = newAmount;
-            
+
             if (adjustAmount !== 0) {
               // move te adjustment to a net line...
               receipt.get('lines').forEach(function (line) {
@@ -527,7 +527,7 @@
                     }
                   });
                 }
-              });  
+              });
               // if line found to make adjustments, apply.
               if (candidateLine) {
                 candidateLine.set('discountedNet', OB.DEC.add(candidateLine.get('discountedNet'), adjustAmount), {
@@ -536,12 +536,12 @@
               }
             }
           }
-          
+
           // Accummulate the total tax amount in this loop too.
           newTotalTaxAmount = OB.DEC.add(newTotalTaxAmount, tax.amount);
         });
-        
-        
+
+
 
         // And now Total Net = Total Gross - Sum(Tax Amounts)
         // And adjust a line net if needed
@@ -557,9 +557,7 @@
         newTotalNet = OB.DEC.sub(totalGross, newTotalTaxAmount);
 
         // Sets the receipt Net
-        receipt.set(
-            'net', newTotalNet, 
-            'taxAmount', newTotalTaxAmount, {
+        receipt.set('net', newTotalNet, 'taxAmount', newTotalTaxAmount, {
           silent: true
         });
       });
@@ -824,45 +822,49 @@
         return calcLineTaxesExcPrice(receipt, line);
       })).then(function () {
         // Ajust gross if net + taxes !== gross
-        var totalTaxAmount = OB.DEC.Zero;
+        var newAmount;
+        var adjustAmount;
+        var candidateLine = null;
+        var candidateTaxLineAmount = OB.DEC.Zero;
         var totalNet = OB.DEC.Zero;
-        var totalGross = OB.DEC.Zero;
-        var gross;
-        var lineToAdjust = null;
-        var lineToAdjustMax = OB.DEC.Zero;
 
-        var adjustment;
+        // Calculate taxes
+        _.forEach(receipt.get('taxes'), function (tax, taxid) {
+          if (tax.docTaxAmount === 'D') {
+            // Adjust taxes in case of taxes at doc level...
+            newAmount = OB.DEC.mul(tax.net, getTaxRateNumber(tax.rate));
+            adjustAmount = OB.DEC.sub(tax.amount, newAmount);
+            tax.amount = newAmount;
 
-//        taxes[taxId].amount = (taxRate.get('docTaxAmount') === 'D') //
-//        ? OB.DEC.mul(taxes[taxId].net, getTaxRateNumber(taxRate.get('rate'))) // Calculate taxes At Document Level
-//        : OB.DEC.add(taxes[taxId].amount, amount); // Calculate taxes At Line Level
-        
-        receipt.get('lines').forEach(function (line) {
-          totalNet = OB.DEC.add(totalNet, line.get('discountedNet'));
-          gross = line.get('discountedGross');
-          totalGross = OB.DEC.add(totalGross, gross);
-          if (OB.DEC.abs(gross) > lineToAdjustMax) {
-            lineToAdjustMax = gross;
-            lineToAdjust = line;
+            if (adjustAmount !== 0) {
+              // move te adjustment to a net line...
+              receipt.get('lines').forEach(function (line) {
+                _.each(line.get('taxLines'), function (taxline, taxlineid) {
+                  if (taxid === taxlineid && Math.sign(newAmount) === Math.sign(taxline.amount)) {
+                    // Candidate for applying the adjustment
+                    if (OB.DEC.abs(taxline.amount) > candidateTaxLineAmount) {
+                      candidateTaxLineAmount = OB.DEC.abs(candidateTaxLineAmount);
+                      candidateLine = line;
+                    }
+                  }
+                });
+              });
+              // if line found to make adjustments, apply.
+              if (candidateLine) {
+                candidateLine.set({
+                  'discountedGross': OB.DEC.sub(candidateLine.get('discountedGross'), adjustAmount),
+                  'gross': OB.DEC.sub(candidateLine.get('gross'), adjustAmount)
+                }, {
+                  silent: true
+                });
+              }
+            }
           }
         });
 
-        if (lineToAdjust) {
-          // Calculate taxes
-          _.forEach(receipt.get('taxes'), function (tax, taxid) {
-            totalTaxAmount = OB.DEC.add(totalTaxAmount, tax.amount);
-          });
-
-          adjustment = OB.DEC.sub(totalGross, OB.DEC.add(totalNet, totalTaxAmount));
-          if (adjustment !== OB.DEC.Zero) {
-            lineToAdjust.set({
-              'discountedGross': OB.DEC.sub(lineToAdjust.get('discountedGross'), adjustment),
-              'gross': OB.DEC.sub(lineToAdjust.get('gross'), adjustment)
-            }, {
-              silent: true
-            });
-          }
-        }
+        receipt.get('lines').forEach(function (line) {
+          totalNet = OB.DEC.add(totalNet, line.get('discountedNet'));
+        });
 
         receipt.set('net', totalNet, {
           silent: true
