Files
odoo-erp/addons/kosbar_erp_ext/references/custom-product-code.md
2026-09-07 16:41:16 +07:00

3.8 KiB
Raw Blame History

Custom Product Code & Item Code Automation

Overview

Odoo 17/19 Community tidak punya field code standar untuk product category. Untuk kebutuhan stock keeping unit (SKU) yang unik, kita buat field item_code yang di‑generate otomatis dari:

item_code = parent_category_code (2 digit) + category_code (2 digit) + product_id (4 digit) + name_slug (lowercase, no space)

Contoh:

  • Kategori anak: id=06, parent=01 → prefix = 0106
  • Produk: id=3, nama="Backup BRT 30 x 36 x 1,25 mm"
  • Hasil: 01060003backupbrt30x36x1,25mm

Implementation Steps

1. Extend product.category → field code

class ProductCategory(models.Model):
    _inherit = 'product.category'
    code = fields.Char(string='Category Code', compute='_compute_code', store=True, size=4)

    @api.model_create_multi
    def create(self, vals_list):
        records = super().create(vals_list)
        for r in records:
            r.code = f'{r.id:02d}'
        return records

2. Extend product.template → field item_code

Field item_code:

  • Stored (store=True) — dipakai untuk pencarian & unique index.
  • Read‑only di view — tidak boleh ditulis manual.
  • On‑change preview → tampilkan prefix kategori saat buat produk baru.
class ProductTemplate(models.Model):
    _inherit = 'product.template'

    item_code = fields.Char(string='Item Code', store=True, readonly=False)

    _sql_constraints = [
        ('item_code_unique', 'UNIQUE(item_code)', 'Item Code harus unik.'),
    ]

    @api.model_create_multi
    def create(self, vals_list):
        records = super().create(vals_list)
        for r in records:
            r.item_code = r._full_item_code(r)
        return records

    def write(self, vals):
        res = super().write(vals)
        if 'name' in vals or 'categ_id' in vals:
            for r in self:
                r.item_code = r._full_item_code(r)
        return res

3. Extend product.product (varian)

Untuk produk ber‑varian, item_code diturunkan via related field ke template:

class ProductProduct(models.Model):
    _inherit = 'product.product'

    item_code = fields.Char(
        string='Item Code',
        related='product_tmpl_id.item_code',
        store=True,
        readonly=True,
    )

4. XML View — field read‑only

<!-- product_template_form_view inheritance -->
<field name="default_code" position="after">
    <field name="item_code" readonly="1" placeholder="Terisi otomatis"/>
</field>

5. PostgreSQL — Unique Index (optional, backup)

Constraint __sql_constraints sudah menambah unique index via Odoo ORM. Untuk kecepatan lebih cepat di PostgreSQL level, dapat manual:

CREATE UNIQUE INDEX IF NOT EXISTS product_template_item_code_uniq
ON product_template (item_code) WHERE item_code IS NOT NULL;

6. Migration — isi data existing

env.cr.execute("""
    CREATE UNIQUE INDEX IF NOT EXISTS product_template_item_code_uniq
    ON product_template (item_code) WHERE item_code IS NOT NULL
""")

cats = env['product.category'].search([])
for c in cats:
    if not c.code:
        c.code = f'{c.id:02d}'

prods = env['product.template'].search([])
for p in prods:
    p.item_code = p._full_item_code(p)

Pitfalls

  • @api.depends('id') not allowed di Odoo 19. Namun id tersedia di create() setelah super() selesai.
  • Field code di kategori harus size ditentukan ( Odoo 17+ lint error tanpa size)
  • Product dengan categ_id = False → gunakan fallback 00.
  • Item Code read‑only di view: bila pakai store=True, field tetap dapat ditulis via ORM (API). Untuk mencegah manual edit, gunakan readonly=True + @api.constrains untuk validasi.

References

  • models/product_template.py — contoh implementasi lengkap (sudah ada di addon kosbar_erp_ext)
  • views/product_views.xml — XML view inheritance