Files
pgz-sport/_audit/audit_CRM_VERIFIED.md
T
CC4 3e5b98a935 CC4: 3-subagent backend hardening done + CRM audit_log fix
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>
2026-05-05 08:28:49 +02:00

9.7 KiB
Raw Blame History

CRM Completeness Verification — CC4 Subagent 2

Date: 2026-05-05 Workspace: /opt/pgz-sport/ API: http://localhost:8095 (systemd: pgz-sport.service) Auth: damir@pgz.hr / PGZ2026! (role pgz_admin, tenant pgz) DB: rinet_v3 schema pgz_sport (10.10.0.2:6432) Tested klub: 2320 (RK Viškovo — Viškovo, demo data created); spot-checks on klub_id=10 (Rukometni klub ZAMET, 58 členova)


1. Per-modul matrica

M7 Članarine — routers/clanarine_router.py

Endpoint HTTP Komentar
GET /api/crm/clanarine 200 42 redova, summary OK (total_dug=2970)
GET /api/crm/clanarine?klub_id=10 200 filter radi
POST /api/crm/clanarine 200 id=288 vraćen, DB potvrđuje INSERT
PUT /api/crm/clanarine/288 200 iznos_propisan 300→350 + napomena updated
GET /api/crm/clanarine/288/uplatnica.pdf 200 application/pdf, magic %PDF-1.3 ✓ HUB-3 OK
GET /api/crm/clanarine/288/qr.png 200 image/png (EPC QR) ✓
POST /api/crm/clanarine/bulk/uplatnice.zip (klub=2320) 200 application/zip 15303 B, magic PK\x03\x04
POST .../bulk/uplatnice.zip only_open=true 200 filtrira nepodmireno OK
GET /api/crm/clanarine/dug?klub_id=2320 200 2 dužnika, total_dug=600

Verdikt M7: PASS (CRUD + HUB-3 PDF + QR + ZIP bulk uplatnice — sve radi)

M8 Liječnički — routers/lijecnicki_router.py

Endpoint HTTP Komentar
GET /api/crm/lijecnicki?klub_id=10 200 6 redova
POST /api/crm/lijecnicki 200 id=139
PUT /api/crm/lijecnicki/139 200 OK
GET /api/crm/zzjz/info 200 ZZJZ PGŽ kontakt info
GET /api/crm/zzjz/termini 200 65 termina, 42 dostupnih (mock raspored)
GET /api/crm/lijecnicki/uskoro-isticu?klub_id=2320 200 2 redova (1 istekao + 1 uskoro), dana_do_isteka izračunan

Verdikt M8: PASS (CRUD + ZZJZ schedule + uskoro-isticu prikaz)

M9 Obrasci — routers/obrasci_router.py

Endpoint HTTP Komentar
GET /api/crm/forms/templates 200 15 templatea, 11 kategorija
GET /api/crm/forms 200 identično (alias)
GET /api/crm/forms/uplata_clanarine 200 schema_json s 10 polja
POST /api/crm/forms/submissions 200 id=3, reference_no=UPLATA_C-2026-3C9D035B
POST /api/crm/forms/submissions/3/submit 200 signature_sha256 generiran, status=submitted
GET /api/crm/forms/submissions/3/pdf 200 application/pdf 45129 B, %PDF-1.3

Verdikt M9: PASS (templates + submission CRUD + signed submit + PDF render)

Dokumenti — pgz_sport_v2_router.py (M3 / module CC1)

Endpoint HTTP Komentar
GET /api/v2/dokumenti/list?limit=3 200 3 dokumenta (Erasmus+, Hrvatska SP, …)
GET /api/v2/dokumenti/by-razina 200 88 grupa po razini/vrsti
GET /api/v2/dokumenti?limit=3 200 BUG: vraća RAG/chat odgovor umjesto liste — vidi grešku #1
GET /api/v2/dokumenti/{id}/pdf N/A nije testirano (gornji bug onemogućuje preuzimanje id-a iz liste; /list radi pa se može testirati ručno)
Upload dokumenta N/A NEMA upload endpointa za dokumente unutar CRM-a — vidi grešku #2

Verdikt Dokumenti: PARTIAL (/list i /by-razina rade; bazni /api/v2/dokumenti rute su zasjenjene — bug)


2. Audit log delta

Period mjerenja: 25 min (od 2026-05-05 08:00 CEST do 08:24 CEST). Ukupno 15 novih audit entryja.

tablica operacija broj
pgz_sport.expense_reports placanja_pdf 6
pgz_sport.expense_reports create / submit / approve / pay 4
pgz_sport.invoices create / delete 3
pgz_sport.invoice_uploads create 2

Bug #3 (kritičan): CRM moduli (M7 clanarine, M8 lijecnicki, M9 obrasci) NE pišu u pgz_sport.audit_log na CRUD operacijama, iako sam za vrijeme testa kreirao 1× clanarinu (id=288), updateao je, kreirao 1× lijecnicki pregled (id=139), updateao ga, kreirao 1× form submission (id=3), submitao ga + insertao 5 demo clanarina + 3 demo pregleda direktno u DB. Niti jedna od tih operacija nije zabilježena. Audit pokriva samo ERP module (expense_reports, invoices, invoice_uploads).


3. Demo dataset summary

Klub 2320 (RK Viškovo) je imao 0 članova prije audita. Insertano:

entitet broj detalji
clanovi (demo) 5 id 49464950, ime Demo1Demo5, oib 11…111855…5550
clanarine paid (status=podmireno) 3 godina 2026, iznos 300, datum_uplate jan/feb/mar 2026
clanarine unpaid (status=nepodmireno) 2 godina 2026, iznos 300, dug 300 svaki — total dug klub 2320 = 600 EUR
lijecnicki expired (vrijedi_do < danas) 1 clan 4946, vrijedi_do = -30 dana
lijecnicki due (vrijedi_do < +30d) 1 clan 4947, vrijedi_do = +15 dana
lijecnicki ok (vrijedi_do > +90d) 1 clan 4948, vrijedi_do = +180 dana

Sve napomene markirane s CC4 sub2% za laku identifikaciju i kasniji cleanup.

Demo članovi i podaci za klub_id=10 (RK Zamet) su već postojali iz prethodnih sprintova (42 clanarine + 6 pregleda) — nije ih trebalo kreirati.


4. Lista grešaka koje sam NAŠAO ali NISAM POPRAVIO

Popravljanje je posao Sub1 — Sub2 samo prijavljuje.

Bug #1: GET /api/v2/dokumenti vraća chat/RAG odgovor umjesto liste dokumenata

  • Endpoint: http://localhost:8095/api/v2/dokumenti?limit=3
  • Očekivano: JSON niz/objekt s redovima iz pgz_sport.dokumenti
  • Aktualno: vraća 200 sa {"answer": "Podaci iz baze ne sadrže informacije o broju putova kada je NK Rijeka osvojila prvenstvo.", "confidence": 0.82, "source_type": "rag", …} — zbog conflicta s nekim catch-all/middleware koji sve neporučene rute proxy-a u DABI/RAG agent
  • Fix hint: u pgz_sport_v2_router.py postoji @router.get("/dokumenti") (line 1601) i @router.get("/dokumenti/list") (line 2222). /list radi, plain /dokumenti ne. Vjerojatno je middleware (vjerojatno orchestrator/DABI middleware u pgz_sport_api.py) hvata path prije dolaska u FastAPI route resolution. Treba provjeriti redoslijed app.middleware/app.add_middleware poziva.

Bug #2: Nema upload endpointa za "dokumenti" CRM tab

  • Brief navodi tab "dokumenti" — POST /api/crm/dokumenti* upload — koji NE postoji.
  • clan_panel_router.py ima POST /api/crm/clanovi/{cid}/avatar, ali to je avatar člana, ne generic dokument upload.
  • pgz_sport.zsp_dokumenti postoji u DB-u, ali nema CRUD endpointa.
  • Fix hint: trebao bi novi dokumenti_router.py ili dodati u clan_panel_router.py POST /api/crm/dokumenti (multipart upload + INSERT u dokumenti).

Bug #3 (kritičan): CRM CRUD ne piše audit log

  • M7/M8/M9 routeri ne pozivaju INSERT INTO pgz_sport.audit_log na CREATE/UPDATE/DELETE.
  • audit_log ima propisan schema (tablica, operacija, record_id, korisnik, promijenjeno_polje, stara_vrijednost, nova_vrijednost) i koristi se u ERP modulima — paritet treba postići i u CRM-u.
  • Fix hint: u svakom od clanarine_router.py, lijecnicki_router.py, obrasci_router.py u POST/PUT/DELETE handlerima dodati helper poziv (npr. _audit_log(table, op, record_id, user, before, after) koji već vjerojatno postoji u shared util-u — treba pogledati kako ga koristi ERP).

Bug #4 (low): klub_oib/klub_iban u dug response su null za klub 2320

  • GET /api/crm/clanarine/dug?klub_id=2320 → ima klub_oib=null, klub_iban=null — RK Viškovo u tablici klubovi vjerojatno nema te podatke. Bulk uplatnice radi jer fallback IBAN; treba provjeriti je li uplatnica.pdf za 2320 sadrži placeholder IBAN (Bug #1 grade — feature/data quality).

Bug #5 (low, kozmetika): [CRM/M7] router fail: Path is not defined u early ERP nalozi

  • ERP putni nalozi imaju NameError: name 'Path' is not defined (vidi journal logs 08:00:08-08:00:09). Nije CRM, ali zaslužuje napomenu jer je u istom service procesu i može srušiti i CRM dependency-je.
  • Fix hint: dodati from fastapi import Path u erp/putni_nalozi.py.

Bug #6 (info, ne kritičan): pgz_sport_v2_router.py:3099 SQL syntax error u list_kategorizirani

  • Error: syntax error at or near "AS" u WHERE c.kategorija_hoo AS hoo_kategorija IS NOT NULL — alias se ne smije koristiti unutar WHERE klauzule.
  • Fix hint: zamjeniti s WHERE c.kategorija_hoo IS NOT NULL.

5. Smoke test rezime (5 live curl-a — Red Team rule)

1. POST /api/auth/login (damir@pgz.hr)              → 200 + JWT 519 chars
2. GET  /api/crm/clanarine                          → 200 + 42 redova
3. POST /api/crm/clanarine (klub=10, clan=99)        → 200 + id=288 + audit_log NIJE NAPISAN (Bug #3)
4. GET  /api/crm/clanarine/288/uplatnica.pdf        → 200 + %PDF-1.3 magic
5. POST /api/crm/clanarine/bulk/uplatnice.zip       → 200 + PK ZIP magic, 15303 B
6. POST /api/crm/forms/submissions/3/submit         → 200 + signature_sha256 generated
7. GET  /api/crm/forms/submissions/3/pdf            → 200 + %PDF magic + 45 KB

Final verdikt

Modul Status
M7 Članarine PASS — full CRUD + HUB-3 PDF + EPC QR + ZIP bulk
M8 Liječnički PASS — full CRUD + ZZJZ schedule + uskoro-isticu
M9 Obrasci PASS — templates + submissions + signed submit + PDF
Dokumenti ⚠️ PARTIAL/list + /by-razina rade; Bug #1 + Bug #2
Audit log za CRM MISSING — Bug #3 (kritičan)

Demo dataset: 5 demo članova + 5 clanarina + 3 lijecnicki pregleda za klub 2320 — spremno za RiTech expo demo.

Kod nije mijenjan (osim insertanja demo redova u DB). Sub1 dobiva Bug #1#6 listu za fix.