Sprečeno dupliranje prodaje/servisa, alat za usklađivanje šifri artikla, ispravke osvežavanja stranica, zaštita od duplikata kategorije/artikla/usluge/troška

- Prodaja i servis: broj naloga se generiše unutar transakcije upisa umesto unapred u handleru, čime se otklanja duplo kreiranje naloga pri dvostrukom slanju forme
- Servis izmena: uklonjen sudar generičkog i sopstvenog auto-snimanja forme (dva paralelna POST-a)
- Magacin: novi alat 'Uskladi šifre sa kategorijama' za masovnu ispravku šifri artikala posle uvođenja šifarnika po kategoriji
- Ispravljeno da forme na 9 stranica (kategorije, admin korisnici/dozvole, profil, podešavanja) posle akcije osveže prikaz umesto da ostanu zastarele do F5
- Kategorija, artikal, usluga i trošak: sprečeno dupliranje naziva/šifre/koda (UNIQUE indeksi + razumljive poruke grešaka)
This commit is contained in:
2026-07-07 03:50:31 +02:00
parent 1ff572dd77
commit bc60288a0d
28 changed files with 682 additions and 110 deletions
+54 -2
View File
@@ -1,6 +1,7 @@
package handler
import (
"errors"
"fmt"
"log/slog"
"net/http"
@@ -8,6 +9,7 @@ import (
"strings"
"time"
"ntech/internal/db"
"ntech/internal/db/sqlite"
"ntech/internal/middleware"
"ntech/internal/model"
@@ -121,7 +123,32 @@ func (h *Handler) SacuvajArtikal(w http.ResponseWriter, r *http.Request) {
id, err := h.Artikli.Kreiraj(r.Context(), &artikal)
if err != nil {
http.Error(w, "Greška pri čuvanju artikla", http.StatusInternalServerError)
poruka := "Greška pri čuvanju artikla."
if errors.Is(err, db.ErrArtikalDuplikatSifre) {
poruka = "Šifra ili barkod već postoji kod drugog artikla."
} else {
slog.Error("čuvanje artikla nije uspelo", "error", err)
}
podesavanja, _ := sqlite.DohvatiSvaPodesavanja(r.Context(), h.DB)
kategorije, _ := h.KategorijeRepo.Lista(r.Context())
dobavljaci, _ := h.DobavljaciRepo.Lista(r.Context(), "")
katIDStr := ""
if artikal.KategorijaID != nil {
katIDStr = strconv.FormatInt(*artikal.KategorijaID, 10)
}
ps := h.popuniPodaciStranice(r, podesavanja)
ps.Stranica = "magacin"
ps.NaslovStranice = "Novi artikal"
h.renderujFormuArtikla(w, PodaciFormeArtikla{
PodaciStranice: ps,
Artikal: artikal,
Kategorije: kategorije,
KategorijaIDStr: katIDStr,
Dobavljaci: dobavljaci,
IzabraniDobavljaci: mapaDobavljaca(citajDobavljaceForme(r)),
Greska: poruka,
Izmena: false,
})
return
}
artikal.ID = id
@@ -262,7 +289,32 @@ func (h *Handler) SacuvajIzmenuArtikla(w http.ResponseWriter, r *http.Request) {
artikal.ID = id
if err := h.Artikli.Izmeni(r.Context(), &artikal); err != nil {
http.Error(w, "Greška pri čuvanju izmene", http.StatusInternalServerError)
poruka := "Greška pri čuvanju izmene."
if errors.Is(err, db.ErrArtikalDuplikatSifre) {
poruka = "Šifra ili barkod već postoji kod drugog artikla."
} else {
slog.Error("čuvanje izmene artikla nije uspelo", "artikal_id", id, "error", err)
}
podesavanja, _ := sqlite.DohvatiSvaPodesavanja(r.Context(), h.DB)
kategorije, _ := h.KategorijeRepo.Lista(r.Context())
dobavljaci, _ := h.DobavljaciRepo.Lista(r.Context(), "")
katIDStr := ""
if artikal.KategorijaID != nil {
katIDStr = strconv.FormatInt(*artikal.KategorijaID, 10)
}
ps := h.popuniPodaciStranice(r, podesavanja)
ps.Stranica = "magacin"
ps.NaslovStranice = "Izmeni artikal"
h.renderujFormuArtikla(w, PodaciFormeArtikla{
PodaciStranice: ps,
Artikal: artikal,
Kategorije: kategorije,
KategorijaIDStr: katIDStr,
Dobavljaci: dobavljaci,
IzabraniDobavljaci: mapaDobavljaca(citajDobavljaceForme(r)),
Greska: poruka,
Izmena: true,
})
return
}