diff options
| author | Azka Nathan <darizkyfaz@gmail.com> | 2023-12-22 13:35:26 +0700 |
|---|---|---|
| committer | Azka Nathan <darizkyfaz@gmail.com> | 2023-12-22 13:35:26 +0700 |
| commit | 8a10587c8582ed68944634928c9a7c34d3321dbe (patch) | |
| tree | 99d93c45df499d9701e2f31d995d5b7160a34a2f | |
| parent | fbb11ab07e66b28459375af175459c3a23148597 (diff) | |
matches so on po and matches po on so
| -rwxr-xr-x | indoteknik_custom/models/__init__.py | 2 | ||||
| -rw-r--r-- | indoteknik_custom/models/automatic_purchase.py | 237 | ||||
| -rwxr-xr-x | indoteknik_custom/models/product_template.py | 5 | ||||
| -rwxr-xr-x | indoteknik_custom/models/purchase_order.py | 1 | ||||
| -rwxr-xr-x | indoteknik_custom/models/purchase_order_line.py | 10 | ||||
| -rw-r--r-- | indoteknik_custom/models/purchase_order_sales_match.py | 22 | ||||
| -rw-r--r-- | indoteknik_custom/models/sales_order_purchase_match.py | 22 | ||||
| -rwxr-xr-x | indoteknik_custom/security/ir.model.access.csv | 4 | ||||
| -rwxr-xr-x | indoteknik_custom/views/purchase_order.xml | 26 | ||||
| -rwxr-xr-x | indoteknik_custom/views/sale_order.xml | 20 |
10 files changed, 292 insertions, 57 deletions
diff --git a/indoteknik_custom/models/__init__.py b/indoteknik_custom/models/__init__.py index 4faf969d..fb986c0d 100755 --- a/indoteknik_custom/models/__init__.py +++ b/indoteknik_custom/models/__init__.py @@ -96,3 +96,5 @@ from . import commision from . import sale_advance_payment_inv from . import purchasing_job from . import purchasing_job_multi_update +from . import purchase_order_sales_match +from . import sales_order_purchase_match diff --git a/indoteknik_custom/models/automatic_purchase.py b/indoteknik_custom/models/automatic_purchase.py index a7b24b4f..070db78f 100644 --- a/indoteknik_custom/models/automatic_purchase.py +++ b/indoteknik_custom/models/automatic_purchase.py @@ -1,7 +1,7 @@ from odoo import models, api, fields from odoo.exceptions import UserError from datetime import datetime -import logging +import logging, math _logger = logging.getLogger(__name__) @@ -50,64 +50,195 @@ class AutomaticPurchase(models.Model): raise UserError('Tidak ada Lines, belum bisa create PO') if self.is_po: raise UserError('Sudah pernah di create PO') + current_time = datetime.now() - vendor_ids = self.env['automatic.purchase.line'].read_group([('automatic_purchase_id', '=', self.id), ('partner_id', '!=', False)], fields=['partner_id'], groupby=['partner_id']) - - counter_po_number = 0 + vendor_ids = self.env['automatic.purchase.line'].read_group( + [('automatic_purchase_id', '=', self.id), ('partner_id', '!=', False)], + fields=['partner_id'], + groupby=['partner_id'] + ) + + counter = 0 for vendor in vendor_ids: - param_header = { - 'partner_id': vendor['partner_id'][0], - # 'partner_ref': 'Automatic PO', - 'currency_id': 12, - 'user_id': self.env.user.id, - 'company_id': 1, # indoteknik dotcom gemilang - 'picking_type_id': 28, # indoteknik bandengan receipts - 'date_order': current_time, - 'note_description': 'Automatic PO' - } + self.create_po_by_vendor(vendor['partner_id'][0]) + + # param_header = { + # 'partner_id': vendor['partner_id'][0], + # 'currency_id': 12, + # 'user_id': self.env.user.id, + # 'company_id': 1, # indoteknik dotcom gemilang + # 'picking_type_id': 28, # indoteknik bandengan receipts + # 'date_order': current_time, + # 'note_description': 'Automatic PO' + # } + + # products_vendors = self.env['automatic.purchase.line'].search([ + # ('automatic_purchase_id', '=', self.id), + # ('partner_id', '=', vendor['partner_id'][0]), + # ('qty_purchase', '>', 0) + # ], order='brand_id') + # counter += 1 # new_po = self.env['purchase.order'].create([param_header]) - products_vendors = self.env['automatic.purchase.line'].search([ - ('automatic_purchase_id', '=', self.id), - ('partner_id', '=', vendor['partner_id'][0]), - ('qty_purchase', '>', 0) - ], order='brand_id') - count = brand_id = 0 - for product in products_vendors: - if count == 200 or brand_id != product.brand_id.id: - count = 0 - counter_po_number += 1 - new_po = self.env['purchase.order'].create([param_header]) - new_po.name = new_po.name + "/A/"+str(counter_po_number) - self.env['automatic.purchase.match'].create([{ - 'automatic_purchase_id': self.id, - 'order_id': new_po.id - }]) - self.env.cr.commit() - # else: - # new_po = self.env['purchase.order'].create([param_header]) - brand_id = product.brand_id.id - count += 10 - - qty_available = product.product_id.qty_onhand_bandengan + product.product_id.qty_incoming_bandengan - product.product_id.outgoing_qty - suggest = 'harus beli' - if qty_available > product.qty_purchase: - suggest = 'masih cukup' + # new_po.name = new_po.name + "/A/" + str(counter) + # self.env['automatic.purchase.match'].create([{ + # 'automatic_purchase_id': self.id, + # 'order_id': new_po.id + # }]) + # self.env.cr.commit() + + # count = 0 + # for product in products_vendors: + # if count == 20: + # self.create_purchase_order_sales_match(new_po) + + # if count == 20: + # counter += 1 + # new_po = self.env['purchase.order'].create([param_header]) + # new_po.name = new_po.name + "/B/" + str(counter) + # self.env['automatic.purchase.match'].create([{ + # 'automatic_purchase_id': self.id, + # 'order_id': new_po.id + # }]) + + # self.create_purchase_order_sales_match(new_po) + # self.env.cr.commit() + + # count += 1 + # qty_available = ( + # product.product_id.qty_onhand_bandengan + + # product.product_id.qty_incoming_bandengan - + # product.product_id.outgoing_qty + # ) + # suggest = 'harus beli' if qty_available <= product.qty_purchase else 'masih cukup' + # param_line = { + # 'order_id': new_po.id, + # 'product_id': product.product_id.id, + # 'product_qty': product.qty_purchase, + # 'qty_available_store': qty_available, + # 'suggest': suggest, + # 'product_uom_qty': product.qty_purchase, + # 'price_unit': product.last_price, + # } + # new_line = self.env['purchase.order.line'].create([param_line]) + # product.current_po_id = new_po.id + # product.current_po_line_id = new_line.id + + # self.create_purchase_order_sales_match(new_po) + + self.notification = 'PO Created successfully' + self.is_po = True + + def create_po_by_vendor(self, vendor_id): + current_time = datetime.now() + + PRODUCT_PER_PO = 20 + + auto_purchase_line = self.env['automatic.purchase.line'] + + param_header = { + 'partner_id': vendor_id, + 'currency_id': 12, + 'user_id': self.env.user.id, + 'company_id': 1, # indoteknik dotcom gemilang + 'picking_type_id': 28, # indoteknik bandengan receipts + 'date_order': current_time, + 'note_description': 'Automatic PO' + } + + domain = [ + ('automatic_purchase_id', '=', self.id), + ('partner_id', '=', vendor_id), + ('qty_purchase', '>', 0) + ] + + products_len = auto_purchase_line.search_count(domain) + page = math.ceil(products_len / PRODUCT_PER_PO) + + # i start from zero (0) + for i in range(page): + new_po = self.env['purchase.order'].create([param_header]) + new_po.name = new_po.name + "/A/" + str(i + 1) + + self.env['automatic.purchase.match'].create([{ + 'automatic_purchase_id': self.id, + 'order_id': new_po.id + }]) + + lines = auto_purchase_line.search( + domain, + offset=i * PRODUCT_PER_PO, + limit=PRODUCT_PER_PO + ) + + for line in lines: + product = line.product_id param_line = { 'order_id': new_po.id, - 'sequence': count, - 'product_id': product.product_id.id, - 'product_qty': product.qty_purchase, - 'qty_available_store': qty_available, - 'suggest': suggest, - 'product_uom_qty': product.qty_purchase, - 'price_unit': product.last_price, + 'product_id': product.id, + 'product_qty': line.qty_purchase, + 'qty_available_store': product.qty_available_bandengan, + 'suggest': product._get_po_suggest(line.qty_purchase), + 'product_uom_qty': line.qty_purchase, + 'price_unit': line.last_price, } - new_line = self.env['purchase.order.line'].create([param_line]) - product.current_po_id = new_po.id - product.current_po_line_id = new_line.id - _logger.info('Automatic Create PO Line %s' % product.product_id.name) - self.notification = self.notification + ' %s' % new_po.name - self.is_po = True + new_po_line = self.env['purchase.order.line'].create([param_line]) + line.current_po_id = new_po.id + line.current_po_line_id = new_po_line.id + + self.create_purchase_order_sales_match(new_po) + + + def create_purchase_order_sales_match(self, purchase_order): + matches_so_product_ids = [line.product_id.id for line in purchase_order.order_line] + + matches_so = self.env['automatic.purchase.sales.match'].search([ + ('automatic_purchase_id', '=', self.id), + ('sale_line_id.product_id', 'in', matches_so_product_ids), + ]) + + for sale_order in matches_so: + matches_so_line = { + 'purchase_order_id': purchase_order.id, + 'sale_id': sale_order.sale_id.id, + 'sale_line_id': sale_order.sale_line_id.id, + 'picking_id': sale_order.picking_id.id, + 'move_id': sale_order.move_id.id, + 'partner_id': sale_order.partner_id.id, + 'partner_invoice_id': sale_order.partner_invoice_id.id, + 'salesperson_id': sale_order.salesperson_id.id, + 'product_id': sale_order.product_id.id, + 'qty_so': sale_order.qty_so, + 'qty_po': sale_order.qty_po, + } + po_matches_so_line = self.env['purchase.order.sales.match'].create([matches_so_line]) + + self.create_sales_order_purchase_match(purchase_order) + + def create_sales_order_purchase_match(self, purchase_order): + #TODO add matches po to sales order by automatic_purchase.sales.match + matches_po_product_ids = [line.product_id.id for line in purchase_order.order_line] + + sales_match_line = self.env['automatic.purchase.sales.match'].search([ + ('automatic_purchase_id', '=', self.id), + ('sale_line_id.product_id', 'in', matches_po_product_ids), + ]) + + for sales_match in sales_match_line: + purchase_line = self.env['automatic.purchase.line'].search([ + ('automatic_purchase_id', '=', self.id), + ('product_id', 'in', [sales_match.product_id.id]), + ]) + + matches_po_line = { + 'sales_order_id' : sales_match.sale_id.id, + 'purchase_order_id' : purchase_line.current_po_id.id, + 'purchase_line_id' : purchase_line.current_po_line_id.id, + 'product_id' : sales_match.product_id.id, + 'qty_so' : sales_match.qty_so, + 'qty_po' : sales_match.qty_po, + } + + sales_order_purchase_match = self.env['sales.order.purchase.match'].create([matches_po_line]) def generate_regular_purchase(self): if self.apo_type == 'reordering': diff --git a/indoteknik_custom/models/product_template.py b/indoteknik_custom/models/product_template.py index 34aff4fa..7ec5a002 100755 --- a/indoteknik_custom/models/product_template.py +++ b/indoteknik_custom/models/product_template.py @@ -347,6 +347,11 @@ class ProductProduct(models.Model): sla_version = fields.Integer(string="SLA Version", default=0) is_edited = fields.Boolean(string='Is Edited') qty_sold = fields.Float(string='Sold Quantity', compute='_get_qty_sold') + + def _get_po_suggest(self, qty_purchase): + if self.qty_available_bandengan < qty_purchase: + return 'harus beli' + return 'masih cukup' def _get_qty_upcoming(self): for product in self: diff --git a/indoteknik_custom/models/purchase_order.py b/indoteknik_custom/models/purchase_order.py index 285c5a95..82ca3108 100755 --- a/indoteknik_custom/models/purchase_order.py +++ b/indoteknik_custom/models/purchase_order.py @@ -16,6 +16,7 @@ _logger = logging.getLogger(__name__) class PurchaseOrder(models.Model): _inherit = 'purchase.order' + order_sales_match_line = fields.One2many('purchase.order.sales.match', 'purchase_order_id', string='Sales Match Lines', states={'cancel': [('readonly', True)], 'done': [('readonly', True)]}, copy=True) sale_order_id = fields.Many2one('sale.order', string='Sale Order') procurement_status = fields.Char(string='Procurement Status', compute='get_procurement_status', readonly=True) po_status = fields.Selection([ diff --git a/indoteknik_custom/models/purchase_order_line.py b/indoteknik_custom/models/purchase_order_line.py index 95813e0d..8d7d818b 100755 --- a/indoteknik_custom/models/purchase_order_line.py +++ b/indoteknik_custom/models/purchase_order_line.py @@ -34,10 +34,16 @@ class PurchaseOrderLine(models.Model): is_ltc = fields.Boolean(string='Sudah di LTC', default=False, help='centang ini jika barang sudah di LTC') note = fields.Char(string='Note') sale_automatic_id = fields.Many2one('sale.order', string='SO') + + + # so_line.qty_reserved (compute) + # so_line.qty_reserved = get from picking_ids where type outgoing and prodid = line.prodid + # po_line.qty_reserved = cek dulu apakah ada relasi ke sale order. Jika ada maka ambil sesuai yang ada di sale order (so_line.qty_reserved), + # jika tidak maka 0 def suggest_purchasing(self): - for line in self: - if line.qty_available < line.product_qty: + for line in self: + if line.product_id.qty_available_bandengan + line.qty_reserved < line.product_qty: line.suggest = 'harus beli' else: line.suggest = 'masih cukup' diff --git a/indoteknik_custom/models/purchase_order_sales_match.py b/indoteknik_custom/models/purchase_order_sales_match.py new file mode 100644 index 00000000..02c19b1f --- /dev/null +++ b/indoteknik_custom/models/purchase_order_sales_match.py @@ -0,0 +1,22 @@ +from odoo import fields, models, api, _ +from odoo.exceptions import AccessError, UserError, ValidationError +from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT +import logging + +_logger = logging.getLogger(__name__) + + +class PurchaseOrderSalesMatch(models.Model): + _name = 'purchase.order.sales.match' + + purchase_order_id = fields.Many2one('purchase.order', string='Purchase Order', index=True, required=True, ondelete='cascade') + sale_id = fields.Many2one('sale.order', string='SO') + sale_line_id = fields.Many2one('sale.order.line', string='SO Line') + picking_id = fields.Many2one('stock.picking', string='Picking') + move_id = fields.Many2one('stock.move', string='Move') + partner_id = fields.Many2one('res.partner', string='Partner') + partner_invoice_id = fields.Many2one('res.partner', string='Invoice Partner') + salesperson_id = fields.Many2one('res.users', string='Sales') + product_id = fields.Many2one('product.product', string='Product') + qty_so = fields.Float(string='Qty SO') + qty_po = fields.Float(string='Qty PO')
\ No newline at end of file diff --git a/indoteknik_custom/models/sales_order_purchase_match.py b/indoteknik_custom/models/sales_order_purchase_match.py new file mode 100644 index 00000000..f5436335 --- /dev/null +++ b/indoteknik_custom/models/sales_order_purchase_match.py @@ -0,0 +1,22 @@ +from odoo import fields, models, api, _ +from odoo.exceptions import AccessError, UserError, ValidationError +from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT +import logging + +_logger = logging.getLogger(__name__) + + +class SalesOrderPurchaseMatch(models.Model): + _name = 'sales.order.purchase.match' + + sales_order_id = fields.Many2one('sale.order', string='Sale Order', index=True, required=True, ondelete='cascade') + purchase_order_id = fields.Many2one('purchase.order', string='SO') + purchase_line_id = fields.Many2one('purchase.order.line', string='SO Line') + product_id = fields.Many2one('product.product', string='Product') + qty_so = fields.Float(string='Qty SO') + qty_po = fields.Float(string='Qty PO') + # picking_id = fields.Many2one('stock.picking', string='Picking') + # move_id = fields.Many2one('stock.move', string='Move') + # partner_id = fields.Many2one('res.partner', string='Partner') + # partner_invoice_id = fields.Many2one('res.partner', string='Invoice Partner') + # salesperson_id = fields.Many2one('res.users', string='Sales')
\ No newline at end of file diff --git a/indoteknik_custom/security/ir.model.access.csv b/indoteknik_custom/security/ir.model.access.csv index e4535561..c22ec688 100755 --- a/indoteknik_custom/security/ir.model.access.csv +++ b/indoteknik_custom/security/ir.model.access.csv @@ -88,4 +88,6 @@ access_v_purchasing_job,access.v.purchasing.job,model_v_purchasing_job,,1,1,1,1 access_sale_advance_payment_inv,access.sale.advance.payment.inv,model_sale_advance_payment_inv,,1,1,1,1 access_purchasing_job_multi_update,access.purchasing.job.multi.update,model_purchasing_job_multi_update,,1,1,1,1 access_automatic_purchase_sales_match,access.automatic.purchase.sales.match,model_automatic_purchase_sales_match,,1,1,1,1 -access_v_sales_outstanding,access.v.sales.outstanding,model_v_sales_outstanding,,1,1,1,1
\ No newline at end of file +access_v_sales_outstanding,access.v.sales.outstanding,model_v_sales_outstanding,,1,1,1,1 +access_purchase_order_sales_match,access.purchase.order.sales.match,model_purchase_order_sales_match,,1,1,1,1 +access_sales_order_purchase_match,access.sale.order.purchase.match,model_sales_order_purchase_match,,1,1,1,1
\ No newline at end of file diff --git a/indoteknik_custom/views/purchase_order.xml b/indoteknik_custom/views/purchase_order.xml index 8e74df4a..c118f3fb 100755 --- a/indoteknik_custom/views/purchase_order.xml +++ b/indoteknik_custom/views/purchase_order.xml @@ -101,6 +101,11 @@ <field name="purchase_order_lines"/> </page> </xpath> + <xpath expr="//form/sheet/notebook/page[@name='purchase_delivery_invoice']" position="after"> + <page string="Matches SO" name="purchase_order_sales_matches_lines"> + <field name="order_sales_match_line"/> + </page> + </xpath> </field> </record> </data> @@ -186,4 +191,25 @@ </field> </record> </data> + + <data> + <record id="purchase_order_sales_matches_tree" model="ir.ui.view"> + <field name="name">purchase.order.sales.matches.tree</field> + <field name="model">purchase.order.sales.match</field> + <field name="arch" type="xml"> + <tree editable="top" create="false" delete="false"> + <field name="sale_id" readonly="1"/> + <field name="sale_line_id" readonly="1" optional="hide"/> + <field name="picking_id" readonly="1" optional="hide"/> + <field name="move_id" readonly="1" optional="hide"/> + <field name="partner_id" readonly="1" optional="hide"/> + <field name="partner_invoice_id" readonly="1"/> + <field name="salesperson_id" readonly="1"/> + <field name="product_id" readonly="1"/> + <field name="qty_so" readonly="1"/> + <field name="qty_po" readonly="1"/> + </tree> + </field> + </record> + </data> </odoo>
\ No newline at end of file diff --git a/indoteknik_custom/views/sale_order.xml b/indoteknik_custom/views/sale_order.xml index 5db2f1e1..6b4a4ed7 100755 --- a/indoteknik_custom/views/sale_order.xml +++ b/indoteknik_custom/views/sale_order.xml @@ -160,8 +160,10 @@ </form> </field> </page> + <page string="Matches PO" name="page_matches_po"> + <field name="order_sales_match_line" readonly="1"/> + </page> </page> - </field> </record> </data> @@ -212,4 +214,20 @@ <field name="code">action = records.open_form_multi_update_status()</field> </record> </data> + + <data> + <record id="sales_order_purchase_matches_tree" model="ir.ui.view"> + <field name="name">sale.order.purchase.matches.tree</field> + <field name="model">sales.order.purchase.match</field> + <field name="arch" type="xml"> + <tree editable="top" create="false" delete="false"> + <field name="purchase_order_id" readonly="1"/> + <field name="purchase_line_id" readonly="1"/> + <field name="product_id" readonly="1"/> + <field name="qty_so" readonly="1"/> + <field name="qty_po" readonly="1"/> + </tree> + </field> + </record> + </data> </odoo>
\ No newline at end of file |
