Merge branch 'develop'
# Conflicts: # internal/handler/podesavanja.go
This commit is contained in:
+1
-1
@@ -392,7 +392,7 @@ def _build_invoice_response(req, request_id):
|
|||||||
json.dumps(vl_payload, ensure_ascii=False, separators=(",", ":")).encode("utf-8")
|
json.dumps(vl_payload, ensure_ascii=False, separators=(",", ":")).encode("utf-8")
|
||||||
).decode("ascii")
|
).decode("ascii")
|
||||||
scheme = "https" if VERIFY_HOST.startswith("https://") else "http"
|
scheme = "https" if VERIFY_HOST.startswith("https://") else "http"
|
||||||
host = VERIFY_HOST.removeprefix("https://").removeprefix("http://")
|
host = VERIFY_HOST.removeprefix("https://").removeprefix("http://").rstrip("/")
|
||||||
verification_url = f"{scheme}://{host}/v/?vl={urllib.parse.quote(vl, safe='')}"
|
verification_url = f"{scheme}://{host}/v/?vl={urllib.parse.quote(vl, safe='')}"
|
||||||
else:
|
else:
|
||||||
verification_url = f"https://sandbox.suf.purs.gov.rs/v/?vl={invoice_number}"
|
verification_url = f"https://sandbox.suf.purs.gov.rs/v/?vl={invoice_number}"
|
||||||
|
|||||||
@@ -253,6 +253,13 @@ services:
|
|||||||
image: ghcr.io/dalibor31/ntech-fisk:latest
|
image: ghcr.io/dalibor31/ntech-fisk:latest
|
||||||
container_name: teron_mock
|
container_name: teron_mock
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- BE_HOST=ntech # NTech service name on the shared network — required so the
|
||||||
|
- BE_PORT=4567 # mock can read company data (name/PIB/address) from the card emulator
|
||||||
|
- VERIFY_HOST=https://ntech.your-domain.com # takes precedence over the "verify_host" setting
|
||||||
|
# in NTech's UI (the mock can't see ntech.db) —
|
||||||
|
# without it the QR links to sandbox.suf.purs.gov.rs
|
||||||
|
# and is sparse instead of encoding the full invoice
|
||||||
volumes:
|
volumes:
|
||||||
- teron-data:/app/data
|
- teron-data:/app/data
|
||||||
networks:
|
networks:
|
||||||
@@ -267,6 +274,8 @@ networks:
|
|||||||
|
|
||||||
The `teron-mock` service is reachable from `ntech` at `http://teron-mock:4566` over the internal Docker network — the port is not exposed to the host.
|
The `teron-mock` service is reachable from `ntech` at `http://teron-mock:4566` over the internal Docker network — the port is not exposed to the host.
|
||||||
|
|
||||||
|
`BE_HOST`/`BE_PORT` must point to the NTech container's card emulator (`internal/be`, TCP port 4567). Without them, `teron-mock` defaults to `127.0.0.1:4567`, which inside its own container never reaches NTech — the mock then silently falls back to placeholder company data ("Test Company DOO", TIN `RS000000000`) instead of your real business profile.
|
||||||
|
|
||||||
To run as a standalone Docker container:
|
To run as a standalone Docker container:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@@ -276,6 +285,10 @@ services:
|
|||||||
image: ghcr.io/dalibor31/ntech-fisk:latest
|
image: ghcr.io/dalibor31/ntech-fisk:latest
|
||||||
container_name: teron_mock
|
container_name: teron_mock
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- BE_HOST=ntech # adjust to the NTech container's name/hostname on this network
|
||||||
|
- BE_PORT=4567
|
||||||
|
- VERIFY_HOST=https://ntech.your-domain.com
|
||||||
ports:
|
ports:
|
||||||
- "4566:4566"
|
- "4566:4566"
|
||||||
volumes:
|
volumes:
|
||||||
|
|||||||
@@ -253,6 +253,13 @@ services:
|
|||||||
image: ghcr.io/dalibor31/ntech-fisk:latest
|
image: ghcr.io/dalibor31/ntech-fisk:latest
|
||||||
container_name: teron_mock
|
container_name: teron_mock
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- BE_HOST=ntech # naziv NTech servisa na deljenoj mreži — neophodno da bi mock
|
||||||
|
- BE_PORT=4567 # mogao da pročita podatke firme (naziv/PIB/adresa) sa kartica emulatora
|
||||||
|
- VERIFY_HOST=https://ntech.tvoja-firma.rs # ima prednost nad podešavanjem "verify_host" u
|
||||||
|
# NTech UI-ju (mock ne vidi ntech.db) — bez ovoga
|
||||||
|
# QR vodi na sandbox.suf.purs.gov.rs i redak je
|
||||||
|
# umesto da enkoduje ceo račun
|
||||||
volumes:
|
volumes:
|
||||||
- teron-data:/app/data
|
- teron-data:/app/data
|
||||||
networks:
|
networks:
|
||||||
@@ -267,6 +274,8 @@ networks:
|
|||||||
|
|
||||||
Servis `teron-mock` je dostupan iz `ntech` kontejnera na adresi `http://teron-mock:4566` preko interne Docker mreže — port nije izložen spolja.
|
Servis `teron-mock` je dostupan iz `ntech` kontejnera na adresi `http://teron-mock:4566` preko interne Docker mreže — port nije izložen spolja.
|
||||||
|
|
||||||
|
`BE_HOST`/`BE_PORT` moraju pokazivati na kartica emulator NTech kontejnera (`internal/be`, TCP port 4567). Bez toga, `teron-mock` po defaultu koristi `127.0.0.1:4567`, što unutar sopstvenog kontejnera nikad ne stiže do NTech-a — mock onda tiho pada na test podatke firme ("Test Company DOO", PIB `RS000000000`) umesto tvog stvarnog profila firme.
|
||||||
|
|
||||||
Za pokretanje kao samostalni Docker kontejner:
|
Za pokretanje kao samostalni Docker kontejner:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
@@ -276,6 +285,10 @@ services:
|
|||||||
image: ghcr.io/dalibor31/ntech-fisk:latest
|
image: ghcr.io/dalibor31/ntech-fisk:latest
|
||||||
container_name: teron_mock
|
container_name: teron_mock
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- BE_HOST=ntech # prilagodi imenu/hostname-u NTech kontejnera na ovoj mreži
|
||||||
|
- BE_PORT=4567
|
||||||
|
- VERIFY_HOST=https://ntech.tvoja-firma.rs
|
||||||
ports:
|
ports:
|
||||||
- "4566:4566"
|
- "4566:4566"
|
||||||
volumes:
|
volumes:
|
||||||
|
|||||||
+1
-1
@@ -151,7 +151,7 @@ func main() {
|
|||||||
h.Verzija = Verzija
|
h.Verzija = Verzija
|
||||||
h.JelDemo = os.Getenv("NTECH_ENV") == "demo"
|
h.JelDemo = os.Getenv("NTECH_ENV") == "demo"
|
||||||
if h.JelDemo {
|
if h.JelDemo {
|
||||||
h.Verzija = "DEMO verzija"
|
h.Verzija = "DEMO - " + h.Verzija
|
||||||
if err := postaviDemoKorisnika(context.Background(), h.KorisniciRepo); err != nil {
|
if err := postaviDemoKorisnika(context.Background(), h.KorisniciRepo); err != nil {
|
||||||
slog.Warn("demo: greška pri postavljanju demo korisnika", "error", err)
|
slog.Warn("demo: greška pri postavljanju demo korisnika", "error", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,12 @@ services:
|
|||||||
image: ghcr.io/dalibor31/ntech-fisk:latest
|
image: ghcr.io/dalibor31/ntech-fisk:latest
|
||||||
container_name: teron_mock
|
container_name: teron_mock
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- BE_HOST=ntech # naziv NTech servisa na ntech-net mreži — bez ovoga mock ne
|
||||||
|
- BE_PORT=4567 # može da pročita firmu sa kartica emulatora (pada na test podatke)
|
||||||
|
- VERIFY_HOST=https://ntech.tvoja-firma.rs # ima prednost nad "Podešavanja → Fiskalizacija"
|
||||||
|
# u NTech UI-ju (mock ne vidi ntech.db); bez ovoga
|
||||||
|
# QR vodi na sandbox.suf.purs.gov.rs i redak je
|
||||||
volumes:
|
volumes:
|
||||||
- teron-data:/app/data
|
- teron-data:/app/data
|
||||||
networks:
|
networks:
|
||||||
|
|||||||
@@ -1125,17 +1125,25 @@ func jePrivatnaAdresa(hostname string) bool {
|
|||||||
if hostname == "localhost" {
|
if hostname == "localhost" {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
ip := net.ParseIP(hostname)
|
if ip := net.ParseIP(hostname); ip != nil {
|
||||||
if ip == nil {
|
return jePrivatnaIP(ip)
|
||||||
// Nije literalna IP adresa (npr. Docker Compose ime servisa poput
|
}
|
||||||
// "teron-mock") — razrešavamo je preko DNS-a pa proveravamo
|
// Hostname (npr. Docker Compose service name kao "teron-mock") — razreši
|
||||||
// razrešenu adresu istim pravilima kao dole.
|
// preko DNS-a i dozvoli samo ako SVE dobijene adrese spadaju u privatne
|
||||||
adrese, err := net.LookupIP(hostname)
|
// opsege (localhost/127/10/172.16-31/192.168).
|
||||||
if err != nil || len(adrese) == 0 {
|
ips, err := net.LookupIP(hostname)
|
||||||
|
if err != nil || len(ips) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, ip := range ips {
|
||||||
|
if !jePrivatnaIP(ip) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
ip = adrese[0]
|
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func jePrivatnaIP(ip net.IP) bool {
|
||||||
ip4 := ip.To4()
|
ip4 := ip.To4()
|
||||||
if ip4 == nil {
|
if ip4 == nil {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -228,6 +228,15 @@
|
|||||||
}
|
}
|
||||||
var observer = new MutationObserver(function(){
|
var observer = new MutationObserver(function(){
|
||||||
observer.disconnect();
|
observer.disconnect();
|
||||||
|
// fiskalizacija je best-effort — ako ESIR/PFR nije bio dostupan,
|
||||||
|
// .fiskalni-racun kartica se neće pojaviti (v. FiskalGreska upozorenje
|
||||||
|
// na stranici); tada ne navigiramo tab na nepostojeći račun (praznina/404),
|
||||||
|
// nego prazan tab zatvorimo.
|
||||||
|
var imaRacun = sadrzaj.querySelector('.fiskalni-racun');
|
||||||
|
if (!imaRacun) {
|
||||||
|
if (tab && !tab.closed) tab.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
// jedan prozor — server u istu stranicu ubacuje i povraćaj viška
|
// jedan prozor — server u istu stranicu ubacuje i povraćaj viška
|
||||||
// avansa (ako postoji), da brauzer ne blokira drugi popup
|
// avansa (ako postoji), da brauzer ne blokira drugi popup
|
||||||
if (tab && !tab.closed) {
|
if (tab && !tab.closed) {
|
||||||
@@ -1015,7 +1024,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{if .FiskalniRacun}}
|
{{if .FiskalniRacun}}
|
||||||
<div class="kartica detalji-kartica animiraj">
|
<div class="kartica detalji-kartica animiraj fiskalni-racun">
|
||||||
<div style="margin-bottom:12px;padding-bottom:10px;border-bottom:0.5px solid var(--ivica);display:flex;justify-content:space-between;align-items:center;">
|
<div style="margin-bottom:12px;padding-bottom:10px;border-bottom:0.5px solid var(--ivica);display:flex;justify-content:space-between;align-items:center;">
|
||||||
<span style="font-size:15px;font-weight:500;color:var(--tekst-glavni);">
|
<span style="font-size:15px;font-weight:500;color:var(--tekst-glavni);">
|
||||||
{{if eq .FiskalniRacun.TipRacuna "Advance"}}Avansni fiskalni račun{{else}}Fiskalni račun{{end}}
|
{{if eq .FiskalniRacun.TipRacuna "Advance"}}Avansni fiskalni račun{{else}}Fiskalni račun{{end}}
|
||||||
@@ -1046,7 +1055,7 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{if .AvansRacun}}
|
{{if .AvansRacun}}
|
||||||
<div class="kartica detalji-kartica animiraj">
|
<div class="kartica detalji-kartica animiraj fiskalni-racun">
|
||||||
<div style="margin-bottom:12px;padding-bottom:10px;border-bottom:0.5px solid var(--ivica);display:flex;justify-content:space-between;align-items:center;">
|
<div style="margin-bottom:12px;padding-bottom:10px;border-bottom:0.5px solid var(--ivica);display:flex;justify-content:space-between;align-items:center;">
|
||||||
<span style="font-size:15px;font-weight:500;color:var(--tekst-glavni);">Avansni fiskalni račun</span>
|
<span style="font-size:15px;font-weight:500;color:var(--tekst-glavni);">Avansni fiskalni račun</span>
|
||||||
<a href="/servis/{{.Nalog.ID}}/fiskalni-racun?tip=avans" target="_blank" class="btn-sekundarno" style="font-size:12px;padding:4px 12px;">Štampaj kopiju</a>
|
<a href="/servis/{{.Nalog.ID}}/fiskalni-racun?tip=avans" target="_blank" class="btn-sekundarno" style="font-size:12px;padding:4px 12px;">Štampaj kopiju</a>
|
||||||
@@ -1068,7 +1077,7 @@
|
|||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
{{if .PovracajAvansa}}
|
{{if .PovracajAvansa}}
|
||||||
<div class="kartica detalji-kartica animiraj">
|
<div class="kartica detalji-kartica animiraj fiskalni-racun">
|
||||||
<div style="margin-bottom:12px;padding-bottom:10px;border-bottom:0.5px solid var(--ivica);display:flex;justify-content:space-between;align-items:center;">
|
<div style="margin-bottom:12px;padding-bottom:10px;border-bottom:0.5px solid var(--ivica);display:flex;justify-content:space-between;align-items:center;">
|
||||||
<span style="font-size:15px;font-weight:500;color:var(--tekst-glavni);">Povraćaj viška avansa</span>
|
<span style="font-size:15px;font-weight:500;color:var(--tekst-glavni);">Povraćaj viška avansa</span>
|
||||||
<a href="/servis/{{.Nalog.ID}}/fiskalni-racun?tip=povracaj" target="_blank" class="btn-sekundarno" style="font-size:12px;padding:4px 12px;">Štampaj kopiju</a>
|
<a href="/servis/{{.Nalog.ID}}/fiskalni-racun?tip=povracaj" target="_blank" class="btn-sekundarno" style="font-size:12px;padding:4px 12px;">Štampaj kopiju</a>
|
||||||
|
|||||||
Reference in New Issue
Block a user