17 iteracija do savršenstva: Razvoj Odoo fiskalizacije uz Claude AI
Uvod
Kako izgleda razvoj softvera uz pomoć AI asistenta? Ova priča opisuje realnu razvojnu sesiju u kojoj smo implementirali novu funkcionalnost u našem Odoo modulu za bosanskohercegovačku fiskalizaciju - automatsku generaciju PDF-a nakon uspješne fiskalizacije računa.
Rezultat: 17 verzija, 2 sata rada, 9 izmijenjenih fajlova i mnoštvo naučenih lekcija.
Kompletan izvještaj sesije: GitHub Gist
Funkcionalnost u akciji

Animirani prikaz automatskog generisanja PDF-a odmah nakon uspješne fiskalizacije računa
Početni zahtjev
Zahtjev je postavio Jasko na našem Nextcloud Talk-u:
Znaš štaš’ napravit, kod fakturisanja čim završi EDI da i PDF sam izgeneriše
Ernad je to formulisao Claude-u kao sljedeći zahtjev:
Process Nowactivate fiscalization, after success we receive fiscal number. After that step print invoice to PDF.Option: This should be available as user option. When checked - generate PDF after fiscalization. Option name:
Generate PDF after fiscalizationdefault false
Razvojna avantura kroz verzije
Faza 1: Pogrešan pristup (verzije 16.0.2.6.5 → 16.0.2.6.6)
Prva implementacija je koristila EDI server endpoint za dobijanje PDF-a:
# POGREŠNO: Koristi EDI server PDF (samo za OFS driver)
if user_for_config.l10n_ba_edi_generate_pdf_after_fiscalization:
pdf_data = invoice._get_edi_pdf_from_server() # ❌
Problem: Korisnik je želio standardni Odoo PDF računa, a ne PDF sa EDI servera.
Faza 2: Prelazak na standardni PDF (verzije 16.0.2.6.7 → 16.0.2.6.10)
Pokušaj korištenja Odoo standardnog izvještaja:
# Pokušaj korištenja standardnog Odoo izvještaja
report = self.env.ref('account.account_invoices')
pdf_content, _ = report._render_qweb_pdf(invoice.ids) # ❌ Pogrešan potpis
Greška: 'list' object has no attribute 'split'
Uzrok: Metoda _render_qweb_pdf() očekuje report_ref kao prvi parametar, a mi smo proslijedili listu ID-eva kao pozicioni argument.
Faza 3: Problem duplikata (verzije 16.0.2.6.11 → 16.0.2.6.16)
Nakon ispravke potpisa metode, pojavio se novi problem - kreiranje duplikata PDF-a.
Pokušaji rješenja:
- Provjera postojećih PDF-a prije generisanja
- Korištenje
action_invoice_print()- vraća samo action dict, ne kreira attachment - Korištenje
report.report_action()- isti problem - Dodavanje detaljnog logovanja
# Provjera postojećih PDF-a
existing_pdf = self.env["ir.attachment"].search([
("res_model", "=", "account.move"),
("res_id", "=", invoice.id),
("mimetype", "=", "application/pdf"),
], limit=1)
Problem: I dalje duplikati!
Faza 4: Konsultacija sa GPT-5 (verzija 16.0.2.6.17)
Pitanje: Kako generisati PDF računa u Odoo 16 bez duplikata?
GPT-5 odgovor:
_render_qweb_pdf()NE kreira automatski attachmente- Automatsko kreiranje se dešava putem
_render_qweb_pdf_prepare_streams() - Potrebno manuelno kreiranje attachmenta
- Koristiti
datasfield sa base64 enkodingom umjestoraw
Preporučeno rješenje:
report = self.env.ref('account.account_invoices')
pdf_content, _ = report._render_qweb_pdf('account.account_invoices', res_ids=invoice.ids)
pdf_name = safe_eval(report.print_report_name, {'object': invoice, 'time': time})
attachment = self.env["ir.attachment"].create({
"name": pdf_name,
"type": "binary",
"datas": base64.b64encode(pdf_content),
"res_model": "account.move",
"res_id": invoice.id,
"mimetype": "application/pdf",
})
Faza 5: Konačno otkriće (verzije 16.0.2.6.18 → 16.0.2.6.22)
Kritična analiza logova:
2025-11-07 12:31:36,861 INFO The PDF documents 'INV_2025_00229.pdf' are now saved in the database
2025-11-07 12:31:36,862 INFO Invoice PDF created: INV_2025_00229.pdf, ID: 620
Otkrovenje:
_render_qweb_pdf()KREIRA automatski attachmente (suprotno GPT-5 tvrdnji)!- U Odoo 16, metoda poziva
_render_qweb_pdf_prepare_streams()koja kreira attachmente - Manuelno kreiranje je uzrokovalo duplikate!
Konačno rješenje:
# Provjeri da li korisnik želi generaciju PDF-a
if user_for_config.l10n_ba_edi_generate_pdf_after_fiscalization:
# 1. Provjeri da li PDF već postoji
existing_pdf = self.env["ir.attachment"].search([
("res_model", "=", "account.move"),
("res_id", "=", invoice.id),
("mimetype", "=", "application/pdf"),
], limit=1)
if not existing_pdf:
# 2. Pozovi _render_qweb_pdf (automatski kreira attachment)
report = self.env.ref('account.account_invoices')
report._render_qweb_pdf('account.account_invoices', res_ids=invoice.ids)
# 3. Verifikuj da je kreiran (samo za logging)
created_pdf = self.env["ir.attachment"].search([
("res_model", "=", "account.move"),
("res_id", "=", invoice.id),
("mimetype", "=", "application/pdf"),
], limit=1, order="id desc")
if created_pdf:
_logger.info(f"PDF auto-kreiran: {created_pdf.name}, ID: {created_pdf.id}")
Izmijenjeni fajlovi
Core implementacija
- account_edi_format.py - Glavna logika PDF generacije
- res_users.py - Polje za korisničku opciju
- res_config_settings.py - Integracija u Settings
Korisnički interfejs
- res_config_settings_views.xml - Settings checkbox
- user_fiscal_config_wizard.py - Wizard model
- user_fiscal_config_wizard_views.xml - Wizard UI
Verzije
- manifest.py - Verzija: 16.0.2.6.5 → 16.0.2.6.22
- pyproject.toml - Sinhronizovana verzija
Ključne lekcije
Tehničke spoznaje
-
Odoo Report Rendering:
_render_qweb_pdf(report_ref, res_ids=None, data=None)- Glavna metoda- Interno poziva
_render_qweb_pdf_prepare_streams()koja KREIRA attachmente - Automatsko kreiranje se dešava kada je report pravilno konfigurisan
-
Attachment kreiranje:
- U Odoo 16,
_render_qweb_pdf()automatski kreira attachmente - Manuelno kreiranje nakon renderinga uzrokuje duplikate
- Provjera postojećih attachmenata sprječava duplikate
- U Odoo 16,
-
User kontekst u EDI:
- EDI procesiranje često radi kao system user (
__system__) - Mora se izvući stvarni korisnik iz računa:
invoice.invoice_user_idiliinvoice.create_uid - Koristiti postavke korisnika sa računa, ne sistemskog korisnika
- EDI procesiranje često radi kao system user (
Istorija verzija
| Verzija | Promjena | Problem |
|---|---|---|
| 16.0.2.6.6 | Inicijalna implementacija sa EDI server PDF | Pogrešan pristup |
| 16.0.2.6.7 | Prelazak na standardni Odoo PDF | Greška u potpisu |
| 16.0.2.6.8-10 | Ispravka potpisa metode | I dalje greške |
| 16.0.2.6.11-16 | Različiti pristupi protiv duplikata | Duplikati i dalje |
| 16.0.2.6.17 | Konsultacija sa GPT-5 | Pogrešan savjet |
| 16.0.2.6.18-21 | Implementacija GPT-5 rješenja | Duplikati! |
| 16.0.2.6.22 | Uklanjanje manuelnog kreiranja | ✅ USPJEH! |
Statistika
- Ukupno verzija: 17 iteracija
- Izmijenjenih fajlova: 9
- Dodato linija: 86
- Uklonjeno linija: 3
- Utrošeno vrijeme: ~2 sata
- Glavni izazov: Razumijevanje Odoo automatskog kreiranja attachmenata
Test checklist
- ✅ Opcija se pojavljuje u Settings za admin korisnike
- ✅ Opcija se pojavljuje u User Fiscal Config Wizard za obične korisnike
- ✅ PDF se generiše kada je opcija uključena i račun fiskalizovan
- ✅ PDF se ne generiše kada je opcija isključena
- ✅ Nema duplikata PDF-a
- ✅ Detekcija postojećih PDF-a radi
- ✅ Fiskalizacija uspijeva čak i ako generisanje PDF-a ne uspije
- ✅ Radi sa oba FPrint i OFS drajverima
- ✅ Database polje pravilno čuva korisničke postavke
- ✅ PDF ima pravilan naziv iz report template-a
Zaključak
Nakon 17 iteracija i ispitivanja više pristupa, rješenje je bilo iznenadjujuće jednostavno: pustiti Odoo-ovu _render_qweb_pdf() metodu da obavi svoj posao automatski.
Glavni izazov je bio razumijevanje da u Odoo 16 ova metoda KREIRA attachmente automatski, suprotno nekoj dokumentaciji i čak i GPT-5 inicijalnom uputstvu.
Ključna spoznaja je došla iz pažljive analize logova koja je pokazala automatsko kreiranje attachmenta prije našeg pokušaja manuelnog kreiranja. Nakon što smo uklonili manuelno kreiranje i pustili Odoo da to uradi, sve je radilo savršeno.
Lekcija o razvoju sa AI
Ova priča ilustruje važan aspekt razvoja softvera uz pomoć AI asistenata:
- AI nije uvijek u pravu - Čak i GPT-5 može dati netačne informacije
- Analiza logova je ključna - Stvarna istina se nalazi u logu, ne u dokumentaciji
- Iterativni razvoj funkcioniše - 17 pokušaja nije neuspjeh, to je proces učenja
- Jednostavnost pobjeđuje - Najbolje rješenje je često najjednostavnije
Alati koje koristimo
Tokom razvoja ove funkcionalnosti koristili smo:
- Claude Code - AI asistent za razvoj (Sonnet 4.5)
- VS Code - Glavni razvojni editor
- Odoo 16 - ERP platforma
- Python 3 - Programski jezik
- PostgreSQL - Baza podataka
- Git - Verzioniranje koda
- FFmpeg - Kreiranje GIF-a za dokumentaciju
Status: ✅ Funkcionalnost implementirana, testirana i puštena u produkciju.
Claude sesije
Tokom razvoja ove funkcionalnosti, Claude Code nije samo pomogao u implementaciji koda, već i u pripremi dokumentacije.

Primjer Claude Code sesije - kreiranje animiranog GIF-a za dokumentaciju funkcionalnosti
Ovaj screenshot prikazuje kako smo koristili Claude Code da automatski kreira animirani GIF iz snimljenog MP4 video fajla koristeći FFmpeg. Claude je:
- Provjerio postojanje fajla
- Kreirao optimizovanu FFmpeg komandu
- Generisao GIF sa smanjenom rezolucijom (800px širina) i framerate-om (10fps)
- Koristio custom paletu za bolje boje
- Smanjio veličinu sa 1.7MB na 762KB
Širi kontekst: AI alati i bring.out
Ovaj blog post je dio veće priče o tome kako su AI alati transformisali naš način razvoja softvera.
👉 Pročitajte cijelu priču: Kako smo postali najveći proizvođači software-a na Odoo open-source platformi u Bosni i Hercegovini
U tom postu možete saznati:
- Kako smo otkrili AI alate preko slučajnog razgovora
- Zašto je terminal pravo mjesto za AI kolaboraciju
- Priču o “Džemu” - našem prvom AI agentu
- Kako smo završili projekat 15 dana prije roka
- Šta AI alati znače za našu poziciju na Odoo tržištu u BiH
Napomene
Ovaj sadržaj je napisao claude.ai 🤖 prema Ernadovim uputama.