From a7ec5e9aa99263bb9430cdf75c1e26f146c8a26a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dalibor=20Markovi=C4=87?= Date: Thu, 25 Jun 2026 00:37:56 +0200 Subject: [PATCH] Servis: garantni list pri preuzimanju, ispravka datuma garancije na otpremnici --- cmd/ntech/main.go | 1 + internal/handler/kes.go | 2 +- internal/handler/servis.go | 119 +++++++++ web/templates/stranice/servis_detalji.html | 5 + .../stranice/servis_garantni_list.html | 240 ++++++++++++++++++ 5 files changed, 366 insertions(+), 1 deletion(-) create mode 100644 web/templates/stranice/servis_garantni_list.html diff --git a/cmd/ntech/main.go b/cmd/ntech/main.go index 8d637d8..61e22ed 100644 --- a/cmd/ntech/main.go +++ b/cmd/ntech/main.go @@ -364,6 +364,7 @@ func main() { 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(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis/{id}/garantni-list", h.StampaGarantnog) r.With(doz("servis.izmeni")).Post("/servis/{id}/status", h.PromeniStatus) r.With(doz("servis.izmeni")).Post("/servis/{id}/garancija", h.AzurirajGaranciju) r.With(doz("servis.izmeni")).Post("/servis/{id}/garancija-dana", h.AzurirajGarancijaDana) diff --git a/internal/handler/kes.go b/internal/handler/kes.go index a57354e..ba07b86 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_revers", "servis_predracun", "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", "servis_garantni_list", } // sablonskeFunkcije su pomoćne funkcije dostupne u svim šablonima. diff --git a/internal/handler/servis.go b/internal/handler/servis.go index 8f7803e..0a9598a 100644 --- a/internal/handler/servis.go +++ b/internal/handler/servis.go @@ -1438,6 +1438,18 @@ func (h *Handler) StampaOtpremnice(w http.ResponseWriter, r *http.Request) { qrKodOtpr = base64.StdEncoding.EncodeToString(png) } + // GarancijaDo se računa od završetka, ne od prijema + if nalog.GarancijaDana == nil || *nalog.GarancijaDana <= 0 { + nalog.GarancijaDo = nil + } else { + baza := time.Now() + if nalog.DatumZavrsetka != nil { + baza = *nalog.DatumZavrsetka + } + t := baza.AddDate(0, 0, *nalog.GarancijaDana) + nalog.GarancijaDo = &t + } + h.renderujStandalone(w, "servis_otpremnica", PodaciOtpremnice{ Nalog: *nalog, ServisniDelovi: delovi, @@ -1459,6 +1471,113 @@ func (h *Handler) StampaOtpremnice(w http.ResponseWriter, r *http.Request) { }) } +// PodaciGarantnog su podaci za garantni list koji se predaje klijentu pri preuzimanju. +type PodaciGarantnog struct { + Nalog model.ServisniNalog + GarancijaDo *time.Time // izračunato od DatumZavrsetka + GarancijaDana + GarancijaTekst string // npr. "60 dana" + Radovi []model.ServisniRad + ServisniDelovi []model.ServisniDeoSaArtiklom + Klijent *model.Klijent + KlijentNaziv string + TehnicarNaziv string + Uslovi string + NazivFirme string + LogoPutanja string + Podnazlov string + Adresa string + Telefon string + PIB string + MaticniBroj string + Barkod string +} + +// StampaGarantnog renderuje garantni list (dostupno od statusa Završeno, samo ako ima garancija) +func (h *Handler) StampaGarantnog(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 + } + + if nalog.GarancijaDana == nil || *nalog.GarancijaDana <= 0 { + http.Error(w, "Nalog nema definisanu garanciju", http.StatusBadRequest) + 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 + } + + 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 + } + + var klijent *model.Klijent + klijentNaziv := "" + if nalog.KlijentID != nil { + k, err := h.KlijentiRepo.DohvatiID(r.Context(), *nalog.KlijentID) + if err == nil { + klijent = k + if k.NazivFirme != "" { + klijentNaziv = k.NazivFirme + } else { + klijentNaziv = strings.TrimSpace(k.Ime + " " + k.Prezime) + } + } + } + + tehnicarNaziv := "" + if nalog.TehnicarID != nil { + tehnicar, err := h.KorisniciRepo.DohvatiPoID(r.Context(), *nalog.TehnicarID) + if err == nil { + tehnicarNaziv = tehnicar.KorisnickoIme + } + } + + baza := time.Now() + if nalog.DatumZavrsetka != nil { + baza = *nalog.DatumZavrsetka + } + garanDo := baza.AddDate(0, 0, *nalog.GarancijaDana) + + h.renderujStandalone(w, "servis_garantni_list", PodaciGarantnog{ + Nalog: *nalog, + GarancijaDo: &garanDo, + GarancijaTekst: garancijaUTekst(*nalog.GarancijaDana), + Radovi: radovi, + ServisniDelovi: delovi, + Klijent: klijent, + KlijentNaziv: klijentNaziv, + TehnicarNaziv: tehnicarNaziv, + Uslovi: vrednostIliDefault(podesavanja, "servis_uslovi", podrazumevaniUsloviServisa), + NazivFirme: podesavanja["naziv_firme"], + LogoPutanja: logoZaDokument(podesavanja), + Podnazlov: podesavanja["podnazlov"], + Adresa: podesavanja["adresa"], + Telefon: podesavanja["telefon"], + PIB: podesavanja["pib"], + MaticniBroj: podesavanja["maticni_broj"], + Barkod: barkodNaloga(nalog.BrojNaloga), + }) +} + // PodaciReversa su podaci za revers — potvrdu o prijemu uređaja na servis. // Dokument se izdaje pri prijemu, pa nema cena. type PodaciReversa struct { diff --git a/web/templates/stranice/servis_detalji.html b/web/templates/stranice/servis_detalji.html index e2e0d4f..fc9f34a 100644 --- a/web/templates/stranice/servis_detalji.html +++ b/web/templates/stranice/servis_detalji.html @@ -149,6 +149,11 @@ Otpremnica + {{if not .BezGarancije}} + + Garantni list + + {{end}} {{end}} {{/* Nalepnica je primarna pri prijemu (lepi se na uređaj); reprint dok traje; ne u „Završeno" */}} {{if eq .Nalog.Status "Primljeno"}} diff --git a/web/templates/stranice/servis_garantni_list.html b/web/templates/stranice/servis_garantni_list.html new file mode 100644 index 0000000..0e19059 --- /dev/null +++ b/web/templates/stranice/servis_garantni_list.html @@ -0,0 +1,240 @@ + + + + + + Garantni list — {{.Nalog.BrojNaloga}} + + + +
+ + +
+ +
+ {{if .LogoPutanja}} + Logo + {{else}} +
{{if .NazivFirme}}{{.NazivFirme}}{{else}}— naziv firme —{{end}}
+ {{end}} +
+ {{if .Podnazlov}}{{.Podnazlov}}
{{end}} + {{if .Adresa}}{{.Adresa}}
{{end}} + {{if .Telefon}}Tel: {{telefon .Telefon}}
{{end}} + {{if .PIB}}PIB: {{.PIB}}{{end}}{{if .MaticniBroj}}{{if .PIB}} · {{end}}MB: {{.MaticniBroj}}{{end}} +
+
+ +
+ {{if .Barkod}}Barkod {{.Nalog.BrojNaloga}}{{end}} +
Garantni list
+
{{.Nalog.BrojNaloga}}
+ {{if .Nalog.DatumZavrsetka}} +
Datum završetka: {{.Nalog.DatumZavrsetka.Format "02.01.2006."}}
+ {{end}} + {{if .TehnicarNaziv}} +
Serviser: {{.TehnicarNaziv}}
+ {{end}} +
+ +
+
Klijent
+ {{if .KlijentNaziv}} +
{{.KlijentNaziv}}
+
+ {{if .Klijent}} + {{if .Klijent.Telefon}}Tel: {{telefon .Klijent.Telefon}}
{{end}} + {{if .Klijent.Email}}{{.Klijent.Email}}
{{end}} + {{if .Klijent.Mesto}}{{.Klijent.Mesto}}{{end}} + {{end}} +
+ {{else}} +
— klijent nije naveden —
+ {{end}} +
+
+ + +
+
+
Garancija na izvršeni servis
+
Trajanje: {{.GarancijaTekst}}
+
+
+
Važi do:
+
{{.GarancijaDo.Format "02.01.2006."}}
+
+
+ + +
+
Uređaj
+
+
+
Naziv uređaja
+
{{if .Nalog.Uredjaj}}{{.Nalog.Uredjaj}}{{else}}{{end}}
+
+
+
Serijski broj
+
{{if .Nalog.SerijskiBroj}}{{.Nalog.SerijskiBroj}}{{else}}{{end}}
+
+
+
Datum prijema
+
{{.Nalog.DatumPrijema.Format "02.01.2006."}}
+
+
+
+ + +
+
Urađeni radovi
+ {{if .Radovi}} + + + + + + + + + + + {{range .Radovi}} + + + + + + + {{end}} + +
Opis radaKol.CenaUkupno
{{.Naziv}}{{printf "%.0f" .Kolicina}}{{dinari .CenaKomada}}{{dinari .Ukupno}}
+ {{else}} +
Nisu evidentirani posebni radovi.
+ {{end}} +
+ + +
+
Zamenjeni delovi / materijal
+ {{if .ServisniDelovi}} + + + + + + + + + + + + {{range .ServisniDelovi}} + {{if not .Predlozeno}} + + + + + + + + {{end}} + {{end}} + +
NazivŠifraKol.CenaUkupno
{{.ArtikalNaziv}}{{.ArtikalSifra}}{{.Kolicina}}{{dinari .CenaKomada}}{{dinari .Ukupno}}
+ {{else}} +
Nisu evidentirani zamenjeni delovi.
+ {{end}} +
+ + + {{if .Nalog.NapomenaKlijentu}} +
+
Napomena
+
{{.Nalog.NapomenaKlijentu}}
+
+ {{end}} + + + {{if .Uslovi}} +
+
Uslovi garancije
+
{{.Uslovi}}
+
+ {{end}} + + +
+
+
Preuzeo (klijent)
+
+
+
Predao (servis)
+
+
+ +
Garantni list važi uz predočenje ovog dokumenta i originalnog reversa.
+ +
+ + +