Srednji prioritet iz pregleda koda: konzistentnost, refaktor, sitne popravke
- konstantno-vremensko poređenje CSRF tokena i kartica-PIN-a
- CSRF grupa proširena na /prijava, /prijava/totp, /setup
- router-level dozvola na svim /admin/podesavanja/* i modul("fiskalizacija")
na fiskal.pazar rutama
- KlijentRepo.Pronadji razlikuje sql.ErrNoRows od stvarnih DB grešaka
- izdvojen zajednički vratiStavkeNaStanje umesto 4 duplirana bloka
(ProdajaRepo/ServisRepo Storno/Obrisi)
- datumi u KIR/KPR sada se upisuju/porede kao "2006-01-02", usklađeno sa KPO
- ArtikalRepo.DohvatiVise (batch dohvat) — ukida N+1 upite u SacuvajNabavku
- KategorijaRepo.Obrisi umesto direktnog SQL-a u handleru, sa
ErrKategorijaUUpotrebi porukom
- KolicinMin -> KolicinaMin (tipfeler), Trosak/Usluga.DatumUnosa string -> time.Time
- dedup OznakaPoreskogBroja (KIR/KPR)
- inicijali() template funkcija (rune, ne bajtovi) za avatar inicijale
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"ntech/internal/db"
|
||||
"ntech/internal/db/sqlite"
|
||||
"ntech/internal/middleware"
|
||||
"ntech/internal/model"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
@@ -159,7 +162,12 @@ func (h *Handler) ObrisiKategoriju(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := h.DB.ExecContext(r.Context(), "DELETE FROM kategorije WHERE id = ?", id); err != nil {
|
||||
if err := h.KategorijeRepo.Obrisi(r.Context(), id); err != nil {
|
||||
if errors.Is(err, db.ErrKategorijaUUpotrebi) {
|
||||
middleware.SetFlash(w, r, h.DB, "greska", "Kategorija je u upotrebi kod artikala i ne može se obrisati.")
|
||||
http.Redirect(w, r, "/magacin/kategorije", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
http.Error(w, "Greška pri brisanju kategorije", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -129,6 +129,15 @@ var sablonskeFunkcije = template.FuncMap{
|
||||
},
|
||||
// zbirF64 vraća zbir dva float64 — za aritmetiku u šablonima
|
||||
"zbirF64": func(a, b float64) float64 { return a + b },
|
||||
// inicijali vraća prva najviše n RUNA stringa (ne bajta) — sigurno za ćirilicu
|
||||
// i č/ć/š/ž/đ, za razliku od ugrađenog {{slice}} koji seče po bajtovima.
|
||||
"inicijali": func(s string, n int) string {
|
||||
r := []rune(s)
|
||||
if len(r) > n {
|
||||
r = r[:n]
|
||||
}
|
||||
return string(r)
|
||||
},
|
||||
}
|
||||
|
||||
// KreirajKes parsuje sve šablone iz fsys i vraća ih keširane u mapi
|
||||
|
||||
@@ -374,13 +374,13 @@ func parseFormuArtikla(r *http.Request, podrazumevanaStopa float64) (model.Artik
|
||||
if err != nil || v < 0 {
|
||||
return artikal, "Minimalna količina mora biti pozitivan broj."
|
||||
}
|
||||
artikal.KolicinMin = v
|
||||
artikal.KolicinaMin = v
|
||||
}
|
||||
|
||||
// usluge i troškovi nemaju stanje na lageru
|
||||
if !artikal.PratiLager() {
|
||||
artikal.Kolicina = 0
|
||||
artikal.KolicinMin = 0
|
||||
artikal.KolicinaMin = 0
|
||||
}
|
||||
|
||||
if c := r.FormValue("nabavna_cena"); c != "" {
|
||||
|
||||
@@ -196,12 +196,27 @@ func (h *Handler) SacuvajNabavku(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// jedan batch-dohvat svih artikala iz stavki — umesto DohvatiID po stavki u svakoj petlji ispod
|
||||
artikalIDji := make([]int64, 0, len(stavke))
|
||||
vidjeni := make(map[int64]bool, len(stavke))
|
||||
for _, s := range stavke {
|
||||
if !vidjeni[s.ArtikalID] {
|
||||
vidjeni[s.ArtikalID] = true
|
||||
artikalIDji = append(artikalIDji, s.ArtikalID)
|
||||
}
|
||||
}
|
||||
artikliMapa, err := h.Artikli.DohvatiVise(r.Context(), artikalIDji)
|
||||
if err != nil {
|
||||
slog.Error("dohvat artikala za nabavku nije uspeo", "error", err)
|
||||
artikliMapa = map[int64]*model.Artikal{}
|
||||
}
|
||||
|
||||
// automatski zavedi u KPR ako je firma PDV obveznik; PDV se izvodi iz stope artikla
|
||||
if h.modulUkljucen(r.Context(), "pdv") {
|
||||
var stavkePdv []model.NabavkaStavkaPdv
|
||||
for _, s := range stavke {
|
||||
var stopa float64
|
||||
if a, e := h.Artikli.DohvatiID(r.Context(), s.ArtikalID); e == nil {
|
||||
if a, ok := artikliMapa[s.ArtikalID]; ok {
|
||||
stopa = a.PdvStopa
|
||||
}
|
||||
stavkePdv = append(stavkePdv, model.NabavkaStavkaPdv{
|
||||
@@ -241,7 +256,7 @@ func (h *Handler) SacuvajNabavku(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
// stara prodajna i tekuća (ponderisana) nabavna — nabavnu zadržavamo
|
||||
var staraProdajna, nabavna float64
|
||||
if a, e := h.Artikli.DohvatiID(r.Context(), s.ArtikalID); e == nil {
|
||||
if a, ok := artikliMapa[s.ArtikalID]; ok {
|
||||
staraProdajna = a.ProdajnaCena
|
||||
nabavna = a.NabavnaCena
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user