Bei Firmenanlage (Registrierung + Betreiber-Firmenanlage) müssen jetzt Adresse (Straße, PLZ, Ort, Land) und Abrechnungsdaten (Rechnungsemail, optional USt-IdNr.) erfasst werden, nicht nur der Firmenname (Migration 0023). USt-IdNr. bewusst optional - Kleinunternehmer nach §19 UStG haben keine. Neue Seite /verwaltung/firma (admin-only) zum Einsehen/ Nachtragen für bestehende Firmen. store.CreateAccount nimmt jetzt ein AccountInput statt nur einen Namen entgegen (Signaturänderung betrifft ~20 Testaufrufe, mechanisch umgestellt). register.html/ betreiber_account_neu.html auf form-card/form-grid umgestellt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
143 lines
5.2 KiB
Go
143 lines
5.2 KiB
Go
package web_test
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/netcell-it/deklarix/internal/store"
|
|
"github.com/netcell-it/deklarix/internal/web"
|
|
)
|
|
|
|
// genehmigeFall reicht einen Antrag ein und genehmigt ihn mit einem
|
|
// echten, zulässigen Werkzeug — Vorbereitung für Register-Tests, die
|
|
// einen tatsächlichen Registereintrag brauchen.
|
|
func genehmigeFall(t *testing.T, fs *fakeStore, s *web.Server) (accountID string) {
|
|
t.Helper()
|
|
acc, err := fs.CreateAccount(context.Background(), store.AccountInput{Name: "Register-Mandant"})
|
|
if err != nil {
|
|
t.Fatalf("CreateAccount: %v", err)
|
|
}
|
|
fs.werkzeuge["werkzeug-ok"] = store.Werkzeug{ID: "werkzeug-ok", Name: "ChatGPT Enterprise", AVVVerfuegbar: true, TrainingStandard: true}
|
|
mitarbeiterCookie := seedUserInAccount(t, fs, acc.ID, "mitarbeiter@example.com", "mitarbeiter")
|
|
createResp := postForm(t, s, mitarbeiterCookie, "/antraege", fullAntragForm())
|
|
if createResp.Code != http.StatusSeeOther {
|
|
t.Fatalf("Antrag anlegen: status = %d, body: %s", createResp.Code, createResp.Body.String())
|
|
}
|
|
var antragID string
|
|
for id := range fs.antraege {
|
|
if fs.antraege[id].AccountID == acc.ID {
|
|
antragID = id
|
|
}
|
|
}
|
|
verantwortlicherCookie := seedUserInAccount(t, fs, acc.ID, "verantwortlicher@example.com", "verantwortlicher")
|
|
entscheidenResp := postForm(t, s, verantwortlicherCookie, "/faelle/"+antragID+"/entscheiden", url.Values{
|
|
"entscheidung": {"genehmigt"}, "werkzeug_id": {"werkzeug-ok"},
|
|
})
|
|
if entscheidenResp.Code != http.StatusSeeOther {
|
|
t.Fatalf("Entscheiden: status = %d, body: %s", entscheidenResp.Code, entscheidenResp.Body.String())
|
|
}
|
|
return acc.ID
|
|
}
|
|
|
|
func TestGenehmigungErzeugtRegistereintrag(t *testing.T) {
|
|
fs := newFakeStore()
|
|
s := newServer(t, fs)
|
|
accountID := genehmigeFall(t, fs, s)
|
|
|
|
list := fs.registereintraege[accountID]
|
|
if len(list) != 1 {
|
|
t.Fatalf("registereintraege = %+v, want exactly one entry", list)
|
|
}
|
|
e := list[0]
|
|
if e.Werkzeug != "ChatGPT Enterprise" || e.Zweck != "Angebotstexte generieren" || e.Datenklasse != "personenbezogen" {
|
|
t.Errorf("Registereintrag = %+v, unerwartete Werte", e)
|
|
}
|
|
if e.Verantwortlicher != "verantwortlicher@example.com" {
|
|
t.Errorf("Verantwortlicher = %q, want verantwortlicher@example.com", e.Verantwortlicher)
|
|
}
|
|
}
|
|
|
|
func TestAbgelehnteEntscheidungErzeugtKeinenRegistereintrag(t *testing.T) {
|
|
fs := newFakeStore()
|
|
s := newServer(t, fs)
|
|
antragID, verantwortlicherCookie := seedFallImAccount(t, fs, s, "verantwortlicher")
|
|
|
|
resp := postForm(t, s, verantwortlicherCookie, "/faelle/"+antragID+"/entscheiden", url.Values{
|
|
"entscheidung": {"abgelehnt"}, "begruendung": {"Kein Werkzeug verfügbar"},
|
|
})
|
|
if resp.Code != http.StatusSeeOther {
|
|
t.Fatalf("status = %d, body: %s", resp.Code, resp.Body.String())
|
|
}
|
|
|
|
for _, list := range fs.registereintraege {
|
|
if len(list) != 0 {
|
|
t.Fatalf("expected no registereintrag for an abgelehnt Entscheidung, got %+v", list)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRegisterListeZeigtGenehmigung(t *testing.T) {
|
|
fs := newFakeStore()
|
|
s := newServer(t, fs)
|
|
accountID := genehmigeFall(t, fs, s)
|
|
verantwortlicherCookie := seedUserInAccount(t, fs, accountID, "reviewer@example.com", "pruefer")
|
|
|
|
resp := getWithCookie(t, s, verantwortlicherCookie, "/registereintraege")
|
|
if resp.Code != http.StatusOK {
|
|
t.Fatalf("status = %d, body: %s", resp.Code, resp.Body.String())
|
|
}
|
|
if !strings.Contains(resp.Body.String(), "ChatGPT Enterprise") {
|
|
t.Errorf("expected the genehmigtes werkzeug in the register, got: %s", resp.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestRegisterExportCSVEnthaeltEintrag(t *testing.T) {
|
|
fs := newFakeStore()
|
|
s := newServer(t, fs)
|
|
accountID := genehmigeFall(t, fs, s)
|
|
verantwortlicherCookie := seedUserInAccount(t, fs, accountID, "reviewer@example.com", "pruefer")
|
|
|
|
resp := getWithCookie(t, s, verantwortlicherCookie, "/registereintraege/export.csv")
|
|
if resp.Code != http.StatusOK {
|
|
t.Fatalf("status = %d, body: %s", resp.Code, resp.Body.String())
|
|
}
|
|
if ct := resp.Header().Get("Content-Type"); !strings.Contains(ct, "text/csv") {
|
|
t.Errorf("Content-Type = %q, want text/csv", ct)
|
|
}
|
|
if !strings.Contains(resp.Body.String(), "ChatGPT Enterprise") {
|
|
t.Errorf("expected the werkzeug in the CSV export, got: %s", resp.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestRegisterExportPDFReturnsPDF(t *testing.T) {
|
|
fs := newFakeStore()
|
|
s := newServer(t, fs)
|
|
accountID := genehmigeFall(t, fs, s)
|
|
verantwortlicherCookie := seedUserInAccount(t, fs, accountID, "reviewer@example.com", "pruefer")
|
|
|
|
resp := getWithCookie(t, s, verantwortlicherCookie, "/registereintraege/export.pdf")
|
|
if resp.Code != http.StatusOK {
|
|
t.Fatalf("status = %d, body: %s", resp.Code, resp.Body.String())
|
|
}
|
|
if ct := resp.Header().Get("Content-Type"); ct != "application/pdf" {
|
|
t.Errorf("Content-Type = %q, want application/pdf", ct)
|
|
}
|
|
if !strings.HasPrefix(resp.Body.String(), "%PDF") {
|
|
t.Error("expected the response body to start with the PDF magic bytes")
|
|
}
|
|
}
|
|
|
|
func TestMitarbeiterCannotAccessRegister(t *testing.T) {
|
|
fs := newFakeStore()
|
|
s := newServer(t, fs)
|
|
cookie := seedAccountWithRole(t, fs, "Test-Mandant", "mitarbeiter@example.com", "mitarbeiter")
|
|
|
|
resp := getWithCookie(t, s, cookie, "/registereintraege")
|
|
if resp.Code != http.StatusNotFound {
|
|
t.Fatalf("status = %d, want 404 for role mitarbeiter on /registereintraege", resp.Code)
|
|
}
|
|
}
|