Repository: netlify/gocommerce
Pull request #188 (2019-09-11 16:33:00)

Calculate taxes based on original price if taxes are included
**- Summary**

Changes the way tax calculation is done when product listing prices include taxes (like in most VAT scenarios).

- Taxes are now calculated based on the original gross amount.
- Net total is calculated by subtracting taxes from gross amount.

**- Test plan**

- Updated tests to verify new behavior
- Added one new scenario that had wrong outcomes before

**- Description for the changelog**

Calculate taxes based on original price if taxes are included

**- A picture of a cute animal (not mandatory but encouraged)**

![](https://media.giphy.com/media/OsfRSG5QcGO8o/giphy.gif)


Patch:
diff --git a/api/payments.go b/api/payments.go
index 77548c3..3045fa8 100644
--- a/api/payments.go
+++ b/api/payments.go
@@ -513,13 +513,8 @@ func queryForOrder(db *gorm.DB, orderID string, log logrus.FieldLogger) (*models
 }
 
 func queryForTransactions(db *gorm.DB, log logrus.FieldLogger, clause, id string) ([]models.Transaction, *HTTPError) {
-	params := []interface{}{}
-	if clause != "" {
-		params = []interface{}{clause, id}
-	}
-
 	trans := []models.Transaction{}
-	if rsp := db.Find(&trans, params...); rsp.Error != nil {
+	if rsp := db.Find(&trans, clause, id); rsp.Error != nil {
 		if rsp.RecordNotFound() {
 			return nil, notFoundError("Transactions not found")
 		}
diff --git a/calculator/calculator.go b/calculator/calculator.go
index 715f438..4614cb6 100644
--- a/calculator/calculator.go
+++ b/calculator/calculator.go
@@ -332,10 +332,13 @@ func calculateTaxes(amountToTax uint64, item Item, params PriceParameters, setti
 	subtotal = 0
 	for _, tax := range taxAmounts {
 		if includeTaxes {
-			tax.price = rint(float64(tax.price) / (100 + float64(tax.percentage)) * 100)
+			taxAmount := rint(float64(tax.price) / float64(100+tax.percentage) * 100 * (float64(tax.percentage) / 100))
+			tax.price -= taxAmount
+			taxes += taxAmount
+		} else {
+			taxes += rint(float64(tax.price) * float64(tax.percentage) / 100)
 		}
 		subtotal += tax.price
-		taxes += rint(float64(tax.price) * float64(tax.percentage) / 100)
 	}
 
 	return


Test patch:
diff --git a/calculator/calculator_test.go b/calculator/calculator_test.go
index 226a281..8db05fd 100644
--- a/calculator/calculator_test.go
+++ b/calculator/calculator_test.go
@@ -349,15 +349,6 @@ func TestMixedDiscounts(t *testing.T) {
 func TestRealWorldTaxCalculations(t *testing.T) {
 	settings := &Settings{
 		PricesIncludeTaxes: true,
-		Taxes: []*Tax{&Tax{
-			Percentage:   7,
-			ProductTypes: []string{"Book"},
-			Countries:    []string{"USA"},
-		}, &Tax{
-			Percentage:   19,
-			ProductTypes: []string{"E-Book"},
-			Countries:    []string{"USA"},
-		}},
 	}
 
 	item1 := &TestItem{
@@ -371,26 +362,63 @@ func TestRealWorldTaxCalculations(t *testing.T) {
 			itemType: "E-Book",
 		}},
 	}
-	item2 := &TestItem{
-		price:    3490,
-		itemType: "Book",
-		items: []Item{&TestItem{
-			price:    2300,
-			itemType: "Book",
-		}, &TestItem{
-			price:    1190,
-			itemType: "E-Book",
-		}},
-	}
-	params := PriceParameters{"USA", "USD", nil, []Item{item1, item2}}
-	price := CalculatePrice(settings, nil, params, testLogger)
 
-	validatePrice(t, price, Price{
-		Subtotal: 5766,
-		Discount: 0,
-		NetTotal: 5766,
-		Taxes:    625,
-		Total:    6391,
+	t.Run("Single items", func(t *testing.T) {
+		settings.Taxes = []*Tax{&Tax{
+			Percentage:   7,
+			ProductTypes: []string{"Book"},
+			Countries:    []string{"USA"},
+		}, &Tax{
+			Percentage:   21,
+			ProductTypes: []string{"E-Book"},
+			Countries:    []string{"USA"},
+		}}
+
+		params := PriceParameters{"USA", "USD", nil, []Item{item1}}
+		price := CalculatePrice(settings, nil, params, testLogger)
+
+		validatePrice(t, price, Price{
+			Subtotal: 2602,
+			Discount: 0,
+			NetTotal: 2602,
+			Taxes:    298,
+			Total:    2900,
+		})
+	})
+
+	t.Run("Two items", func(t *testing.T) {
+		settings.Taxes = []*Tax{&Tax{
+			Percentage:   7,
+			ProductTypes: []string{"Book"},
+			Countries:    []string{"USA"},
+		}, &Tax{
+			Percentage:   19,
+			ProductTypes: []string{"E-Book"},
+			Countries:    []string{"USA"},
+		}}
+
+		item2 := &TestItem{
+			price:    3490,
+			itemType: "Book",
+			items: []Item{&TestItem{
+				price:    2300,
+				itemType: "Book",
+			}, &TestItem{
+				price:    1190,
+				itemType: "E-Book",
+			}},
+		}
+
+		params := PriceParameters{"USA", "USD", nil, []Item{item1, item2}}
+		price := CalculatePrice(settings, nil, params, testLogger)
+
+		validatePrice(t, price, Price{
+			Subtotal: 5766,
+			Discount: 0,
+			NetTotal: 5766,
+			Taxes:    624,
+			Total:    6390,
+		})
 	})
 }