HR firma ne može poslati račun — lanac kvarova u kontnom planu (MC #900023 / #107364 / #107372)
HR firma ne može poslati račun — lanac kvarova u kontnom planu (MC #900023 / #107364 / #107372)
Status: U RADU · Otkriveno: 2026-08-20, odmah nakon aktivacije HR eRačuna (MC #103443)
Mjereno protiv: azdo/main @ d068e36d i produkcijske baze bilko-demo-pg
Aktivacija HR eRačuna je završena i dokazana istog dana, ali prvi račun se ne može poslati. Blokada nije u eRačunu nego jedan sloj niže — u kontnom planu.
1. Simptom
Draft računa se napravi. Slanje puca s HTTP 400. Slanje je tačno ono što okida eRačun, pa cijela aktivacija stoji iza vrata koja se ne otvaraju.
InvoiceService.kt:1982-1986:
val receivableAccount = resolveAccount(orgUuid, ACCOUNT_TYPE_ASSET, "1200", "12%")
?: throw BadRequestException("Required accounts not found (Receivable, Revenue)")
val revenueAccount = resolveAccount(orgUuid, ACCOUNT_TYPE_REVENUE, "6000", "6%")
?: throw BadRequestException("Required accounts not found (Receivable, Revenue)")
2. Dva ukoštena kvara
Kvar 1 — org uopšte nema kontni plan (#107364)
Izmjereno u produkcijskoj bazi: org Smart Forge (65376c57-…) ima nula redova u accounts.
Živi Entra JIT put (provision_user_with_org, V148) upisuje organizations + users + entra_external_identities ali nikad accounts. seedChartOfAccounts() (CountryService.kt:214) ima nula pozivalaca u živom kodu. AuthService.register() je mrtav (410 Gone).
CI ovo ne hvata jer svi testovi ručno rade Accounts.insert kao fixture — dakle testira se mehanizam, ne rezultat.
Kvar 2 — motor traži tuđe šifre (#900023)
resolveAccount() pokušava tačnu šifru, pa prefiks. Trećeg pokušaja nema.
Za HR promašuju tačno dva od šest poziva:
| poziv | traži | HR (CountryService) |
|
|---|---|---|---|
InvoiceService:1985 prihod |
6000 / 6% |
7500 | ✗ |
ExpenseService:659 trošak |
5000 / 5% |
4000/4100 | ✗ |
InvoiceService:1982/2035 potraživanja |
1200 / 12% |
1200 | ✓ |
InvoiceService:2032, ExpenseService:721 banka |
1000 / 10% |
1000 | ✓ |
ExpenseService:662/718 obveze |
2200 / 22% |
2200 | ✓ |
6000 je srpski/bosanski kontni plan. U hrvatskom RRiF-u razred 7 su prihodi — 75xx je ispravno. Motor je hardkodiran na tuđu jurisdikciju.
3. Nalaz koji mijenja popravku — tri nekompatibilna HR plana
U istoj bazi koda postoje tri HR kontna plana i međusobno se poriču:
| izvor | prihod | trošak | obveze | konta |
|---|---|---|---|---|
CountryService.kt CROATIAN_CHART_OF_ACCOUNTS |
7500 | 4000/4100 | 2200 | 9 |
PluginHR.kt:272 getChartOfAccountsDefaults() |
4000 | 5000/5100 | 2000 | 12 |
packages/core (TS) |
— | — | — | 41 |
V97__hr_rrif_chart_of_accounts.sql |
— | — | — | 90, hardkodirano na jedan demo UUID |
Posljedica: koji god plan se seeda, nešto pukne — samo drugo.
CountryServiceplan → prihod i trošak padaju, obveze prolazePluginHRplan → prihod i obveze padaju, trošak prolazi
Zato fallback po tipu konta nije kozmetika nego nosivi dio popravke.
Otvoreno pitanje pod provjerom: PluginHR koristi AccountType.INCOME, a InvoiceService traži ACCOUNT_TYPE_REVENUE. Ako se ne mapiraju na isti account_type_id, fallback po tipu neće raditi ni kad je plan ispravno seedovan. Moguće da je to pravi korijen.
4. Arhitektonska ograda
BUILD-BLUEPRINT.md linija 447, doslovno:
Country plugins — Tax logic and chart-of-accounts defaults belong in
packages/domain-*, not in API service code.
Prvi dispatch je pogrešno tražio popravku u CountryService.kt. Ispravljeno: izvor istine za kontni plan mora biti country plugin (packages/domain-hr), ne API servis.
5. Šta se radi
A. Treći fallback po TIPU konta u oba resolveAccount (InvoiceService.kt:1907, ExpenseService.kt:57) — kad ni tačna šifra ni prefiks ne pogode, uzeti najnižu šifru tog tipa za taj org.
B. Jedinstven izvor istine za HR kontni plan — odabrati koji je od tri ispravan po RRiF-u, ugasiti ostale, dati mu živog pozivaoca na JIT provisioning putu. Ne dodavati četvrti.
Izričito zabranjeno
Ubaciti konto 6000 u hrvatski plan da bi prošlo. Radilo bi danas, a knjige bi nosile pogrešnu šifru. Hrvatski prihod je 75xx i tako ostaje.
Testirati u oba smjera
- HR org s planom mora poslati račun i proknjižiti DR
1200/ CR75xx - RS/BA org mora i dalje razrješavati na
6000/5000tačno kao prije — fallback se okida samo kad prva dva pokušaja vratenull - Nov org kroz JIT provisioning mora dobiti kontni plan svoje zemlje
Verifikacija
Ishodom, ne zelenim buildom: stvaran račun kroz app.bilko.cloud iz HR orga do statusa SENT + red u transactions.
6. Kontekst
SMART FORGE d.o.o., OIB HR09582110234, org 65376c57-…, vlasnik [email protected]. Trenutno 0 računa / 0 kontakata / 0 konta.
Nema propuštenog roka: zakonska obaveza od 01.01.2026. je mogućnost primanja eRačuna, što je aktivirano i dokazano. Slanje se aktivira tek kad postoji račun za izdati.
Aktivacija eRačuna: MC #103443 · Evidence: ~/system/evidence/103443/
No comments to display
No comments to display