package model import ( "fmt" "time" ) // Statusi servisnog naloga const ( 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, StatusPreuzeto, } // ServisniNalog predstavlja jedan servisni nalog type ServisniNalog struct { ID int64 KlijentID *int64 TehnicarID *int64 BrojNaloga string Uredjaj string SerijskiBroj string OpisKvara string TrazeneNadogradnje string Status string CenaOd *float64 CenaDo *float64 CenaKonacna *float64 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 Ostecenja string PinUredjaja string Pribor string NapomenaKlijentu string NalazDijagnostike string // šta je serviser utvrdio pregledom (dijagnoza + predlog popravke) Uradjeno string // šta je serviser stvarno uradio tokom popravke CenaDijagnostike float64 // taksa kad klijent ne prihvati popravku; 0 = ne naplaćuje se PopravkaOdbijena bool // klijent odbio popravku posle dijagnostike → naplaćuje se samo dijagnostika KomentarKlijenta string // poruka klijenta uz prihvatanje/odbijanje predloga OdlukaKlijenta string // '' / 'prihvaceno' / 'odbijeno' DatumOdluke *time.Time // kada je klijent doneo odluku JavniToken string NacinPlacanja string // način plaćanja pri preuzimanju (Gotovina, Kartica, Virman...) Naplaceno float64 // iznos koji je naplaćen pri preuzimanju Stornirano bool RazlogStorniranja string } // ServisniLog je jedan zapis u istoriji događaja servisnog naloga. type ServisniLog struct { ID int64 NalogID int64 Dogadjaj string // npr. "status:U dijagnostici", "odluka:prihvaceno" Napomena string KorisnikID *int64 Datum time.Time } // ServisniDeo predstavlja jedan artikal ugrađen u servisni nalog type ServisniDeo struct { ID int64 NalogID int64 ArtikalID int64 Kolicina int CenaKomada float64 Datum time.Time Predlozeno bool // true = serviser predložio posle dijagnostike; čeka odobrenje klijenta } // Ukupno vraća ukupnu vrednost dela (kolicina × cena) func (d ServisniDeo) Ukupno() float64 { return float64(d.Kolicina) * d.CenaKomada } // UkupnoSaPdv vraća ukupnu vrednost dela sa PDV-om (kolicina × cena_sa_pdv) func (d ServisniDeoSaArtiklom) UkupnoSaPdv() float64 { return float64(d.Kolicina) * d.CenaSaPdv } // ServisniDeoSaArtiklom je servisni deo sa nazivom artikla — za prikaz type ServisniDeoSaArtiklom struct { ServisniDeo ArtikalNaziv string ArtikalSifra string PdvStopa float64 CenaSaPdv float64 Potrazivano int // komada koji nedostaju (iz servisni_potrazivani_delovi), 0 ako nema } // ServisniPotrazivaniDeo beleži artikle koji nedostaju za servisni nalog — // količina koja se traži a nije na stanju; ne skida se sa lagera dok ne stigne type ServisniPotrazivaniDeo struct { ID int64 NalogID int64 ArtikalID int64 Kolicina int CenaKomada float64 Datum time.Time Predlozeno bool // za prikaz: ArtikalNaziv string } // ServisniRad predstavlja jednu stavku rada (uslugu) na servisnom nalogu. // Naziv i cena su snapshot iz cenovnika usluga; cena se može menjati po nalogu. type ServisniRad struct { ID int64 NalogID int64 UslugaID int64 // 0 ako je usluga u međuvremenu obrisana iz cenovnika Naziv string Sifra string Kolicina float64 CenaKomada float64 PdvStopa float64 CenaSaPdv float64 // CenaKomada * (1 + PdvStopa/100) Datum string Predlozeno bool // true = serviser predložio posle dijagnostike; čeka odobrenje klijenta } // Ukupno vraća ukupnu vrednost rada (kolicina × cena) func (r ServisniRad) Ukupno() float64 { return r.Kolicina * r.CenaKomada } // UkupnoSaPdv vraća ukupnu vrednost rada sa PDV-om (kolicina × cena_sa_pdv) func (r ServisniRad) UkupnoSaPdv() float64 { return r.Kolicina * r.CenaSaPdv } // ServisniNalogSaKlijentom proširuje ServisniNalog sa nazivom klijenta za prikaz u listi type ServisniNalogSaKlijentom struct { ServisniNalog KlijentNaziv string ImaPredlog bool // ima predloženih stavki koje čekaju odobrenje klijenta } // KlijentIDVrednost vraća vrednost KlijentID pointera, ili 0 ako je nil func (n ServisniNalog) KlijentIDVrednost() int64 { if n.KlijentID == nil { return 0 } return *n.KlijentID } // TehnicarIDVrednost vraća vrednost TehnicarID pointera, ili 0 ako je nil func (n ServisniNalog) TehnicarIDVrednost() int64 { if n.TehnicarID == nil { return 0 } return *n.TehnicarID } // CenaOdStr vraća formatiranu procenu od, ili prazan string ako nije uneta func (n ServisniNalog) CenaOdStr() string { if n.CenaOd == nil { return "" } return fmt.Sprintf("%.2f", *n.CenaOd) } // CenaDoStr vraća formatiranu procenu do, ili prazan string ako nije uneta func (n ServisniNalog) CenaDoStr() string { if n.CenaDo == nil { return "" } return fmt.Sprintf("%.2f", *n.CenaDo) } // CenaKonacnaStr vraća formatiranu konačnu cenu, ili prazan string ako nije uneta func (n ServisniNalog) CenaKonacnaStr() string { if n.CenaKonacna == nil { return "" } return fmt.Sprintf("%.2f", *n.CenaKonacna) } // AvansStr vraća formatirani avans, ili prazan string ako nije unet func (n ServisniNalog) AvansStr() string { if n.Avans == nil { return "" } return fmt.Sprintf("%.2f", *n.Avans) } // CenaDijagnostikeStr vraća cenu dijagnostike za , ili prazan string kad je 0 func (n ServisniNalog) CenaDijagnostikeStr() string { if n.CenaDijagnostike == 0 { return "" } return fmt.Sprintf("%.2f", n.CenaDijagnostike) } // PreostaloZaNaplatu vraća razliku konacna_cena − avans, minimum 0. // Vraća nil ako konačna cena nije uneta. func (n ServisniNalog) PreostaloZaNaplatu() *float64 { if n.CenaKonacna == nil { return nil } avans := 0.0 if n.Avans != nil { avans = *n.Avans } v := *n.CenaKonacna - avans if v < 0 { v = 0 } return &v } // PreostaloZaNaplatuStr vraća formatirano preostalo za naplatu, ili prazan string func (n ServisniNalog) PreostaloZaNaplatuStr() string { v := n.PreostaloZaNaplatu() if v == nil { return "" } return fmt.Sprintf("%.2f", *v) }