from odoo import models, api, fields from odoo.exceptions import UserError from datetime import datetime import logging _logger = logging.getLogger(__name__) class AutomaticPurchase(models.Model): _name = 'automatic.purchase' _order = 'id desc' date_doc = fields.Date(string='Date', required=True, help='Isi tanggal hari ini') description = fields.Char(string='Description', help='bebas isi nya apa') purchase_lines = fields.One2many('automatic.purchase.line', 'automatic_purchase_id', string='Lines', auto_join=True) notification = fields.Char(string='Notification') is_po = fields.Boolean(string='Is PO') purchase_match = fields.One2many('automatic.purchase.match', 'automatic_purchase_id', string='Matches', auto_join=True) vendor_id = fields.Many2one('res.partner', string='Vendor', help='boleh kosong, jika diisi, maka hanya keluar data untuk vendor tersebut') responsible_id = fields.Many2one('res.users', string='Responsible', required=True) def create_po_from_automatic_purchase(self): if not self.purchase_lines: 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 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' } # 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 not product.taxes_id: raise UserError('Tidak ada Taxes') 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' 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, 'taxes_id': [product.taxes_id.id], '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 _logger.info('Automatic Create PO Line %s' % product.product_id.name) self.notification = self.notification + ' %s' % new_po.name self.is_po = True def generate_automatic_purchase(self): if self.purchase_lines: raise UserError('Sudah digenerate sebelumnya, hapus line terlebih dahulu') query = [ ('product_min_qty', '>', 0), ('product_id.x_manufacture.user_id.id', '=', self.responsible_id.id) ] orderpoints = self.env['stock.warehouse.orderpoint'].search(query) count = 0 for point in orderpoints: # _logger.info('test %s' % point.product_id.name) if point.product_id.virtual_available > point.product_min_qty: continue qty_purchase = point.product_max_qty - point.product_id.virtual_available po_line = self.env['purchase.order.line'].search([('product_id', '=', point.product_id.id), ('order_id.state', '=', 'done')], order='id desc', limit=1) if self.vendor_id: purchase_price = self.env['purchase.pricelist'].search([ ('product_id', '=', point.product_id.id), # ('product_id.x_manufacture.user_id.id', '=', self.responsible_id.id), ('vendor_id', '=', self.vendor_id.id) ], order='count_trx_po desc, count_trx_po_vendor desc', limit=1) else: purchase_price = self.env['purchase.pricelist'].search([ ('product_id', '=', point.product_id.id), # ('product_id.x_manufacture.user_id.id', '=', self.responsible_id.id), ], order='count_trx_po desc, count_trx_po_vendor desc', limit=1) vendor_id = purchase_price.vendor_id.id price, taxes = self._get_valid_purchase_price(purchase_price) if self.vendor_id and self.vendor_id.id != vendor_id: continue self.env['automatic.purchase.line'].create([{ 'automatic_purchase_id': self.id, 'product_id': point.product_id.id, 'qty_purchase': qty_purchase, 'qty_min': point.product_min_qty, 'qty_max': point.product_max_qty, 'qty_available': point.product_id.virtual_available, # 'partner_id': po_line.order_id.partner_id.id, # 'last_price': po_line.price_unit, 'partner_id': vendor_id, 'last_price': price, 'taxes_id': taxes, 'subtotal': qty_purchase * price, 'last_order_id': po_line.order_id.id, 'last_orderline_id': po_line.id, 'brand_id': point.product_id.product_tmpl_id.x_manufacture.id }]) count += 1 _logger.info('Create Automatic Purchase Line %s' % point.product_id.name) self.notification = "Automatic PO Created %s Lines" % count def _get_valid_purchase_price(self, purchase_price): price = 0 taxes = None human_last_update = purchase_price.human_last_update or datetime.min system_last_update = purchase_price.system_last_update or datetime.min price = purchase_price.product_price taxes = purchase_price.taxes_product_id.id if system_last_update > human_last_update: price = purchase_price.system_price taxes = purchase_price.taxes_system_id.id return price, taxes class AutomaticPurchaseLine(models.Model): _name = 'automatic.purchase.line' _description = 'Automatic Purchase Line' _order = 'automatic_purchase_id, id' automatic_purchase_id = fields.Many2one('automatic.purchase', string='Ref', required=True, ondelete='cascade', index=True, copy=False) product_id = fields.Many2one('product.product', string='Product') qty_purchase = fields.Float(string='Qty Purchase') qty_min = fields.Float(string='Qty Min') qty_max = fields.Float(string='Qty Max') qty_available = fields.Float(string='Qty Available') partner_id = fields.Many2one('res.partner', string='Vendor') last_price = fields.Float(string='Last Price') subtotal = fields.Float(string='Subtotal') last_order_id = fields.Many2one('purchase.order', string='Last Order') last_orderline_id = fields.Many2one('purchase.order.line', string='Last Order Line') is_po = fields.Boolean(String='Is PO') current_po_id = fields.Many2one('purchase.order', string='Current') current_po_line_id = fields.Many2one('purchase.order.line', string='Current Line') brand_id = fields.Many2one('x_manufactures', string='Brand') taxes_id = fields.Many2one('account.tax', string='Taxes') class AutomaticPurchaseMatch(models.Model): _name = 'automatic.purchase.match' _order = 'automatic_purchase_id, id' automatic_purchase_id = fields.Many2one('automatic.purchase', string='Ref', required=True, ondelete='cascade', index=True, copy=False) order_id = fields.Many2one('purchase.order', string='Purchase Order') vendor = fields.Char(string='Vendor', compute='_compute_info_po') total = fields.Float(string='Total', compute='_compute_info_po') def _compute_info_po(self): for match in self: match.vendor = match.order_id.partner_id.name match.total = match.order_id.amount_total