summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xfixco_custom/__manifest__.py6
-rwxr-xr-xfixco_custom/models/__init__.py4
-rw-r--r--fixco_custom/models/automatic_purchase.py93
-rw-r--r--fixco_custom/models/brands.py16
-rw-r--r--fixco_custom/models/manage_stock.py2
-rwxr-xr-xfixco_custom/models/product_product.py2
-rw-r--r--fixco_custom/models/product_public_category.py23
-rw-r--r--fixco_custom/models/purchasing_job.py13
-rwxr-xr-xfixco_custom/security/ir.model.access.csv3
-rw-r--r--fixco_custom/views/automatic_purchase.xml2
-rw-r--r--fixco_custom/views/brands_views.xml59
-rwxr-xr-xfixco_custom/views/product_product.xml2
-rw-r--r--fixco_custom/views/product_public_category.xml55
-rw-r--r--fixco_custom/views/purchasing_job.xml1
14 files changed, 241 insertions, 40 deletions
diff --git a/fixco_custom/__manifest__.py b/fixco_custom/__manifest__.py
index 12e15ca..0bcdfaa 100755
--- a/fixco_custom/__manifest__.py
+++ b/fixco_custom/__manifest__.py
@@ -5,10 +5,10 @@
'sequence': 1,
'summary': 'Fixco Custom',
'description': '',
- 'author': 'Stephan Christianus',
+ 'author': 'Stephan Christianus, Azka Nathan',
'website': '',
'images': ['assets/favicon.ico'],
- 'depends': ['base', 'sale'],
+ 'depends': ['base', 'coupon', 'delivery', 'sale', 'sale_management'],
'data': [
'security/ir.model.access.csv',
'views/res_partner.xml',
@@ -37,6 +37,8 @@
'views/automatic_purchase.xml',
'views/purchasing_job.xml',
'views/upload_bills.xml',
+ 'views/brands_views.xml',
+ 'views/product_public_category.xml',
],
'demo': [],
'css': [],
diff --git a/fixco_custom/models/__init__.py b/fixco_custom/models/__init__.py
index f345625..e80acd8 100755
--- a/fixco_custom/models/__init__.py
+++ b/fixco_custom/models/__init__.py
@@ -23,4 +23,6 @@ from . import manage_stock
from . import automatic_purchase
from . import purchasing_job
from . import stock_move
-from . import upload_bills \ No newline at end of file
+from . import upload_bills
+from . import brands
+from . import product_public_category \ No newline at end of file
diff --git a/fixco_custom/models/automatic_purchase.py b/fixco_custom/models/automatic_purchase.py
index 1ef12ca..98a4136 100644
--- a/fixco_custom/models/automatic_purchase.py
+++ b/fixco_custom/models/automatic_purchase.py
@@ -77,6 +77,8 @@ class AutomaticPurchase(models.Model):
'partner_id': vendor.id if vendor else False,
'taxes_id': vendor.tax_id.id if vendor else False,
'price': price,
+ 'product_public_category_id': product.product_public_category_id.id,
+ 'brand_id': product.brand_id.id,
})
self.env['automatic.purchase.line'].create(lines)
@@ -111,42 +113,72 @@ class AutomaticPurchase(models.Model):
self.ensure_one()
if not self.automatic_purchase_lines:
raise UserError(_("No purchase lines to process!"))
-
+
if self.is_po:
raise UserError(_("Purchase order already created!"))
-
+
vendor_lines = {}
+
for line in self.automatic_purchase_lines:
- if line.partner_id.id not in vendor_lines:
- vendor_lines[line.partner_id.id] = []
- vendor_lines[line.partner_id.id].append(line)
-
+ partner_id = line.partner_id.id
+ brand_id = line.brand_id.id if line.brand_id else 0
+ category_id = line.product_public_category_id.id if line.product_public_category_id else 0
+
+ if partner_id != 270:
+ key = (partner_id,)
+ elif brand_id == 3:
+ key = (partner_id, brand_id, category_id)
+ else:
+ key = (partner_id, brand_id)
+
+ vendor_lines.setdefault(key, []).append(line)
+
created_orders = self.env['purchase.order']
-
- for vendor_id, lines in vendor_lines.items():
- vendor = self.env['res.partner'].browse(vendor_id)
-
- chunk_size = 10
+
+ for key, lines in vendor_lines.items():
+ partner_id = key[0]
+ brand_id = key[1] if len(key) > 1 else None
+ category_id = key[2] if len(key) > 2 else None
+
+ vendor = self.env['res.partner'].browse(partner_id)
+
+ chunk_size = 20
line_chunks = [lines[i:i + chunk_size] for i in range(0, len(lines), chunk_size)]
-
+
for index, chunk in enumerate(line_chunks):
- order = self._create_purchase_order(vendor, index + 1, len(line_chunks))
+ order = self._create_purchase_order(
+ vendor,
+ index + 1,
+ len(line_chunks),
+ brand_id=brand_id,
+ category_id=category_id
+ )
created_orders += order
-
+
for line in chunk:
self._create_purchase_order_line(order, line)
-
+
self.purchase_order_ids = [(6, 0, created_orders.ids)]
self.is_po = True
-
+
return self.action_view_purchase_orders()
+
+
- def _create_purchase_order(self, vendor, sequence, total_chunks):
- """Membuat purchase order untuk vendor"""
+ def _create_purchase_order(self, vendor, sequence, total_chunks, brand_id=None, category_id=None):
order_name = f"{self.number} - {vendor.name}"
+
+ if brand_id:
+ brand = self.env['brands'].browse(brand_id)
+ order_name += f" - {brand.name}"
+
+ if category_id:
+ cat = self.env['product.public.category'].browse(category_id)
+ order_name += f" - {cat.name}"
+
if total_chunks > 1:
order_name += f" ({sequence}/{total_chunks})"
-
+
return self.env['purchase.order'].create({
'partner_id': vendor.id,
'origin': self.number,
@@ -155,10 +187,12 @@ class AutomaticPurchase(models.Model):
'currency_id': vendor.property_purchase_currency_id.id or self.env.company.currency_id.id,
'automatic_purchase_id': self.id,
'source': self.apo_type,
+ 'name': order_name,
})
+
+
def _create_purchase_order_line(self, order, line):
- """Membuat purchase order line dari automatic purchase line"""
product = line.product_id
return self.env['purchase.order.line'].create({
@@ -175,24 +209,20 @@ class AutomaticPurchase(models.Model):
def generate_automatic_lines(self):
self.ensure_one()
- # Hapus lines yang sudah ada
self.automatic_purchase_lines.unlink()
manage_stocks = self.env['manage.stock'].search([])
- location_id = 55 # Lokasi gudang ID 55
+ location_id = 55
lines_to_create = []
for stock in manage_stocks:
- # Cari semua stock.quant untuk produk ini di lokasi 55
quant_records = self.env['stock.quant'].search([
('product_id', '=', stock.product_id.id),
('location_id', '=', location_id)
])
- # Hitung total qty_available (quantity - reserved_quantity) untuk lokasi tersebut
total_available = quant_records.quantity or 0.0
- # Log nilai untuk debugging
_logger.info(
"Product %s: Available=%.4f, Min=%.4f, Buffer=%.4f",
stock.product_id.display_name,
@@ -201,14 +231,11 @@ class AutomaticPurchase(models.Model):
stock.buffer_stock
)
- # Gunakan float_compare untuk perbandingan yang akurat
comparison = float_compare(total_available, stock.min_stock, precision_rounding=0.0001)
- if comparison <= 0: # Termasuk saat sama dengan min_stock
- # Hitung qty yang perlu dipesan
+ if comparison <= 0:
qty_purchase = stock.buffer_stock - total_available
- # Pastikan qty_purchase positif
if float_compare(qty_purchase, 0.0, precision_rounding=0.0001) <= 0:
_logger.warning(
"Negative purchase quantity for %s: Available=%.4f, Buffer=%.4f, Purchase=%.4f",
@@ -219,7 +246,6 @@ class AutomaticPurchase(models.Model):
)
continue
- # Dapatkan harga dari purchase.pricelist
pricelist = self.env['purchase.pricelist'].search([
('product_id', '=', stock.product_id.id),
('vendor_id', '=', stock.vendor_id.id)
@@ -228,7 +254,6 @@ class AutomaticPurchase(models.Model):
price = pricelist.price if pricelist else 0.0
subtotal = qty_purchase * price
- # Log penambahan produk
_logger.info(
"Adding product %s: Available=%.4f, Min=%.4f, Purchase=%.4f",
stock.product_id.display_name,
@@ -237,7 +262,6 @@ class AutomaticPurchase(models.Model):
qty_purchase
)
- # Kumpulkan data untuk pembuatan lines
lines_to_create.append({
'automatic_purchase_id': self.id,
'product_id': stock.product_id.id,
@@ -247,6 +271,8 @@ class AutomaticPurchase(models.Model):
'partner_id': stock.vendor_id.id,
'taxes_id': stock.vendor_id.tax_id.id,
'price': price,
+ 'product_public_category_id': stock.product_id.product_public_category_id.id,
+ 'brand_id': stock.product_id.brand_id.id,
})
else:
_logger.info(
@@ -256,7 +282,6 @@ class AutomaticPurchase(models.Model):
stock.min_stock
)
- # Buat lines sekaligus untuk efisiensi
if lines_to_create:
self.env['automatic.purchase.line'].create(lines_to_create)
_logger.info("Created %d purchase lines", len(lines_to_create))
@@ -291,6 +316,8 @@ class AutomaticPurchaseLine(models.Model):
subtotal = fields.Float(string='Subtotal', compute='compute_subtotal')
is_po = fields.Boolean(String='Is PO')
taxes_id = fields.Many2one('account.tax', string='Taxes')
+ brand_id = fields.Many2one('brands', string='Brand')
+ product_public_category_id = fields.Many2one('product.public.category', string='Public Category')
def compute_subtotal(self):
for line in self:
diff --git a/fixco_custom/models/brands.py b/fixco_custom/models/brands.py
new file mode 100644
index 0000000..378adeb
--- /dev/null
+++ b/fixco_custom/models/brands.py
@@ -0,0 +1,16 @@
+from odoo import models, fields # type: ignore
+
+class Brands(models.Model):
+ _name = 'brands'
+ _description = 'Brands'
+
+ name = fields.Char(string='Brand Name', required=True)
+ product_ids = fields.One2many('product.product', 'brand_id', string='Products')
+ category_ids = fields.Many2many(
+ 'product.public.category',
+ # 'brands_category_rel',
+ # 'brand_id',
+ # 'category_id',
+ string='Public Categories'
+)
+ \ No newline at end of file
diff --git a/fixco_custom/models/manage_stock.py b/fixco_custom/models/manage_stock.py
index 29d482f..80aa505 100644
--- a/fixco_custom/models/manage_stock.py
+++ b/fixco_custom/models/manage_stock.py
@@ -78,6 +78,8 @@ class ManageStock(models.Model):
'partner_id': stock.vendor_id.id,
'taxes_id': stock.vendor_id.tax_id.id if stock.vendor_id.tax_id else False,
'price': price,
+ 'product_public_category_id': stock.product_id.product_public_category_id.id,
+ 'brand_id': stock.product_id.brand_id.id,
})
self.env['automatic.purchase.line'].create(lines_to_create)
diff --git a/fixco_custom/models/product_product.py b/fixco_custom/models/product_product.py
index 5117104..72e7ecd 100755
--- a/fixco_custom/models/product_product.py
+++ b/fixco_custom/models/product_product.py
@@ -18,6 +18,8 @@ class ProductProduct(models.Model):
barcode_box = fields.Char("Barcode Box")
qr_code_variant = fields.Binary("QR Code Variant", compute='_compute_qr_code_variant')
qty_multiple = fields.Float('Multiple')
+ brand_id = fields.Many2one('brands', string='Brand')
+ product_public_category_id = fields.Many2one('product.public.category', string='Public Categories')
def check_multiple_qty(self, other_qty):
if self.qty_multiple > 0 and other_qty > 0:
diff --git a/fixco_custom/models/product_public_category.py b/fixco_custom/models/product_public_category.py
new file mode 100644
index 0000000..b706bc1
--- /dev/null
+++ b/fixco_custom/models/product_public_category.py
@@ -0,0 +1,23 @@
+from odoo import fields, models, api
+
+
+class ProductPublicCategory(models.Model):
+ _inherit = "product.public.category"
+
+ brand_id = fields.Many2one('brands', string='Brand')
+ product_ids = fields.One2many('product.product', 'product_public_category_id', string='Products')
+
+ # @api.model
+ # def _onchange_child_frontend_id2(self, parent):
+ # domain = {}
+ # if parent:
+ # parent_records = self.browse(parent)
+ # parent_names = parent_records.mapped('name')
+ # domain['child_frontend_id2'] = [
+ # ('parent_frontend_id', 'in', parent),
+ # ('parent_frontend_id.name', 'ilike', parent_names)
+ # ]
+ # else:
+ # domain['child_frontend_id2'] = []
+ # return {'domain': domain}
+
diff --git a/fixco_custom/models/purchasing_job.py b/fixco_custom/models/purchasing_job.py
index 1af47b7..2c7138a 100644
--- a/fixco_custom/models/purchasing_job.py
+++ b/fixco_custom/models/purchasing_job.py
@@ -17,6 +17,7 @@ class PurchasingJob(models.Model):
action = fields.Char(string='Action')
product_id = fields.Many2one('product.product', string='Product')
vendor_id = fields.Many2one('res.partner', string='Vendor')
+ brand_id = fields.Many2one('brands', string='Brand')
def create_automatic_purchase(self):
if not self:
@@ -54,6 +55,8 @@ class PurchasingJob(models.Model):
'partner_id': stock.vendor_id.id,
'taxes_id': stock.vendor_id.tax_id.id if stock.vendor_id.tax_id else False,
'price': price,
+ 'brand_id': stock.brand_id.id,
+ 'product_public_category_id': stock.product_id.product_public_category_id.id,
})
self.env['automatic.purchase.line'].create(lines_to_create)
@@ -83,7 +86,8 @@ class PurchasingJob(models.Model):
ELSE 'cukup'
END AS action,
a.product_id,
- pp2.vendor_id
+ pp2.vendor_id,
+ b.id AS brand_id
FROM (
SELECT
COALESCE(pp.default_code, pt.default_code) AS item_code,
@@ -91,7 +95,8 @@ class PurchasingJob(models.Model):
get_qty_onhand(pp.id::numeric) AS onhand,
get_qty_incoming(pp.id::numeric) AS incoming,
get_qty_outgoing(pp.id::numeric) AS outgoing,
- pp.id AS product_id
+ pp.id AS product_id,
+ pp.brand_id
FROM stock_move sm
JOIN stock_picking sp ON sp.id = sm.picking_id
JOIN product_product pp ON pp.id = sm.product_id
@@ -99,8 +104,9 @@ class PurchasingJob(models.Model):
WHERE sp.state IN ('draft', 'waiting', 'confirmed', 'assigned')
AND sp.name LIKE '%%OUT%%'
AND sm.location_id = 55
- GROUP BY pp.id, pp.default_code, pt.default_code, pt.name
+ GROUP BY pp.id, pp.default_code, pt.default_code, pt.name, pp.brand_id
) a
+ LEFT JOIN brands b ON b.id = a.brand_id
LEFT JOIN LATERAL (
SELECT vendor_id
FROM purchase_pricelist
@@ -116,3 +122,4 @@ class PurchasingJob(models.Model):
+
diff --git a/fixco_custom/security/ir.model.access.csv b/fixco_custom/security/ir.model.access.csv
index a3f7ac4..4b22abd 100755
--- a/fixco_custom/security/ir.model.access.csv
+++ b/fixco_custom/security/ir.model.access.csv
@@ -28,4 +28,5 @@ access_automatic_purchase_line,access.automatic.purchase.line,model_automatic_pu
access_automatic_purchase,access.automatic.purchase,model_automatic_purchase,,1,1,1,1
access_purchasing_job,access.purchasing.job,model_purchasing_job,,1,1,1,1
access_upload_bills,access.upload.bills,model_upload_bills,,1,1,1,1
-access_upload_bills_line,access.upload.bills.line,model_upload_bills_line,,1,1,1,1 \ No newline at end of file
+access_upload_bills_line,access.upload.bills.line,model_upload_bills_line,,1,1,1,1
+access_brands,access.brands,model_brands,,1,1,1,1 \ No newline at end of file
diff --git a/fixco_custom/views/automatic_purchase.xml b/fixco_custom/views/automatic_purchase.xml
index f985a54..9b0a45b 100644
--- a/fixco_custom/views/automatic_purchase.xml
+++ b/fixco_custom/views/automatic_purchase.xml
@@ -20,6 +20,8 @@
<field name="arch" type="xml">
<tree editable="bottom">
<field name="product_id"/>
+ <field name="brand_id"/>
+ <field name="product_public_category_id"/>
<field name="partner_id" required="1"/>
<field name="taxes_id" domain="[('type_tax_use','=','purchase')]"/>
<field name="qty_purchase"/>
diff --git a/fixco_custom/views/brands_views.xml b/fixco_custom/views/brands_views.xml
new file mode 100644
index 0000000..09fc75a
--- /dev/null
+++ b/fixco_custom/views/brands_views.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+ <record id="view_brands_form" model="ir.ui.view">
+ <field name="name">brands.form</field>
+ <field name="model">brands</field>
+ <field name="arch" type="xml">
+ <form string="Brand">
+ <sheet>
+ <group>
+ <field name="name"/>
+ </group>
+ <notebook>
+ <page string="Products">
+ <field name="product_ids">
+ <tree editable="bottom">
+ <field name="name"/>
+ <field name="default_code"/>
+ <field name="list_price"/>
+ </tree>
+ </field>
+ </page>
+ <page string="Categories">
+ <field name="category_ids">
+ <tree>
+ <field name="name"/>
+ </tree>
+ </field>
+ </page>
+ </notebook>
+ </sheet>
+ </form>
+ </field>
+ </record>
+
+ <record id="view_brands_tree" model="ir.ui.view">
+ <field name="name">brands.tree</field>
+ <field name="model">brands</field>
+ <field name="arch" type="xml">
+ <tree>
+ <field name="name"/>
+ </tree>
+ </field>
+ </record>
+
+ <record id="brands_action" model="ir.actions.act_window">
+ <field name="name">Brands</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">brands</field>
+ <field name="view_mode">tree,form</field>
+ </record>
+
+ <menuitem
+ id="menu_brands"
+ name="Brands"
+ parent="sale_management.menu_product_attribute_action"
+ sequence="4"
+ action="brands_action"
+ />
+</odoo> \ No newline at end of file
diff --git a/fixco_custom/views/product_product.xml b/fixco_custom/views/product_product.xml
index 6c468ba..08952b6 100755
--- a/fixco_custom/views/product_product.xml
+++ b/fixco_custom/views/product_product.xml
@@ -7,10 +7,12 @@
<field name="inherit_id" ref="product.product_normal_form_view"/>
<field name="arch" type="xml">
<field name="categ_id" position="after">
+ <field name="brand_id" />
<field name="qty_multiple" />
<field name="barcode_box" />
<field name="qty_pcs_box" />
<field name="qr_code_variant" widget="image" readonly="True"/>
+ <field name="product_public_category_id" attrs="{'required': [('brand_id', '=', 3)]}"/>
</field>
<field name="uom_po_id" position="after">
<field name="qty_multiple" />
diff --git a/fixco_custom/views/product_public_category.xml b/fixco_custom/views/product_public_category.xml
new file mode 100644
index 0000000..090321f
--- /dev/null
+++ b/fixco_custom/views/product_public_category.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+ <record id="view_product_public_category_form_custom" model="ir.ui.view">
+ <field name="name">product.public.category.form.custom</field>
+ <field name="model">product.public.category</field>
+ <field name="arch" type="xml">
+ <form string="Public Category">
+ <sheet>
+ <group>
+ <field name="name"/>
+ <field name="parent_id"/>
+ <field name="brand_id"/>
+ </group>
+ <notebook>
+ <page string="Products">
+ <field name="product_ids">
+ <tree editable="bottom">
+ <field name="name"/>
+ <field name="default_code"/>
+ <field name="list_price"/>
+ </tree>
+ </field>
+ </page>
+ </notebook>
+ </sheet>
+ </form>
+ </field>
+ </record>
+
+ <record id="view_product_public_category_tree_custom" model="ir.ui.view">
+ <field name="name">product.public.category.tree.custom</field>
+ <field name="model">product.public.category</field>
+ <field name="arch" type="xml">
+ <tree>
+ <field name="name"/>
+ <field name="parent_id"/>
+ <field name="brand_id"/>
+ </tree>
+ </field>
+ </record>
+
+ <record id="action_product_public_category_custom" model="ir.actions.act_window">
+ <field name="name">Public Categories</field>
+ <field name="res_model">product.public.category</field>
+ <field name="view_mode">tree,form</field>
+ </record>
+
+ <menuitem
+ id="menu_product_public_category_custom"
+ name="Public Categories"
+ parent="sale.product_menu_catalog"
+ action="action_product_public_category_custom"
+ sequence="20"
+ />
+</odoo> \ No newline at end of file
diff --git a/fixco_custom/views/purchasing_job.xml b/fixco_custom/views/purchasing_job.xml
index 7d16682..7a15160 100644
--- a/fixco_custom/views/purchasing_job.xml
+++ b/fixco_custom/views/purchasing_job.xml
@@ -8,6 +8,7 @@
<tree string="Procurement Monitoring by Product" create="false" delete="false">
<field name="item_code"/>
<field name="product"/>
+ <field name="brand_id"/>
<field name="vendor_id"/>
<field name="onhand"/>
<field name="incoming"/>