# DigiPOS — plan nadogradnje (upgrade roadmap)

> **Operativni pregled (jul 2026):** za trenutno stanje, ažurirane prioritete i maloprodaju vidi [`newupgrade.md`](newupgrade.md).
>
> **⚙️ 3 režima rada (PRAVILO):** (1) standalone · (2) veza sa ERP-om u cloudu — stalna konekcija (osim kad nema veze) · (3) veza sa ERP-om na zahtev. Svaka funkcija mora raditi u sva tri — vidi [`REZIMI-RADA.md`](REZIMI-RADA.md).

Dokument definiše prioritete razvoja na osnovu uporedne analize tržišta u **Srbiji**:

- **Maloprodaja / prodavnice:** BKC SOFT, UniSoft, Sky POS (SHOP), POSitiv (Logosoft), DCS Retail, Hubie (Europos), eRetail
- **Ugostiteljstvo:** POS Sector, Sky POS (BAR/REST), BKC SOFT
- **Hrvatska:** POS Sector HR, Fiskalizacija 2.0 / eRačun
- **Grčka / turizam:** Epsilon Net, SoftOne, HIT Symposium, Anima Menu

> **Napomena (jul 2026):** Faza E pokriva turizam; **[Faza F](#faza-f--maloprodaja-i-lanci-prodavnica)** je uporedna analiza i roadmap za prodavnice i maloprodajne sisteme — segment gde je konkurencija najjača i gde DigiPOS danas ima najviše gapova.

**Poslednje ažuriranje:** jul 2026  
**Status proizvoda:** self-hosted stack; DigiPOS — **novi** ESIR (LPFR/V-PFR API v3), na odobrenju PU. Postojeći odobreni **KasaB** ostaje poseban proizvod.

---

## Sadržaj

1. [Strategijski cilj](#1-strategijski-cilj)
2. [Gde smo danas](#2-gde-smo-danas)
3. [Faze nadogradnje](#3-faze-nadogradnje)
4. [Faza A — prodajno obavezno](#faza-a--prodajno-obavezno)
5. [Faza B — operativa i zadržavanje](#faza-b--operativa-i-zadržavanje)
6. [Faza C — diferencijacija](#faza-c--diferencijacija)
7. [Hrvatska (opciono)](#faza-d--hrvatska-opciono)
8. [Grčka i turizam — ideje](#faza-e--grčka-i-turizam-ideje)
9. [Maloprodaja i lanci prodavnica](#faza-f--maloprodaja-i-lanci-prodavnica)
10. [Matrica prioriteta](#matrica-prioriteta)
11. [Merenje uspeha (KPI)](#merenje-uspeha-kpi)
12. [Van opsega (ne raditi sada)](#van-opsega-ne-raditi-sada)

---

## 1. Strategijski cilj

Ne takmičiti se direktno sa SaaS provajderima na „mesečni najam + 24/7 + App Store”.

> **Dopuna (jul 2026):** U razmatranju je i **cloud varijanta na sopstvenom VPS-u**
> (PostgreSQL, po uzoru na digi-angular gobackend) — u početku **besplatno** radi
> proboja tržišta (trenutno 5 kasa na terenu koristi program). LAN-first ostaje
> osnova za prodaju; cloud je dodatni kanal (centralno hostovana centrala + V-PFR),
> ne zamena. Odluke koje treba doneti pre početka: MySQL↔PG sloj (lib/db.js je
> jedini dodir sa bazom), multi-tenant izolacija (postojeća kolona `vlasnik` je
> dobra osnova), V-PFR umesto lokalnog LPFR-a za cloud kase.
>
> **Odluka (jul 2026):** postojećih 5 kasa radi na **DBF** (digiesir), pa MySQL
> instalacija po radnji nije prihvatljiva. Ciljna arhitektura:
> **centralna baza na VPS-u (Go servisi + PostgreSQL, kao digi-angular)** +
> **lokalno ugrađena baza bez instalacije (SQLite)** koja se sama inicijalizuje
> pri prvom startu servera — offline prodaja radi uvek, sync ka cloudu asinhron
> (postojeći model iz `lib/sync.js`). Novi kod pisati sa SQL-om portabilnim ka
> SQLite/PG gde god je jeftino.
>
> **✅ Korak 1 urađen (2026-07-06, Claude):** SQLite režim je implementiran —
> `lib/sqlite.js` (adapter nad ugrađenim `node:sqlite`, bez ijedne nove
> zavisnosti, sa prevodiocem MySQL SQL-a u hodu) + `lib/config.js`. Bez
> `config.json`-a server sam pravi `digipos.db` sa celom POS šemom i minimalnim
> knjigovodstvenim tabelama. MySQL režim netaknut (kase uz digi knjige).
> Sledeći koraci za cloud: multi-instanca na VPS-u (jedan port po tenantu ili
> zajednički server sa `vlasnik` izolacijom), V-PFR podešavanje, backup.
>
> **✅ Korak 2 urađen (2026-07-06, Claude):** Go centrala u digi-angular
> gobackend-u (commit `6a08f3a` na `feat/go-merge-i-bilansi`): rute
> `/api/sync/ping|artikli|racuni` sa X-Api-Key, migracija 000092
> (`pos_sync_kljucevi` po vlasniku + `pos_racuni_cloud`), ugovor identičan
> Node centrali pa kasa ne zna razliku. Artikli dolaze direktno iz knjigovodstva
> (`artikli.updated_at`, šifra = `artikli.id`) — nivelacije knjigovođe stižu na
> kase bez duplog unosa. **Preostalo za pilot:** deploy na VPS (`deploy-go.ps1`),
> `INSERT INTO pos_sync_kljucevi (vlasnik_id, naziv, api_key) VALUES (...)`,
> pa na kasi: `central_url = https://<vps>` i `central_key = <api_key>`.

**Ciljna niša (dva segmenta, jedan proizvod):**

| Segment | Ko kupuje | Zašto DigiPOS |
|---------|-----------|---------------|
| **Ugostiteljstvo** | Restoran, kafić, fast food | Stolovi, kuhinja, Wolt/Glovo, QR meni — bez mesečne pretplate |
| **Maloprodaja** | Prodavnica, butik, pekara, lanac | Ista baza `sifre`/`esir` kao knjigovodstvo; centrala + offline sync već postoje |

> Fiskalna kasa za firme sa postojećim knjigovodstvom (`sifre`, `esir`, `vlasnik`), više objekata i lokalnom centralom — **LAN-first**, bez obavezne cloud pretplate.

**Poruka za prodaju — ugostiteljstvo:**

- Jedna baza sa knjigovodstvom — bez duplog unosa artikala
- Prodaja radi bez interneta; sync sa centralom je asinhron
- Konobar na telefonu preko pregledača
- Dostava, kiosk i kuhinja u istom sistemu

**Poruka za prodaju — maloprodaja:**

- Kasa koristi **iste artikle i cene** koje knjigovođa već vodi u `sifre` — nema duplog šifarnika
- **Centrala offline-first:** nivelacije u centrali → automatski na kasama; računi sa prodavnica → u centralu
- Barkod, akcije, loyalty — na kasi; bez mesečnog najma kao Sky POS
- ESIR/LPFR API v3 — migracija šifarnika bez promene knjigovodstva

---

## 2. Gde smo danas

### Već implementirano (ne dirati osnovu)

| Modul | Opis |
|-------|------|
| Kasa restoran | Stolovi, plan sale, porudžbina, prebacivanje stola, predračun, naplata |
| Kasa prodavnica | Barkod, korpa, brza naplata |
| Kuhinja (KDS) | Pristigle porudžbine, označavanje stavki |
| Fiskalizacija RS | LPFR API v3, DEMO + produkcija, 7 načina plaćanja, refundacija, kopija |
| Admin | Artikli, korisnici, stolovi, podešavanja, izveštaji |
| Centrala | Offline sync artikala i računa (`/api/sync/*`) |
| Integracije | SEF, Wolt, Glovo, kiosk, QR meni, loyalty, akcije |
| Dokumentacija | `docs/UPUTSTVO.md`, brzi vodič, `/docs/` portal |

### Status ESIR-a — važna razlika

| | KasaB (postojeći) | DigiPOS (ovaj projekat) |
|--|-------------------|-------------------------|
| **Registar PU** | ✅ odobren, u upotrebi | ⏳ **novi proizvod** — zahtev za odobrenje |
| **Fiskalni tok** | LPFR / V-PFR API v3 | LPFR / V-PFR API v3 (Node.js / web) |
| **Izgled** | Desktop (navikli korisnici) | Web (pregledač), restoran + prodavnica, mobilni |
| **Odnos** | Ostaje dostupan | **Ne zamenjuje** i **ne isključuje** KasaB |

> DigiPOS nije „nova verzija“ KasaB-a — to su **dva odvojena proizvoda**. Klijenti
> koji su navikli na KasaB mogu da nastave sa njim. DigiPOS ide kao **novi** ESIR
> kroz postupak odobrenja PU. Do odobrenja DigiPOS-a: DEMO / sandbox za probu.

**Poruka pri prodaji:** „DigiPOS je novi web ESIR; KasaB ostaje za one koji žele
postojeći, već odobreni rad.“

### Identifikovani gapovi — ugostiteljstvo

| Gap | Konkurenti koji imaju | Prioritet |
|-----|------------------------|-----------|
| ESIR odobrenje za DigiPOS (novi proizvod) | BKC, UniSoft, Sky već imaju *svoj* broj u registru | Kritičan (proces PU) |
| Split računa / naplata po gostu | POS Sector, Sky | Visok |
| Prilozi / modifikatori artikla | POS Sector Standard+ | Visok |
| Native/PWA mobilna app | Sky Touch, POS Sector | Visok |
| DPU lista (RS ugostiteljstvo) | BKC | Srednji |
| Real-time kuhinja (push) | Većina modernih KDS | Nizak–srednji |
| Turizam: zone / ležaljke / poziv konobara | Anima, Quickord, Hoteligy | Srednji (sezonski) |
| Hotel: room charge / PMS | Symposium, PYLON, Hoteligy | Nizak |
| Offline red porudžbina na mobilnom | Anima Menu iOS | Srednji |
| Alergeni na digitalnom meniju | Hoteligy, EU trend | Srednji |

### Identifikovani gapovi — maloprodaja

| Gap | Konkurenti koji imaju | Prioritet |
|-----|------------------------|-----------|
| ESIR odobrenje za DigiPOS (novi proizvod) | BKC (#88), UniSoft, POSitiv (#716), Sky — njihov UI već u registru | **Kritičan (proces PU)** |
| Smene / zatvaranje blagajne | BKC, UniSoft, Sky, DCS | **Visok** |
| Robno knjigovodstvo / lager (UI) | BKC, UniSoft, Sky Office, DCS | **Visok** |
| Automatska KEP knjiga | UniSoft, BKC, Sky, DCS | **Visok** |
| Skidanje zaliha pri prodaji | BKC, UniSoft, DCS, POSitiv | Visok |
| Inventura sa barkod skenerom | BKC, UniSoft, DCS | Visok |
| Težinski barkod (vaga → EAN-13) | BKC, UniSoft | Srednji — **✅ DigiPOS** |
| Varijante artikla (veličina / boja) | POSitiv, LS Central, Hubie | Srednji (butik, obuća) |
| Štampa etiketa (barkod + cena) | UniSoft, BKC | Srednji |
| Predračun / ponuda na kasi | DCS, BKC, Sky | Srednji |
| Customer display (ekran kupca) | Sky, LS Central | Nizak–srednji |
| Prenos robe između objekata | BKC, Sky, Hubie, POSitiv | Srednji (lanac) |
| Cenovnik po objektu | BKC, Hubie, Sky | Srednji (lanac) |
| Native/PWA mobilna app | Sky Tablet, LS Central mPOS | Visok |
| Turnkey (hardver + obuka + najam) | Sky, UniSoft, BKC | Prodajni |
| ERP integracija (SAP, Minimax) | eRetail, POSitiv, Hubie | Nizak (enterprise) |
| Fiskalizacija HR / eRačun | POS Sector HR | Samo ako ulazimo u HR |

**Šta maloprodaja već ima u DigiPOS-u (ne prodavati kao „nedostaje“):**

| Funkcija | Status |
|----------|--------|
| Barkod skener (USB, keyboard wedge) | ✅ pretraga + Enter |
| Brza kasa (korpa → NAPLATI) | ✅ režim `prodavnica` |
| Akcije / happy hour | ✅ `pos_akcije` |
| Loyalty kartice | ✅ skeniranje barkoda kartice |
| Refundacija, kopija, 7 načina plaćanja | ✅ LPFR v3 |
| Centrala: sync artikala i računa | ✅ offline-first |
| SEF eFakture | ✅ modul postoji |
| Integracija sa knjigovodstvenom bazom | ✅ `sifre`, `esir`, `vlasnik` |

---

## Uporedna napomena — Grčka (turizam)

Vidi [Fazu E](#faza-e--grčka-i-turizam-ideje). DigiPOS već ima **GRE jezik**, QR meni, kiosk i zvonce za porudžbine sa stola — bliže Anima Easy Orders nego prosečnom RS POS-u. Nedostaju zone (plaža/bazen), poziv konobara i naplata gosta preko QR-a.

## Uporedna napomena — Maloprodaja

Vidi [Fazu F](#faza-f--maloprodaja-i-lanci-prodavnica). DigiPOS ima **centralu offline-first** i **istu bazu kao knjigovodstvo** — retko kod BKC/UniSoft/Sky. Nedostaju **smene, lager, KEP i težinski barkod** — bez toga teško prodati pekari, mesari ili lancu prodavnica.

---

## 3. Faze nadogradnje

```
2026 Q3          2026 Q4          2027 H1          2027 H2+
────────         ────────         ────────         ────────
  FAZA A    →    FAZA B      →    FAZA C      →   FAZA D (HR)
  prodaja        operativa        diferencijacija   opciono
```

---

## Faza A — prodajno obavezno

**Rok:** Q3 2026  
**Cilj:** Ukloniti blokere pri prodaji restoranima i lančevima u Srbiji.

### A1. ESIR — odobrenje DigiPOS-a (novi proizvod)

**Kontekst:** DigiPOS je **novi, samostalan** ESIR (web, Node.js, LPFR/V-PFR API v3).
Postojeći odobreni **KasaB** ostaje poseban proizvod — DigiPOS ga ne zamenjuje ni
isključuje. Korisnici navikli na KasaB mogu da nastave da ga koriste.

**Šta već imamo:**

- [x] LPFR / V-PFR API v3 u DigiPOS-u
- [x] DEMO LPFR za test bez fiskalnog uređaja
- [x] Audit higijena PIN-ova (HMAC-SHA256, 2026-07-06)
- [x] Sandbox V-PFR: П1–П12 via `scripts/vpfr-sertifikacija.js` (2026-07-14)

**Šta još treba (proces kod PU):**

- [ ] Podneti zahtev PU za **odobrenje DigiPOS-a** kao novog proizvoda
- [ ] Paket: ESIR korisničko + tehničko (`ESIR-KORISNICKO-UPUTSTVO.md`, `ESIR-TEHNICKO-UPUTSTVO.md`)
- [ ] Posle odobrenja: upisati dodeljeni broj u `lib/esir.js` (`ESIR_BROJ`)
- [ ] Dokumentacija za korisnike (posle odobrenja): ESIR broj, BE, LPFR/V-PFR, checklist
- [ ] Procedura verzionisanja i obaveštenja korisnika pri zakonskim izmenama

**Kriterijum gotovo:** DigiPOS upisan u registar PU; fiskalni račun nosi taj broj.

**Do tada (legalno i u prodaji):**

- Probni rad: `lpfr_url = DEMO` ili sandbox V-PFR
- Ne prodavati DigiPOS kao već odobreni KasaB — prodavati kao **novi proizvod u procesu odobrenja**

---

### A2. Split računa

**Problem:** Konkurencija standardno nudi podelu računa po gostu / stavkama.

**Specifikacija:**

- [ ] UI: izbor stavki za naplatu (checkbox po stavci ili „gost 1 / gost 2“)
- [ ] Delimična naplata otvorene porudžbine — sto ostaje otvoren
- [ ] Fiskalni račun samo za izabrane stavke; preostale ostaju na porudžbini
- [ ] Podrška za više uzastopnih naplata na istom stolu
- [ ] Izveštaj: sve naplate vezane za isti `sto_id` / `porudzbina_id`

**API / baza (predlog):**

- `pos_porudzbine` — status `delimicno_naplacena` ili praćenje preko stavki
- `pos_stavke` — polje `naplaceno` / `racun_id`
- Endpoint: `POST /api/porudzbine/:id/naplata-delimicna`

**Kriterijum gotovo:** Konobar može dva puta naplatiti isti sto; fiskalno ispravno; test u DEMO LPFR.

---

### A3. Prilozi i modifikatori

**Problem:** „Pljeskavica bez luka“, „Espresso sa mlekom“ — bez modifikatora gubi se fast food i fine dining segment.

**Specifikacija:**

- [ ] Admin: grupe priloga (npr. „Prilozi“, „Veličina“) i cene (+0 / +50 RSD)
- [ ] Kasa: modal nakon klika na artikal (ako artikal ima priloge)
- [ ] Porudžbina / kuhinja: prilozi vidljivi na KDS i kuhinjskom štampaču
- [ ] Fiskalizacija: prilozi kao posebne stavke ili u nazivu (uskladiti sa LPFR pravilima)

**Kriterijum gotovo:** Min. 2 grupe priloga, štampa u kuhinji, ispravan ukupan iznos na računu.

---

### A4. PWA za konobare i kuhinju

**Problem:** Kupci očekuju „aplikaciju“; pregledač deluje jeftinije od Sky Touch.

**Specifikacija:**

- [x] `manifest.json` + service worker (network-first za statiku sa keš rezervom; `/api/` se nikad ne kešira)
- [x] „Dodaj na početni ekran“ u uputstvu (README → PWA sekcija)
- [x] Fullscreen / `display: standalone` (kasa/admin standalone, kiosk `manifest-kiosk.json` fullscreen)
- [x] Ikona i splash screen (`public/icons/`, generisano `scripts`-om preko Edge-a)
- [x] **HTTPS opcija u serveru** (`https_key`/`https_cert`/`https_port` u config.json) — pregledači traže siguran kontekst za PWA van localhost-a; uputstvo za samopotpisani sertifikat / mkcert u README
- [ ] (Opciono) cache liste artikala za rad pri kratkom prekidu LAN-a — *namerno odloženo: fiskalni podaci se ne keširaju*

**Kriterijum gotovo:** Android/iOS „Instaliraj aplikaciju“; kasa se otvara bez browser chrome-a.
*Urađeno 2026-07-06: SW registrovan i aktivan, precache 7 resursa, offline reload služi aplikaciju iz keša (testirano headless Edge); HTTPS listener ispisuje PWA adresu pri startu.*

---

### A5. Paket „ključ u ruke“

**Problem:** Konkurencija prodaje rešenje, ne repozitorijum.

**Deliverables (dokumentacija, ne kod):**

- [ ] `docs/INSTALACIJA.md` — hardver lista (mini PC, POS-80, skener, tablet)
- [ ] Checklist prvog dana (PIN, LPFR, štampač, Wi‑Fi za telefone)
- [ ] Skripta / wizard za prvo pokretanje (vlasnik, objekat, test račun)
- [ ] Predložena cena paketa: softver + 2h obuke + remote podrška 30 dana

**Kriterijum gotovo:** Novi klijent može da prati dokument od raspakivanja do prvog fiskalnog računa.

---

## Faza B — operativa i zadržavanje

**Rok:** Q4 2026  
**Cilj:** Smanjiti churn; zadovoljiti kasire i vlasnike.

### B1. Smene i zatvaranje blagajne ✅

- [x] Početak smene: kasir, početni float (gotovina u ladici)
- [x] Kraj smene: očekivana vs prebrojana gotovina, razlika (kusur uračunat: gotovina u ladici = uplaćeno − povraćaj − gotovinske refundacije)
- [x] Izveštaj smene: promet, refundacije, po načinu plaćanja + štampa preseka na traku (nefiskalno)
- [x] Admin: pregled svih smena po datumu / objektu (tab **Smene**)
- [x] Podešavanje `smena_obavezna` (1/0): naplata moguća samo dok je smena otvorena
- [x] Kartica **Smena** na kasi (kasir/admin): otvaranje sa float-om, živ presek, zatvaranje sa prebrojavanjem i razlikom

**Tabela:** `pos_smene` (vlasnik, objekat_id, user_id, zatvorio_id, otvorena, zatvorena, float_pocetni, float_krajnji, gotovina_ocekivano, razlika, promet, refundacije, izvestaj_json, napomena) — jedna otvorena smena po objektu; presek se računa iz vremenskog prozora smene (radi i retroaktivno).

*Urađeno 2026-07-06 (Claude): testirano E2E — čuvar bez smene odbija naplatu, dupla smena odbijena, kusur ispravno (uplaćeno 200 na račun 180 → +180 u ladici), zatvaranje sa manjkom −30, presek odštampan.*

---

### B2. Skladište — admin UI

- [ ] Pregled stanja po magacinu / objektu
- [ ] Prijem robe (ručni unos + import)
- [ ] Upozorenje: artikal ispod minimuma
- [ ] Veza sa normativima (postojeći `lib/normativi.js`) — automatsko skidanje pri prodaji jela

---

### B3. Kuhinja real-time

- [ ] WebSocket ili SSE umesto pollinga na 10 s
- [ ] Zvuk + vizuelni badge za novu porudžbinu
- [ ] Push notifikacija u PWA (ako podržano)

**Napomena:** Zadržati polling kao fallback.

---

### B4. DPU lista (RS ugostiteljstvo)

- [ ] Generisanje DPU liste iz prometa (prema važećem pravilniku)
- [ ] Export PDF/Excel za inspekciju i knjigovodstvo
- [ ] Admin → Izveštaj → DPU

---

### B5. Health dashboard (admin)

- [ ] LPFR status (već postoji `Proveri LPFR` — proširiti)
- [ ] Poslednji uspešan sync sa centralom
- [ ] Broj računa u redu za slanje
- [ ] Poslednji backup baze (predložiti `mysqldump` raspored)
- [ ] Verzija aplikacije

---

## Faza C — diferencijacija

**Rok:** H1 2027  
**Cilj:** Funkcije koje opravdavaju izbor DigiPOS-a umesto generičkog SaaS-a.

### C1. Analitika za vlasnika

- [ ] Prosečan račun, broj gostiju po satu (heatmap)
- [ ] Top / bottom artikli (ABC)
- [ ] Uporedni dani / nedelje
- [ ] Performans po konobaru (promet, broj računa)

---

### C2. eOtpremnice (SEO)

- [ ] Integracija sa sistemom eOtpremnica (RS)
- [ ] Veza sa SEF modulom i `firme` šifarnikom

---

### C3. Otvoreni API

- [ ] Dokumentovan REST API (porudžbina, artikli, izveštaji)
- [ ] API ključ po objektu
- [ ] Webhook: `racun.izdat`, `porudzbina.kreirana`

---

### C4. Customer display

- [ ] Ekran za kupca (`/display`) — korpa, ukupan iznos, QR za plaćanje (IPS)

---

## Faza D — Hrvatska (opciono)

**Ulazak na tržište RH zahteva poseban fiskalni modul** — nije prevod postojećeg LPFR toka.

- [ ] Fiskalizacija B2C (XML shema PU RH v2.6+)
- [ ] eRačun B2B (Fiskalizacija 2.0, od 2026)
- [ ] eIzvještavanje
- [ ] Informacijski posrednik (AMS/MPS)
- [ ] KPD klasifikacija stavki
- [ ] Odvojen `mode: hrvatska` ili poseban deployable

**Preporuka:** Ne započinjati pre ESIR akreditacije i Faze A u Srbiji, osim ako postoji eksplicitna poslovna obaveza.

---

## Faza E — Grčka i turizam (ideje)

**Kontekst:** Grčka je referentno tržište za **sezonski turizam** (hotel, plaža, all-inclusive, strani gosti). Fiskalni model (**myDATA / AADE**) je drugačiji od srpskog LPFR-a — ulazak na GR tržište zahteva poseban modul. Ova faza je **inspiracija za funkcije**, ne obavezan fiskalni deploy.

### Ključni grčki provajderi

| Provajder | Fokus | Šta rade posebno dobro |
|-----------|-------|-------------------------|
| [Epsilon Net](https://epsilonnet.gr/en/eidos-logismikou/solutions-for-restaurants-cafes/) (Smart Restaurant, Galaxy, PYLON) | Restoran + hotel | Više **delatnih listi** po stolu, delimična naplata, myDATA, PMS veza |
| [SoftOne GO Estiasis](https://symkon.gr/s1-estiasis/) | Kafić / restoran cloud | Tablet/mobilni POS, delivery, myDATA |
| [HIT Symposium](https://hit.com.gr/en/products/symposium/) | Hotel F&B hub | **Room charge**, NFC, board basis (BB/HB/FB/AI), Opera/Cloudbeds |
| [Anima Menu / Poseidon](https://www.animamenu.gr/) | QR + mobilni konobar | Easy Orders (QR na stolu/ležaljci), **poziv konobara**, offline red na telefonu |
| [Quickord](https://www.quickord.com/en/businesses/beach-bar), Hoteligy, GonnaOrder | Plaža / resort | **Zone** (plaža, bazen, restoran), višejezični meni, alergeni |

### Grčka fiskalna logika (myDATA) — lekcija za dizajn

AADE zahteva slanje **restaurant order forms** (delatnih listi) na myDATA, ne samo konačnog računa — sa **QR kodom** i povezivanjem sa prometom u roku od 24 h ([EY alert](https://www.ey.com/content/dam/ey-unified-site/ey-com/en-gr/technical/tax/tax-alerts/documents/ey-2023-november-alert-mydata-greece-2023-11-21-en.pdf), [VATupdate](https://www.vatupdate.com/2024/08/07/modification-of-decision-for-electronic-invoicing-providers-catering-order-form-and-obligation-to-harmonize-within-15-days-with-new-mydata-versions/)).

**Ideja za DigiPOS (bez GR fiskalizacije):** svaki **Pošalji u kuhinju** generiše interni „order slip ID“ sa QR-om — kasnije se vezuje za fiskalni račun. Korisno za inspekciju, reklamacije i split naplatu.

### E1. Zone i resursi (plaža, bazen, terasa)

**Inspiracija:** Quickord, Hoteligy — QR na **ležaljci**, ne samo na stolu.

- [ ] Proširiti `pos_stolovi`: tip resursa (`sto`, `ležaljka`, `soba`, `šank`)
- [ ] **Zona** već postoji — grupisati: Plaža / Bazen / Sala / Bašta
- [ ] QR po resursu → porudžbina zna tačnu lokaciju za konobara
- [ ] Mapa zone (opciono) — grid ležaljki kao plan stolova

**DigiPOS danas:** stolovi + zone ✅ · ležaljke kao entitet ❌

---

### E2. „Pozovi konobara“ sa QR menija

**Inspiracija:** [Anima Easy Orders](https://www.poseidon.gr/easyorders_en.htm) — gost skenira QR i može da **pozove konobara** bez naručivanja.

- [ ] Dugme na `/meni` i QR stola: **🛎 Pozovi konobara**
- [ ] Notifikacija konobaru (zvuk + badge na Stolovi) — slično postojećem kiosk zvoncu
- [ ] Evidencija poziva (ko, kada, koji sto)

**DigiPOS danas:** zvonce za kiosk porudžbinu ✅ · eksplicitni „poziv konobara“ ❌

---

### E3. Više delatnih listi po istom stolu

**Inspiracija:** Epsilon Smart Restaurant — **multiple order slips per table** (više rundi u kuhinju bez zatvaranja stola).

- [ ] Svaki **Pošalji** = nova „runda“ sa rednim brojem i vremenom
- [ ] Kuhinja prikazuje rundu; konobar vidi šta je poslato u koje vreme
- [ ] Različito od split naplate (A2) — ovo je operativni tok u restoranu sa više jela

---

### E4. Višejezični meni za turiste

**Inspiracija:** Anima, Quickord — GR + EN minimum; turisti na obali.

- [ ] DigiPOS već ima **GRE** u `i18n.js` ✅
- [ ] Proširiti: automatski jezik iz `Accept-Language` na `/meni` i `/kiosk`
- [ ] Admin: prevod naziva artikla (kratko polje `naziv_en`, `naziv_gr` ili JSON)
- [ ] Slike artikala na QR meniju (turisti biraju po slici)

---

### E5. Alergeni i dijetetske oznake

**Inspiracija:** Hoteligy QR meni — alergeni, varijacije.

- [ ] Polje na artiklu: alergeni (gluten, mleko, orašasti…)
- [ ] Ikone na `/meni` i kiosku
- [ ] Filter „bez glutena“ / vegetarijanski

---

### E6. Offline red porudžbina na telefonu konobara

**Inspiracija:** [Anima Menu iOS](https://apps.apple.com/gr/app/mobile-anima-menu/id1367378232) — lokalno čuva porudžbine kad nema Wi‑Fi, šalje batch kad se mreža vrati.

- [ ] PWA + IndexedDB queue za `POST /porudzbine/.../stavke`
- [ ] Vizuelni indikator: „3 porudžbine čekaju slanje“
- [ ] Posebno važno za **plažu** gde Wi‑Fi ne pokriva celu zonu

**Napomena:** Fiskalna naplata i dalje zahteva LPFR — offline samo za **unos porudžbine**, ne za račun.

---

### E7. Naplata gosta na QR meniju (opciono)

**Inspiracija:** Easy Orders — PayPal/kartica pre slanja porudžbine.

- [ ] Integracija payment gateway (IPS, Stripe) na `/meni` — **prepaid** porudžbina
- [ ] Konobar samo isporučuje; manje gužve na naplati
- [ ] Rizik: složenije usklađivanje sa fiskalnim pravilima RS — istražiti pre implementacije

**Preporuka:** Odložiti posle A1/A2; za RS tržište nije prioritet kao za grčku plažu.

---

### E8. Hotel — room charge (dugoročno)

**Inspiracija:** [Symposium](https://hit.com.gr/en/products/symposium/) — troškovi na sobu, PMS (Opera, Cloudbeds).

- [ ] API ka PMS-u: gost skenira QR u sobi → naplata na folio
- [ ] Board basis: ograničenje all-inclusive stavki
- [ ] Poseban modul; van core restorana u RS

---

### Šta DigiPOS već ima a Grčka takođe ceni

| Funkcija | DigiPOS | Grčka konkurencija |
|----------|---------|-------------------|
| QR / digitalni meni | ✅ `/meni` | Anima, Epsilon |
| Gost naručuje sa stola | ✅ kiosk + zvonce | Easy Orders |
| Mobilni konobar | ✅ pregledač | Anima app, SoftOne GO |
| Kuhinja KDS | ✅ | Galaxy, Quickord |
| Delivery | ✅ Wolt/Glovo | SoftOne, PYLON |
| Više jezika | ✅ SRB/ENG/**GRE** | Anima GR/EN |
| Loyalty | ✅ | Galaxy CRM |
| Self-service kiosk | ✅ `/kiosk` | Anima kiosk |

---

### Prioritet Faze E (preporuka)

| ID | Stavka | Effort | Relevantno za |
|----|--------|--------|---------------|
| E2 | Pozovi konobara | Nizak | Zlatibor, Halkidiki, beach barovi |
| E4 | Prevodi + slike menija | Srednji | Turističke zone RS/GR |
| E1 | Zone / ležaljke | Srednji | Hoteli, plaže |
| E3 | Više rundi Pošalji | Srednji | Restorani fine dining |
| E6 | Offline red mobilni | Srednji | Velike bašte, plaža |
| E5 | Alergeni | Nizak–srednji | EU turisti, compliance |
| E7 | Plaćanje na QR | Visok | Grčka; oprezno u RS |
| E8 | Room charge / PMS | Vrlo visok | Hoteli |

**Redosled uz Fazu A:** `E2 → E4 → E1 → E3` (najmanji effort, najveći efekat za turizam).

---

## Faza F — Maloprodaja i lanci prodavnica

**Kontekst:** Na srpskom tržištu **maloprodajni POS** je zreliji i konkurentniji od ugostiteljskog segmenta. BKC SOFT i UniSoft godinama prodaju „kompletno rešenje od blagajne do KEP knjige“; Sky POS drži veliki udeo kroz **mesečni SaaS + hardver najam**. DigiPOS ulazi u ovaj segment sa **jedinstvenom prednošću integracije sa postojećim knjigovodstvom** (`sifre`, `esir`) i **offline centralom** — ali bez punog robnog modula ne može parirati BKC/UniSoft u prodaji prodavnicama.

**Ciljna publika Faze F:** pekare, mesare, butici, drogerije, tehnička roba, mini marketi, **lanci 3–30 prodavnica** koji već koriste isti knjigovodstveni softver.

### Ključni konkurenti — maloprodaja (RS)

| Provajder | ESIR | Model | Tipičan kupac | Šta rade posebno dobro |
|-----------|------|-------|---------------|-------------------------|
| [BKC SOFT](https://bkcsoft.rs/za-maloprodaju/) | #88 | Desktop, paketi Standard→Premium | Kiosk do lanca | Lager real-time, težinski barkod, inventura skenerom, KEP, prenos robe, eOtpremnice |
| [UniSoft POS](https://www.unisoft.co.rs/program-za-maloprodaju/) | Da | Desktop + cloud opcija | SMB prodavnice | **Automatska KEP**, etikete, jeftina licenca, rad bez interneta, robno knjigovodstvo |
| [Sky POS SHOP](https://www.sky-pos.rs/program-za-maloprodaje) | Da | **SaaS mesečno** + Sky Office cloud | Maloprodaja, pekare | 24/7 podrška, hardver najam, offline kasa + cloud menadžment, Sky Mobile izveštaji |
| [POSitiv](https://www.logosoft.rs/positiv/) (Logosoft) | #716 | Centrala + lokalne kase | Lanci, butik | **Varijante veličina/boja**, ERP (SAP, Business Central), skladište + veleprodaja |
| [Hubie POS](https://europos.co.rs/sr/hubie-point-of-sale/) (Europos) | ERP ekosistem | Enterprise | Maloprodajni lanci | Centralizovane cene/promocije/zalihe, skalabilnost desetine–stotine objekata |
| [DCS Retail POS](https://www.dcsoft.rs/programi/dcs-retail-pos) | Da | Desktop | SMB trgovine | Smene, kalkulacije, KEP, grafikoni prometa, ulaz robe |
| [eRetail POS](https://eretail.rs/) | Da | Enterprise | SAP korisnici | Offline prodaja + automatska ERP sinhronizacija artikala/zaliha |
| [LS Central](https://www.rclsyst.rs/Maloprodaja-LS-Central_SR/) (RCL) | International | Premium SaaS | Veći lanci | Browser POS, cross-store lookup, loyalty, mobilni prodavac |

**POS Sector** i **Sky BAR/REST** su u fokusu ugostiteljstva; u maloprodaji ih retko biraju kao primarno rešenje.

### DigiPOS vs konkurencija — matrica (maloprodaja)

| Funkcija | DigiPOS | BKC | UniSoft | Sky SHOP | POSitiv |
|----------|---------|-----|---------|----------|---------|
| ESIR u registru (DigiPOS) | ⏳ novi proizvod na PU | ✅ #88 | ✅ | ✅ | ✅ #716 |
| Barkod na kasi | ✅ | ✅ | ✅ | ✅ | ✅ |
| Akcije / loyalty | ✅ | ✅ | ✅ | ✅ | ✅ |
| Ista baza kao knjigovodstvo | ✅ **`sifre`** | ❌ poseban | ❌ poseban | ❌ cloud | ❌ ERP |
| Offline prodaja (LAN) | ✅ | ✅ | ✅ | ✅ | ✅ |
| Centrala / više prodavnica | ✅ sync | ✅ | ✅ | ✅ cloud | ✅ |
| Smene / zatvaranje blagajne | ❌ | ✅ | ✅ | ✅ | ✅ |
| Lager / prijem robe (UI) | ❌ | ✅ | ✅ | ✅ Office | ✅ |
| KEP knjiga automatski | ❌ | ✅ | ✅ | ✅ | ✅ |
| Težinski barkod (vaga) | ✅ DigiPOS | ✅ | ✅ | ✅ | ○ |
| Varijante (vel/boja) | ❌ | ○ | ○ | ○ | ✅ |
| Štampa etiketa | ❌ | ✅ | ✅ | ✅ | ✅ |
| Inventura skenerom | ❌ | ✅ | ✅ | ✅ | ✅ |
| Predračun u prodavnici | ❌ | ✅ | ✅ | ✅ | ✅ |
| Customer display | ❌ | ○ | ○ | ✅ | ○ |
| Mesečna pretplata obavezna | ❌ | ❌ | **✅** | ○ | ○ |
| Hardver najam / turnkey | ○ | ✅ | ✅ | **✅** | ○ |

✅ ima · ❌ nema · ⏳ u toku · ○ delimično / zavisi od paketa

### Gde se takmičiti (i gde ne)

**Takmičiti se:**

- Firme koje **već imaju** knjigovodstveni softver sa `sifre` / `esir` — migracija kase bez duplog šifarnika
- **Lanci 3–30 objekata** — centrala offline-first je jača od cloud-only rešenja kad internet pada
- Kombinovani objekti (npr. pekara + kafić) — jedan sistem, dva režima (`restoran` / `prodavnica`)

**Ne takmičiti se (za sada):**

- Enterprise SAP/ERP (eRetail, POSitiv + SAP) — potrebna dedicirana integracija
- „Samo najjeftinija kasa“ — UniSoft je cenovno agresivan; DigiPOS prodaje **integraciju + LAN**
- Sky POS model (mesečni najam + 24/7 + oprema) — druga poslovna formula

### F1. Smene i zatvaranje blagajne (retail blocker) ✅

**Problem:** Svaki ozbiljan maloprodajni POS (BKC, UniSoft, Sky, DCS) ima smenu. Bez ovoga kasir ne može da preda kasu.

**Specifikacija:** Ista kao [B1](#b1-smene-i-zatvaranje-blagajne) — prioritet **Visok za maloprodaju**, ne samo Srednji.

**Kriterijum gotovo:** Kasir otvara smenu, prodaje, zatvara smenu sa prebrojavanjem gotovine; admin vidi izveštaj smene po objektu. ✅ *urađeno 2026-07-06, vidi B1*

---

### F2. Robno knjigovodstvo — lager i skidanje pri prodaji

**Problem:** BKC/UniSoft automatski ažuriraju lager pri svakoj prodaji. DigiPOS ima `normativi.js` za restoran, ali nema retail tok.

**Specifikacija:**

- [ ] Tabela stanja po objektu/magacinu (vezano na `objekti`)
- [ ] Automatsko skidanje količine pri izdavanju računa u režimu `prodavnica`
- [ ] Upozorenje na kasi: „artikal nema na stanju“ (opciono, podešavanje)
- [ ] Admin: pregled stanja, minimum zaliha
- [ ] Sinhronizacija stanja sa centralom (opciono F2b)

**Napomena:** Proširuje postojeći predlog [B2](#b2-skladište--admin-ui).

**Kriterijum gotovo:** Posle prodaje 10 kom artikla, stanje u adminu je −10; centrala vidi promet.

---

### F3. Prijem robe, prenos robe, KEP knjiga

**Problem:** UniSoft prodaje „100% automatsku KEP knjigu“; BKC ima prijem robe, prenose, nivelacije. Knjigovođa klijenata očekuje ove dokumente.

**Specifikacija:**

- [ ] Admin: **prijem robe** (ručni unos + import CSV)
- [ ] **Prenos robe** između objekata (lanac)
- [ ] Generisanje **KEP knjige** iz prometa (PDF/Excel, po važećem pravilniku)
- [ ] Veza sa postojećim kalkulacijama u centralnoj bazi (`sifre.updated_at` sync)

**Kriterijum gotovo:** Knjigovođa preuzme KEP za mesec bez ručnog prepisivanja iz POS izveštaja.

---

### F4. Težinski barkod (vage)

**Status:** ✅ Implementirano u DigiPOS (`lib/barkod.js`, `public/app.js`)

**Format (EAN-13):**

| Pozicije | Dužina | Značenje | Primer |
|----------|--------|----------|--------|
| 1–2 | 2 | Prefiks vage | `28` (podrazumevano) |
| 3–7 | 5 | **Šifra artikla (PLU)** | `00123` → artikal 123 |
| 8–12 | 5 | **Težina u gramima** ÷ 1000 | `01500` → **1,500 kg** |
| 13 | 1 | Kontrolna cifra | vaga generiše; DigiPOS je ne proverava |

**Logika:** cena po jedinici iz `sifre.mpcena`; količina iz barkoda; ukupno = količina × mpcena.
Podešavanje: `tezinski_prefiks` (default `28`). Redosled skena: tačan GTIN → težinski → loyalty.

*Urađeno 2026-07-06: E2E (sken `2809003015007` → 1,5 kg).*

**Napomena:** DigiPOS kodira **težinu** u barkodu, ne cenu. Vage koje šalju cenu u poslednjih 5 cifara zahtevaju drugi parser.

**Kriterijum gotovo:** Sken sa vage (prefiks 28) → artikal po PLU, tačna kg na računu.

---

### F5. Varijante artikla (veličina / boja)

**Problem:** Butici i obućare biraju POSitiv zbog evidencije veličina i boja na kasi.

**Specifikacija:**

- [ ] Artikal + varijante (npr. majica M/L/XL, crvena/plava)
- [ ] Svaka varijanta: sopstveni barkod, stanje, cena (opciono)
- [ ] Kasa: izbor varijante posle klika ili sken specifičnog barkoda

**Effort:** Visok — **odložiti** dok nema eksplicitnog klijenta (butik segment).

---

### F6. Štampa etiketa

**Problem:** UniSoft standardno nudi etikete sa nazivom, cenom i barkodom.

**Specifikacija:**

- [ ] Admin: izbor artikala → štampa etiketa (Zebra / ESC-POS / PDF A4)
- [ ] Šablonski format: naziv, cena, barkod (EAN-13), datum

**Kriterijum gotovo:** Novi artikal u šifarniku → etiketa za policu za < 1 min.

---

### F7. Inventura sa skenerom

**Problem:** BKC reklamira inventuru bez ručnog prepisivanja.

**Specifikacija:**

- [ ] Admin → Inventura: novi popis, sken artikala, unos stvarnog stanja
- [ ] Uporedni izveštaj: knjigovodstveno vs stvarno → otpis/viškovi
- [ ] Export za knjigovođu

---

### F8. Maloprodajni UX na kasi

**Problem:** DigiPOS prodavnica režim je funkcionalan ali minimalan vs Sky/UniSoft touch kasa.

**Specifikacija:**

- [x] Brzi unos količine (tastatura / +/- na stavci) — *urađeno 2026-07-06 kroz komandnu konzolu (dole)*
- [x] **Komandna konzola kase — port `oBarCode_onLostFocus` iz digiesir `sample.prg`** (iste komande koje kasiri na 5 postojećih kasa već znaju):

  | Komanda | Radnja |
  |---------|--------|
  | *sken/EAN* | dodaj artikal (cena 0 se odbija, kao digiesir) |
  | *težinski EAN-13* | artikal po PLU + kg (F4) |
  | `+SIFRA` | dodaj artikal po šifri |
  | `5` | dodaj 5 na količinu poslednjeg reda |
  | `.5` / `0,5` | postavi količinu poslednjeg reda |
  | `-` / `-N` | obriši poslednji red / red N |
  | `/10` / `N/10` | rabat 10% na poslednji red / red N |
  | `*10` | rabat 10% na ceo račun |
  | `G` `P` `C` `K` | odmah zatvori račun: gotovina / kartica / ček / prenos |
  | `A123` | kopija današnjeg računa čiji PFR broj završava na 123 |

  *Nije portovano iz digiesir:* bedž radnika za zatvaranje (prijava PIN-om to pokriva), `SC`, lSUR INI barkodovi (BRISIRED/PLUS…), `*P` kod nas ne zatvara račun automatski već samo upisuje rabat (zatvaranje eksplicitno sa `G`/`P`/`C`/`K`).
- [ ] „Parkiraj račun“ / učitaj parkirani (zamena za predračun u prodavnici)
- [ ] Touch-friendly grid (veće dugmiće, kategorije po `sifargru`)
- [ ] Customer display ([C4](#c4-customer-display)) — prikaz korpe kupcu

**Kriterijum gotovo:** Kasir izda račun sa 20 stavki za < 2 min (barkod + ručna korekcija količine). ✅ *komandna konzola: ceo test tok (2 artikla, količine, rabat, brisanje, naplata) < 15 s bez miša*

---

### Prioritet Faze F (preporuka)

| ID | Stavka | Effort | Prodajni efekat | Segment |
|----|--------|--------|-----------------|---------|
| A1 | ESIR DigiPOS (novi proizvod) | Visok (proces) | ⭐⭐⭐⭐⭐ | Svi |
| F1 / B1 | Smene | Srednji | ⭐⭐⭐⭐⭐ | Maloprodaja |
| F2 / B2 | Lager + skidanje | Visok | ⭐⭐⭐⭐⭐ | Maloprodaja |
| F3 | Prijem robe + KEP | Visok | ⭐⭐⭐⭐ | Maloprodaja + knjigovodstvo |
| A4 | PWA | Nizak–srednji | ⭐⭐⭐⭐ | Svi |
| F8 | Retail UX | Srednji | ⭐⭐⭐⭐ | Maloprodaja |
| F6 | Etikete | Srednji | ⭐⭐⭐ | Pekare, marketi |
| F4 | Težinski barkod | Srednji | ⭐⭐⭐ | Pekara, mesara |
| F7 | Inventura skener | Srednji | ⭐⭐⭐ | Lanci |
| F5 | Varijante | Visok | ⭐⭐ | Butik |

**Redosled za prodavnice (paralelno sa Fazom A):**

```
A1 ESIR (proces)  →  F1 Smene  →  F2 Lager  →  F3 prijem robe + KEP  →  F8 Retail UX
                              ↘  F4 težinski (ako pekara/mesara)
```

### Šta DigiPOS već ima a maloprodaja traži

| Funkcija | DigiPOS | Tipičan konkurent |
|----------|---------|-------------------|
| Barkod prodaja | ✅ | Svi |
| Akcije / popusti | ✅ | BKC, UniSoft, Sky |
| Loyalty kartica | ✅ | Sky, BKC Premium |
| Više prodavnica + centrala | ✅ offline sync | Sky, BKC, Hubie |
| Refundacija | ✅ | Svi ESIR |
| Integracija knjigovodstvo | ✅ ista MySQL baza | **Retko kod drugih** |
| Bez mesečne pretplate | ✅ self-hosted | Sky ❌ |

---

## Matrica prioriteta

| ID | Stavka | Faza | Effort | Prodajni efekat | Tehnički rizik |
|----|--------|------|--------|-----------------|----------------|
| A1 | ESIR DigiPOS (novi proizvod) | A | Visok (proces PU) | ⭐⭐⭐⭐⭐ | Nizak |
| A2 | Split računa | A | Srednji | ⭐⭐⭐⭐⭐ | Srednji |
| A3 | Prilozi / modifikatori | A | Srednji–visok | ⭐⭐⭐⭐ | Srednji |
| A4 | PWA | A | Nizak–srednji | ⭐⭐⭐⭐ | Nizak |
| A5 | Turnkey dokumentacija | A | Nizak | ⭐⭐⭐⭐ | Nizak |
| B1 / F1 | Smene | B/F | Srednji | ⭐⭐⭐⭐⭐‡ | Nizak |
| B2 / F2 | Skladište + lager UI | B/F | Visok | ⭐⭐⭐⭐⭐‡ | Srednji |
| F3 | Prijem robe + KEP knjiga | F | Visok | ⭐⭐⭐⭐‡ | Srednji |
| F4 | Težinski barkod | F | Nizak–srednji | ⭐⭐⭐‡ | **Nizak** |
| F6 | Štampa etiketa | F | Srednji | ⭐⭐⭐‡ | Nizak |
| F8 | Retail UX (kasa) | F | Srednji | ⭐⭐⭐⭐‡ | Nizak |
| B3 | Kuhinja real-time | B | Srednji | ⭐⭐⭐ | Srednji |
| B4 | DPU lista | B | Srednji | ⭐⭐⭐ | Nizak |
| B5 | Health dashboard | B | Nizak | ⭐⭐⭐ | Nizak |
| C1 | Analitika | C | Srednji | ⭐⭐⭐ | Nizak |
| C2 | eOtpremnice | C | Visok | ⭐⭐ | Srednji |
| C3 | Otvoreni API | C | Srednji | ⭐⭐⭐ | Srednji |
| C4 | Customer display | C | Nizak | ⭐⭐ | Nizak |
| D1 | Hrvatska fiskalizacija | D | Vrlo visok | ⭐⭐⭐⭐* | Visok |
| E2 | Pozovi konobara (QR) | E | Nizak | ⭐⭐⭐⭐† | Nizak |
| E1 | Zone / ležaljke | E | Srednji | ⭐⭐⭐† | Srednji |
| E4 | Turistički meni (prevod+slike) | E | Srednji | ⭐⭐⭐† | Nizak |

\* samo za HR tržište · † turizam / sezonski objekti · ‡ maloprodaja / prodavnice

### Preporučeni redosled implementacije (dev)

**Ugostiteljstvo:**

```
A4 PWA  →  A2 Split  →  A3 Prilozi  →  B3 KDS WS  →  B5 Health
     ↑
  brz win, paralelno A1 (ESIR proces van koda)
```

**Maloprodaja (prodavnice, lanci):**

```
A1 ESIR (proces)  →  F1 Smene  →  F2 Lager  →  F3 prijem robe + KEP  →  F8 Retail UX
                              ↘  A4 PWA (paralelno)
```

---

## Merenje uspeha (KPI)

| KPI | Cilj (6 meseci posle Faze A) |
|-----|------------------------------|
| Vreme od instalacije do prvog računa | < 2 h (sa turnkey doc) |
| Podrška: „split računa“ | 0 zahteva „nedostaje“ (restoran) |
| Podrška: „smene / KEP / lager“ | 0 zahteva „nedostaje“ (maloprodaja) |
| Kasir: račun sa 10 barkod stavki | < 90 s (posle F8) |
| Konobar: korak do porudžbine | ≤ 3 tap-a (sto → artikal → pošalji) |
| Kuhinja: kašnjenje prikaza | < 2 s (posle B3) |
| Pad prodaje zbog interneta | 0 (offline-first ostaje) |
| Novi ESIR klijenti | meriti posle A1 |
| Novi retail klijenti (lanac / prodavnica) | meriti posle F1+F2 |

---

## Van opsega (ne raditi sada)

- Potpuna zamena MySQL-a cloud SaaS multi-tenant modelom
- Native iOS/Android app (pre PWA i dok nema jasnog ROI)
- Sopstveni payment gateway / procesor kartica
- HR modul pre stabilizacije RS Faze A
- AI preporuke / chatbot za goste
- Previše custom tema / white-label (odložiti)

---

## Povezani dokumenti

| Dokument | Sadržaj |
|----------|---------|
| [README.md](../README.md) | Tehnički pregled, arhitektura |
| [UPUTSTVO.md](UPUTSTVO.md) | Korisničko uputstvo sa slikama |
| [BRZI_VODIC.md](BRZI_VODIC.md) | Jednostrani vodič za osoblje |
| [brzi-vodic.html](brzi-vodic.html) | Štampana verzija |

---

## Dnevnik realizacije (ko je šta uradio)

> **Pravilo:** svaka završena stavka se upisuje ovde — datum, ko (tata / sin / Claude), commit i kratka napomena. Claude upisuje automatski posle svakog commit-a; tata i sin upisuju svoje ručno.

| Datum | Stavka | Ko | Commit | Napomena |
|-------|--------|----|--------|----------|
| 2026-07-05 | Osnova: kasa (restoran+prodavnica), kuhinja, LPFR+DEMO, sync centrala, loyalty, akcije, normativi | tata + Claude | `50359a7` | inicijalni commit repo-a |
| 2026-07-05 | SEF eFakture (UBL XML + slanje) | Claude | `9caa325` | |
| 2026-07-05 | Wolt/Glovo dostave (webhook, ekran Dostave, DEMO simulator) | Claude | `fce5a69` | |
| 2026-07-05 | Javni QR meni (`/meni`, lib/qr.js) | tata/sin | `fce5a69` | rađeno paralelno, ušlo u isti commit |
| 2026-07-05 | Self-service kiosk (`/kiosk`, dnevni broj, kartica Kiosk) | Claude | `cd1ace9` | |
| 2026-07-06 | Kiosk za stolom: QR token po stolu, zaduženi konobar, zvonce, rate limit | Claude | `098ae11` | |
| 2026-07-06 | DigiPOS preimenovanje + i18n СРБ/SRB/ENG/GRE + tamna/svetla tema | Claude | `320528a` | bez hardkodovanih tekstova (public/i18n.js) |
| 2026-07-06 | Korisnička uputstva (`docs/UPUTSTVO.md`, brzi vodič, /docs portal) | tata/sin | `320528a` | |
| 2026-07-06 | Novi screenshotovi + `scripts/screenshots.js` (auto-snimanje) | Claude | `abf48b5` | |
| 2026-07-06 | A1.5 higijena: PIN-ovi samo kao heš (pepper u config.json) | Claude | `30837f1` | migracija automatska; pepper u backup! |
| 2026-07-06 | F4 težinski barkod (port iz digiesir) | Claude | `1cdcf4c` | prefiks 28, PLU+grami |
| 2026-07-06 | Grčka kodna strana štampe (CP737, auto ESC t) | Claude | `846c147` | |
| 2026-07-06 | F8 komandna konzola kase (port digiesir sample.prg) | Claude | `e7c74c7` | +ŠIFRA, količine, rabati, G/P/C/K, A-kopija |
| 2026-07-06 | A4 PWA (manifest, SW, ikonice, HTTPS opcija) | Claude | `7deca2b` | offline shell testiran |
| 2026-07-06 | B1/F1 smene i zatvaranje blagajne | Claude | `b8b2a85` | kartica Smena + admin Smene + presek na traku |
| 2026-07-06 | UPGRADE.md plan (faze A–F, analiza konkurencije RS/HR/GR) | tata | — | dopune: Claude |
| 2026-07-06 | Testovi (`tests/`: api, db, lpfr, qr, receipt, težinski) + `lib/barkod.js` (izdvojen parser) | tata/sin | `b8b2a85` | rađeno paralelno, ušlo u isti commit sa F1 |
| 2026-07-06 | `lib/barkod.js` = jedan izvor istine: UMD (Node+browser), kasa ga koristi preko `/barkod.js`, testovi preko require; `npm test` skripta | Claude | `404150e` | 31/31 testova prolazi; vaga E2E i dalje radi |
| 2026-07-06 | **SQLite režim (nulta instalacija)** — korak 1 ka cloudu: `lib/sqlite.js` (adapter nad `node:sqlite` + SQL prevodilac), `lib/config.js`, samoinstalacija minimalnog knjigovodstva, portabilni upserti (bez ON DUPLICATE); MySQL netaknut | Claude | `8b35593` | `tests/sqlite.test.js`: ceo tok od nule (login→artikal→fiskalni račun→smena) nad svežom SQLite bazom |
| 2026-07-06 | Veliki paket testova (`tests/api-*`, lpfr-demo/edge, receipt-edge, enc1251, barkod, dostava.unit, static + tests/README) — ukupno 134 testa | tata/sin | `8b35593` | svi prolaze i nad novim SQLite slojem; `npm test` serijski (16 s) |
| 2026-07-06 | **Cloud korak 2: Go centrala** u digi-angular gobackend (`/api/sync/*`, migracija 000092, testovi ugovora) — artikli iz knjigovodstva pravo na kase, računi u `pos_racuni_cloud` | Claude | digi-angular `6a08f3a` | build + 30 test paketa OK |
| 2026-07-06 | **Cloud korak 3: DEPLOY na VPS** — migracija 000092 primenjena (psql, verzija 92), novi binar, servis aktivan; **E2E potvrđen**: SQLite kasa ↔ VPS (artikli povučeni, DEMO račun stigao u `pos_racuni_cloud` pa obrisan); pilot ključ za vlasnika 1 ubačen | Claude | — | ⚠ zatečen duplikat migracije 000080 (dva različita fajla, i lokalno i na VPS-u) — `migrate up` je slomljen, verzija se vodi ručno; treba renumerisati jedan par |
| 2026-07-06 | **Uvoz iz digiesir (DBF)**: `lib/dbf.js` (čitač dBase III, CP852/1250/1251) + Admin → Podešavanja → Uvoz — artikli (živi `DBFPATH\SIFRE.dbf`, pa SIFRE3/ART4 kopije), kupci (FIRME), radnici→pos_users (PIN = bedž), popusti→loyalty, porstope→stope+fiskalne oznake (LABEL, CP1251), akcije, basicdata→LPFR/štampač/kodne strane/kolona/QR/težinski, vlasnik.dbf→obveznik (standalone) | Claude | `ace5120` | test na pravim podacima: 14.748 artikala, 94 kupca, 4 radnika (prijava bedžom radi), 3 kartice, oznake Ђ/Е/Г/А tačne |
| 2026-07-06 | ESIR dosije za PU: korisničko + tehničko uputstvo, instalacija, upotreba (MD + print HTML + PDF, `npm run docs:pdf`) | tata/sin | `ace5120` | priprema za A1; ušlo u isti commit sa DBF uvozom |
| 2026-07-06 | **Vrste objekata + P17 uvoz transakcije + P14 reklamno polje/virman**: kodni spisak digi-angular — samo T (maloprodaja) / U (ugostiteljstvo) / S (usluge) su kasa, veleprodaja i magacini (V/R/G) van izbora objekta, maloprodaja se upisuje kao `T` (ne `M`); P17 uvoz transakcije preko fajla (.json/.csv) idempotentno (`pos_racuni.transaction_uid`) za mobilnog konobara; P14 `reklama_tekst` ispod KRAJ FISKALNOG RAČUNA + virman tekući račun za SVAKO virmansko plaćanje (`fiskalizuj` uvek uzima `vlasnik.tekuci`); testovi izolovani na SQLite (`tests/helpers.js`, ne diraju živu `sokdooco_knjige`), seed stolova vezan za objekat | Claude | `2cfb480` | 152/152 testova; port digiesir `Vlasnik->Poruka` pristupa; avans tok ostaje jedini funkcionalni ESIR gap |
| 2026-07-08 | **Muzički dinar (SOKOJ/OFPS)** — admin unosi iznos (`muzicki_dinar`, DEFAULT 0); kad je >0 dodaje se kao stavka „Muzички динар" na **svaki Promet-Prodaja** račun (u `fiskalizuj`, lokalna kopija stavki → NE ulazi u lager) i uvećava total; 0 = ne iskazuje se. Klijent (`/bootstrap` → `muzickiDinar`) prikazuje i uključuje u plaćanje na naplati, splitu i brzoj prodaji (`naplataTotal`). i18n СРБ/SRB/ENG/GRE. | Claude | — | `tests/muzicki-dinar.test.js` 2/2 (izolovano); pun paket crven zbog UTC-vs-lokalni datum bug oko ponoći (odvojeno) |
| 2026-07-08 | **Test infra: retry na nov port** — `tests/helpers.js` širi opseg (3400–9400) + retry (5×) na nov port ako server ne krene (fast-fail na `exit`, jer `app.listen` bez `.on('error')` pada na EADDRINUSE); uklanja flaky sudar portova pri mnogo test fajlova. | Claude | — | — |
| 2026-07-08 | **Objava instalacije + landing na knjigovodstvu** — `scripts/objavi-instalaciju.sh` (`npm run objavi`) builduje Windows paket i scp-uje ga na hosting (`sokdooco@sokdoo.com:2233 → public_html/digi-knjigovodstvo/download/`), dostupan na `https://digi-knjigovodstvo.rs/download/digipos-windows-x64.zip` (zip ~39 MB, NE ide u git — GitHub repo je privatan pa release link ne radi za posetioce). U **digi-angular** landing dodata sekcija „DigiPOS 2.0" (`#digipos`) + dugme za preuzimanje + `srb.json` ključevi. Radi se **uz svaki puš** kada želimo novu instalaciju kod korisnika. | Claude | `1dfb3ee` | upload na produkciju pokreće korisnik (outward-facing) |
| 2026-07-08 | **Priručnik: standalone poglavlja** — dodato „Standalone — svakodnevni poslovi": promena cene (Artikli → Izmeni → Cena), dodavanje količine na stanje (Prijem robe / izmena stanja / inventura), grupe artikala (Podgrupe + čekiranje „Na kasi"). ODT prebildovan (49 preloma). | Claude | `b3f5172` | ciljna grupa: najmanji korisnici u standalone (besplatna godina od avgusta) |
| 2026-07-08 | **Pretraga izdatih računa po kupcu** — `/racuni?kupac=<PIB/JMBG/broj LK>` traži kroz sve datume (kupac je u `poslato` JSON-u `inv.buyerId` „tip:vrednost"; `poslato LIKE` predfilter + precizan JS filter po `buyerId`); vraća polje `kupac` i ne šalje ceo JSON. Kasa → Računi: polje pretrage „Kupac: PIB/JMBG/broj LK" + kolona Kupac + „Sve za dan". i18n СРБ/SRB/ENG/GRE. | Claude | `68b1c80` | 191/191 (`tests/racuni-kupac.test.js`) |
| 2026-07-08 | **Grupe artikala: admin bira šta stoji na kasi** — grupe (`sifargru`) se prikazuju kao dugmad na kasi u OBA režima ako postoje **i** ako ih je admin čekirao. Vidljivost po grupi (`na_kasi`) čuva se kao CSV skrivenih opsega u `podgrupe_sakrij` (bez izmene šeme). Admin → Artikli → Podgrupe: čekboks „Na kasi" po grupi (`POST /podgrupe/:opseg/kasa`). Ranija tvrda zabrana podgrupa u prodavnici uklonjena (prazna traka se i dalje sama sakriva). i18n СРБ/SRB/ENG/GRE. | Claude | `8361673` | 189/189 (`tests/podgrupe.test.js`) |
| 2026-07-08 | **Da/ne podešavanja kao čekboksovi** — u administraciji 9 „(1/0)" polja (`sef_demo`, `sef_send_to_cir`, `qr_menu_enabled`, `smena_obavezna`, `lager_obavezan`, `lager_prikaz_kasa`, `title_center`, `kiosk_enabled`, `dostava_auto_prihvat`) sada su čekboksovi (čuva se `'1'`/`'0'`); labela se prikazuje bez „(1/0)" (strip na render-u, i18n ključevi netaknuti). | Claude | `37c84e3` | — |
| 2026-07-08 | **Štampači se biraju iz liste (ne kuca se ime)** — novi `GET /api/stampaci` (admin) enumeriše instalirane Windows štampače (`lib/print.js listajStampace`, PowerShell `Get-CimInstance Win32_Printer` preko `-EncodedCommand` zbog pipe/quoting-a); polja `printer`/`kitchen_printer`/`label_printer` u administraciji su sada **padajuće liste** (instalirani + FILE/NONE + „— isključeno —"/„— glavni štampač —"), uz čuvanje ranije upisane vrednosti ako nije u listi. i18n СРБ/SRB/ENG/GRE. | Claude | `88d233a` | 186/186 (`tests/stampaci.test.js`); opciono: obnoviti `13-admin-podesavanja.png` |
| 2026-07-08 | **`14-prodavnica-kasa.png` obnovljen (pun asortiman)** — dodato 17 cena po objektu (`magart`, objekat 31: kafić P/H + elektro/solar maloprodaja) pa prebildovan set: prodavnički grid pun, restoran demo koristi kafić stavke. Skrinšot potvrđuje sve tri UI izmene: bez trake jezika, bez podgrupa u prodavnici, samo artikli sa cenom+nazivom. | Claude | `32f8c80` | 02–06 + 14 osveženi; ODT prebildovan |
| 2026-07-08 | **Skrinšotovi osveženi + `screenshots.js` popravljen** — 12 skrinšota kase/admina snimljeno sa novom UI (bez trake jezika u kasi); ODT priručnika prebildovan. `scripts/screenshots.js`: posle **F9** (režim se izvodi iz `objekti.vrsta`, ne iz `mode` podešavanja) maloprodajni ekran je prazan — dodato `vrsta='T'` za prodavnički skrinšot i storno probne porudžbine **dok je još restoran mod**. Zaostalo: `14-prodavnica-kasa.png` nije obnovljen jer objekat 31 („Малопродаја у комбију") ima samo **1 artikal sa cenom po objektu** (magart) → mreža bi bila prazna; treba objekat sa punim asortimanom ili nivelacija demo artikala. | Claude | `8e8801c` | 09/14 nepromenjeni (admin zadržava jezik; 14 preskočen) |
| 2026-07-08 | **Veliki priručnik (ODT)** — `docs/PRIRUCNIK-DIGIPOS.md` + `scripts/build-prirucnik-odt.js` (`npm run docs:prirucnik`) → `docs/DigiPOS-prirucnik.odt`: reklamni deo („zašto DigiPOS"), rečnik za početnike, instalacija korak-po-korak, upotreba (restoran + prodavnica), administracija, backup, FAQ, kratko uputstvo za osoblje. 46 preloma stranica, 24 skrinšota (>40 str.). | Claude | `4049c89` | napomena: skrinšotovi kase još prikazuju staru traku jezika — pre finalnog PDF-a pokrenuti `node scripts/screenshots.js` pa `npm run docs:prirucnik` |
| 2026-07-08 | **Kasa/meni skrivaju neispravne artikle** — `/artikli` (ne-admin) i `meniArtikli` (QR meni, kiosk) ne prikazuju artikle sa **cenom 0** ni **bez naziva** (`TRIM(COALESCE(naziv,''))<>''`). Filter cena>0 se sada primenjuje i u **fallback** grani (kad `magart` JOIN padne na delimičnoj MySQL bazi), ne samo u `cenaPoObjektu`. Admin (`?sve=1`) i dalje vidi ceo šifarnik da bi ih uredio/obrisao. | Claude | `b608c60` | **184/184** (`tests/cene-po-objektu.test.js` +1: bezimeni artikal) |
| 2026-07-08 | **UI čišćenje kase** — (1) podgrupe menija (kafa, sokovi…) se **ne prikazuju u prodavnici** (ugostiteljska navigacija; `app.js` učitava `/podgrupe` samo u `restoran` modu). (2) **Izbor jezika samo u adminu** — `langBar('lang-bar', {jezik:false})` u kasi (login + zaglavlje) prikazuje **samo temu**; kasa/kuhinja nasleđuju jezik iz `localStorage.digi_lang`. Kupački ekrani (kiosk, QR meni) i admin zadržavaju pun izbor jezika. | Claude | `d1a7c1d` | ostaje: ponovo snimiti skrinšotove (`node scripts/screenshots.js`) da odraze novu UI |
| 2026-07-08 | **Ispravka datuma oko ponoći (UTC→lokalni)** — `new Date().toISOString().slice(0,10)` vraća UTC datum, a zapisi se čuvaju lokalno (`prevediSql`: `datetime('now','localtime')`); oko lokalne ponoći default datum je promašivao dan → prazni dnevni izveštaji/računi/DPU/smene/inventura. Server → `datumKey()` (7 mesta), klijent `app.js`/`admin.js` → `danasLokalno()` (8 mesta), `lib/sef.js dateOnly` → lokalne komponente. Testovi (`dpu`, `api-dostava`) → `danasLokalno` iz `helpers`. | Claude | `03332e2` | **183/183** (pun paket zelen) |
| 2026-07-07 | **A3 Prilozi/modifikatori** — napomena po stavci (`pos_stavke.napomena`, migracija) ide na kuhinjski tiket; katalog `pos_prilozi` (GET `/prilozi`, admin CRUD, tab „Prilozi"); primena priloga `POST /stavke/:id/prilog` — plaćeni prilog ulazi u cenu linije (fiskalno korektno, PDV artikla); različite napomene = odvojene linije (merge uzima napomenu u obzir). Frontend: 🗨 na liniji korpe → modal (čipovi priloga + slobodan tekst). i18n СРБ/SRB/ENG/GRE. | Claude | `b2fbb17` | 181/181 (`tests/prilozi.test.js`) |
| 2026-07-07 | **A2 Split računa** — podela računa za sto (ugostiteljstvo): `POST /porudzbine/:id/split` fiskalizuje **podskup** stavki (izabrane količine) kao poseban Promet-Prodaja, umanjuje porudžbinu, kad se isprazni → `naplacena`; lager skida po naplaćenom (poštuje `vodi_robno`). Frontend: dugme „Podeli" + modal (količine „na ovaj račun" + način plaćanja). i18n СРБ/SRB/ENG/GRE. | Claude | `6cbb4f4` | 178/178 (`tests/split.test.js`) |
| 2026-07-07 | **Cena po objektu — dorada** — admin polje cene **read-only** u knjigovodstvenom (MySQL) modu (cena iz nivelacije/`magart`), editabilno u standalone (`mpcena` fallback); `/bootstrap` izlaže `standalone`/`vodiRobno`. Dostava (Wolt/Glovo) meni koristi cenu po objektu. Standalone `pos_cene` punjenje: jedan objekat po serveru radi preko `mpcena` fallback-a; puni per-objekat sync (magart) = zaseban Go/centrala zadatak. | Claude | `a13bc49` | 176/176 |
| 2026-07-07 | **Cena po objektu + robno po param011** — kasa vuče cenu PO OBJEKTU (MySQL `magart.cena` gde magacin=objekat; SQLite `pos_cene`→`mpcena` fallback), prikazuje **samo cena>0** (`sifre.mpcena` nebitna); pretraga artikala i **po ceni**. `getSettings` čita `dodatnipodaci.param011` → `vodi_robno = restoran ILI param011`: maloprodaja bez param011 NE skida stanje (korpa=istina, minus=greška evidencije), ugostiteljstvo (U) uvek vodi robno (DPU obavezan); popis/stanje/inventura UVEK. Primenjeno: `/artikli`, `/meni`, `/kiosk/meni`, kiosk stavka, etikete, DPU, restoran dodavanje stavke. Nova tabela `pos_cene`. | Claude | `8faf1ae` | 176/176 (`tests/cene-po-objektu.test.js`); potvrđeno na živoj bazi (objekat 31→1, 28→93 artikla); admin cena read-only i standalone `pos_cene` punjenje = TODO |
| 2026-07-07 | **Pravilo: 3 režima rada** — `docs/REZIMI-RADA.md` (kanonski): (1) standalone import/export, (2) standalone sync na zahtev (digi-knjigovodstvo.rs/VPS), (3) cloud VPS Go offline-first. Pokazivači u `README.md`/`newupgrade.md`/`UPGRADE.md`; svaka funkcija mora raditi u sva tri. | Claude | — | uz to: deploy digi-angular na localhost/knjige popravljen (base-href `/knjige/` — beli ekran zbog `base=/`) |
| 2026-07-07 | **A1 ESIR dosije za PU** — `docs/ESIR-DOSIJE-PU.md`: popunjen ЕСИР Упитник (7.4.2, delovi 1–16, П1–П17 odgovoreni za DigiPOS). `scripts/esir-primeri.js`: generiše 12 primera računa iz pravog `lib/receipt.js` renderera (svih 20 tipova + specijalni: virman sa tekućim računom, avans АП/АР, konačni ПП по авансу sa „Плаћено авансом"/реклама) + ESC/POS→tekst dekoder. `scripts/build-esir-dosije.js` → `docs/DigiPOS-ESIR-dosije.odt` (preko `lib/odt-builder.js` — Markdown→ODT). | Claude | `2f6950e` | 173/173 (`tests/esir-primeri.test.js`); DEMO QR — zameniti pravim iz razvojnog okruženja PU; dopuniti detalje apliканта i izvezti ODT→PDF |
| 2026-07-07 | **F7 Inventura mobilnim telefonom** — `pos_inventura` + `pos_inventura_stavke`; `/api/inventura/*`: popis (barkod ili šifra, `dodaj`=inkrement za scan), razlika vs `pos_stanje`, `proknjizi` → `lager.postavi` (stanje=popisano, `korekcija` dokument, čuva `minimum`); `punPopis` → nepopisano sa stanjem ide na 0; izveštaj manjak/višak. Inventura view u `public/app.js`: kamera `BarcodeDetector` (Android/HTTPS, debounce+vibracija) + ručni unos (svuda), lista sa razlikom, pun popis checkbox. | Claude | `cb1f1e0` | 169/169 (`tests/inventura.test.js`); kamera progresivno poboljšanje, iOS/ostalo ručni unos; probati uživo na telefonu |
| 2026-07-07 | **B4 DPU — Lista dnevnog prometa** (ugostiteljstvo, materijalna po danu) — `lib/dpu.js`: kretanje robe iz prodaje (`pos_racuni` invoice_type=0 × `pos_stavke`; prodaja=izlaz, refund=ulaz) + robnih dokumenata (prijem=ulaz, prenos izlaz/ulaz); preneseno (datum<D), nabavljeno/utrošeno (datum=D), zaliha_kraj, promet piće/hrana po `hp`, totali; port formule iz digi-angular `stampanjelistadpu.php`. `GET /izvestaj/dpu`, Admin → DPU tab (datum/objekat, štampa + CSV). Portabilno MySQL+SQLite. | Claude | `4f26d13` | 164/164 (`tests/dpu.test.js`); cena = `sifre.mpcena`; ručne korekcije stanja se ne uračunavaju; uporediti sa zvaničnim uzorkom |
| 2026-07-07 | **F6 Štampa etiketa** (ESC/POS termalni) — `lib/etiketa.js`: naziv + cena + barkod koji štampač crta nativno (`GS k`): EAN13 ako je `barcode` validan (13 cifara + kontrolna), inače Code128 šifre (skener vrati šifru → kasa nađe artikal); N kopija; reuse `makeEncoder` (CP1251). `POST /etikete`, setting `label_printer` (prazno = glavni), Admin → Artikli dugme 🏷 + bulk „Etikete (iz pretrage)". i18n. | Claude | `822c43e` | 162/162 (`tests/etiketa.test.js`); fizički otisak proveriti na pravom label štampaču (visina/širina `GS h`/`GS w` po rolni) |
| 2026-07-06 | **Avansni tok (ESIR 9.1/9.2)** — poslednji funkcionalni ESIR gap: `pos_avansi` (lanac po `grupa`); `POST /avans` (Avans-Prodaja `invoiceType 4`, avans-stavka `Аванс (<oznaka>)` u memoriji bez lagera, реф na prethodni AP); `GET /avansi`; `POST /avansi/:grupa/zatvori` (Avans-Refundacija bez štampe kupcu → реф na poslednji AP; pa Promet-Prodaja → реф na AR, u reklami „Аванс: <AP> <datum>", kupac plaća preostalo = ukupno−avans); `fiskalizuj` + `dateAndTimeOfIssue/avans/reklama/bezStampe`, `/prodaja`→`obradiProdaju()`; GUI dugme „Avans" + modal; i18n | Claude | `54d41d1` | 155/155 testova (`tests/avans.test.js`); reconciliacija/ref-lanac provereni samo na DEMO PFR — proveriti na pravom L-PFR pre produkcije |
| 2026-07-14 | **Sandbox PDF isečci П1–П12** — `vpfr-sertifikacija.js --pdf` traži `verificationQRCode` sa V-PFR i štampa tiho na **Microsoft Print to PDF** (`gdiprint.ps1 -OutFile`). Izlaz: `docs/sertifikacija-sandbox/pdf/*.pdf` (13 fajlova, QR ~11 KB GIF). | Claude | `62df047` | opciono fizički termalni štampač |
| 2026-07-14 | **Odluka A (strogo PFR-only): DEMO ne izmišlja oznake; prodaja bez mapiranja se odbija** — uklonjen svi runtime fallback-ovi `taxLabels[grupa] \|\| 'Ђ'` (kasa, kiosk, dostava, muzički dinar). Nova `fiskalnaOznaka()` u `lib/db.js` baca 400 ako nema mapiranja. `GET /artikli` vraća prazan `label` dok se ne preuzme sa PFR-a. Avans prihvata samo oznake iz `tax_labels`. DEMO i dalje nema `currentTaxRates`. Testovi: fixture `tax_labels` u `helpers.js` simulira već preuzeto sa PFR-a; `sqlite`/`tax-rates` assertuju odbijanje bez mape. | Claude | `62df047` | bez fizičkog L/V-PFR nema punog šifarnik-toka ni „golih“ DEMO prodaja bez fixture-a |
| 2026-07-14 | **Šifarnik poreskih stopa (12-П1/П6): oznake se ČITAJU sa PFR-a, ne izmišljaju** — uklonjen nekompatibilan seed u `lib/db.js` koji je pragom (`stopa>=20?'Ђ'…`) izmišljao fiskalne oznake. Sada: `taxRatesFromStatus()` (`lib/lpfr.js`) izvlači oznake/stope iz `/status` (`currentTaxRates`); `GET/POST /api/lpfr/tax-rates` (`routes/api.js`) čita sa PFR-a i upisuje vezu *ERP šifra→PFR oznaka*, uz odbijanje svake oznake koje nema u tekućem PFR odgovoru (12-П6). Admin ekran **Šifarnik poreskih stopa** (`public/admin.js`, i18n СРБ/SRB/ENG/GRE): dugme „Preuzmi stope sa PFR-a" + tabela ERP šifra/opis/stopa → padajuća lista **samo PFR oznaka**. DEMO nema stope (nema fizičkog PFR-a) — ništa se ne izmišlja. | Claude | `ae43ce3` | **212/212** (`tests/tax-rates.test.js`, `sqlite.test.js` ažuriran: oznake prazne do preuzimanja). Uživo: oznake pročitane sa sandbox V-PFR (group 8: A=10%, Ж=19%, B=0%, E=6%…). Ispravka po instrukciji korisnika: ESIR ne sme nigde da postavlja poreske osnovice/oznake |
| 2026-07-14 | **V-PFR digitalni sertifikat + sandbox PU (priprema za sertifikaciju ESIR-a)** — `lib/lpfr.js`: kad je `lpfr_cert` popunjen prelazi u V-PFR režim — učitava klijentski PFX (mutual-TLS), verifikuje server preko sistemskog CA (Let's Encrypt), ПАК šalje kao `PAC` zaglavlje na svaki zahtev (`_hdr`); `verifyPin` u cert režimu validira PAC na `/status` (nema `POST /pin`). Nova podešavanja `lpfr_cert`/`lpfr_cert_pass`/`lpfr_ca`/`lpfr_insecure` (`lib/db.js`, admin polja). Sandbox sertifikati (JID `3LAMY8QM`) u `cert/` (gitignore). `scripts/vpfr-test.js` — dijagnostika bez baze (`/status`, `verifyPin`, opciono `--invoice`). Doc `docs/SERTIFIKACIJA-SANDBOX.md` + dopune `ESIR-TEHNICKO-UPUTSTVO.md`. | Claude | `d734cda` | **208/208** (`tests/lpfr-vpfr.test.js` 3/3, bez mreže). **Uživo potvrđeno** na `vsdc.sandbox.suf.purs.gov.rs`: `/status`→200, `verifyPin`→`0100`, test račun potpisan (`3LAMY8QM-…`, važeći QR). Sledeće: uskladiti `tax_labels` sa sandbox oznakama (A=10%, Ж=19%…) i odraditi scenarije „Ručno testiranje ESIR-a" |
| 2026-07-15 | **ESIR instalacija na daljinu + sertifikacioni izlazi** — (1) `docs/esir-setup/`: `DigiPOS-ESIR-Setup.cmd` (jedan klik → skida zip, raspakuje, startuje, otvara `localhost:3000`), `esir-setup.ps1` (Windows), `install-android-termux.sh` (Android), `mobilni.html`/`iphone.html`/`index.html` landing; reinstalacija **čuva postojeći `app\digipos.db`**. `objavi-instalaciju.sh` šalje setup na `digi-knjigovodstvo.rs/esir-setup/` uz zip. (2) `scripts/vpfr-sertifikacija.js`: scenariji П1–П12 na sandbox V-PFR (oznake isključivo sa `/status`), izlaz req/res JSON + isečci + `--pdf` (Microsoft Print to PDF preko `gdiprint.ps1 -OutFile`). (3) `public/pfr-monitor.js`: stalna provera veze sa PFR-om (10-П2) — trajna traka, klik → ponovni pokušaj. (4) ESIR uputstva za instalaciju/konfiguraciju (MD + print HTML + ODT + PDF), ćirilizacija (`cirilizuj-esir-docs.js`), brend boje (`docs/branding/colors.json`). | Claude | `62df047` | **226/226**; upload na produkciju pokreće korisnik (outward-facing) |
| 2026-07-15 | **Setup na daljinu: jedan izvor istine + 3 ispravke otkrivene testom** — (1) `DigiPOS-ESIR-Setup.cmd` sveden na preuzimanje i poziv `esir-setup.ps1` (ranije ista logika prepisana inline u CMD-u → drift pri svakoj izmeni PS1); `docs/esir-setup/esir-setup.ps1` izbačen iz gita (generiše ga `objavi-instalaciju.sh` iz `scripts/esir-setup.ps1`). (2) **BUG (zatečen)**: em-dash u komentaru CMD-a **iznad** `chcp 65001` pomerao je cmd-ov bajt-pomeraj za 2 → sledeća komanda čitana raspolovljena (`'ho' is not recognized`, zaglavlje nestalo). Svaki korisnik daljinske instalacije je ovo video. CMD je sada **isključivo ASCII** (provera: `LC_ALL=C grep -n '[^ -~]' DigiPOS-ESIR-Setup.cmd`). (3) **BUG (zatečen)**: `esir-setup.ps1` je UTF-8 **bez BOM-a**, a Windows PowerShell 5.1 takav .ps1 čita kao ANSI → „firma → PFR" krkljanac; dodat BOM. (4) **Rizik (zatečen)**: hosting na nepostojeći URL vraća HTML sa statusom **200**, pa je `Invoke-WebRequest` uspevao i CMD je izvršavao tuđi HTML kao skriptu — dodat sentinel `DIGIPOS-ESIR-SETUP-V1` koji se proverava pre pokretanja. | Claude | `b6ce4b9` | testirana 4 puta (uspeh / PS1 exit 1 / HTML-404 odbijen / BOM+sentinel), izlazni kodovi tačni; **226/226**. Ostaje: SHA-256 uz zip pre nego što `/esir-setup` postane javan |

| 2026-07-15 | **Tajne iz koda + SHA-256 uz pakete** — (1) `scripts/_vpfr-env.js` (novo): `VPFR_CERT_PASS` i `VPFR_PAC` se čitaju isključivo iz env-a; ranije su stajali kao hardkodovan default (`RRUJ9MPK`/`5WJJXA`) u `vpfr-sertifikacija.js` i `vpfr-test.js` — prvi put na PRAVOM sertifikatu default bi tiho poslao pogrešnu tajnu, a tajna ostaje u istoriji gita zauvek. Bez env-a skripta staje sa uputstvom (exit 2). Uklonjen i pomen ПАК-а iz komentara `lib/db.js`; `tests/lpfr-vpfr.test.js` koristi izmišljen `PAKTEST1`. (2) `objavi-instalaciju.sh` uz svaki paket koji se skida automatski (win/android/linux) objavljuje `<paket>.sha256`; `esir-setup.ps1` (novi `-Sha256Url`) i `install-android-termux.sh` odbijaju paket koji se ne poklapa. Povod: dokazano je da hosting na nepostojeći URL vraća HTML sa statusom **200**, pa „preuzeto uspešno" ne znači da je stigao naš paket. (3) **BUG (zatečen)**: `npm test` je bio `node --test` bez putanje → skenira ceo projekat i pokupi `scripts/vpfr-test.js` (ime odgovara `*-test.js`), pa je **svaki test run otvarao mutual-TLS vezu ka PU sandbox-u** pravim sertifikatom i padao bi bez mreže. Sada `node --test "tests/*.test.js"`. | Claude | `34c42c9` | **225/225** (jedan „test" manje = `vpfr-test.js` se više ne broji). Provera setup-a: ispravan paket prolazi, podmetnut i HTML-umesto-sume se odbijaju pre raspakivanja |
| 2026-07-17 | **ESIR broj 1614/2.0 (dodela PU) + primeri za upitnik deo 17, priloženo na TAP** — (1) `lib/esir.js`: `ESIR_BROJ = '1614/2.0'` (PU dodelila broj 1614 za verziju 2.0); broj upisan u korisničko §1.1, tehničko, konfiguraciju, instalaciju i dosije deo 1; `esir-primeri.js` i `vpfr-sertifikacija.js` čitaju broj iz `lib/esir.js` (jedan izvor istine). (2) **BUG (zatečen)**: `receipt.js` — ESC `a` sekvenca ispred „Артикли:" curila u `buf.tekst`, pa je GDI/PDF štampa crtala kontrolne bajtove kao „Ла Артикли:"; poravnanje sada ide samo u ESC/POS bafer (+ regresioni test u `driverprint.test.js`). (3) **Novo potpisivanje svih 23 sandbox primera** (PFR `…-88`–`…-110`, datum toka 17.07) — pravilo (tata): isečak mora nositi ESIR broj važeći u trenutku potpisivanja; re-render starih potpisa sa novim brojem deluje kao naknadna izmena isečka. `scripts/rerender-sandbox-pdf.js` (novo) ostaje samo za interne provere prikaza. (4) `scripts/build-upitnik17-uzorci.js` (novo): 15 PNG uzoraka za portal — naziv datoteke = PFR broj (portal odbija svaki drugi naziv), QR svakog uzorka mašinski očitan (jsqr) i uparen sa `verificationUrl`; mapa slot→fajl u `upitnik17/PREGLED.md`. (5) `docs/UPITNIK-DOSTAVA-PRIMERI.md` (novo): tačka „Tipovi dostavljanja" — papirno/elektronski, sa referencama i primerima. (6) `CLAUDE.md` (novo, /init): komande, arhitektura, pravila projekta. Dosije deo 17: novi PFR brojevi; svi ODT/PDF regenerisani. | Claude | `afc9771` | **285/285**; **svih 15 uzoraka uspešno priloženo na TAP portal**; uzorci u `docs/sertifikacija-sandbox/upitnik17/` |
| 2026-07-21 | **Usklađivanje ESIR uzoraka sa „Ручно тестирање ЕСИР" v1.1 (СУФ-01) + primedbe PU** — (1) `lib/receipt.js` (pogađa i produkciju): srpski format brojeva (decimalni **zarez**, tačka za hiljade — `1.259,10 / -349,99 / 3.000,00`), poreska oznaka u artiklu ide kao „Назив (Ознака)/јм" (kao primeri str. 22–36), količina na **min. 2 decimale** (`1,00 / 0,258`). (2) `scripts/vpfr-sertifikacija.js`: request nosi `invoiceNumber = ESIR_BROJ` (`1614/2.0`) — ranije prazno (**primedba PU**); osnovna korpa **3 stavke / 3 stope** (Ж opšta / A posebna / B nulta); Промет по авансу — 3 stavke/3 stope, polje reklame = **poslednja Аванс Рефундација** (АР), Реф. број = АР; **GTIN (обавезно, v1.1 §ГТИН)** — EAN-13 (validna kontrolna cifra, GS1-СРБ prefiks 860) na pakovanu robu (Цеђени сок/Хлеб/Салата), šalje se kroz **JSON kao zaseban element** (Portal ga vidi), **ne štampa se** na isečku. (3) Svih 23 sandbox uzorka re-potpisano na V-PFR (PFR `…-180`–`…-202`), 15 portal PNG + Промет-по-авансу PNG; svih **23/23** request nosi `1614/2.0`, **12** računa GTIN u JSON, **0** na isečku. | Claude | `da2aa6d` | **285/285**; QR svih uzoraka mašinski očitan (jsqr); radi se prema **СУФ-01 v1.1 (26.05.2022)**, ne legacy 2021 |
| 2026-07-21 | **Avans — reklama konačnog Prometa nosi poslednju Аванс Рефундацију (PU tačka 15)** — `routes/api.js` `POST /avansi/:grupa/zatvori`: kod zatvaranja avansnog lanca reklama je upisivala broj poslednje **Аванс Продаје** (`zadnji.pfrbroj`), a PU „Ручно тестирање ЕСИР" (СУФ-01) tačka 15 traži broj poslednje **Аванс Рефундације**. Sada `reklama = „Аванс рефундација: <AR> <датум>"` (Реф. број je i ranije bio AR); `reklama` se vraća i u odgovoru endpointa (frontend + test). `tests/avans.test.js`: tvrdi da reklama sadrži broj АР a NE broj АП. | Claude | `7d021ad` | **285/285**; ista greška je maločas ispravljena u `vpfr-sertifikacija.js` (uzorci) — sada i u **proizvodu** koji PU sertifikuje (ne samo na slici) |
| 2026-07-22 | **ESIR — druga runda primedbi PU (bold, svi načini plaćanja, QR samokontrola)** — odgovor na komentare recenzenta na TAP portalu (21.07.2026; primedbe pročitane uživo kroz `claude-in-chrome`). (1) `lib/receipt.js` + `scripts/gdiprint.ps1`: poruka **„ОВО НИЈЕ ФИСКАЛНИ РАЧУН"** na sredini nefiskalnog računa je sada **BOLD** (primedba: „mora biti BOLD") — ESC/POS `ESC ! 0x18` (emphasized+double-height), a za GDI/PDF (PNG uzorci) linija dobija marker `\x02` koji `gdiprint.ps1` crta `FontStyle.Bold`-om (IsBold/StripB u merenju i crtanju); `routes/api.js` uklanja marker iz teksta mejla. (2) `scripts/vpfr-sertifikacija.js`: Промет Продаја (portal slot) prikazuje **SVE načine plaćanja** (primedba: „navedite sve načine plaćanja"). (3) `scripts/rerender-sandbox-pdf.js`: ispravka avans-reklame (poslednja **АР**, ne АП) — isti bug kao u `vpfr-sertifikacija.js`/produkciji, jer rerender iz sačuvanih req/res nije nosio ispravku. (4) `scripts/build-upitnik17-uzorci.js`: QR samokontrola → **UPOZORENJE umesto blokade** kada jsqr ne pročita raster gušćeg QR-a ali je **native PFR GIF validan** (merodavan; realni ZXing skeneri ga čitaju). Regenerisano svih 23 uzorka + 15 portal PNG (+ Промет-по-авансу). | Claude | `97059cb` | **285/285**; **svih 15 priloga okačeno na TAP i пријава poslata na pregled** (status „Техничка измена достављена"). Primedba „ESIR broj na SUF" je već rešena ranije (`da2aa6d`: `invoiceNumber=1614/2.0` u requestu). |
| 2026-07-22 | **Auto-provera nove verzije + datum builda na PIN ekranu** — (1) `lib/esir.js` `buildDatum()`: datum builda iz `build-info.json` (upisuje `npm run package` u sam paket — jedini pouzdan izvor u instalaciji bez gita) → fallback git commit datum → `mtime`; `oProgramu`/`/api/o-programu` ga nose. (2) `lib/azuriranje.js` (novo) + javna ruta `GET /api/azuriranje` (iznad prijave, vidi se na PIN ekranu): tiho čita `https://esir.digi-knjigovodstvo.rs/latest.json`, poredi semver; **mek na offline** (standalone kasa često bez mreže → nema banera, bez greške). (3) `public/app.js`: PIN ekran sitno „DigiPOS vX · build YYYY-MM-DD" + „⬇ Dostupno ажурирање vY"; „O programu" modal → status + dugme **Preuzmi**. i18n СРБ/SRB/ENG/GRE, tamna+svetla tema. (4) `scripts/build-package.js` upisuje `build-info.json`; `scripts/objavi-instalaciju.sh` pravi i šalje `latest.json` u koren subdomena (`esir.digi-knjigovodstvo.rs` = `.../esir-setup`). | Claude | `785ba8a` | **289/289** (`tests/azuriranje.test.js`); vizuelno potvrđeno (PIN ekran + „O programu", tamna i svetla tema). Baner „ажурирање" se pojavi tek kad `npm run objavi` postavi `latest.json` sa višom verzijom u `package.json` |
| 2026-07-22 | **Ажурирање по ДАТУМУ билда, не по верзији (2.0 је пријављен ПУ)** — верзија `2.0` (ЕСИР 1614/2.0) је пријављена ПУ и не сме да се мења, па би поређење по семверу вечно давало „нема ажурирања". Сада: `lib/esir.js buildInfo()` враћа пун ISO датум билда; `lib/azuriranje.js novijiBuild()` пореди ISO датуме (норм. на секунде) → `dostupno = виша верзија ИЛИ (иста верзија И новији билд)`, ново поље `samoBuild`. `public/app.js`: кад је `samoBuild`, банер и „О програму" показују „build YYYY-MM-DD" уместо „vX". `objavi-instalaciju.sh latest.json` носи `datum` (време објаве) — старије касе (исти 2.0) добијају банер чим се објави новији билд, без дирања пријављене верзије. | Claude | `7f7549b` | **291/291** (`tests/azuriranje.test.js` +2: иста верзија/новији билд, иста/старији); уживо потврђено (банер „build 2099-01-01" при верзији 2.0.0) |
| 2026-07-22 | **Прва објава ауто-update пакета + исправка датума у `latest.json`** — `npm run objavi` подигао ЕСИР 2.0 build на сервер (win/linux/android + `latest.json`), проверено уживо (SHA-256 се поклапа са `.sha256` фајлом). **BUG (затечен при проби):** `latest.json` је носио време ОБЈАВЕ (`date -u`), а `build-info.json` у ZIP-у време БИЛДА (~4 min раније) → свежа инсталација је видела сервер као новији и **лажно нудила ажурирање на саму себе**. `objavi-instalaciju.sh` сада чита `datum` из `dist/stage-win/DigiPOS/app/build-info.json` (исти као у пакету који се скида). Проба standalone продавнице (SQLite, скинут ZIP са сајта, SHA потврђен) → `/api/azuriranje` `dostupno:false` (нема банера) против стварног сервера. | Claude | `213b05a` | ЕСИР број 2.0 се НЕ мења (пријављен ПУ); свежа инсталација се више не нуди себи |
| 2026-07-22 | **Примедбе из пробе: окренут шифарник стопа + JSON преглед по рачуну** — (1) Шифарник пореских стопа окренут: редови су сада **ознаке које Л-ПФР враћа** (фиксан извор), а за сваку се бира ЕРП шифра пореза — не обрнуто (примедба корисника). Складиштење остаје `{ЕРП група: ПФР ознака}` (runtime `fiskalnaOznaka(grupa)` непромењен), предизбор преко обрнуте мапе, чување одбија исту ЕРП шифру на две ПФР ознаке. (2) **JSON комуникација по рачуну (као HWGUI „ОдштампајОдговор"):** дугме „JSON" у Админ → Рачуни отвара **захтев (послато)** + **одговор (од ПФР-а)** у модалу, са копирањем. Подаци су и раније чувани (`pos_racuni.poslato/odgovor`), само није било прегледа; нови `GET /api/racuni/:id/json` (`samoAdmin`); листа рачуна и даље не шаље цео JSON. `public/i18n.js` СРБ/SRB/ENG/GRE. | Claude | `57d2a5c` | **292/292** (`api-fiskalno`: `/racuni/:id/json` враћа захтев+одговор); проба standalone продавнице (SQLite, скинут ZIP са сајта) |
| 2026-07-22 | **Лепши boolean редови у Подешавањима** — ситни подразумевани checkbox (inline flex, могао да га поремети `.field label{display:block}`) замењен класом `.checkrow`: уоквирен заобљен ред, checkbox 22px `accent-color`, лево поравнат, hover. Само `public/admin.js` (један ред) + `public/style.css`. | Claude | `1763cf0` | frontend-only; визуелно потврђено на dev админу |
| 2026-07-22 | **Каса: наплата Кеш/Мешовито/Картицом + трајни Обука toggle + „ИД купца" дугме** — примедбе из пробе. (1) Наплата подељена на **три посебна начина**: Кеш (предато готовина + повраћај), Мешовито (све линије ручно), Картицом (тачан износ) — сегментована контрола, изабрани „улегнут" (`.toggle-on`); брзи „Картицом" се скрива кад је унос картице онемогућен. (2) **Режим ОБУКЕ = глобални toggle** у `sale-tools` који стоји ТРАЈНО „улегнуто" (`.obuka-on`, памти се `localStorage fp_obuka`); док је укључен: наранџасти банер „ОБУКА — НИЈЕ ФИСКАЛНИ РАЧУН", „ИЗДАЈ ОБУКУ", сваки рачун `invoiceType=3`; заменио per-рачун checkbox. (3) **„ИД купца" посебно дугме** у наплати — toggle који отвара поља тип+број и стоји „улегнуто" кад је активно. `public/app.js`/`style.css`/`i18n.js` (СРБ/SRB/ENG/GRE). | Claude | `d3731c5` | **293/293** (frontend — визуелно потврђено на проби: банер+улегнут Обука, модал Кеш/Мешовито/ИД купца) |
| 2026-07-22 | **Претрага рачуна по ИД купца (buyerID)** — Админ → Рачуни: поље „ИД купца" у алатници + колона „ИД купца" у табели. Бекенд `/racuni?kupac=` је већ постојао (претрага кроз СВЕ датуме, LIKE предфилтер + прецизно по `buyerId` из `poslato`); недостајао само UI. Унос ИД-а искључује датумски филтер, промена датума поништава претрагу. i18n СРБ/SRB/ENG/GRE. | Claude | `4f8931b` | **293/293** (`api-fiskalno`: `/racuni?kupac=` налази рачун по buyerID, + негативан случај) |

## Changelog ovog dokumenta

| Datum | Izmene |
|-------|--------|
| 2026-07-06 | Inicijalna verzija — Faze A–D, matrica prioriteta, KPI |
| 2026-07-06 | Faza E — Grčka / turizam; Faza F — maloprodaja i konkurencija |
| 2026-07-06 | DigiPOS = novi ESIR na odobrenju PU; KasaB ostaje poseban proizvod |

---

*Za implementaciju pojedinačne stavke otvoriti issue/task sa ID-om (npr. `A2-split-racuna`) i linkom na ovu specifikaciju.*
