package ledger import ( "errors" "testing" "sultan/pkg/store" ) // Kunden entstehen automatisch aus Mandanten-IDs; vorhandene bleiben unberührt. func TestEnsureCustomers(t *testing.T) { l := open(t) if err := l.EnsureCustomers(ctx, "webproxy11", []TenantRef{{ID: "kunde", Name: "Kunde A"}, {ID: "andere", Name: "Andere"}}); err != nil { t.Fatal(err) } c, err := l.GetCustomer(ctx, "kunde") if err != nil || c.Name != "Kunde A" || !c.Auto || c.Cycle != CycleUnclassified || c.FlatRate != nil { t.Errorf("automatisch angelegt: %+v, %v", c, err) } // Von Hand geändert: ein späterer Bericht überschreibt nichts. c.Name, c.Group, c.Note, c.Cycle = "Kunde A GmbH", "extern", "Kumpel, zahlt in Bier", CycleQuarterly cents := int64(8900) c.FlatRate = ¢s if err := l.UpdateCustomer(ctx, c); err != nil { t.Fatal(err) } l.EnsureCustomers(ctx, "webproxy11", []TenantRef{{ID: "kunde", Name: "Neuer Name"}}) got, _ := l.GetCustomer(ctx, "kunde") if got.Name != "Kunde A GmbH" || got.Auto || got.Group != "extern" || got.Cycle != CycleQuarterly || *got.FlatRate != 8900 { t.Errorf("nach erneutem Bericht: %+v", got) } // Ungültige Mandanten-IDs (sollte es nicht geben) werden übersprungen. if err := l.EnsureCustomers(ctx, "webproxy11", []TenantRef{{ID: "Kein Gültiger"}}); err != nil { t.Errorf("ungültige ID: %v", err) } } // Zuordnung: Payee + Mandant > Mandant auf allen Payees > gleiche ID. Ein // zugeordneter Mandant erzeugt keinen eigenen Kunden mehr. func TestResolveCustomer(t *testing.T) { l := open(t) l.AddCustomer(ctx, Customer{ID: "k-1001", Name: "Kunde A"}) l.AddCustomer(ctx, Customer{ID: "familie", Name: "Familie", Group: "familie"}) if err := l.MapTenant(ctx, "", "kunde", "k-1001"); err != nil { t.Fatal(err) } if err := l.MapTenant(ctx, "webproxy12", "kunde-a", "k-1001"); err != nil { // Tippfehler auf Nebencluster t.Fatal(err) } l.EnsureCustomers(ctx, "webproxy11", []TenantRef{{ID: "kunde"}, {ID: "neffe"}}) l.EnsureCustomers(ctx, "webproxy12", []TenantRef{{ID: "kunde-a"}}) tests := []struct{ payee, tenant, want string }{ {"webproxy11", "kunde", "k-1001"}, {"webproxy12", "kunde", "k-1001"}, {"webproxy12", "kunde-a", "k-1001"}, {"webproxy11", "neffe", "neffe"}, // automatisch {"webproxy11", "unbekannt", ""}, } r, err := l.CustomerResolver(ctx) if err != nil { t.Fatal(err) } for _, tt := range tests { if got := r.Resolve(tt.payee, tt.tenant); got != tt.want { t.Errorf("Resolve(%s, %s) = %q, erwartet %q", tt.payee, tt.tenant, got, tt.want) } } if _, err := l.GetCustomer(ctx, "kunde"); !errors.Is(err, store.ErrNotFound) { t.Errorf("zugeordneter Mandant hat eigenen Kunden erzeugt: %v", err) } if _, err := l.GetCustomer(ctx, "kunde-a"); !errors.Is(err, store.ErrNotFound) { t.Errorf("Tippfehler-Mandant hat eigenen Kunden erzeugt: %v", err) } maps, _ := l.ListMappings(ctx) if len(maps) != 2 { t.Errorf("Zuordnungen: %+v", maps) } if err := l.UnmapTenant(ctx, "webproxy12", "kunde-a"); err != nil { t.Fatal(err) } if err := l.UnmapTenant(ctx, "webproxy12", "kunde-a"); !errors.Is(err, store.ErrNotFound) { t.Errorf("zweites Entfernen: %v", err) } if err := l.MapTenant(ctx, "", "x", "gibts-nicht"); !errors.Is(err, store.ErrNotFound) { t.Errorf("Zuordnung zu unbekanntem Kunden: %v", err) } } func TestCustomers_CRUD(t *testing.T) { l := open(t) if err := l.AddCustomer(ctx, Customer{ID: "familie", Name: "Familie", Group: "familie", Cycle: CycleYearly}); err != nil { t.Fatal(err) } if err := l.AddCustomer(ctx, Customer{ID: "familie", Name: "x"}); !errors.Is(err, store.ErrExists) { t.Errorf("doppelt: %v", err) } for _, bad := range []Customer{{ID: "Ungültig", Name: "x"}, {ID: "ok", Name: ""}, {ID: "ok2", Name: "x", Cycle: "wöchentlich"}} { if err := l.AddCustomer(ctx, bad); !errors.Is(err, store.ErrInvalid) { t.Errorf("%+v: %v", bad, err) } } l.AddCustomer(ctx, Customer{ID: "k-1001", Name: "Kunde A", Group: "extern"}) list, _ := l.ListCustomers(ctx) if len(list) != 2 || list[0].ID != "familie" { t.Errorf("Liste: %+v", list) } if err := l.UpdateCustomer(ctx, Customer{ID: "gibts-nicht", Name: "x"}); !errors.Is(err, store.ErrNotFound) { t.Errorf("Update unbekannt: %v", err) } l.MapTenant(ctx, "", "kunde", "k-1001") if err := l.DeleteCustomer(ctx, "k-1001"); err != nil { t.Fatal(err) } if maps, _ := l.ListMappings(ctx); len(maps) != 0 { t.Errorf("Zuordnungen nach Löschen: %+v", maps) } }