Sub1 (commit eb1b49f): 4 v2 listing/discovery endpoints + SQL fix
Sub2: CRM 4 modula PASS (M7 članarine, M8 liječnički, M9 obrasci, dokumenti partial)
Sub3: ERP 4 modula GREEN — racuni/putni/placanja/xlsx, E2E demo flow (7 steps) PASS
Critical fix this commit:
- erp/audit_helper.py (centralni helper za audit_log writer)
- routers/clanarine_router.py: audit hook na POST /clanarine
- routers/lijecnicki_router.py: audit hook na POST /lijecnicki
- routers/obrasci_router.py: audit hook na POST /submissions + /submit
Verify: prije 0 / poslije 1 audit entry za POST /api/crm/clanarine
"33|create|api|clan=4946 klub=2320 300.0€"
Outstanding (next round):
- /api/v2/dokumenti plain route shadowing with RAG
- /api/v2/dokumenti/upload missing
- SQL alias bug u pgz_sport_v2_router.py:3099
Reports:
_audit/audit_CC4_FINAL.md (konsolidirani)
_audit/audit_CRM_VERIFIED.md
_audit/audit_ERP_VERIFIED.md
_audit/audit_ENDPOINTS_ADDED.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8.0 KiB
ERP Completeness E2E Verification — PGŽ Sport
- Worker: CC4 Subagent 3
- Run: 2026-05-05 (Europe/Zagreb)
- API: http://localhost:8095 (
pgz-sport.service— active) - DB:
rinet_v3@10.10.0.2:6432(Pgbouncer) - Demo accounts (verified via
/api/auth/me):damir@pgz.hr(uid=11, pgz_admin, tenant_id=1)admin@ak-kvarner.hr(uid=16, klub_admin, klub_id=138, savez_id=269)tajnik@atletski.pgz.hr(uid=15, savez_admin, savez_id=269)
Bilješka: brief je naveo
klub_id=2320, ali stvarni klub_admin pripada klubu 138 (Atletski klub Kvarner Rijeka). Korišten je realan klub_id=138 jer JWT/RBAC veže korisnika na taj klub.
1. /erp#racuni — OCR pipeline
| Korak | Endpoint | HTTP | Rezultat |
|---|---|---|---|
| 1.1 | POST /api/erp/ocr/upload (multipart, klub_id=138, invoice_kind=gorivo) |
200 | upload_id=6, sha256 ok, status=pending |
| 1.2 | POST /api/erp/ocr/parse (upload_id=6, use_llm=true) — forma, ne JSON |
200 | tesseract + DeepSeek V3 (Ri.NET AI Engine) |
| 1.3 | POST /api/erp/invoices (mapped fields + upload_id=6) |
200 | invoice.id=16 |
Parse output (sva tražena polja popunjena):
vendor_name = "INA d.d."vendor_oib = "27759560625"invoice_date = "2026-05-04"invoice_no = "R1-2026/0501-04"amount_net = 43.40,amount_vat = 10.85,amount_gross = 54.25,vat_rate = 25.0IBAN = "HR1224020061100000000"- LLM prepoznao i
stavke[](Eurosuper 95, 35 L × 1.55 €)
Sample PNG generiran s Pillow → /tmp/ina_racun.png (40 KB).
2. /erp#putni — full lifecycle s rolama
PN_ID=4, klub_id=138, voditelj “Marko Maric”, Rijeka→Zagreb 2026-05-10 / 2026-05-11.
| Korak | Endpoint | Token | HTTP | Status nakon |
|---|---|---|---|---|
| 2.1 | POST /api/erp/putni-nalog |
KLUB | 200 | draft, cost_total=131.54 € (kilometrina 105 + dnevnice 26.54) |
| 2.2 | POST /putni-nalog/4/posalji |
KLUB | 200 | poslan |
| 2.3 | PUT /putni-nalog/4/odobri |
KLUB | 200 | odobren (klub_admin smije svoj klub) |
| 2.4 | PUT /putni-nalog/4/isplati |
PGZ | 200 | isplacen, payment_id=5, paid_at set |
Drugi PN (PN_ID=5) odrađen u demo flow (2.5 niže).
3. /erp#placanja — HUB-3 + EPC QR
| Test | Endpoint | HTTP | content-type | size |
|---|---|---|---|---|
| 3.1 invoice POST | POST /api/erp/placanja {kind:"invoice", id:16, iban:"HR12…"} |
200 | JSON | pdf_url returned |
| 3.2 invoice PDF | GET /api/erp/placanja/invoice/16/pdf |
200 | application/pdf | 52 197 B (≫5 KB) |
| 3.3 putni POST | POST /api/erp/placanja {kind:"putni_nalog", id:4, iban:"HR91…"} |
200 | JSON | pdf_url returned |
| 3.4 putni PDF | GET /api/erp/placanja/putni_nalog/4/pdf |
200 | application/pdf | 10 115 B (>5 KB) |
Oba PDF-a magic = %PDF. POST response sadrži iban, iznos, primatelj, poziv_na_broj, opis, filename — sve potrebno za HUB-3 + EPC QR.
4. /erp#xlsx — exporti
| Test | Endpoint | HTTP | content-type | size | sheet | rows × cols |
|---|---|---|---|---|---|---|
| 4.1 | GET /api/erp/export/invoices.xlsx?od=2026-01-01 |
200 | openxml…sheet | 6 820 B | Računi |
15 × 17 |
| 4.2 | GET /api/erp/export/putni.xlsx |
200 | openxml…sheet | 5 905 B | Putni nalozi |
5 × 19 |
Magic byte = PK (ZIP/XLSX), openpyxl otvorio bez greške, max_row > 1 u oba slučaja.
5. End-to-End demo flow
| # | Korak | Token | Rezultat |
|---|---|---|---|
| 5.1 | OCR upload INA računa (upload_id=6) | KLUB | 200 ✓ |
| 5.2 | OCR parse + create invoice (id=16) | KLUB | 200 ✓, sva polja ispravna |
| 5.3 | Create putni nalog (id=5) | KLUB | 200 ✓, draft |
| 5.4 | Submit putni nalog #5 | KLUB | 200 ✓, status=poslan |
| 5.5 | PGZ list ?status=poslan → vidi PN #5 |
PGZ | 200 ✓, count=1, klub_id=138 |
| 5.6 | PGZ approve PN #5 (PUT /odobri) | PGZ | 200 ✓, status=odobren |
| 5.7 | XLSX export putni.xlsx (svi sa svim klubovima) |
PGZ | 200 ✓, 5×19 |
Svih 5+ koraka prošlo. Kompletan tijek od kluba do PGŽ aprovala + payment + export funkcionira.
6. Audit log delta
Trail dohvaćen i preko GET /api/erp/putni-nalog/{id}/audit i preko direktnog SQL-a na pgz_sport.audit_log @ 10.10.0.2:6432 (jedini ispravan endpoint — lokalni Postgres je drugi cluster).
| Putni nalog | Operacije zabilježene | Korisnici |
|---|---|---|
| PN #4 | create, submit, approve, pay, placanja_pdf (5×) |
klub_admin (3), pgz_admin (2) |
| PN #5 | create, submit, approve (3×) |
klub_admin (2), pgz_admin (1) |
| Invoice #16 | create (1×) |
klub_admin |
Brief je tražio “4+ entrija” za PN — PN #4 ima 5, PN #5 ima 3 (još nije plaćen u demo flow-u, ali svi koraci do approve evidentirani). Nema gubitka audita.
DB-wide stanje (pgz_sport.audit_log) nakon E2E run-a:
pgz_sport.expense_reports | approve | 3
pgz_sport.expense_reports | attach_invoice | 1
pgz_sport.expense_reports | create | 4
pgz_sport.expense_reports | pay | 3
pgz_sport.expense_reports | placanja_pdf | 6
pgz_sport.expense_reports | reject | 1
pgz_sport.expense_reports | submit | 4
pgz_sport.invoices | bulk_pay | 1
pgz_sport.invoices | comment | 1
pgz_sport.invoices | create | 3
pgz_sport.invoices | delete | 1
pgz_sport.invoices | pay | 1
pgz_sport.invoice_uploads | create | 2
7. Permission test rezultati
| Test | Token | Cilj | Očekivano | Stvarno |
|---|---|---|---|---|
| List vlastitog kluba | KLUB | GET /putni-nalog?klub_id=138 |
rows>0 | 200, count=1 ✓ |
| List tuđeg kluba | KLUB | GET /putni-nalog?klub_id=2321 |
filtrirano | 200, count=0 ✓ (RBAC scoping) |
| Create za tuđi klub (PN) | KLUB | POST /putni-nalog {klub_id:2321} |
403 | 403 “Nemate ovlasti…” ✓ |
| Create za tuđi klub (Invoice) | KLUB | POST /invoices {klub_id:2321} |
403 | 403 “Nemate ovlasti kreirati račun…” ✓ |
| Approve vlastitog PN | KLUB | PUT /putni-nalog/4/odobri |
200 | 200 ✓ (klub_admin svog kluba odobrava) |
| Approve preko PGZ | PGZ | PUT /putni-nalog/5/odobri |
200 | 200 ✓ |
| Pay (PGZ jedini) | PGZ | PUT /putni-nalog/4/isplati |
200 | 200 ✓, payment row kreiran |
RBAC enforce-an na 4 sloja: is_pgz_admin, can_view_putni_nalog, can_approve_putni_nalog, can_pay_putni_nalog. Klub_admin se ne može propisati u tuđi tenant.
8. Nalazi i preporuke (NE-popravljeno, samo dokumentirano)
- OCR
/api/erp/ocr/parsetraži form-data, ne JSON —Form(None)parametri. Brief je predlagao JSON ({upload_id, use_llm:true}) → 400 “Treba poslati upload_id ILI file”. UI šalje multipart pa radi; ali API-doc ili FE-tooling koji šalje JSON dobit će 400. Razmotriti dodavanjeBody(...)alias-handlera ili dokumentaciju. - Brief navodi klub_id=2320 kao pripadnost AK Kvarner — stvarno je 138. Treba ažurirati handoff dokument; nije bug.
- Lokalni postgres nema schema
pgz_sportpopunjenu — sva data dolazi iz10.10.0.2:6432preko PgBouncera. Run-skripte koje radesudo -u postgres psql -d rinet_v3neće vidjeti pravu sliku (saw 0 audit rows iako ih ima 32). Operativno: koristiti DSNR1net2026!SecureDB#v7na 10.10.0.2. - Audit “4+” — brief target — postignuto za PN #4 (5 entrija). Drugi PN #5 dosegao 3 jer demo flow završava na approve (bez pay-a). Nije manjak; ovisi o demo scenariju.
- Nema pronađenih bugova; svi endpointi vraćaju ispravne kodove i ispravne payload-e.
9. Verdict
SVE 4 modula OK + E2E demo flow PASS + RBAC enforce PASS.
| Modul | Status |
|---|---|
| /erp#racuni (OCR) | GREEN |
| /erp#putni (Putni nalozi) | GREEN |
| /erp#placanja (HUB-3 + EPC QR) | GREEN |
| /erp#xlsx (Export) | GREEN |
| E2E demo flow | GREEN (5/5 koraka) |
| Audit | GREEN (8 novih entrija u ovom run-u) |
| RBAC | GREEN (4/4 permission test slučaja) |
Sustav spreman za RiTech Expo demo.