Servis: garancija kao trajanje u danima + Tehničar → Serviser
- Garancija se u detaljima prikazuje kao trajanje na srpskom (npr. „1 mesec i 15 dana", „2 meseca", „20 dana"); helper garancijaTekst + srpska deklinacija - Nova kolona garancija_dana (trajanje od završetka); garancija_do ostaje za fazu Završeno - Modal: textbox „Trajanje garancije (dana)" umesto kalendara; Podrazumevano i Bez garancije - Nova ruta/handler AzurirajGarancijaDana; forma izmene čuva trajanje (ne briše) - Podešavanja → Servis: rok garancije prebačen iz meseci u dane (servis_garancija_dana, default 60) - „Garancija do" uklonjena iz forme Izmeni nalog (kod arhiviran u docs/); SacuvajIzmenaNaloga čuva garanciju iz baze da je auto-snimanje ne pregazi - Prikazni tekst „Tehničar" → „Serviser" svuda (identifikatori Tehnicar/tehnicar_id netaknuti)
This commit is contained in:
@@ -192,6 +192,7 @@ type ServisRepository interface {
|
||||
Izmeni(ctx context.Context, n *model.ServisniNalog) error
|
||||
AzurirajStatus(ctx context.Context, id int64, status string) error
|
||||
AzurirajGaranciju(ctx context.Context, id int64, garancijaDo *time.Time) error
|
||||
AzurirajGarancijaDana(ctx context.Context, id int64, dana *int) error
|
||||
AzurirajPredvidjenDatum(ctx context.Context, id int64, predvidjenDatum *time.Time) error
|
||||
AzurirajTehnicar(ctx context.Context, id int64, tehnicarID *int64) error
|
||||
AzurirajNapomenuKlijentu(ctx context.Context, id int64, tekst string) error
|
||||
|
||||
@@ -57,7 +57,7 @@ func (r *ServisRepo) Lista(ctx context.Context, pretraga, status string) ([]mode
|
||||
SELECT
|
||||
sn.id, sn.klijent_id, sn.tehnicar_id, sn.broj_naloga, sn.uredjaj, sn.serijski_broj,
|
||||
sn.opis_kvara, sn.trazene_nadogradnje, sn.status, sn.cena_od, sn.cena_do, sn.cena_konacna,
|
||||
sn.avans, sn.napomena, sn.garancija_do, sn.datum_prijema, sn.datum_zavrsetka, sn.predvidjen_datum,
|
||||
sn.avans, sn.napomena, sn.garancija_do, sn.garancija_dana, sn.datum_prijema, sn.datum_zavrsetka, sn.predvidjen_datum,
|
||||
sn.ostecenja, sn.pin_uredjaja, sn.pribor, sn.napomena_klijentu, sn.javni_token,
|
||||
COALESCE(kp.naziv, '') AS klijent_naziv
|
||||
FROM servisni_nalozi sn
|
||||
@@ -104,7 +104,7 @@ func (r *ServisRepo) DohvatiID(ctx context.Context, id int64) (*model.ServisniNa
|
||||
SELECT
|
||||
id, klijent_id, tehnicar_id, broj_naloga, uredjaj, serijski_broj,
|
||||
opis_kvara, trazene_nadogradnje, status, cena_od, cena_do, cena_konacna,
|
||||
avans, napomena, garancija_do, datum_prijema, datum_zavrsetka, predvidjen_datum,
|
||||
avans, napomena, garancija_do, garancija_dana, datum_prijema, datum_zavrsetka, predvidjen_datum,
|
||||
ostecenja, pin_uredjaja, pribor, napomena_klijentu, javni_token
|
||||
FROM servisni_nalozi WHERE id = ?`, id)
|
||||
|
||||
@@ -127,14 +127,14 @@ func (r *ServisRepo) Kreiraj(ctx context.Context, n *model.ServisniNalog) (int64
|
||||
rezultat, err := r.db.ExecContext(ctx, `
|
||||
INSERT INTO servisni_nalozi
|
||||
(klijent_id, tehnicar_id, broj_naloga, uredjaj, serijski_broj, opis_kvara, trazene_nadogradnje,
|
||||
status, cena_od, cena_do, cena_konacna, avans, napomena, garancija_do, datum_zavrsetka, predvidjen_datum,
|
||||
status, cena_od, cena_do, cena_konacna, avans, napomena, garancija_do, garancija_dana, datum_zavrsetka, predvidjen_datum,
|
||||
ostecenja, pin_uredjaja, pribor, datum_prijema, javni_token)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
nullInt64(n.KlijentID), nullInt64(n.TehnicarID), n.BrojNaloga, n.Uredjaj,
|
||||
nullString(n.SerijskiBroj), n.OpisKvara, n.TrazeneNadogradnje, n.Status,
|
||||
nullFloat64(n.CenaOd), nullFloat64(n.CenaDo), nullFloat64(n.CenaKonacna),
|
||||
nullFloat64(n.Avans), nullString(n.Napomena),
|
||||
nullTime(n.GarancijaDo), nullTime(n.DatumZavrsetka), nullTime(n.PredvidjenDatum),
|
||||
nullTime(n.GarancijaDo), nullInt(n.GarancijaDana), nullTime(n.DatumZavrsetka), nullTime(n.PredvidjenDatum),
|
||||
nullString(n.Ostecenja), nullString(n.PinUredjaja), nullString(n.Pribor),
|
||||
n.DatumPrijema, token,
|
||||
)
|
||||
@@ -156,7 +156,7 @@ func (r *ServisRepo) DohvatiJavniToken(ctx context.Context, token string) (*mode
|
||||
SELECT
|
||||
id, klijent_id, tehnicar_id, broj_naloga, uredjaj, serijski_broj,
|
||||
opis_kvara, trazene_nadogradnje, status, cena_od, cena_do, cena_konacna,
|
||||
avans, napomena, garancija_do, datum_prijema, datum_zavrsetka, predvidjen_datum,
|
||||
avans, napomena, garancija_do, garancija_dana, datum_prijema, datum_zavrsetka, predvidjen_datum,
|
||||
ostecenja, pin_uredjaja, pribor, napomena_klijentu, javni_token
|
||||
FROM servisni_nalozi WHERE javni_token = ?`, token)
|
||||
|
||||
@@ -173,12 +173,12 @@ func (r *ServisRepo) Izmeni(ctx context.Context, n *model.ServisniNalog) error {
|
||||
UPDATE servisni_nalozi SET
|
||||
klijent_id = ?, tehnicar_id = ?, uredjaj = ?, serijski_broj = ?, opis_kvara = ?, trazene_nadogradnje = ?,
|
||||
status = ?, cena_od = ?, cena_do = ?, cena_konacna = ?,
|
||||
avans = ?, napomena = ?, garancija_do = ?, datum_zavrsetka = ?, predvidjen_datum = ?,
|
||||
avans = ?, napomena = ?, garancija_do = ?, garancija_dana = ?, datum_zavrsetka = ?, predvidjen_datum = ?,
|
||||
ostecenja = ?, pin_uredjaja = ?, pribor = ?
|
||||
WHERE id = ?`,
|
||||
nullInt64(n.KlijentID), nullInt64(n.TehnicarID), n.Uredjaj, nullString(n.SerijskiBroj), n.OpisKvara, n.TrazeneNadogradnje,
|
||||
n.Status, nullFloat64(n.CenaOd), nullFloat64(n.CenaDo), nullFloat64(n.CenaKonacna),
|
||||
nullFloat64(n.Avans), nullString(n.Napomena), nullTime(n.GarancijaDo), nullTime(n.DatumZavrsetka), nullTime(n.PredvidjenDatum),
|
||||
nullFloat64(n.Avans), nullString(n.Napomena), nullTime(n.GarancijaDo), nullInt(n.GarancijaDana), nullTime(n.DatumZavrsetka), nullTime(n.PredvidjenDatum),
|
||||
nullString(n.Ostecenja), nullString(n.PinUredjaja), nullString(n.Pribor),
|
||||
n.ID,
|
||||
)
|
||||
@@ -229,6 +229,19 @@ func (r *ServisRepo) AzurirajGaranciju(ctx context.Context, id int64, garancijaD
|
||||
return nil
|
||||
}
|
||||
|
||||
// AzurirajGarancijaDana postavlja trajanje garancije u danima (od završetka radova).
|
||||
// dana == nil ili 0 → bez garancije.
|
||||
func (r *ServisRepo) AzurirajGarancijaDana(ctx context.Context, id int64, dana *int) error {
|
||||
_, err := r.db.ExecContext(ctx,
|
||||
"UPDATE servisni_nalozi SET garancija_dana = ? WHERE id = ?",
|
||||
nullInt(dana), id,
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("ntech: ServisRepo.AzurirajGarancijaDana: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AzurirajPredvidjenDatum postavlja ili briše ručni override predviđenog datuma popravke.
|
||||
// predvidjenDatum == nil → vraća se na izvedeni default (prijem + rok iz podešavanja).
|
||||
func (r *ServisRepo) AzurirajPredvidjenDatum(ctx context.Context, id int64, predvidjenDatum *time.Time) error {
|
||||
@@ -251,7 +264,7 @@ func (r *ServisRepo) AzurirajPredvidjenDatum(ctx context.Context, id int64, pred
|
||||
return nil
|
||||
}
|
||||
|
||||
// AzurirajTehnicar postavlja ili uklanja dodeljenog tehničara na nalogu.
|
||||
// AzurirajTehnicar postavlja ili uklanja dodeljenog servisera na nalogu.
|
||||
// tehnicarID == nil → nedodeljen.
|
||||
func (r *ServisRepo) AzurirajTehnicar(ctx context.Context, id int64, tehnicarID *int64) error {
|
||||
_, err := r.db.ExecContext(ctx,
|
||||
@@ -359,11 +372,12 @@ func scanNalog(scan func(...any) error, n *model.ServisniNalog, klijentNaziv *st
|
||||
var serijskiBroj, napomena, ostecenja, pinUredjaja, pribor, napomenaKlijentu, javniToken sql.NullString
|
||||
var cenaOd, cenaDo, cenaKonacna, avans sql.NullFloat64
|
||||
var garancijaDo, datumZavrsetka, predvidjenDatum sql.NullTime
|
||||
var garancijaDana sql.NullInt64
|
||||
|
||||
args := []any{
|
||||
&n.ID, &klijentID, &tehnicarID, &n.BrojNaloga, &n.Uredjaj, &serijskiBroj,
|
||||
&n.OpisKvara, &n.TrazeneNadogradnje, &n.Status, &cenaOd, &cenaDo, &cenaKonacna,
|
||||
&avans, &napomena, &garancijaDo, &n.DatumPrijema, &datumZavrsetka, &predvidjenDatum,
|
||||
&avans, &napomena, &garancijaDo, &garancijaDana, &n.DatumPrijema, &datumZavrsetka, &predvidjenDatum,
|
||||
&ostecenja, &pinUredjaja, &pribor, &napomenaKlijentu, &javniToken,
|
||||
}
|
||||
|
||||
@@ -417,6 +431,10 @@ func scanNalog(scan func(...any) error, n *model.ServisniNalog, klijentNaziv *st
|
||||
v := predvidjenDatum.Time
|
||||
n.PredvidjenDatum = &v
|
||||
}
|
||||
if garancijaDana.Valid {
|
||||
v := int(garancijaDana.Int64)
|
||||
n.GarancijaDana = &v
|
||||
}
|
||||
n.JavniToken = javniToken.String
|
||||
|
||||
return nil
|
||||
|
||||
@@ -20,6 +20,15 @@ func nullInt64(v *int64) sql.NullInt64 {
|
||||
return sql.NullInt64{Int64: *v, Valid: true}
|
||||
}
|
||||
|
||||
// nullInt pretvara *int pokazivač u sql.NullInt64 —
|
||||
// koristi se za opciona celobrojna polja (npr. trajanje garancije u danima)
|
||||
func nullInt(v *int) sql.NullInt64 {
|
||||
if v == nil {
|
||||
return sql.NullInt64{}
|
||||
}
|
||||
return sql.NullInt64{Int64: int64(*v), Valid: true}
|
||||
}
|
||||
|
||||
// nullFloat64 pretvara *float64 pokazivač u sql.NullFloat64 —
|
||||
// koristi se za opciona numerička polja kao što su cene
|
||||
func nullFloat64(v *float64) sql.NullFloat64 {
|
||||
|
||||
@@ -68,6 +68,8 @@ var sablonskeFunkcije = template.FuncMap{
|
||||
},
|
||||
// telefon formatira srpski broj telefona radi lakšeg čitanja: "0641234567" → "064 123 4567"
|
||||
"telefon": formatirajTelefon,
|
||||
// garancijaTekst prikazuje trajanje garancije (dani) na srpskom: 45 → „1 mesec i 15 dana"
|
||||
"garancijaTekst": garancijaTekst,
|
||||
// json serijalizuje vrednost u JSON za ugradnju u <script> (npr. Alpine x-data);
|
||||
// template.JS sprečava da html/template dodatno escapuje rezultat
|
||||
"json": func(v any) (template.JS, error) {
|
||||
|
||||
@@ -49,7 +49,7 @@ type PodaciPodesavanja struct {
|
||||
BackupIntervalSati string
|
||||
BackupBrojKopija string
|
||||
KalkulacijaMarza string
|
||||
ServisGarancijaMeseci string
|
||||
ServisGarancijaDana string
|
||||
PredracunRokDana string
|
||||
PredvidjenRokDana string
|
||||
LoginPozadina string
|
||||
@@ -366,15 +366,15 @@ func (h *Handler) SacuvajPodesavanja(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// podrazumevani rok garancije za servis (meseci, 0–120)
|
||||
if v := strings.TrimSpace(r.FormValue("servis_garancija_meseci")); v != "" {
|
||||
// podrazumevana garancija za servis (dani, 0–3650)
|
||||
if v := strings.TrimSpace(r.FormValue("servis_garancija_dana")); v != "" {
|
||||
n, err := strconv.Atoi(v)
|
||||
if err != nil || n < 0 || n > 120 {
|
||||
middleware.SetFlash(w, r, h.DB, "greska", "Rok garancije mora biti broj između 0 i 120 meseci.")
|
||||
if err != nil || n < 0 || n > 3650 {
|
||||
middleware.SetFlash(w, r, h.DB, "greska", "Garancija mora biti broj između 0 i 3650 dana.")
|
||||
http.Redirect(w, r, sledeci, http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "servis_garancija_meseci", strconv.Itoa(n)); err != nil {
|
||||
if err := ntechsqlite.SacuvajPodesavanje(r.Context(), h.DB, "servis_garancija_dana", strconv.Itoa(n)); err != nil {
|
||||
http.Error(w, "Greška pri čuvanju podešavanja", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
@@ -779,7 +779,7 @@ func (h *Handler) napuniPodaciPodesavanja(r *http.Request, naslov string) (Podac
|
||||
BackupIntervalSati: vrednostIliDefault(podesavanja, "backup_interval_sati", "24"),
|
||||
BackupBrojKopija: vrednostIliDefault(podesavanja, "backup_broj_kopija", "7"),
|
||||
KalkulacijaMarza: vrednostIliDefault(podesavanja, "kalkulacija_marza", "20"),
|
||||
ServisGarancijaMeseci: vrednostIliDefault(podesavanja, "servis_garancija_meseci", "2"),
|
||||
ServisGarancijaDana: vrednostIliDefault(podesavanja, "servis_garancija_dana", "60"),
|
||||
PredracunRokDana: vrednostIliDefault(podesavanja, "predracun_rok_dana", "7"),
|
||||
PredvidjenRokDana: vrednostIliDefault(podesavanja, "predvidjen_rok_dana", "15"),
|
||||
}, nil
|
||||
|
||||
+105
-15
@@ -3,6 +3,7 @@ package handler
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strconv"
|
||||
@@ -148,7 +149,7 @@ func (h *Handler) NoviNalog(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
tehnicari, err := h.KorisniciRepo.Lista(r.Context())
|
||||
if err != nil {
|
||||
http.Error(w, "Greška pri učitavanju tehničara", http.StatusInternalServerError)
|
||||
http.Error(w, "Greška pri učitavanju servisera", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -293,7 +294,7 @@ func (h *Handler) IzmeniNalog(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
tehnicari, err := h.KorisniciRepo.Lista(r.Context())
|
||||
if err != nil {
|
||||
http.Error(w, "Greška pri učitavanju tehničara", http.StatusInternalServerError)
|
||||
http.Error(w, "Greška pri učitavanju servisera", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -381,6 +382,8 @@ func (h *Handler) SacuvajIzmenaNaloga(w http.ResponseWriter, r *http.Request) {
|
||||
nalog.DatumZavrsetka = stari.DatumZavrsetka
|
||||
nalog.PredvidjenDatum = stari.PredvidjenDatum
|
||||
nalog.DatumPrijema = stari.DatumPrijema
|
||||
nalog.GarancijaDo = stari.GarancijaDo // garancija se uređuje u detaljima, ne u formi
|
||||
nalog.GarancijaDana = stari.GarancijaDana // isto — trajanje garancije se ne dira u formi
|
||||
}
|
||||
|
||||
// garancija ne sme da bude pre datuma prijema
|
||||
@@ -537,12 +540,9 @@ func (h *Handler) DetaljiNaloga(w http.ResponseWriter, r *http.Request) {
|
||||
nalog.PredvidjenDatum = defaultPredvidjenDatum(nalog.DatumPrijema, podesavanja)
|
||||
}
|
||||
|
||||
// podrazumevana garancija (za dugme „Podrazumevano" u popup-u) i stanje „bez garancije" iz baze
|
||||
garancijaDefault := ""
|
||||
if d := defaultGarancija(nalog.DatumPrijema, podesavanja); d != nil {
|
||||
garancijaDefault = d.Format("2006-01-02")
|
||||
}
|
||||
bezGarancije := nalog.GarancijaDo == nil
|
||||
// podrazumevano trajanje garancije u danima (dugme „Podrazumevano") i stanje „bez garancije" iz baze
|
||||
garancijaDefault := strconv.Itoa(defaultGarancijaDana(podesavanja))
|
||||
bezGarancije := nalog.GarancijaDana == nil || *nalog.GarancijaDana <= 0
|
||||
|
||||
klijentNaziv := ""
|
||||
if nalog.KlijentID != nil {
|
||||
@@ -560,10 +560,10 @@ func (h *Handler) DetaljiNaloga(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// lista tehničara za izbor u popup-u „Promeni tehničara"
|
||||
// lista servisera za izbor u popup-u „Promeni servisera"
|
||||
tehnicari, err := h.KorisniciRepo.Lista(r.Context())
|
||||
if err != nil {
|
||||
slog.Error("greška pri učitavanju tehničara", "error", err)
|
||||
slog.Error("greška pri učitavanju servisera", "error", err)
|
||||
}
|
||||
|
||||
delovi, err := h.deloviSaPotrazivanima(r.Context(), id)
|
||||
@@ -905,7 +905,7 @@ func parseFormuNaloga(r *http.Request) (model.ServisniNalog, string) {
|
||||
}
|
||||
}
|
||||
|
||||
// opcioni tehničar
|
||||
// opcioni serviser
|
||||
if tidStr := r.FormValue("tehnicar_id"); tidStr != "" {
|
||||
if tid, err := strconv.ParseInt(tidStr, 10, 64); err == nil {
|
||||
nalog.TehnicarID = &tid
|
||||
@@ -1021,6 +1021,60 @@ func defaultPredvidjenDatum(datumPrijema time.Time, podesavanja map[string]strin
|
||||
return &t
|
||||
}
|
||||
|
||||
// srpskiPlural vraća odgovarajući oblik reči za dati broj (1 / 2–4 / 5+).
|
||||
func srpskiPlural(n int, jedan, par, mnogo string) string {
|
||||
if n < 0 {
|
||||
n = -n
|
||||
}
|
||||
d, dd := n%10, n%100
|
||||
switch {
|
||||
case d == 1 && dd != 11:
|
||||
return jedan
|
||||
case d >= 2 && d <= 4 && (dd < 12 || dd > 14):
|
||||
return par
|
||||
default:
|
||||
return mnogo
|
||||
}
|
||||
}
|
||||
|
||||
// garancijaUTekst formatira trajanje garancije (u danima) na srpskom:
|
||||
// 20 → „20 dana", 45 → „1 mesec i 15 dana", 60 → „2 meseca".
|
||||
func garancijaUTekst(dana int) string {
|
||||
if dana <= 0 {
|
||||
return "bez garancije"
|
||||
}
|
||||
m := dana / 30
|
||||
d := dana % 30
|
||||
mesecRec := srpskiPlural(m, "mesec", "meseca", "meseci")
|
||||
danRec := srpskiPlural(d, "dan", "dana", "dana")
|
||||
switch {
|
||||
case m > 0 && d > 0:
|
||||
return fmt.Sprintf("%d %s i %d %s", m, mesecRec, d, danRec)
|
||||
case m > 0:
|
||||
return fmt.Sprintf("%d %s", m, mesecRec)
|
||||
default:
|
||||
return fmt.Sprintf("%d %s", d, danRec)
|
||||
}
|
||||
}
|
||||
|
||||
// garancijaTekst je šablonski helper: trajanje garancije u danima → tekst, ili „—" za prazno.
|
||||
func garancijaTekst(dana *int) string {
|
||||
if dana == nil || *dana <= 0 {
|
||||
return "—"
|
||||
}
|
||||
return garancijaUTekst(*dana)
|
||||
}
|
||||
|
||||
// defaultGarancijaDana vraća podrazumevano trajanje garancije u danima iz podešavanja
|
||||
// (servis_garancija_dana, podrazumevano 60).
|
||||
func defaultGarancijaDana(podesavanja map[string]string) int {
|
||||
dana, err := strconv.Atoi(vrednostIliDefault(podesavanja, "servis_garancija_dana", "60"))
|
||||
if err != nil || dana < 0 {
|
||||
return 60
|
||||
}
|
||||
return dana
|
||||
}
|
||||
|
||||
// garancijaPrePrijema vraća true ako je datum garancije raniji od datuma prijema (po danu).
|
||||
// Garancija ne sme da bude pre prijema uređaja.
|
||||
func garancijaPrePrijema(garancija, prijem time.Time) bool {
|
||||
@@ -1483,6 +1537,42 @@ func (h *Handler) AzurirajGaranciju(w http.ResponseWriter, r *http.Request) {
|
||||
http.Redirect(w, r, "/servis/"+strconv.FormatInt(id, 10), http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// AzurirajGarancijaDana postavlja trajanje garancije u danima (od završetka radova);
|
||||
// „bez garancije" ili prazno/0 → bez garancije.
|
||||
func (h *Handler) AzurirajGarancijaDana(w http.ResponseWriter, r *http.Request) {
|
||||
if _, ok := h.zahtevajDozvolu(w, r, "servis.izmeni"); !ok {
|
||||
return
|
||||
}
|
||||
id, err := parseID(chi.URLParam(r, "id"))
|
||||
if err != nil {
|
||||
http.Error(w, "Neispravan ID naloga", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err := r.ParseForm(); err != nil {
|
||||
http.Error(w, "Greška pri čitanju forme", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
var dana *int
|
||||
if r.FormValue("bez_garancije") != "1" {
|
||||
if s := strings.TrimSpace(r.FormValue("garancija_dana")); s != "" {
|
||||
n, err := strconv.Atoi(s)
|
||||
if err != nil || n < 0 {
|
||||
http.Error(w, "Garancija mora biti ceo broj dana.", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if n > 0 {
|
||||
dana = &n
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := h.ServisRepo.AzurirajGarancijaDana(r.Context(), id, dana); err != nil {
|
||||
slog.Error("greška pri ažuriranju garancije (dana)", "id", id, "error", err)
|
||||
http.Error(w, "Greška pri ažuriranju garancije", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, "/servis/"+strconv.FormatInt(id, 10), http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// AzurirajPredvidjenDatum postavlja ručni override predviđenog datuma popravke;
|
||||
// prazno polje vraća nalog na izvedeni default (prijem + rok iz podešavanja).
|
||||
func (h *Handler) AzurirajPredvidjenDatum(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -1515,7 +1605,7 @@ func (h *Handler) AzurirajPredvidjenDatum(w http.ResponseWriter, r *http.Request
|
||||
http.Redirect(w, r, "/servis/"+strconv.FormatInt(id, 10), http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// AzurirajTehnicar menja dodeljenog tehničara na nalogu; prazna vrednost → nedodeljen.
|
||||
// AzurirajTehnicar menja dodeljenog servisera na nalogu; prazna vrednost → nedodeljen.
|
||||
func (h *Handler) AzurirajTehnicar(w http.ResponseWriter, r *http.Request) {
|
||||
if _, ok := h.zahtevajDozvolu(w, r, "servis.izmeni"); !ok {
|
||||
return
|
||||
@@ -1533,14 +1623,14 @@ func (h *Handler) AzurirajTehnicar(w http.ResponseWriter, r *http.Request) {
|
||||
if t := strings.TrimSpace(r.FormValue("tehnicar_id")); t != "" {
|
||||
v, err := strconv.ParseInt(t, 10, 64)
|
||||
if err != nil {
|
||||
http.Error(w, "Neispravan tehničar", http.StatusBadRequest)
|
||||
http.Error(w, "Neispravan serviser", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
tehnicarID = &v
|
||||
}
|
||||
if err := h.ServisRepo.AzurirajTehnicar(r.Context(), id, tehnicarID); err != nil {
|
||||
slog.Error("greška pri ažuriranju tehničara", "id", id, "error", err)
|
||||
http.Error(w, "Greška pri ažuriranju tehničara", http.StatusInternalServerError)
|
||||
slog.Error("greška pri ažuriranju servisera", "id", id, "error", err)
|
||||
http.Error(w, "Greška pri ažuriranju servisera", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
http.Redirect(w, r, "/servis/"+strconv.FormatInt(id, 10), http.StatusSeeOther)
|
||||
|
||||
@@ -40,6 +40,7 @@ type ServisniNalog struct {
|
||||
Avans *float64
|
||||
Napomena string
|
||||
GarancijaDo *time.Time
|
||||
GarancijaDana *int // trajanje garancije u danima (od završetka); nil/0 = bez garancije
|
||||
DatumPrijema time.Time
|
||||
PredvidjenDatum *time.Time
|
||||
DatumZavrsetka *time.Time
|
||||
|
||||
Reference in New Issue
Block a user