feat: Werkzeugkatalog-Pflege für die Plattform (Ebene 5)
Betreiber können den zentralen Werkzeugkatalog jetzt über die UI
pflegen (GET /betreiber/werkzeuge, GET/POST .../neu, GET/POST
.../{id}, POST .../{id}/loeschen) statt nur per SQL. Bearbeitet
ausschließlich zentrale (account_id IS NULL) Einträge — ein
mandantenspezifischer Katalogeintrag bleibt über diese Seiten
unerreichbar (404), das ist weiterhin Sache des jeweiligen Mandanten.
Ohne befüllten Katalog konnte bisher keine Bewertung tatsächlich zu
"genehmigt" mit einem echten Werkzeug führen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -269,6 +269,58 @@ func (f *fakeStore) ListWerkzeugeForAccount(ctx context.Context, accountID strin
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (f *fakeStore) ListZentraleWerkzeuge(ctx context.Context) ([]store.Werkzeug, error) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
var out []store.Werkzeug
|
||||
for _, w := range f.werkzeuge {
|
||||
if w.AccountID == nil {
|
||||
out = append(out, w)
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (f *fakeStore) CreateWerkzeug(ctx context.Context, in store.WerkzeugInput) (store.Werkzeug, error) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
w := store.Werkzeug{
|
||||
ID: f.newID(), AccountID: in.AccountID, Name: in.Name, Anbieter: in.Anbieter,
|
||||
Verarbeitungsort: in.Verarbeitungsort, AVVVerfuegbar: in.AVVVerfuegbar, AVVURL: in.AVVURL,
|
||||
TrainingOptOut: in.TrainingOptOut, TrainingStandard: in.TrainingStandard, AufbewahrungTage: in.AufbewahrungTage,
|
||||
Zertifizierungen: in.Zertifizierungen, GeeigneteZwecke: in.GeeigneteZwecke, Einschraenkungen: in.Einschraenkungen,
|
||||
LetztePruefung: in.LetztePruefung, Quelle: in.Quelle, CreatedAt: time.Now(), UpdatedAt: time.Now(),
|
||||
}
|
||||
f.werkzeuge[w.ID] = w
|
||||
return w, nil
|
||||
}
|
||||
|
||||
func (f *fakeStore) UpdateWerkzeug(ctx context.Context, id string, in store.WerkzeugInput) (store.Werkzeug, error) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
w, ok := f.werkzeuge[id]
|
||||
if !ok {
|
||||
return store.Werkzeug{}, store.ErrNotFound
|
||||
}
|
||||
w.Name, w.Anbieter, w.Verarbeitungsort = in.Name, in.Anbieter, in.Verarbeitungsort
|
||||
w.AVVVerfuegbar, w.AVVURL = in.AVVVerfuegbar, in.AVVURL
|
||||
w.TrainingOptOut, w.TrainingStandard, w.AufbewahrungTage = in.TrainingOptOut, in.TrainingStandard, in.AufbewahrungTage
|
||||
w.Zertifizierungen, w.GeeigneteZwecke, w.Einschraenkungen = in.Zertifizierungen, in.GeeigneteZwecke, in.Einschraenkungen
|
||||
w.LetztePruefung, w.Quelle, w.UpdatedAt = in.LetztePruefung, in.Quelle, time.Now()
|
||||
f.werkzeuge[id] = w
|
||||
return w, nil
|
||||
}
|
||||
|
||||
func (f *fakeStore) DeleteWerkzeug(ctx context.Context, id string) error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
if _, ok := f.werkzeuge[id]; !ok {
|
||||
return store.ErrNotFound
|
||||
}
|
||||
delete(f.werkzeuge, id)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *fakeStore) GetWerkzeug(ctx context.Context, id string) (store.Werkzeug, error) {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
@@ -666,7 +718,7 @@ func TestHandleIndexRendersForMitarbeiter(t *testing.T) {
|
||||
func TestBetreiberRoutesRejectNonBetreiberWith404(t *testing.T) {
|
||||
s, _, cookie := newAuthedTestServer(t)
|
||||
|
||||
for _, path := range []string{"/betreiber", "/betreiber/accounts", "/betreiber/audit-log"} {
|
||||
for _, path := range []string{"/betreiber", "/betreiber/accounts", "/betreiber/audit-log", "/betreiber/werkzeuge"} {
|
||||
resp := getWithCookie(t, s, cookie, path)
|
||||
if resp.Code != http.StatusNotFound {
|
||||
t.Errorf("GET %s status = %d, want 404 for a non-betreiber user", path, resp.Code)
|
||||
|
||||
Reference in New Issue
Block a user