Skip to Content

Довідник УКТЗЕД в Odoo: як прив'язати код до товару

Задача: завести довідник УКТЗЕД у базу і прив'язати код до товару так, щоб він читався в документах, а не лежав окремою моделлю. УКТЗЕД (Українська класифікація товарів зовнішньоекономічної діяльності) — національний класифікатор товарів, код від 2 до 10 цифр; для послуг коду немає за визначенням. У KitWorks під цю задачу є три модулі — kw_uktzed, kw_uktzed_data, l10n_ua_uktz — і з назв здається, що це один продукт. Це не так.

Як влаштований довідник

Розглянемо модель. kw_uktzed і l10n_ua_uktz незалежно одне від одного оголошують ту саму:

class UktzedCode(models.Model):
    _name = 'kw.uktzed.code'
    _description = 'Uktzed code'
    _inherit = ['generic.mixin.parent.names']
    _parent_name = 'parent_id'

    name = fields.Char(string='Code', )
    active = fields.Boolean(default=True, )
    parent_id = fields.Many2one(comodel_name='kw.uktzed.code', )
    title = fields.Char()
    description = fields.Text()
    # ...

Окремої моделі під кожен рівень ієрархії немає — це самопосилання через parent_id. Домішка generic.mixin.parent.names додає перевірку на циклічність і обчислює display_name обходом батьків знизу вгору («Розділ / Група / Позиція / …»). Код товару — це поле name: розділи римськими цифрами (I, II, …), далі 2-, 4-, 6-, 8- і 10-значні коди:

<record model="kw.uktzed.code" id="kw_uktzed_code_1">
    <field name="name">I</field>
    <field name="title">(з 01 по 05) Живі тварини; продукти тваринного походження</field>
</record>

Той самий запис у l10n_ua_uktz — інший формат:

{
    "name": "I",
    "title": "(з 01 по 05) Живі тварини; продукти тваринного походження"
}

У даних, що постачаються з модулями, 16 560 записів, з них 10 473 — кінцеві 10-значні коди. Решта — вузли дерева (розділи, групи, товарні позиції), на товар не чіпляються.

Два модулі на одну модель

kw_uktzed_data довантажує ці 16 560 записів у kw_uktzed XML-даними (data/data.xml, ~4,3 МБ, noupdate="1") — вони підтягуються автоматично при встановленні. l10n_ua_uktz даних при встановленні не завантажує: той самий довідник лежить у форматі JSON (~4,7 МБ) і чекає, поки в Загальних налаштуваннях, розділ «Uktzed», хтось натисне «Upload Uktzed» — візард із трьома джерелами: з модуля, з файлу, за посиланням.

Неправильно — ставити і kw_uktzed_data, і l10n_ua_uktz одразу: жоден не залежить від іншого, і Odoo об'єднає два незалежно написані визначення однієї моделі. Правильно — обрати один і саме з ним будувати подальшу реалізацію: обидва вантажать той самий довідник, різниця лише у способі завантаження.

Важливо! Завантаження в l10n_ua_uktz завжди створює новий запис, без перевірки, чи такий код уже є:

def upload_json(self, data):
    name = data.get('name')
    title = data.get('title')
    parent_id = False
    parent_id_name = data.get('parent_id')
    if parent_id_name:
        parent = self.sudo().env['kw.uktzed.code'].search([
            ('name', '=', parent_id_name)], limit=1)
        parent_id = parent.id if parent else False
    if name or title:
        self.sudo().env['kw.uktzed.code'].create(
            {'name': name, 'title': title, 'parent_id': parent_id})

Повторний запуск майстра після оновлення класифікатора не оновить довідник, а задублює його. Вбудованого шляху «оновити класифікатор» немає: XML з noupdate="1" при апгрейді нічого не перезапише, а json-візард лише ще раз усе створить.

Прив'язка до товару: чого немає в жодному з двох модулів

Ні kw_uktzed, ні l10n_ua_uktz не додають жодного поля на product.template. Довідник доступний лише через власне меню «UKTZED → Codes» — готова ієрархічна модель без готової інтеграції з карткою товару.

Важливо! Якщо стоїть тільки kw_uktzed/l10n_ua_uktz — довідник є, а прив'язати код до товару штатно нічим. Потрібне поле під конкретний проєкт — звичайний Many2one:

uktzed_id = fields.Many2one(
    comodel_name='kw.uktzed.code',
    string='UKTZED Code',
)

Куди код потрапляє на практиці

Ні kw_uktzed, ні l10n_ua_uktz код нікуди не виводять і ніде не читають. Ну по суті вони і не повинні — це довідник і спосіб його завантажити; прив'язка до товару й показ коду в документі (рахунку, накладній, митній декларації) — окрема робота під конкретний проєкт.

Важливо! Це стосується і оновлення самого довідника: коли класифікатор зміниться (з'являються нові коди, скасовуються старі), штатного способу перезалити вже завантажені дані немає в жодному з двох модулів — kw_uktzed_data через noupdate="1" пропускає зміни при апгрейді, а l10n_ua_uktz, як показано вище, лише додасть дублі. Звірка після оновлення класифікатора — ручна робота.

Масове проставлення кодів наявним товарам

Коли товарів багато й вручну не варіант — це задача під kw_generic_import. Готового шаблону з колонкою УКТЗЕД немає: kw_generic_import_product імпортує default_code, barcode, category, ціни, атрибути. Але власне поле-Many2one під код УКТЗЕД на product.template рушій резолвить конвертером m2o_by_name — точним збігом по полю name, яке в kw.uktzed.code і є кодом. Досить додати один рядок мапінгу в шаблон імпорту — решта працює як для будь-якого Many2one. Про сам рушій — окрема стаття: https://kitworks.systems/blog/programuvannia-2/generic-import-arhitektura-136. Я б перед Run Import спершу прогнав Dry Run — рядки без збігу видно одразу, і в базу нічого не пишеться.

Довідник УКТЗЕД в Odoo: як прив'язати код до товару
KitWorks, Volodymyr Karabanov 22 серпня 2026 р.
Поділитися цією публікацією
Архів