Servis: nalepnica za uređaj (70×40 mm) sa QR kodom
This commit is contained in:
@@ -357,6 +357,7 @@ 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}", h.DetaljiNaloga)
|
||||||
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis/{id}/stampa", h.StampaServisa)
|
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis/{id}/stampa", h.StampaServisa)
|
||||||
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}/otpremnica", h.StampaOtpremnice)
|
||||||
|
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}/predracun", h.StampaPredracuna)
|
r.With(ntechmw.RequireDozvola(h.DozvoleRepo.ImaDozvolu, "servis.pregled")).Get("/servis/{id}/predracun", h.StampaPredracuna)
|
||||||
r.With(doz("servis.izmeni")).Post("/servis/{id}/status", h.PromeniStatus)
|
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", h.AzurirajGaranciju)
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ var saSidebar = []string{
|
|||||||
|
|
||||||
// standalone su šabloni bez base layouta
|
// standalone su šabloni bez base layouta
|
||||||
var standaloneIme = []string{
|
var standaloneIme = []string{
|
||||||
"prijava", "setup", "totp_provera", "prodaja_stampa", "servis_stampa", "servis_otpremnica", "servis_predracun", "servis_status_javni",
|
"prijava", "setup", "totp_provera", "prodaja_stampa", "servis_stampa", "servis_otpremnica", "servis_predracun", "servis_nalepnica", "servis_status_javni",
|
||||||
}
|
}
|
||||||
|
|
||||||
// sablonskeFunkcije su pomoćne funkcije dostupne u svim šablonima.
|
// sablonskeFunkcije su pomoćne funkcije dostupne u svim šablonima.
|
||||||
|
|||||||
@@ -1298,6 +1298,52 @@ func (h *Handler) StampaOtpremnice(w http.ResponseWriter, r *http.Request) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PodaciNalepnice su podaci za malu nalepnicu (70×40 mm) koja se lepi na uređaj
|
||||||
|
type PodaciNalepnice struct {
|
||||||
|
Nalog model.ServisniNalog
|
||||||
|
KlijentNaziv string
|
||||||
|
QRKod string // base64 PNG QR koda sa URL-om naloga
|
||||||
|
}
|
||||||
|
|
||||||
|
// StampaNalepnice renderuje malu nalepnicu sa brojem naloga, klijentom, uređajem i QR kodom
|
||||||
|
func (h *Handler) StampaNalepnice(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
|
||||||
|
}
|
||||||
|
|
||||||
|
klijentNaziv := ""
|
||||||
|
if nalog.KlijentID != nil {
|
||||||
|
k, err := h.KlijentiRepo.DohvatiID(r.Context(), *nalog.KlijentID)
|
||||||
|
if err == nil {
|
||||||
|
if k.NazivFirme != "" {
|
||||||
|
klijentNaziv = k.NazivFirme
|
||||||
|
} else {
|
||||||
|
klijentNaziv = strings.TrimSpace(k.Ime + " " + k.Prezime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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_nalepnica", PodaciNalepnice{
|
||||||
|
Nalog: *nalog,
|
||||||
|
KlijentNaziv: klijentNaziv,
|
||||||
|
QRKod: qrKod,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// PodaciPredracuna su podaci za predračun/ponudu koja se šalje klijentu pre rada
|
// PodaciPredracuna su podaci za predračun/ponudu koja se šalje klijentu pre rada
|
||||||
type PodaciPredracuna struct {
|
type PodaciPredracuna struct {
|
||||||
Nalog model.ServisniNalog
|
Nalog model.ServisniNalog
|
||||||
|
|||||||
@@ -60,6 +60,9 @@
|
|||||||
Otpremnica
|
Otpremnica
|
||||||
</a>
|
</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
<a href="/servis/{{.Nalog.ID}}/nalepnica" target="_blank" class="btn-sekundarno">
|
||||||
|
Nalepnica
|
||||||
|
</a>
|
||||||
<a href="/servis/izmeni/{{.Nalog.ID}}" class="btn-primarno" hx-boost="true" hx-target="#glavni-sadrzaj" hx-select="#glavni-sadrzaj" hx-swap="outerHTML">
|
<a href="/servis/izmeni/{{.Nalog.ID}}" class="btn-primarno" hx-boost="true" hx-target="#glavni-sadrzaj" hx-select="#glavni-sadrzaj" hx-swap="outerHTML">
|
||||||
Izmeni nalog
|
Izmeni nalog
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="sr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Nalepnica — {{.Nalog.BrojNaloga}}</title>
|
||||||
|
<style>
|
||||||
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||||
|
html, body { background: #f4f4f5; }
|
||||||
|
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif; color: #111; }
|
||||||
|
|
||||||
|
/* nalepnica 70×40 mm */
|
||||||
|
.nalepnica {
|
||||||
|
width: 70mm;
|
||||||
|
height: 40mm;
|
||||||
|
background: #fff;
|
||||||
|
padding: 3mm;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 3mm;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
/* na ekranu — centrirano sa okvirom radi pregleda */
|
||||||
|
@media screen {
|
||||||
|
.nalepnica { margin: 24px auto; border: 1px dashed #bbb; box-shadow: 0 1px 4px rgba(0,0,0,.1); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.podaci { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 1.5mm; }
|
||||||
|
.broj { font-family: monospace; font-size: 14pt; font-weight: 700; line-height: 1.1; }
|
||||||
|
.red { font-size: 8pt; line-height: 1.25; }
|
||||||
|
.red .labela { color: #777; text-transform: uppercase; letter-spacing: .3px; font-size: 6.5pt; }
|
||||||
|
.red .vrednost { font-weight: 600; word-break: break-word; }
|
||||||
|
.prazno { color: #aaa; font-style: italic; font-weight: 400; }
|
||||||
|
|
||||||
|
.qr { flex: 0 0 auto; }
|
||||||
|
.qr img { display: block; width: 26mm; height: 26mm; }
|
||||||
|
|
||||||
|
@page { size: 70mm 40mm; margin: 0; }
|
||||||
|
@media print {
|
||||||
|
html, body { background: #fff; }
|
||||||
|
.nalepnica { margin: 0; border: 0; box-shadow: none; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="nalepnica">
|
||||||
|
<div class="podaci">
|
||||||
|
<div class="broj">{{.Nalog.BrojNaloga}}</div>
|
||||||
|
<div class="red">
|
||||||
|
<div class="labela">Klijent</div>
|
||||||
|
<div class="vrednost">{{if .KlijentNaziv}}{{.KlijentNaziv}}{{else}}<span class="prazno">—</span>{{end}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="red">
|
||||||
|
<div class="labela">Uređaj</div>
|
||||||
|
<div class="vrednost">{{if .Nalog.Uredjaj}}{{.Nalog.Uredjaj}}{{else}}<span class="prazno">—</span>{{end}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{if .QRKod}}
|
||||||
|
<div class="qr"><img src="data:image/png;base64,{{.QRKod}}" alt="QR"></div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
<script>window.addEventListener('load', function(){ window.print(); });</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user