fix: oprava prázdneho IČ DPH riadku na faktúrach SK firiem (v2.0.6)
Migrácia 2.0.5 skryla natívny VAT t-if blok pre SK krajinu, ale t-else zostal neopravený a renderoval prázdny "IČ DPH:" riadok. Migrácia 2.0.6 mení tento t-else na t-if="forced_vat and country != SK" vo všetkých 7 external_layout šablónach (rôzna indentácia: 28/32/40 medzier). Pridaný CLAUDE.md s dokumentáciou modulu. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,83 @@
|
|||||||
|
# l10n_sk_partner — Slovak Tax IDs for Odoo 19.0
|
||||||
|
|
||||||
|
## Účel modulu
|
||||||
|
|
||||||
|
Modul pridáva slovenské daňové identifikátory na kontakty a faktúry:
|
||||||
|
- **IČO** (`company_registry`) — 8 číslic, natívne pole Odoo, label prepísaný na "IČO" pre SK krajinu
|
||||||
|
- **DIČ** (`dic`) — vlastné pole, 10 číslic
|
||||||
|
- **IČ DPH** (`vat`) — štandardné Odoo pole, validácia formátu `SK` + 10 číslic
|
||||||
|
|
||||||
|
## Štruktúra
|
||||||
|
|
||||||
|
```
|
||||||
|
l10n_sk_partner/
|
||||||
|
├── models/
|
||||||
|
│ ├── res_partner.py # Pole dic, is_vat_payer, validácie, label IČO
|
||||||
|
│ └── res_company.py # Sync dic → income_tax_id pri uložení firmy
|
||||||
|
├── views/
|
||||||
|
│ └── res_partner_views.xml # Pole dic a is_vat_payer na formulári partnera
|
||||||
|
├── report/
|
||||||
|
│ └── report_layout_sk.xml # Prázdny, opravy sa robia cez migration scripty
|
||||||
|
├── migrations/
|
||||||
|
│ ├── 19.0.2.0.4/post-migrate.py # Oprava šablón faktúr (IČO/DIČ pre odberateľa)
|
||||||
|
│ ├── 19.0.2.0.5/post-migrate.py # Skrytie natívneho VAT t-if bloku v external_layout pre SK
|
||||||
|
│ └── 19.0.2.0.6/post-migrate.py # Oprava VAT t-else bloku (zostatok po 2.0.5)
|
||||||
|
└── hooks.py # post_init_hook — oprava l10n_sk.vat_registry_tax_id_external_layout
|
||||||
|
```
|
||||||
|
|
||||||
|
## Kľúčové rozhodnutia
|
||||||
|
|
||||||
|
### Prečo migration scripty miesto XML pohľadov
|
||||||
|
|
||||||
|
Moduly `l10n_sk` a `web` definujú šablóny faktúr ako databázové záznamy (`ir.ui.view`). Štandardný `inherit_id` v XML spôsoboval problémy (duplicitné bloky, zlý rendering). Riešenie: priame prepísanie `arch_db` cez SQL v migration scriptoch.
|
||||||
|
|
||||||
|
- `hooks.py` → oprava `l10n_sk.vat_registry_tax_id_external_layout` (blok IČO/DIČ firmy)
|
||||||
|
- `migrations/19.0.2.0.4` → oprava `l10n_sk.report_invoice_document` (IČO/DIČ odberateľa)
|
||||||
|
- `migrations/19.0.2.0.5` → skrytie natívneho VAT `t-if` bloku v `web.external_layout_*` šablónach pre SK
|
||||||
|
- `migrations/19.0.2.0.6` → oprava VAT `t-else` bloku (2.0.5 opravila `t-if`, ale `t-else` zostal — renderoval prázdny "IČ DPH:" riadok)
|
||||||
|
|
||||||
|
### Podmienka zobrazovania
|
||||||
|
|
||||||
|
Všetky bloky IČO/DIČ sa zobrazujú len keď `company.account_fiscal_country_id.code == 'SK'` alebo `company_id.country_code == 'SK'`, takže modul neovplyvňuje zahraničné lokalizácie.
|
||||||
|
|
||||||
|
### Validácie
|
||||||
|
|
||||||
|
| Pole | Formát | Constraint |
|
||||||
|
|------|--------|------------|
|
||||||
|
| `company_registry` (IČO) | presne 8 číslic | `_check_ico` |
|
||||||
|
| `dic` (DIČ) | presne 10 číslic | `_check_dic` |
|
||||||
|
| `vat` (IČ DPH) | `SK` + 10 číslic | `_check_sk_vat` (len pre SK krajinu) |
|
||||||
|
|
||||||
|
### Automatické správanie
|
||||||
|
|
||||||
|
- `_onchange_vat_fill_dic` — pri zadaní IČ DPH automaticky vyplní DIČ (bez `SK` prefixu), ak je prázdne
|
||||||
|
- `is_vat_payer` — computed field, `True` ak `vat` začína `SK`
|
||||||
|
- `res_company.write()` — pri každom uložení firmy syncuje `partner.dic` → `company.income_tax_id`
|
||||||
|
|
||||||
|
## Závislosti
|
||||||
|
|
||||||
|
- `contacts` — základná správa kontaktov
|
||||||
|
- `account` — modul faktúr
|
||||||
|
- `l10n_sk` — slovenská lokalizácia (definuje šablóny, ktoré tento modul opravuje)
|
||||||
|
|
||||||
|
## Nasadenie
|
||||||
|
|
||||||
|
Modul je nasadený na produkčnom serveri `10.10.10.240`, databáza `seri_db`.
|
||||||
|
|
||||||
|
Po aktualizácii modulu spustiť:
|
||||||
|
```bash
|
||||||
|
# Na serveri
|
||||||
|
odoo -d seri_db -u l10n_sk_partner --stop-after-init
|
||||||
|
```
|
||||||
|
|
||||||
|
Migration scripty sa spustia automaticky pri upgrade keď sa zmení verzia v `__manifest__.py`.
|
||||||
|
|
||||||
|
## Časté problémy
|
||||||
|
|
||||||
|
**Duplicitný IČ DPH na faktúre** — vyriešené v `migrations/19.0.2.0.5` + `19.0.2.0.6`. 2.0.5 zmenila `t-if="not forced_vat"` na `t-if="not forced_vat and country != SK"`, ale `t-else` zostal a renderoval prázdny "IČ DPH:" riadok. 2.0.6 zmenila tento `t-else` na `t-if="forced_vat and country != SK"`. Ak sa objaví znovu po reinstalácii `web` modulu, treba zvýšiť verziu a upgradovať modul.
|
||||||
|
|
||||||
|
**Pozor na `\\n` v JSON texte pri migration scriptoch** — `arch_db::text` obsahuje newline ako literálne `\n` (2 znaky: backslash + n), nie skutočný newline. V regex to treba matchovať ako `\\n`, v `replace()` ako Python string `'\\n'` (= `\\` + `n`). Práve preto zlyhala 2.0.5 — použila Python `'\n'` (skutočný newline) v regex patternu. Riešenie v 2.0.6: `replace()` s `_NL = '\\n'`.
|
||||||
|
|
||||||
|
**Rôzna indentácia v external_layout šablónach** — VAT blok má rôzny počet medzier po `\n` podľa layoutu: standard/bold/folder/striped/wave = 28, boxed = 32, bubble = 40. Pri replace() treba použiť správny počet medzier pre každý layout.
|
||||||
|
|
||||||
|
**`hooks.py` vs migration script** — `post_init_hook` sa spustí len pri prvej inštalácii. Pre opravy existujúcich inštalácií treba migration script s vyššou verziou.
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
{
|
{
|
||||||
'name': 'Slovakia - Partner DIČ',
|
'name': 'Slovakia - Partner DIČ',
|
||||||
'version': '19.0.2.0.5',
|
'version': '19.0.2.0.6',
|
||||||
'category': 'Localization',
|
'category': 'Localization',
|
||||||
'summary': 'Pridáva DIČ pole na kontakty a opravuje IČO label pre Slovensko',
|
'summary': 'Pridáva DIČ pole na kontakty a opravuje IČO label pre Slovensko',
|
||||||
'description': """
|
'description': """
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Migration script pre l10n_sk_partner 19.0.2.0.6
|
||||||
|
Opravuje t-else VAT blok vo všetkých external_layout šablónach.
|
||||||
|
|
||||||
|
Migrácia 2.0.5 úspešne opravila t-if pre SK (skryla natívny VAT blok),
|
||||||
|
ale t-else zostal neopravený lebo regex nesprávne matchoval \\n v JSON texte.
|
||||||
|
Pre SK firmu je teraz t-if vždy False → t-else sa vždy vykreslí → prázdny
|
||||||
|
"IČ DPH:" riadok na faktúre.
|
||||||
|
|
||||||
|
Riešenie: t-else zmeníme na t-if="forced_vat and country != SK" pomocou
|
||||||
|
replace() s presným JSON textom (\\n a \" sú literálne 2-znakové sekvencie).
|
||||||
|
Rôzne layouty majú rôznu indentáciu obsahu:
|
||||||
|
- standard, bold, folder, striped, wave: 28 medzier
|
||||||
|
- boxed: 32 medzier
|
||||||
|
- bubble: 40 medzier
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Backslash + double-quote = JSON escaped attribute quote
|
||||||
|
_Q = '\\"'
|
||||||
|
# Backslash + n = JSON encoded newline
|
||||||
|
_NL = '\\n'
|
||||||
|
|
||||||
|
|
||||||
|
def _old(spaces):
|
||||||
|
return (
|
||||||
|
'<li t-else=' + _Q + _Q + '>'
|
||||||
|
+ _NL + ' ' * spaces
|
||||||
|
+ '<t t-esc=' + _Q + 'company.country_id.vat_label'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _new(spaces):
|
||||||
|
return (
|
||||||
|
'<li t-if=' + _Q
|
||||||
|
+ "forced_vat and company.account_fiscal_country_id.code != 'SK'"
|
||||||
|
+ _Q + '>'
|
||||||
|
+ _NL + ' ' * spaces
|
||||||
|
+ '<t t-esc=' + _Q + 'company.country_id.vat_label'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# (key, indentation_spaces)
|
||||||
|
LAYOUTS = [
|
||||||
|
('web.external_layout_standard', 28),
|
||||||
|
('web.external_layout_striped', 28),
|
||||||
|
('web.external_layout_bold', 28),
|
||||||
|
('web.external_layout_folder', 28),
|
||||||
|
('web.external_layout_wave', 28),
|
||||||
|
('web.external_layout_boxed', 32),
|
||||||
|
('web.external_layout_bubble', 40),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def migrate(cr, version):
|
||||||
|
for key, spaces in LAYOUTS:
|
||||||
|
cr.execute("""
|
||||||
|
UPDATE ir_ui_view
|
||||||
|
SET arch_db = replace(arch_db::text, %s, %s)::jsonb,
|
||||||
|
arch_updated = true
|
||||||
|
WHERE key = %s
|
||||||
|
""", (_old(spaces), _new(spaces), key))
|
||||||
|
cr.execute("SELECT * FROM ir_ui_view WHERE key = %s AND arch_updated = true", (key,))
|
||||||
|
if cr.fetchone():
|
||||||
|
pass # updated ok
|
||||||
Reference in New Issue
Block a user