# DigiPOS — novi plan nadogradnje (jul 2026)

Ažurirani roadmap na osnovu stanja koda **6. jul 2026**. Detaljne specifikacije po fazama ostaju u [`UPGRADE.md`](UPGRADE.md); ovaj dokument je **operativni pregled**: šta je urađeno, šta je sledeće, kako prodavati.

**Status proizvoda:** self-hosted + SQLite nulta instalacija; DigiPOS **čeka odobrenje PU** kao novi proizvod; odobreni **KasaB** ostaje poseban; **5 kasa** na terenu (digiesir/DBF).

> **⚙️ 3 režima rada (PRAVILO):** (1) standalone · (2) ERP u cloudu — stalna konekcija (osim kad nema veze) · (3) ERP na zahtev. Sve funkcije rade u sva tri — [`REZIMI-RADA.md`](REZIMI-RADA.md).

---

## Sadržaj

1. [Rezime za 30 sekundi](#1-rezime-za-30-sekundi)
2. [Šta je urađeno (6. jul)](#2-šta-je-urađeno-6-jul)
3. [Šta još fali](#3-šta-još-fali)
4. [Maloprodaja vs konkurencija (ažurirano)](#4-maloprodaja-vs-konkurencija-ažurirano)
5. [Novi prioriteti — redosled rada](#5-novi-prioriteti--redosled-rada)
6. [Završeno: F2 + F3 MVP](#6-završeno-f2--f3-mvp)
7. [Prodajne poruke (jul 2026)](#7-prodajne-poruke-jul-2026)
8. [KPI — revidirani](#8-kpi--revidirani)
9. [Van opsega](#9-van-opsega)
10. [Dnevnik (nastavak)](#10-dnevnik-nastavak)

---

## 1. Rezime za 30 sekundi

| Oblast | Procena | Komentar |
|--------|---------|----------|
| **Retail upgrade (R-lista)** | ~**80%** | Smene, vaga, komandna konzola, PWA, DBF migracija, F2/F3 robno, F8 parkiranje/touch — gotovo |
| **#1 preostali retail gap** | **F6/F7 etikete + inventura** | Operativni robni UX za pekare/markete i lance |
| **#1 procesni gap** | **A1 ESIR** | Dokumentacija spremna; PU odobrenje blokira legalnu produkciju na novom UI |
| **Najjači fit danas** | **Migracija digiesir → DigiPOS** | Isti LPFR tok, iste komande, DBF uvoz 14k+ artikala |
| **Cloud put** | Pilot ✅ | SQLite lokalno + Go centrala na VPS; sync E2E potvrđen |

---

## 2. Šta je urađeno (6. jul)

### Maloprodaja / kasa

| ID | Stavka | Gde u kodu | Test |
|----|--------|------------|------|
| **F1 / B1** | Smene i zatvaranje blagajne | `pos_smene`, `/api/smena/*`, kartica Smena (`public/app.js`), admin tab Smene | `tests/smene.test.js` |
| **F4** | Težinski barkod (port digiesir) | `lib/barkod.js`, `tezinski_prefiks` u podešavanjima | `tests/tezinski.test.js` |
| **F8** | Komandna konzola kase | `komandaKase()` u `public/app.js` — `+SIFRA`, količine, rabati, `G/P/C/K`, `A-kopija` | E2E ručno |
| **F8** | Parkiraj račun + touch grid | `pos_parkirani_racuni`, `/api/parkirani/*`, dugmad Parkiraj/Parkirani, Touch/Kompakt režim | `tests/parkirani.test.js` |
| **F9** | Prvi start + režim po objektu | Setup bira standalone ili firmu po PIB-u + objekat; `objekti.vrsta` određuje restoran/prodavnicu | `tests/maloprodaja-mode.test.js` |
| **F2 / B2** | Lager MVP po objektu | `pos_stanje`, `lib/lager.js`, `/api/stanje/*`, admin tab Stanje, stanje na kasi opciono | `tests/stanje.test.js`, `tests/sqlite.test.js` |
| **F3** | Prijem robe, prenos robe, KEP MVP | `pos_robni_dokumenti`, `pos_robne_stavke`, `pos_kep`, `/api/robno/*`, admin tab Stanje | `tests/stanje.test.js`, `tests/sqlite.test.js` |
| **A4** | PWA | `manifest.json`, `sw.js`, HTTPS u serveru | offline shell |
| **P17** | Uvoz transakcije preko fajla (.json/.csv) — mobilni konobar; idempotentno (`transactionUid` → nema duplog računa) | dugme „Uvezi" u `public/app.js`, `/api/prodaja` + `pos_racuni.transaction_uid` | `tests/uvoz-transakcije.test.js` |
| **Avans** | Avansni tok (ESIR 9.1/9.2): AP → Avans-Refundacija → Promet-Prodaja, referentni lanac, reklama, `pos_avansi` | `/api/avans`, `/api/avansi`, `/api/avansi/:grupa/zatvori`, dugme „Avans" | `tests/avans.test.js` |
| **F6** | Štampa etiketa (ESC/POS termalni): naziv + cena + barkod (EAN13 nativno `GS k`, fallback Code128 šifre) | `lib/etiketa.js`, `/api/etikete`, `label_printer`, Admin → Artikli → 🏷 | `tests/etiketa.test.js` |
| **B4** | DPU — Lista dnevnog prometa (ugostiteljstvo), materijalna po danu: preneseno/nabavljeno/utrošeno/zaliha/promet piće-hrana iz prodaje + robnih dokumenata; štampa + CSV | `lib/dpu.js`, `/api/izvestaj/dpu`, Admin → DPU tab | `tests/dpu.test.js` |
| **F7** | Inventura mobilnim telefonom: popis (kamera `BarcodeDetector` + ručni unos), razlika vs stanje, proknjiženje = korekcija (parcijalno / pun popis → 0), manjak/višak | `pos_inventura*`, `/api/inventura/*`, Inventura view u `public/app.js` | `tests/inventura.test.js` |
| **A1 (dosije)** | ESIR dosije za PU: popunjen ЕСИР Упитник (7.4.2) + 12 primera računa (§17/§9) generisanih iz `receipt.js`; ODT za predaju | `docs/ESIR-DOSIJE-PU.md`, `scripts/esir-primeri.js` + `build-esir-dosije.js` (`lib/odt-builder.js`), `docs/DigiPOS-ESIR-dosije.odt` | `tests/esir-primeri.test.js` |
| **Cena po objektu** | Kasa vuče cenu **po objektu** (MySQL `magart`, SQLite `pos_cene`→`mpcena`), prikazuje samo cena>0; pretraga i po ceni; `param011`→`vodi_robno` (maloprodaja bez robno ne skida stanje, ugostiteljstvo uvek); primenjeno na kasu/meni/kiosk/etikete/DPU | `lib/db.js`, `routes/api.js` (`upitArtikli`/`cenePoObjektu`/`meniArtikli`), `lib/dpu.js`, `pos_cene` | `tests/cene-po-objektu.test.js` |
| **A2 Split računa** | Podela računa za sto: konobar bira stavke+količine na deo → poseban fiskalni račun (Promet-Prodaja), ostatak ostaje otvoren; kad se isprazni → naplaćena. Lager skida po naplaćenom (uz `vodi_robno`) | `routes/api.js` (`POST /porudzbine/:id/split`), `public/app.js` (modal „Podeli") | `tests/split.test.js` |
| **A3 Prilozi/modifikatori** | Napomena/modifikator po stavci (`pos_stavke.napomena` → kuhinjski tiket); katalog `pos_prilozi` (admin CRUD); plaćeni prilog ulazi u cenu linije (fiskalno korektno); različite napomene = odvojene linije | `lib/db.js`, `routes/api.js` (`/prilozi`, `/stavke/:id/prilog`), `public/app.js` (modal 🗨), `public/admin.js` (tab Prilozi) | `tests/prilozi.test.js` |
| **Muzički dinar (SOKOJ)** | Admin unosi iznos (`muzicki_dinar`); >0 → dodaje se kao stavka na svaki Promet-Prodaja račun (u `fiskalizuj`, lokalna kopija — ne dira lager) i uvećava total; 0 → ne iskazuje se. Klijent prikazuje i uključuje u plaćanje (naplata/split/brza) | `lib/db.js`, `routes/api.js` (`fiskalizuj`, bootstrap), `public/app.js`, `public/admin.js` | `tests/muzicki-dinar.test.js` |
| — | Prodavnica režim | barkod, korpa, `/api/prodaja`, loyalty, akcije | postojeći |

### Infrastruktura i migracija

| Stavka | Opis |
|--------|------|
| **SQLite režim** | `lib/sqlite.js` + `lib/config.js` — `digipos.db` bez MySQL instalacije |
| **Cloud centrala (Go)** | `/api/sync/*` na VPS, `pos_racuni_cloud`, artikli iz knjigovodstva |
| **DBF uvoz** | `lib/dbf.js`, Admin → Uvoz iz digiesir (artikli, kupci, radnici, loyalty, basicdata) |
| **ESIR dosije za PU** | korisničko + tehničko uputstvo, instalacija, upotreba |
| **Testovi** | 134 testa (`npm test`), uklj. SQLite ceo tok login→račun→smena |

### Ugostiteljstvo (bez promene prioriteta)

Stolovi, kuhinja, Wolt/Glovo, kiosk, QR meni, loyalty, centrala sync — **netaknuto u ugostiteljskom objektu**. Kada je aktivni objekat maloprodaja, kasa i API ne nude konobare, stolove, kuhinju ni kiosk.

**Vrste objekata (knjigovodstvo `objekti.vrsta`, `varchar(1)`, kodni spisak iz digi-angular):** samo tri vrste su prodajno mesto sa kasom i prikazuju se u izboru objekta (`jeKasaObjekat()` filtrira `/setup/objekti` i `/objekti`):

| Kod | Značenje | Kasa | Mode |
|-----|----------|------|------|
| **T** | Maloprodaja trgovina | ✅ | prodavnica |
| **U** | Ugostiteljski objekat | ✅ | restoran |
| **S** | Usluge (fizičkim licima → fiskalni račun) | ✅ | prodavnica |
| V | Magacin veletrgovine | ❌ | — |
| R | Magacin repromaterijala | ❌ | — |
| G | Magacin gotovih proizvoda | ❌ | — |

`vrstaZaUpis()` upisuje kanonske oznake (maloprodaja → **`T`**, ne više `M`); čitanje i dalje prihvata legacy `M` i pune nazive. Setup nudi samo maloprodaju i ugostiteljstvo; magacini (V/R/G) su default u knjigovodstvu i namerno se ne nude kao kasa.

---

## 3. Šta još fali

### Kritično (blokira prodaju ili legalnost)

| ID | Stavka | Segment | Effort |
|----|--------|---------|--------|
| **A1** | ESIR DigiPOS u registru PU (novi proizvod) | Svi | Proces PU |

### Visoko (konkurencija ima standardno)

| ID | Stavka | Napomena |
|----|--------|----------|
| ~~**A2**~~ | ~~Split računa~~ | ✅ urađeno (`/porudzbine/:id/split`) |
| ~~**A3**~~ | ~~Prilozi / modifikatori~~ | ✅ urađeno (napomena po stavci + katalog `pos_prilozi`) |
| **A5** | Turnkey `INSTALACIJA.md` | Novi klijenti bez digiesir |

### Srednje / odložiti

| ID | Stavka | Kada |
|----|--------|------|
| **F5** | Varijante (veličina/boja) | Eksplicitan butik klijent |
| **B3** | Kuhinja WebSocket | Posle A2/A3 |
| **C4** | Customer display | Posle F8 |
| **C5** | POS čitač kartica (ECR) — DigiPOS ↔ platni terminal (iznos ide na terminal, odgovor vraća status plaćanja) | Kada klijent traži |
| **C6** | IPS Pokaži — plaćanje očitavanjem QR koda (NBS IPS instant): kasa generiše IPS QR sa iznosom, kupac skenira m-bankingom, potvrda plaćanja | Kada klijent traži |
| **D** | Hrvatska fiskalizacija | Posle A1 u RS |

### Šta NE prodavati kao „nedostaje“

Barkod, brza kasa, akcije, loyalty, refundacija, 7 plaćanja, centrala sync, SEF, integracija `sifre`/`esir`, **smene**, **težinski barkod**, **PWA**, **digiesir komande**, **lager MVP / skidanje po prodaji**, **prijem robe / prenos / KEP MVP**.

---

## 4. Maloprodaja vs konkurencija (ažurirano)

Konkurenti: BKC SOFT, UniSoft, Sky SHOP, DCS Retail, POSitiv, Hubie.

| Funkcija | DigiPOS **danas** | BKC | UniSoft | Sky SHOP |
|----------|-------------------|-----|---------|----------|
| ESIR za **ovaj** UI | ⏳ PU proces | ✅ | ✅ | ✅ |
| Barkod / brza kasa | ✅ | ✅ | ✅ | ✅ |
| Akcije / loyalty | ✅ | ✅ | ✅ | ✅ |
| Ista baza kao knjigovodstvo | ✅ **`sifre`** | ❌ | ❌ | ❌ cloud |
| Centrala / više prodavnica | ✅ offline sync | ✅ | ✅ | ✅ |
| **Smene** | ✅ | ✅ | ✅ | ✅ |
| **Težinski barkod** | ✅ | ✅ | ✅ | ✅ |
| **Komandna konzola (digiesir)** | ✅ | ○ | ○ | ○ |
| PWA | ✅ | ○ | ○ | ✅ |
| DBF / digiesir migracija | ✅ | ❌ | ❌ | ❌ |
| Lager / prijem robe (UI) | ✅ MVP | ✅ | ✅ | ✅ |
| KEP automatski | ✅ MVP | ✅ | ✅ | ✅ |
| Etikete | ❌ | ✅ | ✅ | ✅ |
| Inventura skenerom | ❌ | ✅ | ✅ | ✅ |
| Bez mesečne pretplate | ✅ | ✅ | ✅ | ❌ |
| SQLite bez instalacije | ✅ | ❌ | ❌ | ❌ |

✅ ima · ❌ nema · ⏳ u toku · ○ delimično

**Zaključak:** Paritet sa BKC/UniSoft na **kasi, smenama i osnovnom robnom toku**; i dalje zaostajanje na UX detaljima robnog modula (štampa dokumenata, etikete, inventura skenerom).

---

## 5. Novi prioriteti — redosled rada

### Dva paralelna toka

```
PROCES (van koda)                    RAZVOJ
─────────────────                    ─────────────────────────────────────
A1 ESIR → PU podnošenje              F6 etikete  →  F7 inventura
     ↓                                        ↓
A5 Turnkey doc (paralelno)           štampa nalepnica, skener inventure
     ↓                                        ↓
                                     F6 Etikete  |  F7 Inventura
```

### Maloprodaja (prodavnice)

```
A1 (proces)  →  F6 etikete  →  F7 inventura
```

**F2 završeno:** stanje se vodi po `vlasnik + objekat_id + sifra`, tako da više kasa u istom maloprodajnom objektu dele isti lager. Normalan režim ne blokira prodaju ako je roba fizički na kasi; stanje može otići u minus i time pokazuje grešku u evidenciji. Stroga blokada postoji samo uz `lager_obavezan=1`.

### Ugostiteljstvo

```
A1 (proces)  →  A2 Split  →  A3 Prilozi  →  B3 KDS push
         A4 PWA ✅ već urađeno
```

### Grčka / turizam (Faza E)

Bez promene: `E2 pozovi konobara → E4 prevodi → E1 zone` — vidi [`UPGRADE.md` § Faza E](UPGRADE.md#faza-e--grčka-i-turizam-ideje).

---

## 6. Završeno: F2 + F3 MVP

**Cilj:** Posle prodaje artikla stanje se smanji; admin vidi stanje; kasa opciono prikazuje stanje.

### Baza

```sql
CREATE TABLE pos_stanje (
  id          INTEGER PRIMARY KEY AUTOINCREMENT,
  vlasnik     INTEGER NOT NULL,
  objekat_id  INTEGER NOT NULL,
  sifra       INTEGER NOT NULL,
  kolicina    DECIMAL(12,3) NOT NULL DEFAULT 0,
  minimum     DECIMAL(12,3) NOT NULL DEFAULT 0,
  updated_at  DATETIME,
  UNIQUE (vlasnik, objekat_id, sifra)
);
```

Portabilan SQL (SQLite + MySQL); bez `ON DUPLICATE` — upsert preko `INSERT IGNORE` + `UPDATE`.

### API

| Metoda | Ruta | Opis |
|--------|------|------|
| GET | `/api/stanje?objekat=&q=` | Pregled + pretraga |
| PUT | `/api/stanje/:sifra` | Ručna korekcija / postavljanje minimuma |
| POST | `/api/stanje/prijem-robe` | Ulaz robe (lista `{sifra, kolicina}`) — MVP pre punog F3 |

### Logika prodaje

- U `POST /api/prodaja`, `/api/porudzbine/:id/naplata` i `/api/dostave/:id/naplata`: posle uspešnog računa skida stanje.
- Stanje je na nivou objekta, ne kase: više kasa jednog objekta dele isti `pos_stanje`.
- Podešavanje `lager_obavezan` (0/1): stroga kontrola; ako nema na stanju → blok. Default je `0`, jer roba fizički može biti na kasi i tada minus lager pokazuje grešku u evidenciji.
- Podešavanje `lager_prikaz_kasa` (0/1): prikazuje trenutno stanje na kartici artikla i u korpi.

### Admin UI

- Novi tab **Stanje** — tabela, filter, minimum, upozorenja ispod minimuma
- Kasnije spojiti sa F3 prijemom robe u isti tab **Robno**

### Kriterijum gotovo (F2 MVP)

1. Prijem robe 100 kom → prodaja 10 → admin pokazuje 90
2. `lager_obavezan=1` → prodaja 91. kom odbijena
3. Radi u SQLite i MySQL režimu
4. Test u `tests/stanje.test.js`

**Status 2026-07-06:** završeno i testirano. Relevantni fajlovi: `lib/lager.js`, `routes/api.js`, `public/admin.js`, `public/app.js`, `tests/stanje.test.js`, `tests/sqlite.test.js`.

### Završeno: F3 Prijem robe + KEP MVP

- Prijem robe kao dokument, ne samo direktno povećanje stanja.
- Prenos robe između objekata.
- KEP ulaz/izlaz iz prometa i lagera.
- Pregled negativnog stanja i korekcije po objektu.

### F3 baza i API

| Tabela | Namena |
|--------|--------|
| `pos_robni_dokumenti` | glava robnog dokumenta: prijem, prenos, korekcija |
| `pos_robne_stavke` | stavke robnog dokumenta |
| `pos_kep` | KEP vrednosna evidencija po objektu |

| Metoda | Ruta | Opis |
|--------|------|------|
| POST | `/api/robno/prijem-robe` | prijem robe kao dokument + stanje + KEP ulaz |
| POST | `/api/robno/prenos` | prenos robe između objekata + KEP izlaz/ulaz |
| GET | `/api/robno/dokumenti` | lista robnih dokumenata |
| GET | `/api/robno/dokumenti/:id` | dokument sa stavkama |
| GET | `/api/robno/kep` | KEP knjiga za objekat i period |
| GET | `/api/stanje?negativno=1` | pregled negativnog stanja |

**Status 2026-07-06:** završeno i testirano. Prodaja upisuje KEP izlaz po računu, prijem robe upisuje KEP ulaz, prenos robe upisuje izlaz iz izvornog i ulaz u odredišni objekat.

### Završeno: F8 UX ostatak

- Parkiraj račun / vrati parkirani račun.
- Touch grid po kategorijama za nove korisnike koji ne rade preko tastature.
- `Touch/Kompakt` režim se pamti u browseru (`localStorage`).
- Parkirani računi se čuvaju serverski po vlasniku/objektu.

### F8 baza i API

| Tabela | Namena |
|--------|--------|
| `pos_parkirani_racuni` | privremeno odložene korpe za brzu prodaju |

| Metoda | Ruta | Opis |
|--------|------|------|
| GET | `/api/parkirani` | lista parkiranih računa |
| POST | `/api/parkirani` | parkira trenutnu korpu |
| POST | `/api/parkirani/:id/vrati` | vraća parkirani račun i uklanja ga iz liste |
| DELETE | `/api/parkirani/:id` | briše parkirani račun |

**Status 2026-07-06:** završeno i testirano u `tests/parkirani.test.js`.

### Sledeće: F6/F7

- F6 štampa etiketa iz šifarnika/lagera.
- F7 inventura skenerom i razlika inventure.

---

## 7. Prodajne poruke (jul 2026)

### Migracija digiesir (najjači argument)

> „Isti fiskalni tok, iste komande na tastaturi, isti težinski barkod — novi web ekran, PWA na telefonu, centrala u oblaku ako želite. Uvoz jednim klikom iz DBF.“

### Nova prodavnica (SQLite)

> „Bez MySQL instalacije — `node server.js` i kasa radi. Smene, vaga, barkod, loyalty, lager, prijem robe, prenos robe i KEP MVP.“

### Lanac sa knjigovodstvom

> „Nivelacije knjigovođe stižu na sve kase automatski; računi se skupljaju u centrali; prodaja radi bez interneta.“

### Šta NE obećavati

- Napredni robni modul: štampa dokumenata, etikete i inventura skenerom
- Registrovan ESIR broj za DigiPOS (još nije — zahtev PU u toku); KasaB ostaje odvojen
- Varijante artikala / butik ERP
- Hrvatska fiskalizacija

---

## 8. KPI — revidirani

| KPI | Cilj | Status jul 2026 |
|-----|------|-----------------|
| Podrška: „nema smena“ | 0 zahteva | ✅ dostignuto (F1) |
| Podrška: „nema vage“ | 0 zahteva | ✅ dostignuto (F4) |
| Podrška: „nema lagera/KEP“ | 0 zahteva | ✅ F2+F3 MVP gotovo |
| Podrška: „ne mogu da odložim račun“ | 0 zahteva | ✅ F8 parkiranje gotovo |
| Kasir: 10 barkod stavki | < 90 s | ✅ blizu (komandna konzola) |
| Migracija digiesir | < 1 dan | ✅ DBF uvoz |
| Nova instalacija (SQLite) | < 30 min do prvog računa | ✅ bez MySQL |
| ESIR DigiPOS u registru | A1 završen | ⏳ u toku |
| Novi retail klijent (lanac) | meriti posle F6/F7 | — |

---

## 9. Van opsega

- Potpuni ERP / SAP integracija (eRetail segment)
- Native iOS/Android app (PWA je dovoljan)
- Sopstveni payment procesor
- HR modul pre A1 u RS
- Varijante artikala bez eksplicitnog klijenta
- White-label / više tema

---

## 10. Dnevnik (nastavak)

Nastavlja se tabela iz [`UPGRADE.md` § Dnevnik realizacije](UPGRADE.md#dnevnik-realizacije-ko-je-šta-uradio).

| Datum | Stavka | Ko | Napomena |
|-------|--------|-----|----------|
| 2026-07-06 | `newupgrade.md` — ažurirani prioriteti posle F1/F4/F8/A4 | Claude | ovaj dokument; matrica maloprodaje ispravljena |
| 2026-07-06 | F2 Lager MVP | Codex | `pos_stanje` po objektu, skidanje posle prodaje, admin tab Stanje, stanje na kasi, testovi SQLite/MySQL tok |
| 2026-07-06 | F3 Robni MVP | Codex | prijem robe kao dokument, prenos između objekata, KEP ulaz/izlaz, negativno stanje, SQLite test prenosa |
| 2026-07-06 | F9 Prvi start + režim po objektu | Codex | setup ekran: standalone ili PIB firme → izbor objekta; `objekti.vrsta` sada upravlja režimom kase, maloprodaja gasi kiosk/stolove/kuhinju/konobara |
| 2026-07-06 | F8 parkiranje + touch grid | Codex | `pos_parkirani_racuni`, `/api/parkirani/*`, Parkiraj/Parkirani, Touch/Kompakt režim |

---

## Povezani dokumenti

| Dokument | Sadržaj |
|----------|---------|
| [`UPGRADE.md`](UPGRADE.md) | Puna specifikacija faza A–F, konkurencija, dnevnik |
| [`UPUTSTVO.md`](UPUTSTVO.md) | Korisničko uputstvo |
| [`README.md`](../README.md) | Tehnički pregled, arhitektura, PWA |
| [`UPUTSTVO-ZA-INSTALACIJU.md`](UPUTSTVO-ZA-INSTALACIJU.md) | Instalacija, SQLite, težinski prefiks |

---

*Sledeći razvojni task: `F6-etikete-mvp`, zatim `F7-inventura-skenerom`.*
