Merge fix/nedoslednosti u develop

This commit is contained in:
2026-07-16 13:59:33 +02:00
11 changed files with 43 additions and 41 deletions
+1 -1
View File
@@ -6,5 +6,5 @@ type ErrNedovoljnoKolicine struct {
} }
func (e *ErrNedovoljnoKolicine) Error() string { func (e *ErrNedovoljnoKolicine) Error() string {
return "Nedovoljno količine na stanju za artikal: " + e.ArtikalNaziv return "ntech: nedovoljno količine na stanju za artikal: " + e.ArtikalNaziv
} }
+3
View File
@@ -29,6 +29,9 @@ var ErrArtikalDuplikatSifre = errors.New("ntech: šifra ili barkod artikla već
var ErrUslugaDuplikatSifre = errors.New("ntech: šifra usluge već postoji") var ErrUslugaDuplikatSifre = errors.New("ntech: šifra usluge već postoji")
var ErrTrosakDuplikatSifre = errors.New("ntech: šifra troška već postoji") var ErrTrosakDuplikatSifre = errors.New("ntech: šifra troška već postoji")
// ErrArtikalNePostoji se vraća kada se menja cena nepostojećeg artikla
var ErrArtikalNePostoji = errors.New("ntech: artikal ne postoji")
// ArtikalRepository definiše operacije nad artiklima // ArtikalRepository definiše operacije nad artiklima
type ArtikalRepository interface { type ArtikalRepository interface {
Lista(ctx context.Context, filter ArtikalFilter) ([]model.ArtikalSaKategorijom, error) Lista(ctx context.Context, filter ArtikalFilter) ([]model.ArtikalSaKategorijom, error)
+2 -4
View File
@@ -7,6 +7,7 @@ import (
"fmt" "fmt"
"time" "time"
"ntech/internal/db"
"ntech/internal/model" "ntech/internal/model"
) )
@@ -20,9 +21,6 @@ func NoviNivelacijaRepo(db *sql.DB) *NivelacijaRepo {
return &NivelacijaRepo{db: db} return &NivelacijaRepo{db: db}
} }
// ErrArtikalNePostoji se vraća kada se menja cena nepostojećeg artikla
var ErrArtikalNePostoji = errors.New("artikal ne postoji")
// PromeniCenu transakciono menja prodajnu cenu artikla i upisuje nivelacioni zapis. // PromeniCenu transakciono menja prodajnu cenu artikla i upisuje nivelacioni zapis.
// Stara cena se čita iz baze unutar transakcije; izvor je "rucno". // Stara cena se čita iz baze unutar transakcije; izvor je "rucno".
func (r *NivelacijaRepo) PromeniCenu(ctx context.Context, artikalID int64, novaCena float64, razlog string, korisnikID *int64) (*model.Nivelacija, error) { func (r *NivelacijaRepo) PromeniCenu(ctx context.Context, artikalID int64, novaCena float64, razlog string, korisnikID *int64) (*model.Nivelacija, error) {
@@ -35,7 +33,7 @@ func (r *NivelacijaRepo) PromeniCenu(ctx context.Context, artikalID int64, novaC
var stara float64 var stara float64
err = tx.QueryRowContext(ctx, "SELECT prodajna_cena FROM artikli WHERE id = ?", artikalID).Scan(&stara) err = tx.QueryRowContext(ctx, "SELECT prodajna_cena FROM artikli WHERE id = ?", artikalID).Scan(&stara)
if errors.Is(err, sql.ErrNoRows) { if errors.Is(err, sql.ErrNoRows) {
return nil, ErrArtikalNePostoji return nil, db.ErrArtikalNePostoji
} }
if err != nil { if err != nil {
return nil, fmt.Errorf("ntech: NivelacijaRepo.PromeniCenu: čitanje cene: %w", err) return nil, fmt.Errorf("ntech: NivelacijaRepo.PromeniCenu: čitanje cene: %w", err)
+2 -1
View File
@@ -5,6 +5,7 @@ import (
"errors" "errors"
"testing" "testing"
"ntech/internal/db"
"ntech/internal/model" "ntech/internal/model"
) )
@@ -62,7 +63,7 @@ func TestPromeniCenu_NepostojeciArtikal(t *testing.T) {
nivRepo := NoviNivelacijaRepo(baza) nivRepo := NoviNivelacijaRepo(baza)
_, err := nivRepo.PromeniCenu(ctx, 9999, 500, "test", nil) _, err := nivRepo.PromeniCenu(ctx, 9999, 500, "test", nil)
if !errors.Is(err, ErrArtikalNePostoji) { if !errors.Is(err, db.ErrArtikalNePostoji) {
t.Errorf("greška = %v, očekivano ErrArtikalNePostoji", err) t.Errorf("greška = %v, očekivano ErrArtikalNePostoji", err)
} }
+2 -2
View File
@@ -5,7 +5,7 @@ import (
"strings" "strings"
"time" "time"
ntechsqlite "ntech/internal/db/sqlite" "ntech/internal/db/sqlite"
"ntech/internal/middleware" "ntech/internal/middleware"
"ntech/internal/model" "ntech/internal/model"
) )
@@ -28,7 +28,7 @@ func (h *Handler) AdminBlokiraneIP(w http.ResponseWriter, r *http.Request) {
if _, ok := h.zahtevajDozvolu(w, r, "bezbednost.odblokiraj"); !ok { if _, ok := h.zahtevajDozvolu(w, r, "bezbednost.odblokiraj"); !ok {
return return
} }
podesavanja, err := ntechsqlite.DohvatiSvaPodesavanja(r.Context(), h.DB) podesavanja, err := sqlite.DohvatiSvaPodesavanja(r.Context(), h.DB)
if err != nil { if err != nil {
http.Error(w, "Greška pri učitavanju podešavanja", http.StatusInternalServerError) http.Error(w, "Greška pri učitavanju podešavanja", http.StatusInternalServerError)
return return
+2 -2
View File
@@ -10,7 +10,7 @@ import (
"unicode" "unicode"
"ntech/internal/config" "ntech/internal/config"
ntechsqlite "ntech/internal/db/sqlite" "ntech/internal/db/sqlite"
"ntech/internal/fiskal" "ntech/internal/fiskal"
"ntech/internal/middleware" "ntech/internal/middleware"
"ntech/internal/model" "ntech/internal/model"
@@ -46,7 +46,7 @@ func (h *Handler) FiskalniPazar(w http.ResponseWriter, r *http.Request) {
if _, ok := h.zahtevajDozvolu(w, r, "fiskal.pazar"); !ok { if _, ok := h.zahtevajDozvolu(w, r, "fiskal.pazar"); !ok {
return return
} }
podesavanja, err := ntechsqlite.DohvatiSvaPodesavanja(r.Context(), h.DB) podesavanja, err := sqlite.DohvatiSvaPodesavanja(r.Context(), h.DB)
if err != nil { if err != nil {
http.Error(w, "Greška pri učitavanju podešavanja", http.StatusInternalServerError) http.Error(w, "Greška pri učitavanju podešavanja", http.StatusInternalServerError)
return return
+2 -1
View File
@@ -7,6 +7,7 @@ import (
"strings" "strings"
"time" "time"
"ntech/internal/db"
"ntech/internal/db/sqlite" "ntech/internal/db/sqlite"
"ntech/internal/middleware" "ntech/internal/middleware"
"ntech/internal/model" "ntech/internal/model"
@@ -91,7 +92,7 @@ func (h *Handler) PromeniCenuArtikla(w http.ResponseWriter, r *http.Request) {
korisnikID := &k.ID korisnikID := &k.ID
_, err = h.NivelacijaRepo.PromeniCenu(r.Context(), id, novaCena, razlog, korisnikID) _, err = h.NivelacijaRepo.PromeniCenu(r.Context(), id, novaCena, razlog, korisnikID)
switch { switch {
case errors.Is(err, sqlite.ErrArtikalNePostoji): case errors.Is(err, db.ErrArtikalNePostoji):
middleware.SetFlash(w, r, h.DB, "greska", "Artikal nije pronađen.") middleware.SetFlash(w, r, h.DB, "greska", "Artikal nije pronađen.")
http.Redirect(w, r, "/magacin", http.StatusSeeOther) http.Redirect(w, r, "/magacin", http.StatusSeeOther)
case err != nil: case err != nil:
+24 -24
View File
@@ -24,7 +24,7 @@ import (
"ntech/internal/auth" "ntech/internal/auth"
"ntech/internal/db" "ntech/internal/db"
ntechsqlite "ntech/internal/db/sqlite" "ntech/internal/db/sqlite"
"ntech/internal/middleware" "ntech/internal/middleware"
"ntech/internal/model" "ntech/internal/model"
) )
@@ -314,7 +314,7 @@ func (h *Handler) Podesavanja(w http.ResponseWriter, r *http.Request) {
if _, ok := h.zahtevajDozvolu(w, r, "podesavanja.pregled"); !ok { if _, ok := h.zahtevajDozvolu(w, r, "podesavanja.pregled"); !ok {
return return
} }
podesavanja, err := ntechsqlite.DohvatiSvaPodesavanja(r.Context(), h.DB) podesavanja, err := sqlite.DohvatiSvaPodesavanja(r.Context(), h.DB)
if err != nil { if err != nil {
http.Error(w, "Greška pri učitavanju podešavanja", http.StatusInternalServerError) http.Error(w, "Greška pri učitavanju podešavanja", http.StatusInternalServerError)
return return
@@ -450,7 +450,7 @@ func (h *Handler) VratiBackup(w http.ResponseWriter, r *http.Request) {
os.Remove(h.PutanjaBaze + "-wal") os.Remove(h.PutanjaBaze + "-wal")
os.Remove(h.PutanjaBaze + "-shm") os.Remove(h.PutanjaBaze + "-shm")
novaDB, err := ntechsqlite.OtvoriDB(h.PutanjaBaze) novaDB, err := sqlite.OtvoriDB(h.PutanjaBaze)
if err != nil { if err != nil {
slog.Error("vrati backup: greška pri otvaranju nove baze (potreban restart)", "error", err) slog.Error("vrati backup: greška pri otvaranju nove baze (potreban restart)", "error", err)
return return
@@ -567,7 +567,7 @@ func (h *Handler) UvezizBazu(w http.ResponseWriter, r *http.Request) {
os.Remove(h.PutanjaBaze + "-wal") os.Remove(h.PutanjaBaze + "-wal")
os.Remove(h.PutanjaBaze + "-shm") os.Remove(h.PutanjaBaze + "-shm")
novaDB, err := ntechsqlite.OtvoriDB(h.PutanjaBaze) novaDB, err := sqlite.OtvoriDB(h.PutanjaBaze)
if err != nil { if err != nil {
slog.Error("uvezi bazu: greška pri otvaranju nove baze (potreban restart)", "error", err) slog.Error("uvezi bazu: greška pri otvaranju nove baze (potreban restart)", "error", err)
return return
@@ -699,7 +699,7 @@ func (h *Handler) SacuvajPodesavanja(w http.ResponseWriter, r *http.Request) {
if vrednost == "" { if vrednost == "" {
continue continue
} }
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, kljuc, vrednost); err != nil { if err := sqlite.SacuvajPodesavanje(r.Context(), h.DB, kljuc, vrednost); err != nil {
http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError) http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError)
return return
} }
@@ -728,7 +728,7 @@ func (h *Handler) SacuvajPodesavanja(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, sledeci, http.StatusSeeOther) http.Redirect(w, r, sledeci, http.StatusSeeOther)
return return
} }
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "backup_interval_sati", strconv.Itoa(n)); err != nil { if err := sqlite.SacuvajPodesavanje(r.Context(), h.DB, "backup_interval_sati", strconv.Itoa(n)); err != nil {
http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError) http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError)
return return
} }
@@ -740,7 +740,7 @@ func (h *Handler) SacuvajPodesavanja(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, sledeci, http.StatusSeeOther) http.Redirect(w, r, sledeci, http.StatusSeeOther)
return return
} }
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "backup_broj_kopija", strconv.Itoa(n)); err != nil { if err := sqlite.SacuvajPodesavanje(r.Context(), h.DB, "backup_broj_kopija", strconv.Itoa(n)); err != nil {
http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError) http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError)
return return
} }
@@ -754,7 +754,7 @@ func (h *Handler) SacuvajPodesavanja(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, sledeci, http.StatusSeeOther) http.Redirect(w, r, sledeci, http.StatusSeeOther)
return return
} }
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "kalkulacija_marza", strconv.FormatFloat(marza, 'f', -1, 64)); err != nil { if err := sqlite.SacuvajPodesavanje(r.Context(), h.DB, "kalkulacija_marza", strconv.FormatFloat(marza, 'f', -1, 64)); err != nil {
http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError) http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError)
return return
} }
@@ -768,7 +768,7 @@ func (h *Handler) SacuvajPodesavanja(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, sledeci, http.StatusSeeOther) http.Redirect(w, r, sledeci, http.StatusSeeOther)
return return
} }
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "servis_garancija_dana", strconv.Itoa(n)); err != nil { if err := sqlite.SacuvajPodesavanje(r.Context(), h.DB, "servis_garancija_dana", strconv.Itoa(n)); err != nil {
http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError) http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError)
return return
} }
@@ -782,7 +782,7 @@ func (h *Handler) SacuvajPodesavanja(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, sledeci, http.StatusSeeOther) http.Redirect(w, r, sledeci, http.StatusSeeOther)
return return
} }
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "servis_cena_dijagnostike", strconv.FormatFloat(cena, 'f', -1, 64)); err != nil { if err := sqlite.SacuvajPodesavanje(r.Context(), h.DB, "servis_cena_dijagnostike", strconv.FormatFloat(cena, 'f', -1, 64)); err != nil {
http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError) http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError)
return return
} }
@@ -796,7 +796,7 @@ func (h *Handler) SacuvajPodesavanja(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, sledeci, http.StatusSeeOther) http.Redirect(w, r, sledeci, http.StatusSeeOther)
return return
} }
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "predracun_rok_dana", strconv.Itoa(n)); err != nil { if err := sqlite.SacuvajPodesavanje(r.Context(), h.DB, "predracun_rok_dana", strconv.Itoa(n)); err != nil {
http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError) http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError)
return return
} }
@@ -809,7 +809,7 @@ func (h *Handler) SacuvajPodesavanja(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, sledeci, http.StatusSeeOther) http.Redirect(w, r, sledeci, http.StatusSeeOther)
return return
} }
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "predvidjen_rok_dana", strconv.Itoa(n)); err != nil { if err := sqlite.SacuvajPodesavanje(r.Context(), h.DB, "predvidjen_rok_dana", strconv.Itoa(n)); err != nil {
http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError) http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError)
return return
} }
@@ -819,7 +819,7 @@ func (h *Handler) SacuvajPodesavanja(w http.ResponseWriter, r *http.Request) {
// pa korisnik može i da skrati ili isprazni tekst // pa korisnik može i da skrati ili isprazni tekst
if _, ima := r.Form["servis_uslovi"]; ima { if _, ima := r.Form["servis_uslovi"]; ima {
uslovi := strings.TrimSpace(r.FormValue("servis_uslovi")) uslovi := strings.TrimSpace(r.FormValue("servis_uslovi"))
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "servis_uslovi", uslovi); err != nil { if err := sqlite.SacuvajPodesavanje(r.Context(), h.DB, "servis_uslovi", uslovi); err != nil {
http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError) http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError)
return return
} }
@@ -828,7 +828,7 @@ func (h *Handler) SacuvajPodesavanja(w http.ResponseWriter, r *http.Request) {
// klauzula na predračunu (slobodan tekst); čuva se uvek // klauzula na predračunu (slobodan tekst); čuva se uvek
if _, ima := r.Form["servis_klauzula_predracuna"]; ima { if _, ima := r.Form["servis_klauzula_predracuna"]; ima {
klauzula := strings.TrimSpace(r.FormValue("servis_klauzula_predracuna")) klauzula := strings.TrimSpace(r.FormValue("servis_klauzula_predracuna"))
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "servis_klauzula_predracuna", klauzula); err != nil { if err := sqlite.SacuvajPodesavanje(r.Context(), h.DB, "servis_klauzula_predracuna", klauzula); err != nil {
http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError) http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError)
return return
} }
@@ -837,7 +837,7 @@ func (h *Handler) SacuvajPodesavanja(w http.ResponseWriter, r *http.Request) {
// bazna adresa za QR kod (npr. http://192.168.1.25:3000); prazno → koristi se host iz zahteva // bazna adresa za QR kod (npr. http://192.168.1.25:3000); prazno → koristi se host iz zahteva
if _, ima := r.Form["qr_bazni_url"]; ima { if _, ima := r.Form["qr_bazni_url"]; ima {
bazni := strings.TrimSpace(r.FormValue("qr_bazni_url")) bazni := strings.TrimSpace(r.FormValue("qr_bazni_url"))
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "qr_bazni_url", bazni); err != nil { if err := sqlite.SacuvajPodesavanje(r.Context(), h.DB, "qr_bazni_url", bazni); err != nil {
http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError) http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError)
return return
} }
@@ -943,7 +943,7 @@ func (h *Handler) OtpremiLogo(w http.ResponseWriter, r *http.Request) {
// timestamp u URL-u sprečava browser da koristi staru keširanu sliku // timestamp u URL-u sprečava browser da koristi staru keširanu sliku
putanja := fmt.Sprintf("/static/uploads/logo%s?v=%d", ext, time.Now().Unix()) putanja := fmt.Sprintf("/static/uploads/logo%s?v=%d", ext, time.Now().Unix())
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "logo_putanja", putanja); err != nil { if err := sqlite.SacuvajPodesavanje(r.Context(), h.DB, "logo_putanja", putanja); err != nil {
slog.Error("upload loga: greška pri čuvanju putanje", "error", err) slog.Error("upload loga: greška pri čuvanju putanje", "error", err)
http.Redirect(w, r, "/admin/podesavanja/opste?logo_greska=Greška+pri+čuvanju+podešavanja", http.StatusSeeOther) http.Redirect(w, r, "/admin/podesavanja/opste?logo_greska=Greška+pri+čuvanju+podešavanja", http.StatusSeeOther)
return return
@@ -961,7 +961,7 @@ func (h *Handler) UkloniLogo(w http.ResponseWriter, r *http.Request) {
for _, s := range stari { for _, s := range stari {
os.Remove(s) os.Remove(s)
} }
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "logo_putanja", ""); err != nil { if err := sqlite.SacuvajPodesavanje(r.Context(), h.DB, "logo_putanja", ""); err != nil {
slog.Error("ukloni logo: greška pri čuvanju", "error", err) slog.Error("ukloni logo: greška pri čuvanju", "error", err)
} }
http.Redirect(w, r, "/admin/podesavanja/opste?sacuvano=1", http.StatusSeeOther) http.Redirect(w, r, "/admin/podesavanja/opste?sacuvano=1", http.StatusSeeOther)
@@ -1047,7 +1047,7 @@ func (h *Handler) OtpremiLoginPozadinu(w http.ResponseWriter, r *http.Request) {
} }
// briše staru pozadinu sa diska ako postoji // briše staru pozadinu sa diska ako postoji
staraPodesavanja, _ := ntechsqlite.DohvatiSvaPodesavanja(r.Context(), h.DB) staraPodesavanja, _ := sqlite.DohvatiSvaPodesavanja(r.Context(), h.DB)
if stara := staraPodesavanja["login_pozadina"]; stara != "" { if stara := staraPodesavanja["login_pozadina"]; stara != "" {
// putanja u bazi je oblika /static/uploads/ime.ext?v=..., izvlačimo samo ime fajla // putanja u bazi je oblika /static/uploads/ime.ext?v=..., izvlačimo samo ime fajla
deoBezverzije, _, _ := strings.Cut(stara, "?") deoBezverzije, _, _ := strings.Cut(stara, "?")
@@ -1081,7 +1081,7 @@ func (h *Handler) OtpremiLoginPozadinu(w http.ResponseWriter, r *http.Request) {
} }
putanja := fmt.Sprintf("/static/uploads/%s?v=%d", novoIme, time.Now().Unix()) putanja := fmt.Sprintf("/static/uploads/%s?v=%d", novoIme, time.Now().Unix())
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "login_pozadina", putanja); err != nil { if err := sqlite.SacuvajPodesavanje(r.Context(), h.DB, "login_pozadina", putanja); err != nil {
slog.Error("upload login pozadine: greška pri čuvanju putanje", "error", err) slog.Error("upload login pozadine: greška pri čuvanju putanje", "error", err)
middleware.SetFlash(w, r, h.DB, "greska", "Greška pri čuvanju podešavanja.") middleware.SetFlash(w, r, h.DB, "greska", "Greška pri čuvanju podešavanja.")
http.Redirect(w, r, "/admin/podesavanja/izgled", http.StatusSeeOther) http.Redirect(w, r, "/admin/podesavanja/izgled", http.StatusSeeOther)
@@ -1098,7 +1098,7 @@ func (h *Handler) UkloniLoginPozadinu(w http.ResponseWriter, r *http.Request) {
return return
} }
podesavanja, err := ntechsqlite.DohvatiSvaPodesavanja(r.Context(), h.DB) podesavanja, err := sqlite.DohvatiSvaPodesavanja(r.Context(), h.DB)
if err == nil { if err == nil {
if stara := podesavanja["login_pozadina"]; stara != "" { if stara := podesavanja["login_pozadina"]; stara != "" {
deoBezverzije, _, _ := strings.Cut(stara, "?") deoBezverzije, _, _ := strings.Cut(stara, "?")
@@ -1107,7 +1107,7 @@ func (h *Handler) UkloniLoginPozadinu(w http.ResponseWriter, r *http.Request) {
} }
} }
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "login_pozadina", ""); err != nil { if err := sqlite.SacuvajPodesavanje(r.Context(), h.DB, "login_pozadina", ""); err != nil {
slog.Error("ukloni login pozadinu: greška pri čuvanju", "error", err) slog.Error("ukloni login pozadinu: greška pri čuvanju", "error", err)
middleware.SetFlash(w, r, h.DB, "greska", "Greška pri uklanjanju slike.") middleware.SetFlash(w, r, h.DB, "greska", "Greška pri uklanjanju slike.")
http.Redirect(w, r, "/admin/podesavanja/izgled", http.StatusSeeOther) http.Redirect(w, r, "/admin/podesavanja/izgled", http.StatusSeeOther)
@@ -1164,7 +1164,7 @@ func (h *Handler) SacuvajLoginPozadinaStilove(w http.ResponseWriter, r *http.Req
"login_pozadina_opacity": opacityStr, "login_pozadina_opacity": opacityStr,
"login_pozadina_zatamnjenje_kartice": zatamnjenjeKarticeStr, "login_pozadina_zatamnjenje_kartice": zatamnjenjeKarticeStr,
} { } {
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, kljuc, vrednost); err != nil { if err := sqlite.SacuvajPodesavanje(r.Context(), h.DB, kljuc, vrednost); err != nil {
slog.Error("greška pri čuvanju stila login pozadine", "kljuc", kljuc, "error", err) slog.Error("greška pri čuvanju stila login pozadine", "kljuc", kljuc, "error", err)
middleware.SetFlash(w, r, h.DB, "greska", "Greška pri čuvanju podešavanja.") middleware.SetFlash(w, r, h.DB, "greska", "Greška pri čuvanju podešavanja.")
http.Redirect(w, r, "/admin/podesavanja/izgled", http.StatusSeeOther) http.Redirect(w, r, "/admin/podesavanja/izgled", http.StatusSeeOther)
@@ -1177,7 +1177,7 @@ func (h *Handler) SacuvajLoginPozadinaStilove(w http.ResponseWriter, r *http.Req
// napuniPodaciPodesavanja učitava sva podešavanja i kreira strukturu za template // napuniPodaciPodesavanja učitava sva podešavanja i kreira strukturu za template
func (h *Handler) napuniPodaciPodesavanja(r *http.Request, naslov string) (PodaciPodesavanja, error) { func (h *Handler) napuniPodaciPodesavanja(r *http.Request, naslov string) (PodaciPodesavanja, error) {
podesavanja, err := ntechsqlite.DohvatiSvaPodesavanja(r.Context(), h.DB) podesavanja, err := sqlite.DohvatiSvaPodesavanja(r.Context(), h.DB)
if err != nil { if err != nil {
return PodaciPodesavanja{}, err return PodaciPodesavanja{}, err
} }
@@ -1282,7 +1282,7 @@ func (h *Handler) TestFiskalizacije(w http.ResponseWriter, r *http.Request) {
} }
pfrURL := strings.TrimSpace(r.FormValue("pfr_url")) pfrURL := strings.TrimSpace(r.FormValue("pfr_url"))
if pfrURL == "" { if pfrURL == "" {
podesavanja, err := ntechsqlite.DohvatiSvaPodesavanja(r.Context(), h.DB) podesavanja, err := sqlite.DohvatiSvaPodesavanja(r.Context(), h.DB)
if err != nil { if err != nil {
http.Error(w, "Greška", http.StatusInternalServerError) http.Error(w, "Greška", http.StatusInternalServerError)
return return
+2 -2
View File
@@ -11,7 +11,7 @@ import (
"time" "time"
"ntech/internal/auth" "ntech/internal/auth"
ntechsqlite "ntech/internal/db/sqlite" "ntech/internal/db/sqlite"
"ntech/internal/middleware" "ntech/internal/middleware"
) )
@@ -39,7 +39,7 @@ func (h *Handler) PrikazPrijave(w http.ResponseWriter, r *http.Request) {
loginBlurPozadine := "0" loginBlurPozadine := "0"
loginBlurKartice := "12" loginBlurKartice := "12"
loginZatamnjenjeKartice := "0" loginZatamnjenjeKartice := "0"
if podesavanja, err := ntechsqlite.DohvatiSvaPodesavanja(context.Background(), h.DB); err == nil { if podesavanja, err := sqlite.DohvatiSvaPodesavanja(context.Background(), h.DB); err == nil {
loginPozadina = podesavanja["login_pozadina"] loginPozadina = podesavanja["login_pozadina"]
if v := podesavanja["login_pozadina_opacity"]; v != "" { if v := podesavanja["login_pozadina_opacity"]; v != "" {
loginOpacity = v loginOpacity = v
+2 -3
View File
@@ -613,9 +613,8 @@ func parseFormuProdaje(r *http.Request, validneStope map[float64]bool) (model.Pr
// StornoProdaje stornira prodajni nalog: vraća artikle na stanje i označava nalog kao storniran // StornoProdaje stornira prodajni nalog: vraća artikle na stanje i označava nalog kao storniran
func (h *Handler) StornoProdaje(w http.ResponseWriter, r *http.Request) { func (h *Handler) StornoProdaje(w http.ResponseWriter, r *http.Request) {
k := middleware.KorisnikIzKonteksta(r.Context()) k, ok := h.zahtevajDozvolu(w, r, "prodaja.storno")
if !h.DozvoleRepo.ImaDozvolu(r.Context(), k.Uloga, "prodaja.storno") { if !ok {
http.Error(w, "Nemate dozvolu za storniranje prodaje.", http.StatusForbidden)
return return
} }
id, err := parseID(chi.URLParam(r, "id")) id, err := parseID(chi.URLParam(r, "id"))
+1 -1
View File
@@ -317,7 +317,7 @@ function toggleCenaPdv() {
<h3>Promeni prodajnu cenu</h3> <h3>Promeni prodajnu cenu</h3>
<button type="submit" class="premesti-zatvori" aria-label="Zatvori">&times;</button> <button type="submit" class="premesti-zatvori" aria-label="Zatvori">&times;</button>
</form> </form>
<form method="POST" action="/magacin/promeni-cenu/{{.ID}}" style="display:flex;flex-direction:column;gap:12px;padding:16px;"> <form method="POST" action="/magacin/promeni-cenu/{{.ID}}" data-refresh="#magacin-rezultati" style="display:flex;flex-direction:column;gap:12px;padding:16px;">
<div style="font-size:13px;color:var(--tekst-sporedni);">Trenutna cena: <strong>{{dinariCeli .Cena}} din</strong></div> <div style="font-size:13px;color:var(--tekst-sporedni);">Trenutna cena: <strong>{{dinariCeli .Cena}} din</strong></div>
<div> <div>
<label class="polje-labela">Nova cena (din)</label> <label class="polje-labela">Nova cena (din)</label>