Servis: idempotency zaštita od duplog POST-a pri kreiranju naloga (isti obrazac kao prodaja)
This commit is contained in:
@@ -39,8 +39,8 @@ Legenda ozbiljnosti: 🔴 visok · 🟡 srednji · 🟢 nizak
|
||||
|
||||
- [ ] Svih **20** `BeginTx(...)` poziva u `internal/db/sqlite/*.go` ima `defer tx.Rollback()` odmah posle provere greške (provereno u: `artikal.go`, `rezervni_kodovi.go`, `servisni_potrazivani_delovi.go`, `nabavka.go`, `prodaja.go`, `nivelacija.go`, `servisni_radovi.go`, `servisni_delovi.go`, `servis.go`) — **nema propusta**, bez akcije.
|
||||
|
||||
- [ ] 🟡 **`ServisRepo.Kreiraj` (`internal/db/sqlite/servis.go:142`) nema idempotency zaštitu** kakva je upravo dodata za `ProdajaRepo.Kreiraj` (migracija 106, `idempotency_key`). Broj naloga (`sledeciBrojServisa`) se generiše unutar iste tx (ispravno, sprečava koliziju brojeva), ali DVA nezavisna HTTP POST zahteva (mrežni retry, "Nazad" pa resubmit, dva otvorena taba) i dalje mogu napraviti DVA validna servisna naloga sa istim podacima ali različitim brojevima — isti arhitekturni gep koji je upravo zatvoren za prodaju. Handler: `internal/handler/servis.go` `SacuvajNalog` (red ~218).
|
||||
**Preporuka**: primeniti isti obrazac (idempotency_key kolona + parcijalni UNIQUE indeks + skriveno polje u `servis_forma.html`) ako se želi potpuna zaštita, konzistentno sa prodajom.
|
||||
- [x] 🟡 **`ServisRepo.Kreiraj` nema idempotency zaštitu — ISPRAVLJENO.**
|
||||
Primenjen isti obrazac kao za prodaju (migracija 106): nova migracija `migrations/107_servis_idempotency_key.sql` (kolona `idempotency_key` + parcijalni `UNIQUE` indeks na `servisni_nalozi`), `model.ServisniNalog.IdempotencyKey` polje, `ServisRepo.Kreiraj` (`internal/db/sqlite/servis.go`) proverava postojeći ključ pre insert-a i vraća postojeći ID ako je nalog već kreiran istim ključem, `parseFormuNaloga` (`internal/handler/servis.go`) čita `idempotency_key` iz forme, `servis_forma.html` dobija skriveno polje + JS UUID generator (samo za novi nalog, ne za izmenu). Dodat `internal/db/sqlite/servis_idempotency_test.go` (2 testa: sa ključem vraća isti ID, bez ključa prave se dva odvojena naloga kao ranije) — oba prolaze.
|
||||
|
||||
- [ ] 🟢 `NabavkaRepo.Kreiraj` (`internal/db/sqlite/nabavka.go:178`) nema interni sekvencijalni broj (koristi `broj_racuna` dobavljača, korisnički unet) — nema race-a oko generisanja broja, ali isti opšti rizik "dva odvojena POST-a = dve nabavke" postoji arhitekturno kao i svuda gde nema idempotency ključa. Niži prioritet jer nema poznatu žalbu/simptom.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user