- PFR API ključ (pfr_api_key) u podešavanjima i fiskalizaciji - Formatiranje fiskalnog računa: veličina fonta, QR kod, layout - PFR mock: QR box_size/border, automatski PIN retry posle BE restarta - Servis: animirane kanban kartice, formatiranje računa - Dashboard i testovi: sitne ispravke
218 lines
13 KiB
HTML
218 lines
13 KiB
HTML
{{template "base" .}}
|
|
|
|
{{define "naslov"}}Podešavanja — Fiskalizacija — NTech{{end}}
|
|
|
|
{{define "sadrzaj"}}
|
|
<div class="stranica-stack" style="width:100%;max-width:100%;">
|
|
|
|
<div class="kartica animiraj" style="margin-bottom:16px;">
|
|
<div style="display:flex;align-items:center;gap:10px;margin-bottom:16px;padding-bottom:12px;border-bottom:0.5px solid var(--ivica);">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--sb-akcent)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="5" width="20" height="14" rx="2"/><line x1="2" y1="10" x2="22" y2="10"/></svg>
|
|
<span style="font-size:15px;font-weight:500;color:var(--tekst-glavni);">L-PFR veza</span>
|
|
</div>
|
|
|
|
<form method="POST" action="/podesavanja/sacuvaj">
|
|
<input type="hidden" name="_next" value="/admin/podesavanja/fiskalizacija">
|
|
|
|
<div style="display:flex;flex-direction:column;gap:16px;max-width:480px;">
|
|
|
|
<div>
|
|
<label for="pfr_tip" class="polje-labela">Tip fiskalnog servera</label>
|
|
<select id="pfr_tip" name="pfr_tip"
|
|
style="width:100%;padding:8px 12px;background:var(--pozadina);border:0.5px solid var(--ivica);border-radius:8px;color:var(--tekst-glavni);font-size:14px;">
|
|
<option value="teron" {{if eq .PfrTip "teron"}}selected{{end}}>Teron L-PFR</option>
|
|
</select>
|
|
<div class="pomocni-tekst" style="margin-top:4px;">Trenutno podržan samo Teron L-PFR.</div>
|
|
</div>
|
|
|
|
<div>
|
|
<label for="fiskalni_pismo" class="polje-labela">Pismo fiskalnog računa</label>
|
|
<select id="fiskalni_pismo" name="fiskalni_pismo"
|
|
style="width:100%;padding:8px 12px;background:var(--pozadina);border:0.5px solid var(--ivica);border-radius:8px;color:var(--tekst-glavni);font-size:14px;">
|
|
<option value="latin" {{if ne .FiskalPismo "cyrillic"}}selected{{end}}>Latinica</option>
|
|
<option value="cyrillic" {{if eq .FiskalPismo "cyrillic"}}selected{{end}}>Ćirilica</option>
|
|
</select>
|
|
<div class="pomocni-tekst" style="margin-top:4px;">Pismo kojim Fisk štampa tekst računa. Stupi na snagu posle restarta Fisk servera. Env var <code>FISKALNI_PISMO</code> ima prednost.</div>
|
|
</div>
|
|
|
|
<div>
|
|
<label for="pfr_kasir" class="polje-labela">Kasir (ime na računu)</label>
|
|
<input type="text" id="pfr_kasir" name="pfr_kasir" value="{{.PfrKasir}}"
|
|
placeholder="npr. Petar Petrović"
|
|
style="width:100%;padding:8px 12px;background:var(--pozadina);border:0.5px solid var(--ivica);border-radius:8px;color:var(--tekst-glavni);font-size:14px;box-sizing:border-box;">
|
|
<div class="pomocni-tekst" style="margin-top:4px;">Ime koje se štampa u redu „Kasir" na fiskalnom računu. Prazno = prikazuje se „NTech".</div>
|
|
</div>
|
|
|
|
<div>
|
|
<label for="pfr_url" class="polje-labela">URL fiskalnog servera</label>
|
|
<input type="text" id="pfr_url" name="pfr_url" value="{{.PfrUrl}}"
|
|
placeholder="http://127.0.0.1:4566"
|
|
style="width:100%;padding:8px 12px;background:var(--pozadina);border:0.5px solid var(--ivica);border-radius:8px;color:var(--tekst-glavni);font-size:14px;box-sizing:border-box;">
|
|
<div class="pomocni-tekst" style="margin-top:4px;">
|
|
Lokalno: <code>http://127.0.0.1:4566</code> ·
|
|
Docker: <code>http://teron-mock:4566</code>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<label for="pfr_api_key" class="polje-labela">API ključ</label>
|
|
<input type="text" id="pfr_api_key" name="pfr_api_key" value="{{.PfrApiKey}}"
|
|
placeholder="mock-api-key-0000"
|
|
style="width:100%;padding:8px 12px;background:var(--pozadina);border:0.5px solid var(--ivica);border-radius:8px;color:var(--tekst-glavni);font-size:14px;box-sizing:border-box;font-family:monospace;">
|
|
<div class="pomocni-tekst" style="margin-top:4px;">Bearer token koji NTech šalje PFR serveru. Mock podrazumevano: <code>mock-api-key-0000</code>.</div>
|
|
</div>
|
|
|
|
<div style="display:flex;gap:10px;align-items:center;flex-wrap:wrap;">
|
|
<button type="submit"
|
|
style="padding:9px 18px;background:var(--sb-akcent);border:none;border-radius:8px;color:#fff;font-size:13px;font-weight:500;cursor:pointer;">
|
|
Sačuvaj
|
|
</button>
|
|
<button type="button"
|
|
hx-get="/podesavanja/fiskalizacija/test"
|
|
hx-include="#pfr_url"
|
|
hx-target="#fisk-test-rezultat"
|
|
hx-swap="innerHTML"
|
|
hx-indicator="#fisk-test-spinner"
|
|
style="padding:9px 18px;background:var(--kartica);border:0.5px solid var(--ivica);border-radius:8px;color:var(--tekst-sporedni);font-size:13px;cursor:pointer;">
|
|
Testiraj vezu
|
|
</button>
|
|
<span id="fisk-test-spinner" class="htmx-indicator" style="font-size:12px;color:var(--tekst-sporedni);">Proveravam...</span>
|
|
</div>
|
|
|
|
</div>
|
|
</form>
|
|
|
|
<div id="fisk-test-rezultat" style="margin-top:16px;"></div>
|
|
|
|
</div>
|
|
|
|
<!-- Kartica emulator -->
|
|
<div class="kartica animiraj">
|
|
<div style="display:flex;align-items:center;gap:10px;margin-bottom:16px;padding-bottom:12px;border-bottom:0.5px solid var(--ivica);">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--sb-akcent)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M3 10h18"/><path d="M7 15h.01"/><path d="M11 15h2"/></svg>
|
|
<span style="font-size:15px;font-weight:500;color:var(--tekst-glavni);">Kartica emulator (BE)</span>
|
|
</div>
|
|
<div class="pomocni-tekst" style="margin-bottom:16px;">
|
|
Bezbednosni element — drži PIN, limite i brojače. Radi kao goroutine unutar NTech-a (port 4567).
|
|
Promene PIN-a i limita stupaju na snagu tek posle restarta servera.
|
|
</div>
|
|
|
|
<form method="POST" action="/podesavanja/sacuvaj">
|
|
<input type="hidden" name="_next" value="/admin/podesavanja/fiskalizacija">
|
|
|
|
<div style="display:flex;flex-direction:column;gap:16px;max-width:480px;">
|
|
|
|
<div>
|
|
<label for="be_enabled" class="polje-labela">Kartica emulator</label>
|
|
<select id="be_enabled" name="be_enabled"
|
|
style="width:100%;padding:8px 12px;background:var(--pozadina);border:0.5px solid var(--ivica);border-radius:8px;color:var(--tekst-glavni);font-size:14px;">
|
|
<option value="true" {{if ne .BeEnabled "false"}}selected{{end}}>Uključen (mock kartica)</option>
|
|
<option value="false" {{if eq .BeEnabled "false"}}selected{{end}}>Isključen (pravi Teron uređaj)</option>
|
|
</select>
|
|
<div class="pomocni-tekst" style="margin-top:4px;">Isključi kad koristiš pravi Teron/fizički L-PFR. Stupi na snagu posle restarta servera. Env var <code>BE_ENABLED=false</code> ima prednost.</div>
|
|
</div>
|
|
|
|
<div>
|
|
<label for="be_pin" class="polje-labela">PIN kartice</label>
|
|
<input type="text" id="be_pin" name="be_pin" value="{{.BePin}}"
|
|
maxlength="8" placeholder="1234"
|
|
style="width:100%;padding:8px 12px;background:var(--pozadina);border:0.5px solid var(--ivica);border-radius:8px;color:var(--tekst-glavni);font-size:14px;box-sizing:border-box;font-family:monospace;">
|
|
<div class="pomocni-tekst" style="margin-top:4px;">PIN koji Fisk šalje pri verify_pin komandi. Podrazumevano: <code>1234</code>. Env var <code>BE_PIN</code> ima prednost.</div>
|
|
</div>
|
|
|
|
<div>
|
|
<label for="be_limit" class="polje-labela">Limit iščitavanja (din)</label>
|
|
<input type="number" id="be_limit" name="be_limit" value="{{.BeLimit}}"
|
|
min="1000" step="1000" placeholder="500000"
|
|
style="width:100%;padding:8px 12px;background:var(--pozadina);border:0.5px solid var(--ivica);border-radius:8px;color:var(--tekst-glavni);font-size:14px;box-sizing:border-box;">
|
|
<div class="pomocni-tekst" style="margin-top:4px;">Maksimalni neisčitani promet pre blokade kartice. Podrazumevano: <code>500 000</code>. Env var <code>BE_LIMIT</code> ima prednost.</div>
|
|
</div>
|
|
|
|
<div>
|
|
<label for="verify_host" class="polje-labela">Domen za verifikacioni QR link</label>
|
|
<input type="text" id="verify_host" name="verify_host" value="{{.VerifyHost}}"
|
|
placeholder="ntech.moja-firma.rs:3000"
|
|
style="width:100%;padding:8px 12px;background:var(--pozadina);border:0.5px solid var(--ivica);border-radius:8px;color:var(--tekst-glavni);font-size:14px;box-sizing:border-box;">
|
|
<div class="pomocni-tekst" style="margin-top:4px;">
|
|
Npr. <code>192.168.1.10:3000</code> ili <code>ntech.firma.rs</code>.
|
|
Prazno = QR vodi na <code>sandbox.suf.purs.gov.rs</code>.
|
|
Env var <code>VERIFY_HOST</code> ima prednost nad ovim poljem.
|
|
Fisk čita ovu vrednost pri pokretanju.
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<button type="submit"
|
|
style="padding:9px 18px;background:var(--sb-akcent);border:none;border-radius:8px;color:#fff;font-size:13px;font-weight:500;cursor:pointer;">
|
|
Sačuvaj
|
|
</button>
|
|
</div>
|
|
|
|
</div>
|
|
</form>
|
|
|
|
<!-- Status kartice (live) -->
|
|
<div style="margin-top:20px;padding-top:16px;border-top:0.5px solid var(--ivica);">
|
|
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:10px;gap:8px;flex-wrap:wrap;">
|
|
<span style="font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:0.5px;color:var(--tekst-sporedni);">Status kartice</span>
|
|
<div style="display:flex;gap:8px;">
|
|
<button type="button"
|
|
hx-post="/podesavanja/fiskalizacija/be-reset-audit"
|
|
hx-target="#be-status-panel"
|
|
hx-swap="innerHTML"
|
|
hx-confirm="Simulirati Proof of Audit? Ovo će resetovati neisčitani iznos na 0."
|
|
style="padding:5px 12px;background:transparent;border:0.5px solid var(--ivica);border-radius:6px;color:var(--tekst-sporedni);font-size:12px;cursor:pointer;">
|
|
Resetuj limit
|
|
</button>
|
|
<button type="button"
|
|
hx-get="/podesavanja/fiskalizacija/be-status"
|
|
hx-target="#be-status-panel"
|
|
hx-swap="innerHTML"
|
|
style="padding:5px 12px;background:transparent;border:0.5px solid var(--ivica);border-radius:6px;color:var(--tekst-sporedni);font-size:12px;cursor:pointer;">
|
|
Osveži
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div id="be-status-panel"
|
|
hx-get="/podesavanja/fiskalizacija/be-status"
|
|
hx-trigger="load"
|
|
hx-swap="innerHTML">
|
|
<span style="font-size:12px;color:var(--tekst-sporedni);">Učitavanje...</span>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<style>
|
|
.fisk-status {
|
|
display: inline-flex;
|
|
flex-direction: column;
|
|
gap: 6px;
|
|
padding: 10px 14px;
|
|
border-radius: 8px;
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
}
|
|
.fisk-status.uspeh {
|
|
background: color-mix(in srgb, var(--zelena, #22c55e) 12%, transparent);
|
|
color: var(--zelena, #22c55e);
|
|
border: 0.5px solid color-mix(in srgb, var(--zelena, #22c55e) 30%, transparent);
|
|
}
|
|
.fisk-status.greska {
|
|
background: color-mix(in srgb, var(--crvena, #ef4444) 12%, transparent);
|
|
color: var(--crvena, #ef4444);
|
|
border: 0.5px solid color-mix(in srgb, var(--crvena, #ef4444) 30%, transparent);
|
|
}
|
|
.fisk-status-detalji {
|
|
display: flex;
|
|
gap: 16px;
|
|
flex-wrap: wrap;
|
|
font-size: 12px;
|
|
font-weight: 400;
|
|
opacity: 0.85;
|
|
}
|
|
</style>
|
|
{{end}}
|