From 51febc5d411e6ffd6b358ed1432062af664fea7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dalibor=20Markovi=C4=87?= Date: Tue, 23 Jun 2026 13:23:07 +0200 Subject: [PATCH] Servis: revers i predracun (iz stavki radova+delova), uslovi servisa u podesavanjima, status U dijagnostici - Revers (servis_revers.html) - dokument prijema bez cena, sa QR, oscecenjima i uslovima servisa - Predracun (servis_predracun.html) - procena iz stavki radova i delova, klauzula, dugme uvek dostupno - Podesavanja > Servis: kartica Uslovi servisa (servis_uslovi + servis_klauzula_predracuna), auto-snimanje, bez dugmeta Sacuvaj - Genericki data-autosave obrazac u base.html - Status U dijagnostici: konstanta + kanban kolona + dugme Pocni dijagnostiku (vidljivo u Primljeno) --- cmd/ntech/main.go | 2 + internal/handler/kes.go | 2 +- internal/handler/podesavanja.go | 36 +++ internal/handler/servis.go | 203 ++++++++++++++++ internal/model/servis.go | 12 +- .../stranice/podesavanja_servis.html | 34 ++- web/templates/stranice/servis.html | 1 + web/templates/stranice/servis_detalji.html | 18 ++ web/templates/stranice/servis_predracun.html | 223 ++++++++++++++++++ web/templates/stranice/servis_revers.html | 203 ++++++++++++++++ web/templates/teme/podrazumevana/base.html | 11 + 11 files changed, 735 insertions(+), 10 deletions(-) create mode 100644 web/templates/stranice/servis_predracun.html create mode 100644 web/templates/stranice/servis_revers.html diff --git a/cmd/ntech/main.go b/cmd/ntech/main.go index 117cbb5..cf69870 100644 --- a/cmd/ntech/main.go +++ b/cmd/ntech/main.go @@ -357,6 +357,8 @@ func main() { r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis/{id}", h.DetaljiNaloga) r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis/{id}/radni-nalog", h.StampaRadnogNaloga) r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis/{id}/otpremnica", h.StampaOtpremnice) + r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis/{id}/revers", h.StampaReversa) + r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis/{id}/predracun", h.StampaPredracuna) r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis/{id}/nalepnica", h.StampaNalepnice) r.With(doz("servis.izmeni")).Post("/servis/{id}/status", h.PromeniStatus) r.With(doz("servis.izmeni")).Post("/servis/{id}/garancija", h.AzurirajGaranciju) diff --git a/internal/handler/kes.go b/internal/handler/kes.go index 662ae09..1e52367 100644 --- a/internal/handler/kes.go +++ b/internal/handler/kes.go @@ -43,7 +43,7 @@ var saSidebar = []string{ // standalone su šabloni bez base layouta var standaloneIme = []string{ - "prijava", "setup", "totp_provera", "prodaja_stampa", "servis_radni_nalog", "servis_otpremnica", "servis_nalepnica", "servis_status_javni", + "prijava", "setup", "totp_provera", "prodaja_stampa", "servis_radni_nalog", "servis_otpremnica", "servis_revers", "servis_predracun", "servis_nalepnica", "servis_status_javni", } // sablonskeFunkcije su pomoćne funkcije dostupne u svim šablonima. diff --git a/internal/handler/podesavanja.go b/internal/handler/podesavanja.go index 00e3b13..7959a71 100644 --- a/internal/handler/podesavanja.go +++ b/internal/handler/podesavanja.go @@ -20,6 +20,19 @@ import ( "ntech/internal/model" ) +// podrazumevaniUsloviServisa je podrazumevani tekst uslova servisa koji se +// štampa na reversu; korisnik ga može izmeniti u Podešavanja → Servis. +const podrazumevaniUsloviServisa = `1. Servis ne odgovara za podatke na uređaju. Klijent je dužan da sam napravi rezervnu kopiju podataka pre predaje. +2. Uređaj se preuzima uz ovaj revers i ličnu kartu. Bez reversa uređaj se ne izdaje. +3. Rok za podizanje uređaja je 30 dana od obaveštenja o završetku. Po isteku roka servis ne odgovara za uređaj. +4. Ako klijent odustane od popravke, naplaćuje se dijagnostika prema cenovniku. +5. Garancija na izvršeni servis važi za zamenjene delove i obavljeni rad, ne i za nove kvarove. +6. Potpisom klijent potvrđuje da je saglasan sa navedenim uslovima.` + +// podrazumevanaKlauzulaPredracuna je podrazumevana napomena koja se štampa na +// dnu predračuna; korisnik je može izmeniti u Podešavanja → Servis. +const podrazumevanaKlauzulaPredracuna = `Procena je data na osnovu zahteva klijenta i nije fiskalni dokument. Ako se tokom rada utvrdi dodatni kvar, servis kontaktira klijenta radi saglasnosti pre nastavka radova i izmene cene.` + // PodaciPodesavanja su podaci za stranicu podešavanja type PodaciPodesavanja struct { model.PodaciStranice @@ -52,6 +65,8 @@ type PodaciPodesavanja struct { ServisGarancijaDana string PredracunRokDana string PredvidjenRokDana string + ServisUslovi string + ServisKlauzulaPredracuna string LoginPozadina string LoginPozadinaOpacity string LoginPozadinaBlurPozadine string @@ -407,6 +422,25 @@ func (h *Handler) SacuvajPodesavanja(w http.ResponseWriter, r *http.Request) { } } + // uslovi servisa (slobodan tekst, štampa se na reversu); čuva se uvek, + // pa korisnik može i da skrati ili isprazni tekst + if _, ima := r.Form["servis_uslovi"]; ima { + uslovi := strings.TrimSpace(r.FormValue("servis_uslovi")) + if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "servis_uslovi", uslovi); err != nil { + http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError) + return + } + } + + // klauzula na predračunu (slobodan tekst); čuva se uvek + if _, ima := r.Form["servis_klauzula_predracuna"]; ima { + klauzula := strings.TrimSpace(r.FormValue("servis_klauzula_predracuna")) + if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "servis_klauzula_predracuna", klauzula); err != nil { + http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError) + return + } + } + http.Redirect(w, r, sledeci+"?sacuvano=1", http.StatusSeeOther) } @@ -782,6 +816,8 @@ func (h *Handler) napuniPodaciPodesavanja(r *http.Request, naslov string) (Podac ServisGarancijaDana: vrednostIliDefault(podesavanja, "servis_garancija_dana", "60"), PredracunRokDana: vrednostIliDefault(podesavanja, "predracun_rok_dana", "7"), PredvidjenRokDana: vrednostIliDefault(podesavanja, "predvidjen_rok_dana", "15"), + ServisUslovi: vrednostIliDefault(podesavanja, "servis_uslovi", podrazumevaniUsloviServisa), + ServisKlauzulaPredracuna: vrednostIliDefault(podesavanja, "servis_klauzula_predracuna", podrazumevanaKlauzulaPredracuna), }, nil } diff --git a/internal/handler/servis.go b/internal/handler/servis.go index 8bc2c15..d02506e 100644 --- a/internal/handler/servis.go +++ b/internal/handler/servis.go @@ -1284,6 +1284,209 @@ func (h *Handler) StampaOtpremnice(w http.ResponseWriter, r *http.Request) { }) } +// PodaciReversa su podaci za revers — potvrdu o prijemu uređaja na servis. +// Dokument se izdaje pri prijemu, pa nema cena. +type PodaciReversa struct { + Nalog model.ServisniNalog + Klijent *model.Klijent + KlijentNaziv string + KlijentOznakaIdent string // labela identifikacije ("JMBG" / "Br. lične karte") + KlijentBrojIdent string // vrednost identifikacionog broja + TehnicarNaziv string + QRKod string // base64 QR ka javnoj status strani naloga + Uslovi string // uslovi servisa iz podešavanja (servis_uslovi) + NazivFirme string + Podnazlov string + Adresa string + Telefon string + PIB string +} + +// StampaReversa renderuje revers (potvrdu o prijemu uređaja na servis) +func (h *Handler) StampaReversa(w http.ResponseWriter, r *http.Request) { + id, err := parseID(chi.URLParam(r, "id")) + if err != nil { + http.Error(w, "Neispravan ID naloga", http.StatusBadRequest) + return + } + + nalog, err := h.ServisRepo.DohvatiID(r.Context(), id) + if err != nil { + http.Error(w, "Nalog nije pronađen", http.StatusNotFound) + return + } + + podesavanja, err := sqlite.DohvatiSvaPodesavanja(r.Context(), h.DB) + if err != nil { + http.Error(w, "Greška pri učitavanju podešavanja", http.StatusInternalServerError) + return + } + + var klijent *model.Klijent + klijentNaziv := "" + klijentOznaka := "" + klijentBroj := "" + if nalog.KlijentID != nil { + k, err := h.KlijentiRepo.DohvatiID(r.Context(), *nalog.KlijentID) + if err == nil { + klijent = k + klijentNaziv = k.PunoIme() + if k.JMBG != "" { + klijentOznaka = k.OznakaIdentifikacije() + klijentBroj = k.JMBG + } + } + } + + tehnicarNaziv := "" + if nalog.TehnicarID != nil { + tehnicar, err := h.KorisniciRepo.DohvatiPoID(r.Context(), *nalog.TehnicarID) + if err == nil { + tehnicarNaziv = tehnicar.KorisnickoIme + } + } + + nalogURL := qrNalogURL(r, nalog.JavniToken) + var qrKod string + if png, err := qrcode.Encode(nalogURL, qrcode.Medium, 160); err == nil { + qrKod = base64.StdEncoding.EncodeToString(png) + } + + h.renderujStandalone(w, "servis_revers", PodaciReversa{ + Nalog: *nalog, + Klijent: klijent, + KlijentNaziv: klijentNaziv, + KlijentOznakaIdent: klijentOznaka, + KlijentBrojIdent: klijentBroj, + TehnicarNaziv: tehnicarNaziv, + QRKod: qrKod, + Uslovi: vrednostIliDefault(podesavanja, "servis_uslovi", podrazumevaniUsloviServisa), + NazivFirme: podesavanja["naziv_firme"], + Podnazlov: podesavanja["podnazlov"], + Adresa: podesavanja["adresa"], + Telefon: podesavanja["telefon"], + PIB: podesavanja["pib"], + }) +} + +// PodaciPredracuna su podaci za predračun — procenu cene za tražene radove i delove, +// koju klijent odobrava pre popravke. Gradi se iz stavki radova i delova na nalogu. +type PodaciPredracuna struct { + Nalog model.ServisniNalog + Radovi []model.ServisniRad + UkupnoRad float64 + ServisniDelovi []model.ServisniDeoSaArtiklom + UkupnoDelovi float64 + UkupnoSve float64 + DatumIzdavanja time.Time + VaziDo time.Time + Klauzula string + QRKod string + Klijent *model.Klijent + KlijentNaziv string + TehnicarNaziv string + NazivFirme string + Podnazlov string + Adresa string + Telefon string + PIB string +} + +// StampaPredracuna renderuje predračun (procenu cene) na osnovu traženih radova i delova +func (h *Handler) StampaPredracuna(w http.ResponseWriter, r *http.Request) { + id, err := parseID(chi.URLParam(r, "id")) + if err != nil { + http.Error(w, "Neispravan ID naloga", http.StatusBadRequest) + return + } + + nalog, err := h.ServisRepo.DohvatiID(r.Context(), id) + if err != nil { + http.Error(w, "Nalog nije pronađen", http.StatusNotFound) + return + } + + radovi, err := h.ServisniRadoviRepo.DohvatiZaNalog(r.Context(), id) + if err != nil { + http.Error(w, "Greška pri učitavanju radova", http.StatusInternalServerError) + return + } + + delovi, err := h.deloviSaPotrazivanima(r.Context(), id) + if err != nil { + http.Error(w, "Greška pri učitavanju delova", http.StatusInternalServerError) + return + } + + podesavanja, err := sqlite.DohvatiSvaPodesavanja(r.Context(), h.DB) + if err != nil { + http.Error(w, "Greška pri učitavanju podešavanja", http.StatusInternalServerError) + return + } + + var klijent *model.Klijent + klijentNaziv := "" + if nalog.KlijentID != nil { + k, err := h.KlijentiRepo.DohvatiID(r.Context(), *nalog.KlijentID) + if err == nil { + klijent = k + klijentNaziv = k.PunoIme() + } + } + + tehnicarNaziv := "" + if nalog.TehnicarID != nil { + tehnicar, err := h.KorisniciRepo.DohvatiPoID(r.Context(), *nalog.TehnicarID) + if err == nil { + tehnicarNaziv = tehnicar.KorisnickoIme + } + } + + var ukupnoRad float64 + for _, rd := range radovi { + ukupnoRad += rd.Ukupno() + } + var ukupnoDelovi float64 + for _, d := range delovi { + ukupnoDelovi += d.Ukupno() + } + + // rok važenja iz podešavanja (default 7 dana) + rok := 7 + if v, err := strconv.Atoi(podesavanja["predracun_rok_dana"]); err == nil && v > 0 { + rok = v + } + datumIzdavanja := time.Now() + vaziDo := datumIzdavanja.AddDate(0, 0, rok) + + nalogURL := qrNalogURL(r, nalog.JavniToken) + var qrKod string + if png, err := qrcode.Encode(nalogURL, qrcode.Medium, 160); err == nil { + qrKod = base64.StdEncoding.EncodeToString(png) + } + + h.renderujStandalone(w, "servis_predracun", PodaciPredracuna{ + Nalog: *nalog, + Radovi: radovi, + UkupnoRad: ukupnoRad, + ServisniDelovi: delovi, + UkupnoDelovi: ukupnoDelovi, + UkupnoSve: ukupnoRad + ukupnoDelovi, + DatumIzdavanja: datumIzdavanja, + VaziDo: vaziDo, + Klauzula: vrednostIliDefault(podesavanja, "servis_klauzula_predracuna", podrazumevanaKlauzulaPredracuna), + QRKod: qrKod, + Klijent: klijent, + KlijentNaziv: klijentNaziv, + TehnicarNaziv: tehnicarNaziv, + NazivFirme: podesavanja["naziv_firme"], + Podnazlov: podesavanja["podnazlov"], + Adresa: podesavanja["adresa"], + Telefon: podesavanja["telefon"], + PIB: podesavanja["pib"], + }) +} + // PodaciNalepnice su podaci za malu nalepnicu (70×40 mm) koja se lepi na uređaj type PodaciNalepnice struct { Nalog model.ServisniNalog diff --git a/internal/model/servis.go b/internal/model/servis.go index b84dee0..084e817 100644 --- a/internal/model/servis.go +++ b/internal/model/servis.go @@ -7,16 +7,18 @@ import ( // Statusi servisnog naloga const ( - StatusPrimljeno = "Primljeno" - StatusCekaDelove = "Čeka delove" - StatusUPopravci = "U popravci" - StatusZavrseno = "Završeno" - StatusPreuzeto = "Preuzeto" + StatusPrimljeno = "Primljeno" + StatusUDijagnostici = "U dijagnostici" + StatusCekaDelove = "Čeka delove" + StatusUPopravci = "U popravci" + StatusZavrseno = "Završeno" + StatusPreuzeto = "Preuzeto" ) // SviStatusi je uređena lista statusa za prikaz u dropdownu var SviStatusi = []string{ StatusPrimljeno, + StatusUDijagnostici, StatusCekaDelove, StatusUPopravci, StatusZavrseno, diff --git a/web/templates/stranice/podesavanja_servis.html b/web/templates/stranice/podesavanja_servis.html index d67e334..e5c0129 100644 --- a/web/templates/stranice/podesavanja_servis.html +++ b/web/templates/stranice/podesavanja_servis.html @@ -9,11 +9,11 @@
Podešavanja su uspešno sačuvana.
{{end}} -
+ -
+
Servis @@ -59,9 +59,35 @@
+
-
- +
+
+ + Uslovi servisa +
+ +
+ + +
+ Ovaj tekst se štampa na reversu (potvrdi o prijemu uređaja na servis). Slobodno ga + izmeni prema svojim pravilima — svaka stavka u novom redu. Snima se automatski. +
+
+ +
+ + +
+ Napomena na dnu predračuna (procena cene). Snima se automatski. +
diff --git a/web/templates/stranice/servis.html b/web/templates/stranice/servis.html index 3fd9190..2772561 100644 --- a/web/templates/stranice/servis.html +++ b/web/templates/stranice/servis.html @@ -4,6 +4,7 @@ {{define "status-badge"}} {{if eq . "Primljeno"}}{{.}} +{{else if eq . "U dijagnostici"}}{{.}} {{else if eq . "Čeka delove"}}{{.}} {{else if eq . "U popravci"}}{{.}} {{else if eq . "Završeno"}}{{.}} diff --git a/web/templates/stranice/servis_detalji.html b/web/templates/stranice/servis_detalji.html index 3bd369d..c347426 100644 --- a/web/templates/stranice/servis_detalji.html +++ b/web/templates/stranice/servis_detalji.html @@ -14,6 +14,7 @@ {{define "status-badge-detalji"}} {{if eq . "Primljeno"}}{{.}} +{{else if eq . "U dijagnostici"}}{{.}} {{else if eq . "Čeka delove"}}{{.}} {{else if eq . "U popravci"}}{{.}} {{else if eq . "Završeno"}}{{.}} @@ -44,9 +45,26 @@
{{template "status-badge-detalji" .Nalog.Status}} + {{if eq .Nalog.Status "Primljeno"}} + +
+ + + +
+ {{end}}
+ + Revers + + + Predračun + Radni nalog diff --git a/web/templates/stranice/servis_predracun.html b/web/templates/stranice/servis_predracun.html new file mode 100644 index 0000000..8751e10 --- /dev/null +++ b/web/templates/stranice/servis_predracun.html @@ -0,0 +1,223 @@ + + + + + + Predračun — {{.Nalog.BrojNaloga}} + + + +
+ + +
+
+
{{if .NazivFirme}}{{.NazivFirme}}{{else}}— naziv firme —{{end}}
+
+ {{if .Podnazlov}}{{.Podnazlov}}
{{end}} + {{if .Adresa}}{{.Adresa}}
{{end}} + {{if .Telefon}}Tel: {{telefon .Telefon}}
{{end}} + {{if .PIB}}PIB: {{.PIB}}{{end}} +
+
+
+
+
Predračun (procena)
+
{{.Nalog.BrojNaloga}}
+
Datum: {{.DatumIzdavanja.Format "02.01.2006."}}
+
Važi do: {{.VaziDo.Format "02.01.2006."}}
+
+ {{if .QRKod}} + QR {{.Nalog.BrojNaloga}} + {{end}} +
+
+ + +
+
+
Izdao (servis)
+
{{if .NazivFirme}}{{.NazivFirme}}{{else}}—{{end}}
+
+ {{if .Adresa}}{{.Adresa}}
{{end}} + {{if .Telefon}}{{telefon .Telefon}}{{end}} +
+
+
+
Za (klijent)
+ {{if .KlijentNaziv}} +
{{.KlijentNaziv}}
+
+ {{if .Klijent}} + {{if .Klijent.Telefon}}Tel: {{telefon .Klijent.Telefon}}
{{end}} + {{if .Klijent.Mesto}}{{.Klijent.Mesto}}{{end}} + {{end}} +
+ {{else}} +
— klijent nije naveden —
+ {{end}} +
+
+ + +
+
Uređaj i traženi radovi
+
Uređaj: {{if .Nalog.Uredjaj}}{{.Nalog.Uredjaj}}{{else}}{{end}}{{if .Nalog.SerijskiBroj}} · S/N: {{.Nalog.SerijskiBroj}}{{end}}
+
Zahtev klijenta: {{if .Nalog.OpisKvara}}{{.Nalog.OpisKvara}}{{else}}{{end}}
+
+ + + {{if .Radovi}} +
+
Radovi
+ + + + + + + + + + + {{range .Radovi}} + + + + + + + {{end}} + + + + + +
UslugaKol.CenaUkupno
{{.Naziv}}{{.Kolicina}}{{dinari .CenaKomada}} din{{dinari .Ukupno}} din
Ukupno radovi{{dinari .UkupnoRad}} din
+
+ {{end}} + + + {{if .ServisniDelovi}} +
+
Delovi i materijal
+ + + + + + + + + + + {{range .ServisniDelovi}} + + + + + + + {{end}} + + + + + +
ArtikalKol.Cena/komUkupno
{{.ArtikalNaziv}}{{.Kolicina}}{{dinari .CenaKomada}} din{{dinari .Ukupno}} din
Ukupno delovi{{dinari .UkupnoDelovi}} din
+
+ {{end}} + + {{if and (not .Radovi) (not .ServisniDelovi)}} +
+
Na nalog još nisu uneti radovi ni delovi — dodaj ih u detaljima naloga da bi se prikazali na predračunu.
+
+ {{end}} + + +
+ {{if .Radovi}}
Radovi{{dinari .UkupnoRad}} din
{{end}} + {{if .ServisniDelovi}}
Delovi i materijal{{dinari .UkupnoDelovi}} din
{{end}} +
+
Ukupno (procena):
+
{{dinari .UkupnoSve}} din
+
+
+ + + {{if .Klauzula}} +
{{.Klauzula}}
+ {{end}} + +
Predračun važi do {{.VaziDo.Format "02.01.2006."}}.
+ + +
+
+
Saglasan sa procenom (klijent)
+
+
+
Izdao{{if .TehnicarNaziv}} — {{.TehnicarNaziv}}{{end}} (servis)
+
+
+ +
+ + + + + diff --git a/web/templates/stranice/servis_revers.html b/web/templates/stranice/servis_revers.html new file mode 100644 index 0000000..27e0241 --- /dev/null +++ b/web/templates/stranice/servis_revers.html @@ -0,0 +1,203 @@ + + + + + + Revers — {{.Nalog.BrojNaloga}} + + + +
+ + +
+
+
{{if .NazivFirme}}{{.NazivFirme}}{{else}}— naziv firme —{{end}}
+
+ {{if .Podnazlov}}{{.Podnazlov}}
{{end}} + {{if .Adresa}}{{.Adresa}}
{{end}} + {{if .Telefon}}Tel: {{telefon .Telefon}}
{{end}} + {{if .PIB}}PIB: {{.PIB}}{{end}} +
+
+
+
+
Revers — potvrda o prijemu
+
{{.Nalog.BrojNaloga}}
+
Datum prijema: {{.Nalog.DatumPrijema.Format "02.01.2006."}}
+ {{if .Nalog.PredvidjenDatum}} +
Predviđen rok: {{.Nalog.PredvidjenDatum.Format "02.01.2006."}}
+ {{end}} +
+ {{if .QRKod}} + QR {{.Nalog.BrojNaloga}} + {{end}} +
+
+ + +
+
+
Primio (servis)
+
{{if .NazivFirme}}{{.NazivFirme}}{{else}}—{{end}}
+
+ {{if .Adresa}}{{.Adresa}}
{{end}} + {{if .Telefon}}{{telefon .Telefon}}{{end}} +
+
+
+
Predao (klijent)
+ {{if .KlijentNaziv}} +
{{.KlijentNaziv}}
+
+ {{if .Klijent}} + {{if .Klijent.Telefon}}Tel: {{telefon .Klijent.Telefon}}
{{end}} + {{if .Klijent.Mesto}}{{.Klijent.Mesto}}
{{end}} + {{end}} + {{if .KlijentBrojIdent}}{{.KlijentOznakaIdent}}: {{.KlijentBrojIdent}}{{end}} +
+ {{else}} +
— klijent nije naveden —
+ {{end}} +
+
+ + +
+
Uređaj na servisu
+
+
+
Naziv uređaja
+
{{if .Nalog.Uredjaj}}{{.Nalog.Uredjaj}}{{else}}{{end}}
+
+
+
Serijski broj
+
{{if .Nalog.SerijskiBroj}}{{.Nalog.SerijskiBroj}}{{else}}{{end}}
+
+ {{if .Nalog.PinUredjaja}} +
+
PIN / lozinka
+
{{.Nalog.PinUredjaja}}
+
+ {{end}} +
+ {{if .Nalog.Pribor}} +
+
Pribor predat uz uređaj
+
{{.Nalog.Pribor}}
+
+ {{end}} + {{if .Nalog.Ostecenja}} +
+
Vidljiva oštećenja pri prijemu
+
{{.Nalog.Ostecenja}}
+
+ {{end}} + {{if .Nalog.TrazeneNadogradnje}} +
+
Tražene nadogradnje
+
{{.Nalog.TrazeneNadogradnje}}
+
+ {{end}} +
+ + +
+
Prijavljeni kvar (po izjavi klijenta)
+
{{if .Nalog.OpisKvara}}{{.Nalog.OpisKvara}}{{else}}{{end}}
+
+ + + {{if .Nalog.NapomenaKlijentu}} +
+
Napomena
+
{{.Nalog.NapomenaKlijentu}}
+
+ {{end}} + + + {{if .Uslovi}} +
+
Uslovi servisa
+
{{.Uslovi}}
+
+ {{end}} + + +
+
+
Predao (klijent)
+
+
+
Primio{{if .TehnicarNaziv}} — {{.TehnicarNaziv}}{{end}} (servis)
+
+
+ +
Revers se izdaje u dva primerka — po jedan za klijenta i za servis. Uređaj se preuzima uz ovaj revers.
+ +
+ + + + + diff --git a/web/templates/teme/podrazumevana/base.html b/web/templates/teme/podrazumevana/base.html index 556e111..43a561a 100644 --- a/web/templates/teme/podrazumevana/base.html +++ b/web/templates/teme/podrazumevana/base.html @@ -361,6 +361,17 @@ }); }); + // auto-snimanje — forme sa data-autosave se snimaju na svaku promenu polja + // (bez dugmeta „Sačuvaj"); 'change' se okida na blur za text/number/textarea, + // a na izbor za select/checkbox. Submit prolazi kroz AJAX logiku ispod. + document.querySelectorAll('form[data-autosave]').forEach(function(f) { + if (f._autosave) return; + f._autosave = true; + f.addEventListener('change', function() { + if (f.requestSubmit) f.requestSubmit(); else f.submit(); + }); + }); + // AJAX submit — forme koje serveru vraćaju ?sacuvano= ostaju na stranici (scroll se ne gubi) document.querySelectorAll('form[method="POST"],form[method="post"]').forEach(function(f) { if (f._ajaxSave) return;