From 0c294b6d39d4366d4adac7c0ad6adf488031a7e6 Mon Sep 17 00:00:00 2001 From: Alex Ardhian Date: Mon, 7 Sep 2026 17:06:40 +0700 Subject: [PATCH] Docs: template Excel import produk & kategori + panduan README --- templates/README-IMPORT.md | 24 +++++++++ templates/generate_templates.py | 60 +++++++++++++++++++++++ templates/import-product-categories.csv | 7 +++ templates/import-product-categories.xlsx | Bin 0 -> 5092 bytes templates/import-products.xlsx | Bin 0 -> 5265 bytes 5 files changed, 91 insertions(+) create mode 100644 templates/README-IMPORT.md create mode 100644 templates/generate_templates.py create mode 100644 templates/import-product-categories.csv create mode 100644 templates/import-product-categories.xlsx create mode 100644 templates/import-products.xlsx diff --git a/templates/README-IMPORT.md b/templates/README-IMPORT.md new file mode 100644 index 0000000..7434dd3 --- /dev/null +++ b/templates/README-IMPORT.md @@ -0,0 +1,24 @@ +# Template Import Odoo + +Folder ini berisi contoh file template untuk import master data ke Odoo ERP. + +## Isi Folder +| File | Kegunaan | +|---|---| +| `import-products.xlsx` | Template import produk (Product Name, Category, Price, Cost, Barcode) | +| `import-product-categories.xlsx` | Template import kategori produk (Name + Parent Category) | +| `import-product-categories.csv` | Versi CSV kategori (untuk referensi/format cepat) | + +## Cara Pakai +1. **Kategori dulu, baru Produk** (Produk butuh kategori yang sudah ada). +2. Buka Odoo → **Inventory/Sales → Configuration → Product Categories** → tombol **Import**. + - Petakan: `Nama Kategori` → `Name`, `Parent Category` → `Parent Category`. +3. Setelah kategori masuk, `code` 2-digit otomatis terisi oleh addon. +4. Buka **Inventory/Sales → Products → Products** → tombol **Import**. + - Petakan: `Product Name` → `Name`, `Product Category` → `Product Category`, dll. +5. **Jangan isi** kolom `Item Code`/`Internal Reference` — otomatis di-generate addon. + - Format: `parent_code + child_code + product_id(4) + nama_lowercase_tanpa_spasi (koma → titik)`. + +## Contoh hasil otomatis +- Kategori `Elektronik` (code `01`), kategori `Laptop` (code `04`, parent `Elektronik`), produk `MacBook Air M2` (id `0001`): + - `item_code = 01040001macbookairm2` diff --git a/templates/generate_templates.py b/templates/generate_templates.py new file mode 100644 index 0000000..4ffa20d --- /dev/null +++ b/templates/generate_templates.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +"""Generate template Excel untuk import produk & kategori Odoo.""" +from openpyxl import Workbook +from openpyxl.styles import Font, PatternFill, Alignment + +HEADER_FILL = PatternFill('solid', fgColor='0B6E4F') +HEADER_FONT = Font(bold=True, color='FFFFFF') + +def styled_header(ws, headers): + ws.append(headers) + for cell in ws[1]: + cell.fill = HEADER_FILL + cell.font = HEADER_FONT + cell.alignment = Alignment(horizontal='center') + +# ---------- 1. Template Produk ---------- +wb = Workbook() +ws = wb.active +ws.title = 'Products' +styled_header(ws, ['Product Name', 'Product Category', 'Sales Price', 'Cost', 'Barcode']) + +rows = [ + ['iPhone 15 128GB', 'Smartphone', 15000000, 12000000, 1234567890123], + ['Samsung Galaxy S24', 'Smartphone', 14000000, 11000000, 1234567890124], + ['MacBook Air M2', 'Laptop', 25000000, 20000000, 1234567890125], + ['Wireless Mouse', 'Mouse', 500000, 350000, 1234567890126], + ['Mechanical Keyboard', 'Keyboard', 750000, 500000, 1234567890127], +] +for r in rows: + ws.append(r) + +widths = [22, 18, 13, 13, 16] +for i, w in enumerate(widths, 1): + ws.column_dimensions[chr(64 + i)].width = w + +wb.save('/home/ardhi/Application/odoo-erp/templates/import-products.xlsx') +print('OK: import-products.xlsx') + +# ---------- 2. Template Kategori ---------- +wb2 = Workbook() +ws2 = wb2.active +ws2.title = 'Categories' +styled_header(ws2, ['Nama Kategori', 'Parent Category']) + +cat_rows = [ + ['Elektronik', ''], + ['Smartphone', 'Elektronik'], + ['Laptop', 'Elektronik'], + ['Aksesoris', ''], + ['Mouse', 'Aksesoris'], + ['Keyboard', 'Aksesoris'], +] +for r in cat_rows: + ws2.append(r) + +ws2.column_dimensions['A'].width = 22 +ws2.column_dimensions['B'].width = 22 + +wb2.save('/home/ardhi/Application/odoo-erp/templates/import-product-categories.xlsx') +print('OK: import-product-categories.xlsx') diff --git a/templates/import-product-categories.csv b/templates/import-product-categories.csv new file mode 100644 index 0000000..00bfe69 --- /dev/null +++ b/templates/import-product-categories.csv @@ -0,0 +1,7 @@ +Nama Kategori,Parent Category +Elektronik, +Smartphone,Electronics +Laptop,Electronics +Aksesoris, +Mouse,Aksesoris +Keyboard,Aksesoris \ No newline at end of file diff --git a/templates/import-product-categories.xlsx b/templates/import-product-categories.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..2bd71e70af1973e2ca9c13f41c63d2b48dd85998 GIT binary patch literal 5092 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 Q0EC!R0+YqXNq;^43*4s_?f?J) literal 0 HcmV?d00001