Files
GoNtech/web/templates/stranice/servis_revers.html
T
Dasko ff59c3edcf PDV pravilo na štampanim dokumentima + fiksni layout + QR popravka
- PDV uslovi (Moduli.pdv) na: predračun, otpremnica, garantni list, prodaja_stampa
- Modal za preuzimanje: jedna cena (sa/bez PDV), ne duplo
- Javna status stranica: PDV uslovi za cene, predlog, checkbox-ove
- Svi print templejti: viewport=device-width+min-width, bez responsive
- JavniToken generisan za postojeće naloge bez tokena (QR popravka)
- UkupnoSaPdv() metode na ServisniRad i ServisniDeoSaArtiklom
- UkupnoBezPdv() na StavkaProdaje
2026-06-27 02:06:18 +02:00

285 lines
13 KiB
HTML

<!DOCTYPE html>
<html lang="sr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Revers — {{.Nalog.BrojNaloga}}</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif; font-size: 13px; color: #111; background: #fff; min-width: 780px; }
.strana { max-width: 780px; margin: 0 auto; padding: 32px 40px; }
/* zaglavlje: tri okvira (firma · klijent · dokument) */
.zaglavlje { display: flex; align-items: stretch; margin-bottom: 20px; gap: 12px; }
.zg-okvir { flex: 1; padding: 12px 14px; border: 1.5px solid #bbb; border-radius: 12px; }
.firma-naziv { font-size: 18px; font-weight: 700; }
.firma-info { font-size: 11px; color: #555; margin-top: 4px; line-height: 1.7; }
.dok-tip { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 1px; color: #555; margin-bottom: 4px; }
.dok-broj { font-size: 18px; font-weight: 700; font-family: monospace; }
.dok-datum { font-size: 12px; color: #555; margin-top: 4px; }
/* strane */
.strane-blok { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 20px; }
.strana-kartica { padding: 12px 14px; border: 0.5px solid #ddd; border-radius: 6px; }
.strana-tip { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.6px; color: #888; margin-bottom: 6px; }
.strana-naziv { font-size: 14px; font-weight: 600; }
.strana-info { font-size: 12px; color: #555; margin-top: 3px; line-height: 1.6; }
/* odeljci */
.odeljak { margin-bottom: 18px; }
.odeljak-naslov { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.8px; color: #555; margin-bottom: 8px; padding-bottom: 4px; border-bottom: 0.5px solid #ccc; }
/* podaci */
.podaci-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
.polje-labela { font-size: 10px; color: #777; text-transform: uppercase; letter-spacing: 0.4px; margin-bottom: 3px; }
.polje-vrednost { font-size: 13px; font-weight: 500; }
.polje-vrednost-mono { font-family: monospace; font-size: 13px; font-weight: 500; }
.polje-tekst { font-size: 13px; line-height: 1.6; white-space: pre-wrap; }
.prazno { color: #aaa; font-style: italic; }
/* PIN istaknut */
.pin-vrednost { font-family: monospace; font-size: 13px; font-weight: 700; background: #fef9c3; padding: 1px 6px; border-radius: 4px; }
/* napomena klijentu */
.napomena-blok { padding: 10px 14px; border: 0.5px solid #cbd5e1; background: #f8fafc; border-radius: 6px; font-size: 12px; line-height: 1.6; white-space: pre-wrap; }
/* uslovi servisa */
.uslovi-blok { font-size: 11px; color: #444; line-height: 1.7; white-space: pre-wrap; }
/* potpisi */
.potpisi { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; margin-top: 36px; padding-top: 16px; border-top: 0.5px solid #ccc; }
.potpis-linija { border-top: 1px solid #888; margin-top: 44px; padding-top: 6px; font-size: 11px; color: #555; text-align: center; }
/* napomena na dnu */
.dno-info { margin-top: 20px; font-size: 11px; color: #888; text-align: center; }
@page { size: A4; margin: 12mm 14mm 18mm; }
@media print {
body { font-size: 12px; }
.strana { padding: 32px 40px; max-width: 780px; }
.dugme-stampa { display: none !important; }
/* uslovi servisa (sa potpisima) idu na novu stranicu */
.uslovi-strana { break-before: page; }
.stampa-broj-strane { display: block; text-align: center; font-size: 9px; color: #888; margin-top: 16px; }
.stampa-samo-ekran { display: none !important; }
}
.stampa-broj-strane { display: none; }
.stampa-samo-ekran { display: block; }
.dugme-stampa { position: fixed; bottom: 24px; right: 24px; background: #111; color: #fff; border: none; padding: 12px 22px; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.2); }
.dugme-stampa:hover { background: #333; }
</style>
</head>
<body>
<div class="strana">
<!-- zaglavlje -->
<div class="zaglavlje">
<!-- LEVO: firma — logo na vrhu, tekst ispod -->
<div class="zg-okvir">
{{if .LogoPutanja}}
<img src="{{.LogoPutanja}}" alt="Logo" style="max-height:54px;max-width:100%;object-fit:contain;display:block;margin-bottom:8px;">
{{else}}
<div class="firma-naziv">{{if .NazivFirme}}{{.NazivFirme}}{{else}}— naziv firme —{{end}}</div>
{{end}}
<div class="firma-info">
{{if .Podnazlov}}{{.Podnazlov}}<br>{{end}}
{{if .Adresa}}{{.Adresa}}<br>{{end}}
{{if .Telefon}}Tel: {{telefon .Telefon}}<br>{{end}}
{{if .PIB}}PIB: {{.PIB}}{{end}}{{if .MaticniBroj}}{{if .PIB}} &middot; {{end}}MB: {{.MaticniBroj}}{{end}}
</div>
</div>
<!-- SREDINA: barkod na vrhu, ispod dokument i datumi (QR je u sekciji „Uređaj na servisu") -->
<div class="zg-okvir" style="flex:1.3;">
{{if .Barkod}}<img src="data:image/png;base64,{{.Barkod}}" alt="Barkod {{.Nalog.BrojNaloga}}" style="display:block;width:100%;max-height:46px;object-fit:contain;margin-bottom:10px;">{{end}}
<div class="dok-tip">Revers — potvrda o prijemu</div>
<div class="dok-broj">{{.Nalog.BrojNaloga}}</div>
<div class="dok-datum">Datum prijema: {{.Nalog.DatumPrijema.Format "02.01.2006."}}</div>
{{if .Nalog.PredvidjenDatum}}
<div class="dok-datum">Predviđen rok: {{.Nalog.PredvidjenDatum.Format "02.01.2006."}}</div>
{{end}}
</div>
<!-- DESNO: klijent -->
<div class="zg-okvir">
<div class="strana-tip">Klijent</div>
{{if .KlijentNaziv}}
<div class="strana-naziv">{{.KlijentNaziv}}</div>
<div class="strana-info">
{{if .Klijent}}
{{if .Klijent.Telefon}}Tel: {{telefon .Klijent.Telefon}}<br>{{end}}
{{if .Klijent.Email}}{{.Klijent.Email}}<br>{{end}}
{{if .Klijent.Mesto}}{{.Klijent.Mesto}}<br>{{end}}
{{if .Klijent.PIB}}PIB: {{.Klijent.PIB}}{{end}}
{{end}}
</div>
{{else}}
<div class="strana-naziv prazno">— klijent nije naveden —</div>
{{end}}
</div>
</div>
<!-- uređaj (QR skroz desno — klijent ga skenira da prati status) -->
<div class="odeljak">
<div class="odeljak-naslov">Uređaj na servisu</div>
<div style="display:flex;gap:16px;align-items:flex-start;">
<div style="flex:1;">
<div class="podaci-grid" style="margin-bottom:10px;">
<div>
<div class="polje-labela">Naziv uređaja</div>
<div class="polje-vrednost">{{if .Nalog.Uredjaj}}{{.Nalog.Uredjaj}}{{else}}<span class="prazno"></span>{{end}}</div>
</div>
<div>
<div class="polje-labela">Serijski broj</div>
<div class="polje-vrednost-mono">{{if .Nalog.SerijskiBroj}}{{.Nalog.SerijskiBroj}}{{else}}<span class="prazno"></span>{{end}}</div>
</div>
{{if .Nalog.PinUredjaja}}
<div>
<div class="polje-labela">PIN / lozinka</div>
<div><span class="pin-vrednost">{{.Nalog.PinUredjaja}}</span></div>
</div>
{{end}}
</div>
{{if .Nalog.Pribor}}
<div style="margin-top:8px;">
<div class="polje-labela">Pribor predat uz uređaj</div>
<div class="polje-tekst">{{.Nalog.Pribor}}</div>
</div>
{{end}}
{{if .Nalog.Ostecenja}}
<div style="margin-top:8px;">
<div class="polje-labela">Vidljiva oštećenja pri prijemu</div>
<div class="polje-tekst">{{.Nalog.Ostecenja}}</div>
</div>
{{end}}
{{if .Nalog.TrazeneNadogradnje}}
<div style="margin-top:8px;">
<div class="polje-labela">Tražene nadogradnje</div>
<div class="polje-tekst">{{.Nalog.TrazeneNadogradnje}}</div>
</div>
{{end}}
</div>
{{if .QRKod}}
<div style="text-align:center;flex-shrink:0;">
<img src="data:image/png;base64,{{.QRKod}}" width="128" height="128" alt="QR {{.Nalog.BrojNaloga}}"
style="image-rendering:pixelated;border:1px solid #ddd;border-radius:4px;">
<div style="font-size:9px;color:#888;margin-top:3px;">Skenirajte za status</div>
</div>
{{end}}
</div>
</div>
<!-- prijavljeni kvar -->
<div class="odeljak">
<div class="odeljak-naslov">Prijavljeni kvar (po izjavi klijenta)</div>
<div class="polje-tekst">{{if .Nalog.OpisKvara}}{{.Nalog.OpisKvara}}{{else}}<span class="prazno"></span>{{end}}</div>
</div>
<!-- napomena klijentu -->
{{if .Nalog.NapomenaKlijentu}}
<div class="odeljak">
<div class="odeljak-naslov">Napomena</div>
<div class="napomena-blok">{{.Nalog.NapomenaKlijentu}}</div>
</div>
{{end}}
<!-- uslovi servisa -->
{{if .Uslovi}}
<div class="odeljak uslovi-strana">
<div class="odeljak-naslov">Uslovi servisa</div>
<div class="uslovi-blok">{{.Uslovi}}</div>
</div>
{{end}}
<!-- potpisi -->
<div class="potpisi">
<div>
<div class="potpis-linija">Predao (klijent)</div>
</div>
<div>
<div class="potpis-linija">Primio (servis)</div>
</div>
</div>
<div class="dno-info">Revers se izdaje u dva primerka — po jedan za klijenta i za servis. Uređaj se preuzima uz ovaj revers.</div>
</div>
<button class="dugme-stampa" onclick="window.print()">Štampaj</button>
<script>
// Brojevi strana pri štampi — radi u svim browser-ima
(function() {
const sadrzaj = document.querySelector('.strana');
if (!sadrzaj) return;
let originalniHTML = '';
// Visina štampane strane (A4 - margine) u px
const VISINA_STRANE_PX = (297 - 12 - 18) * 96 / 25.4;
function izmeriVisinu(el) {
const test = el.cloneNode(true);
test.style.cssText = 'position:absolute;visibility:hidden;width:' + sadrzaj.offsetWidth + 'px;max-width:none;';
document.body.appendChild(test);
const h = test.scrollHeight;
document.body.removeChild(test);
return h;
}
window.addEventListener('beforeprint', function() {
if (originalniHTML) return;
originalniHTML = sadrzaj.innerHTML;
const ukupnaVisina = izmeriVisinu(sadrzaj);
const brStrana = Math.max(1, Math.ceil(ukupnaVisina / VISINA_STRANE_PX));
if (brStrana <= 1) return;
const deca = Array.from(sadrzaj.children);
sadrzaj.innerHTML = '';
let stranaBr = 1;
let visinaTrenutne = 0;
let stranaDiv = napraviStranu(stranaBr, brStrana);
sadrzaj.appendChild(stranaDiv);
for (const el of deca) {
const h = izmeriVisinu(el);
if (visinaTrenutne + h > VISINA_STRANE_PX && visinaTrenutne > 200) {
dodajBrojac(stranaDiv, stranaBr, brStrana);
stranaBr++;
stranaDiv = napraviStranu(stranaBr, brStrana);
sadrzaj.appendChild(stranaDiv);
visinaTrenutne = 0;
}
stranaDiv.appendChild(el.cloneNode(true));
visinaTrenutne += h;
}
dodajBrojac(stranaDiv, stranaBr, brStrana);
});
function napraviStranu(br, ukupno) {
const d = document.createElement('div');
d.className = 'stampa-stranica';
d.style.cssText = 'min-height:' + (VISINA_STRANE_PX - 30) + 'px;';
if (br < ukupno) d.style.pageBreakAfter = 'always';
return d;
}
function dodajBrojac(stranaDiv, br, ukupno) {
const brojac = document.createElement('div');
brojac.className = 'stampa-broj-strane';
brojac.textContent = br + ' / ' + ukupno;
stranaDiv.appendChild(brojac);
}
window.addEventListener('afterprint', function() {
if (originalniHTML) {
sadrzaj.innerHTML = originalniHTML;
originalniHTML = '';
}
});
})();
</script>
</body>
</html>