PDV: profil firme blokira nemoguće kombinacije, stope iz šifarnika umesto hardkoda

- Podešavanja: nemoguća kombinacija (samo evidencija + PDV/fiskalizacija=da)
  se sad odbija i na serveru, ne samo u brauzeru (validirajProfilFirme).
- Servis: fiskalni račun/refund više ne iskazuje PDV kad firma nije PDV
  obveznik (stavkeFiskalnogServisa nulira stopu, isto kao Prodaja).
- Avans: uklonjena hardkodovana konstanta 20% PDV — stopa se sad uzima iz
  šifarnika (Podešavanja → Kalkulacija i PDV) ili je 0 kad firma nije
  obveznik.
- fiskal.NapraviZahtev: uklonjen fallback koji je prepisivao namerno
  postavljenu 0% stopu nazad na 20% (poništavao je zaštitu Prodaje za
  ne-PDV firme).
- Forme (usluge, artikli) i validacija PDV stope u prodaji sad koriste
  šifarnik umesto literala 20 / 0,10,20.

Detaljna pravna analiza i status svake stavke u docs/Greške.md (van git-a).
This commit is contained in:
2026-07-03 01:50:57 +02:00
parent 85a2ee1b64
commit 524c6de6ba
11 changed files with 174 additions and 57 deletions
+7 -5
View File
@@ -63,7 +63,7 @@ func (h *Handler) NovaUsluga(w http.ResponseWriter, r *http.Request) {
if err != nil {
sifra = "USL-001"
}
h.renderujFormuUsluge(w, r, model.Usluga{Sifra: sifra, PdvStopa: 20, JedinicaMere: "usluga"}, false, "")
h.renderujFormuUsluge(w, r, model.Usluga{Sifra: sifra, PdvStopa: h.podrazumevanaPdvStopa(r.Context()), JedinicaMere: "usluga"}, false, "")
}
// IzmeniUslugu prikazuje formu sa postojećom uslugom
@@ -86,7 +86,7 @@ func (h *Handler) SacuvajUslugu(w http.ResponseWriter, r *http.Request) {
if _, ok := h.zahtevajDozvolu(w, r, "artikal.dodaj"); !ok {
return
}
usluga, greska := parseFormuUsluge(r)
usluga, greska := parseFormuUsluge(r, h.podrazumevanaPdvStopa(r.Context()))
if greska != "" {
h.renderujFormuUsluge(w, r, usluga, false, greska)
return
@@ -108,7 +108,7 @@ func (h *Handler) SacuvajIzmenuUsluge(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Neispravan ID usluge", http.StatusBadRequest)
return
}
usluga, greska := parseFormuUsluge(r)
usluga, greska := parseFormuUsluge(r, h.podrazumevanaPdvStopa(r.Context()))
usluga.ID = id
if greska != "" {
h.renderujFormuUsluge(w, r, usluga, true, greska)
@@ -139,7 +139,9 @@ func (h *Handler) ObrisiUslugu(w http.ResponseWriter, r *http.Request) {
}
// parseFormuUsluge čita i validira polja forme usluge. Vraća model i poruku o grešci.
func parseFormuUsluge(r *http.Request) (model.Usluga, string) {
// podrazumevanaStopa je opšta PDV stopa iz šifarnika (v. Handler.podrazumevanaPdvStopa) —
// koristi se samo kad korisnik nije uneo stopu, nikad hardkodovana vrednost.
func parseFormuUsluge(r *http.Request, podrazumevanaStopa float64) (model.Usluga, string) {
if err := r.ParseForm(); err != nil {
return model.Usluga{}, "Greška pri čitanju forme."
}
@@ -154,7 +156,7 @@ func parseFormuUsluge(r *http.Request) (model.Usluga, string) {
}
pdv, err := strconv.ParseFloat(strings.TrimSpace(r.FormValue("pdv_stopa")), 64)
if err != nil || pdv < 0 {
pdv = 20
pdv = podrazumevanaStopa
}
jm := strings.TrimSpace(r.FormValue("jedinica_mere"))