diff options
| author | Simen A. W. Olsen <hello@simenandre.no> | 2026-10-27 17:19:57 +0100 |
|---|---|---|
| committer | Simen A. W. Olsen <hello@simenandre.no> | 2026-10-27 17:19:57 +0100 |
| commit | 0571b30b6da27dc4c9e617403deab09b974ac641 (patch) | |
| tree | f3dfab18e22a48d06c64e563ba9bcf478c01a5bc /internal/mapping/mapping_test.go | |
| download | accounted-multicase-intgr-main.tar.gz accounted-multicase-intgr-main.zip | |
Diffstat (limited to 'internal/mapping/mapping_test.go')
| -rw-r--r-- | internal/mapping/mapping_test.go | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/internal/mapping/mapping_test.go b/internal/mapping/mapping_test.go new file mode 100644 index 0000000..d9190cd --- /dev/null +++ b/internal/mapping/mapping_test.go @@ -0,0 +1,118 @@ +package mapping + +import ( + "errors" + "testing" + "time" + + "simenandre.no/accounted-multicase-intgr/internal/accounted" + "simenandre.no/accounted-multicase-intgr/internal/multicase" +) + +func config() *Config { + return &Config{ + Accounts: map[string]string{"3000": "3001", "1460": "1460", "4301": "4000"}, + CustomerLedgerAccount: "1510", + VATCodes: map[string]VATCode{ + "3": {Rate: 25, Account: "2611"}, + "6": {Rate: 0}, + }, + RoundingAccount: "3740", + MaxRoundingOre: 100, + SourceType: "manual", + } +} + +func voucher(lines ...multicase.Line) multicase.Voucher { + return multicase.Voucher{ + Type: "11", TypeText: "Faktura", Number: "100", Text: "Demo kunde", + Date: time.Date(2026, 10, 1, 0, 0, 0, 0, time.UTC), Lines: lines, + } +} + +func TestSplitNet(t *testing.T) { + tests := []struct { + gross, want int64 + rate float64 + }{ + {270019, 216015, 25}, + {-270019, -216015, 25}, + {12500, 10000, 25}, + {1, 1, 25}, + {11200, 10000, 12}, + {5000, 5000, 0}, + } + for _, tt := range tests { + if got := SplitNet(tt.gross, tt.rate); got != tt.want { + t.Errorf("SplitNet(%d, %v) = %d, want %d", tt.gross, tt.rate, got, tt.want) + } + } +} + +func TestBuildSplitsVATAndMapsCustomerLedger(t *testing.T) { + e, err := config().Build(voucher( + multicase.Line{Account: "3000", Amount: -270019, VATCode: "3", CustomerNo: "20001"}, + multicase.Line{Account: "20001", Amount: 270019, CustomerNo: "20001"}, + )) + if err != nil { + t.Fatal(err) + } + want := []accounted.Line{ + {Account: "3001", Credit: 216015}, + {Account: "2611", Credit: 54004}, + {Account: "1510", Debit: 270019}, + } + if len(e.Lines) != len(want) { + t.Fatalf("lines = %+v", e.Lines) + } + for i, w := range want { + g := e.Lines[i] + if g.Account != w.Account || g.Debit != w.Debit || g.Credit != w.Credit { + t.Errorf("line %d = %+v, want %+v", i, g, w) + } + } + if e.SourceID != "multicase:11:100" || e.EntryDate != "2026-10-01" || e.Description != "Faktura 100: Demo kunde" { + t.Errorf("header = %+v", e) + } +} + +func TestBuildReportsUnmapped(t *testing.T) { + _, err := config().Build(voucher( + multicase.Line{Account: "9999", Amount: -100}, + multicase.Line{Account: "1460", Amount: 100, VATCode: "42"}, + )) + var u *UnmappedError + if !errors.As(err, &u) || len(u.Accounts) != 1 || u.Accounts[0] != "9999" || len(u.VATCodes) != 1 || u.VATCodes[0] != "42" { + t.Fatalf("err = %v", err) + } +} + +func TestBuildRounding(t *testing.T) { + e, err := config().Build(voucher( + multicase.Line{Account: "1460", Amount: 1978734}, + multicase.Line{Account: "4301", Amount: -1832162}, + multicase.Line{Account: "4301", Amount: -146573}, + )) + if err != nil { + t.Fatal(err) + } + last := e.Lines[len(e.Lines)-1] + if last.Account != "3740" || last.Debit != 1 { + t.Errorf("rounding line = %+v", last) + } + + _, err = config().Build(voucher( + multicase.Line{Account: "1460", Amount: 1000}, + multicase.Line{Account: "4301", Amount: -500}, + )) + if err == nil { + t.Error("expected an error for a voucher off by more than max_rounding_ore") + } +} + +func TestBuildSkipsZeroLines(t *testing.T) { + _, err := config().Build(voucher(multicase.Line{Account: "20001", Amount: 0, CustomerNo: "20001"})) + if !errors.Is(err, ErrEmpty) { + t.Fatalf("err = %v, want ErrEmpty", err) + } +} |
