3.8 KiB
3.8 KiB
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. Namunidtersedia dicreate()setelah super() selesai.- Field
codedi kategori harussizeditentukan ( Odoo 17+ lint error tanpasize) - Product dengan
categ_id = False→ gunakan fallback00. - Item Code read‑only di view: bila pakai
store=True, field tetap dapat ditulis via ORM (API). Untuk mencegah manual edit, gunakanreadonly=True+@api.constrainsuntuk validasi.
References
models/product_template.py— contoh implementasi lengkap (sudah ada di addonkosbar_erp_ext)views/product_views.xml— XML view inheritance