all the refactor
Build and Publish / BuildAndDeployAmd64 (push) Failing after 5s
Build and Publish / BuildAndDeployArm64 (push) Failing after 6s

This commit is contained in:
2026-06-28 17:51:52 +02:00
parent 7db0d236c7
commit aa8b2bdedc
84 changed files with 4328 additions and 2344 deletions
+51 -46
View File
@@ -3,10 +3,12 @@ package cart
import (
"encoding/json"
"testing"
"git.k6n.net/mats/platform/money"
)
func TestPriceMarshalJSON(t *testing.T) {
p := Price{IncVat: 13700, VatRates: map[float32]int64{25: 2500, 12: 1200}}
p := Price{IncVat: 13700, VatRates: map[int]money.Cents{2500: 2500, 1200: 1200}}
// ExVat = 13700 - (2500+1200) = 10000
data, err := json.Marshal(p)
if err != nil {
@@ -27,29 +29,29 @@ func TestPriceMarshalJSON(t *testing.T) {
if out.IncVat != 13700 {
t.Fatalf("expected incVat 13700 got %d", out.IncVat)
}
if out.Vat["25"] != 2500 || out.Vat["12"] != 1200 {
if out.Vat["2500"] != 2500 || out.Vat["1200"] != 1200 {
t.Fatalf("unexpected vat map: %#v", out.Vat)
}
}
func TestNewPriceFromIncVat(t *testing.T) {
p := NewPriceFromIncVat(1250, 25)
p := NewPriceFromIncVat(1250, 2500) // 25% in basis points
if p.IncVat != 1250 {
t.Fatalf("expected IncVat %d got %d", 1250, p.IncVat)
}
if p.VatRates[25] != 250 {
t.Fatalf("expected VAT 25 rate %d got %d", 250, p.VatRates[25])
if p.VatRates[2500] != 250 {
t.Fatalf("expected VAT 2500bp rate %d got %d", 250, p.VatRates[2500])
}
if p.ValueExVat() != 1000 {
t.Fatalf("expected exVat %d got %d", 750, p.ValueExVat())
t.Fatalf("expected exVat %d got %d", 1000, p.ValueExVat())
}
}
func TestSumPrices(t *testing.T) {
// We'll construct prices via raw struct since constructor expects tax math.
// IncVat already includes vat portions.
a := Price{IncVat: 1250, VatRates: map[float32]int64{25: 250}} // ex=1000
b := Price{IncVat: 2740, VatRates: map[float32]int64{25: 500, 12: 240}} // ex=2000
// IncVat already includes vat portions. Keys are basis points (2500 = 25%).
a := Price{IncVat: 1250, VatRates: map[int]money.Cents{2500: 250}} // ex=1000
b := Price{IncVat: 2740, VatRates: map[int]money.Cents{2500: 500, 1200: 240}} // ex=2000
c := Price{IncVat: 0, VatRates: nil}
sum := SumPrices(a, b, c)
@@ -60,11 +62,11 @@ func TestSumPrices(t *testing.T) {
if len(sum.VatRates) != 2 {
t.Fatalf("expected 2 vat rates got %d", len(sum.VatRates))
}
if sum.VatRates[25] != 750 {
t.Fatalf("expected 25%% vat 750 got %d", sum.VatRates[25])
if sum.VatRates[2500] != 750 {
t.Fatalf("expected 25%% vat 750 got %d", sum.VatRates[2500])
}
if sum.VatRates[12] != 240 {
t.Fatalf("expected 12%% vat 240 got %d", sum.VatRates[12])
if sum.VatRates[1200] != 240 {
t.Fatalf("expected 12%% vat 240 got %d", sum.VatRates[1200])
}
if sum.ValueExVat() != 3000 { // 3990 - (750+240)
t.Fatalf("expected exVat 3000 got %d", sum.ValueExVat())
@@ -73,19 +75,21 @@ func TestSumPrices(t *testing.T) {
func TestSumPricesEmpty(t *testing.T) {
sum := SumPrices()
if sum.IncVat != 0 || sum.VatRates == nil { // constructor sets empty map
// SumPrices nils an empty VatRates map (cleaner JSON); a nil map still reads
// as zero, so only the totals need to be zero here.
if sum.IncVat != 0 || sum.TotalVat() != 0 {
t.Fatalf("expected zero price got %#v", sum)
}
}
func TestMultiplyPriceFunction(t *testing.T) {
base := Price{IncVat: 1250, VatRates: map[float32]int64{25: 250}}
base := Price{IncVat: 1250, VatRates: map[int]money.Cents{2500: 250}}
multiplied := MultiplyPrice(base, 3)
if multiplied.IncVat != 1250*3 {
t.Fatalf("expected IncVat %d got %d", 1250*3, multiplied.IncVat)
}
if multiplied.VatRates[25] != 250*3 {
t.Fatalf("expected VAT 25 rate %d got %d", 250*3, multiplied.VatRates[25])
if multiplied.VatRates[2500] != 250*3 {
t.Fatalf("expected VAT 2500bp rate %d got %d", 250*3, multiplied.VatRates[2500])
}
if multiplied.ValueExVat() != (1250-250)*3 {
t.Fatalf("expected exVat %d got %d", (1250-250)*3, multiplied.ValueExVat())
@@ -93,8 +97,8 @@ func TestMultiplyPriceFunction(t *testing.T) {
}
func TestPriceAddSubtract(t *testing.T) {
a := Price{IncVat: 1000, VatRates: map[float32]int64{25: 200}}
b := Price{IncVat: 500, VatRates: map[float32]int64{25: 100, 12: 54}}
a := Price{IncVat: 1000, VatRates: map[int]money.Cents{2500: 200}}
b := Price{IncVat: 500, VatRates: map[int]money.Cents{2500: 100, 1200: 54}}
acc := NewPrice()
acc.Add(a)
@@ -103,7 +107,7 @@ func TestPriceAddSubtract(t *testing.T) {
if acc.IncVat != 1500 {
t.Fatalf("expected IncVat 1500 got %d", acc.IncVat)
}
if acc.VatRates[25] != 300 || acc.VatRates[12] != 54 {
if acc.VatRates[2500] != 300 || acc.VatRates[1200] != 54 {
t.Fatalf("unexpected VAT map: %#v", acc.VatRates)
}
@@ -113,46 +117,47 @@ func TestPriceAddSubtract(t *testing.T) {
if acc.IncVat != 0 {
t.Fatalf("expected IncVat 0 got %d", acc.IncVat)
}
if len(acc.VatRates) != 2 || acc.VatRates[25] != 0 || acc.VatRates[12] != 0 {
if len(acc.VatRates) != 2 || acc.VatRates[2500] != 0 || acc.VatRates[1200] != 0 {
t.Fatalf("expected zeroed vat rates got %#v", acc.VatRates)
}
}
func TestPriceMultiplyMethod(t *testing.T) {
p := Price{IncVat: 2000, VatRates: map[float32]int64{25: 400}}
p := Price{IncVat: 2000, VatRates: map[int]money.Cents{2500: 400}}
// Value before multiply
exBefore := p.ValueExVat()
p.Multiply(2)
if p.IncVat != 4000 {
t.Fatalf("expected IncVat 4000 got %d", p.IncVat)
}
if p.VatRates[25] != 800 {
t.Fatalf("expected VAT 800 got %d", p.VatRates[25])
if p.VatRates[2500] != 800 {
t.Fatalf("expected VAT 800 got %d", p.VatRates[2500])
}
if p.ValueExVat() != exBefore*2 {
t.Fatalf("expected exVat %d got %d", exBefore*2, p.ValueExVat())
}
}
func TestGetTaxAmount(t *testing.T) {
func TestComputeTax(t *testing.T) {
tests := []struct {
total int64
tax int
rateBp int
expected int64
desc string
}{
{1250, 2500, 250, "25% VAT"}, // 1250 / (1 + 100/25) = 1250 / 5 = 250
{1000, 2000, 166, "20% VAT"}, // 1000 / (1 + 100/20) = 1000 / 6 ≈ 166
// ex-VAT-first integer math: tax = total - total*10000/(10000+rateBp).
{1250, 2500, 250, "25% VAT"}, // exVat 1000, tax 250
{1000, 2000, 167, "20% VAT"}, // exVat 1000*10000/12000=833, tax 167 (Klarna convention)
{1200, 2500, 240, "25% VAT on 1200"},
{0, 2500, 0, "zero total"},
{100, 1000, 9, "10% VAT"}, // tax=1000 for 10%, 100 / (1 + 100/10) = 100 / 11 ≈ 9
{100, 10000, 50, "100% VAT"}, // tax=10000 for 100%, 100 / (1 + 100/100) = 100 / 2 = 50
{100, 1000, 10, "10% VAT"}, // exVat 100*10000/11000=90, tax 10
{100, 10000, 50, "100% VAT"}, // exVat 50, tax 50
}
for _, tt := range tests {
result := GetTaxAmount(tt.total, tt.tax)
result := ComputeTax(money.Cents(tt.total), tt.rateBp).Int64()
if result != tt.expected {
t.Errorf("GetTaxAmount(%d, %d) [%s] = %d; expected %d", tt.total, tt.tax, tt.desc, result, tt.expected)
t.Errorf("ComputeTax(%d, %d) [%s] = %d; expected %d", tt.total, tt.rateBp, tt.desc, result, tt.expected)
}
}
}
@@ -170,11 +175,11 @@ func TestNewPriceFromIncVatEdgeCases(t *testing.T) {
t.Errorf("expected exVat 1000, got %d", p.ValueExVat())
}
// High VAT rate, e.g., 50%
p = NewPriceFromIncVat(1500, 50)
expectedVat := int64(1500 / (1 + 100/50)) // 1500 / 3 = 500
if p.VatRates[50] != expectedVat {
t.Errorf("expected VAT %d for 50%%, got %d", expectedVat, p.VatRates[50])
// High VAT rate, e.g., 50% = 5000 basis points
p = NewPriceFromIncVat(1500, 5000)
expectedVat := money.Cents(500) // exVat 1500*10000/15000=1000, tax 500
if p.VatRates[5000] != expectedVat {
t.Errorf("expected VAT %d for 50%%, got %d", expectedVat, p.VatRates[5000])
}
if p.ValueExVat() != 1500-expectedVat {
t.Errorf("expected exVat %d, got %d", 1500-expectedVat, p.ValueExVat())
@@ -182,7 +187,7 @@ func TestNewPriceFromIncVatEdgeCases(t *testing.T) {
}
func TestPriceValueExVatAndTotalVat(t *testing.T) {
p := Price{IncVat: 13700, VatRates: map[float32]int64{25: 2500, 12: 1200}}
p := Price{IncVat: 13700, VatRates: map[int]money.Cents{2500: 2500, 1200: 1200}}
exVat := p.ValueExVat()
totalVat := p.TotalVat()
if exVat != 10000 {
@@ -206,33 +211,33 @@ func TestPriceValueExVatAndTotalVat(t *testing.T) {
}
func TestMultiplyPriceWithZeroQty(t *testing.T) {
base := Price{IncVat: 1250, VatRates: map[float32]int64{25: 250}}
base := Price{IncVat: 1250, VatRates: map[int]money.Cents{2500: 250}}
multiplied := MultiplyPrice(base, 0)
if multiplied.IncVat != 0 {
t.Errorf("expected IncVat 0, got %d", multiplied.IncVat)
}
if len(multiplied.VatRates) != 1 || multiplied.VatRates[25] != 0 {
if len(multiplied.VatRates) != 1 || multiplied.VatRates[2500] != 0 {
t.Errorf("expected VAT 0, got %v", multiplied.VatRates)
}
}
func TestPriceAddSubtractEdgeCases(t *testing.T) {
a := Price{IncVat: 1000, VatRates: map[float32]int64{25: 200}}
b := Price{IncVat: 500, VatRates: map[float32]int64{12: 54}} // Different rate
a := Price{IncVat: 1000, VatRates: map[int]money.Cents{2500: 200}}
b := Price{IncVat: 500, VatRates: map[int]money.Cents{1200: 54}} // Different rate
acc := NewPrice()
acc.Add(a)
acc.Add(b)
if acc.VatRates[25] != 200 || acc.VatRates[12] != 54 {
t.Errorf("expected VAT 25:200, 12:54, got %v", acc.VatRates)
if acc.VatRates[2500] != 200 || acc.VatRates[1200] != 54 {
t.Errorf("expected VAT 2500:200, 1200:54, got %v", acc.VatRates)
}
// Subtract more than added (negative VAT)
acc.Subtract(a)
acc.Subtract(b)
acc.Subtract(a) // Subtract extra a
if acc.VatRates[25] != -200 || acc.VatRates[12] != 0 {
t.Errorf("expected negative VAT for 25 after over-subtract, got %v", acc.VatRates)
if acc.VatRates[2500] != -200 || acc.VatRates[1200] != 0 {
t.Errorf("expected negative VAT for 2500 after over-subtract, got %v", acc.VatRates)
}
}