from odoo import fields, models, api, tools, _ import logging from datetime import datetime _logger = logging.getLogger(__name__) class PurchasingJob(models.Model): _name = 'v.purchasing.job' _auto = False _rec_name = 'product_id' product_id = fields.Many2one('product.product', string="Product") vendor_id = fields.Many2one('res.partner', string="Vendor") brand = fields.Char(string='Brand') item_code = fields.Char(string='Item Code') product = fields.Char(string='Product Name') onhand = fields.Float(string='OnHand') incoming = fields.Float(string="Incoming") outgoing = fields.Float(string="Outgoing") action = fields.Char(string="Status") status_apo = fields.Selection([ ('not_apo', 'Belum APO'), ('apo', 'APO') ], string='APO?') purchase_representative_id = fields.Many2one('res.users', string="Purchase Representative", readonly=True) note = fields.Char(string="Note") note_detail = fields.Text(string="Note Detail") date_po = fields.Datetime(string='Date PO', copy=False) so_number = fields.Text(string='SO Number', copy=False) check_pj = fields.Boolean(compute='_get_check_pj', string='Linked') def action_open_job_detail(self): self.ensure_one() Seen = self.env['purchasing.job.seen'] seen = Seen.search([ ('product_id', '=', self.product_id.id) ], limit=1) if seen: seen.write({ 'so_snapshot': self.so_number, 'seen_date': fields.Datetime.now(), 'user_id': self.env.user.id, }) else: Seen.create({ 'user_id': self.env.user.id, 'product_id': self.product_id.id, 'so_snapshot': self.so_number, }) return { 'name': 'Purchasing Job Detail', 'type': 'ir.actions.act_window', 'res_model': 'v.purchasing.job', 'res_id': self.id, 'view_mode': 'form', 'target': 'current', } @api.depends('so_number') def _get_check_pj(self): seen = self.env['purchasing.job.seen'] for rec in self: seen = seen.search([('product_id', '=', rec.product_id.id)], limit=1) rec.check_pj = bool(seen and seen.so_snapshot == rec.so_number) def _set_as_seen(self): Seen = self.env['purchasing.job.seen'] for rec in self: seen = Seen.search([ ('product_id', '=', rec.product_id.id) ], limit=1) if seen: seen.write({ 'so_snapshot': rec.so_number, 'seen_date': fields.Datetime.now(), 'user_id': rec.env.user.id, }) else: Seen.create({ 'user_id': self.env.user.id, 'product_id': rec.product_id.id, 'so_snapshot': rec.so_number, }) rec.check_pj = True def unlink(self): # Example: Delete related records from the underlying model underlying_records = self.env['purchasing.job'].search([ ('product_id', 'in', self.mapped('product_id').ids) ]) underlying_records.unlink() return super(PurchasingJob, self).unlink() def redirect_to_pjs(self): states = self.env['purchasing.job.state'].search([ ('purchasing_job_id', '=', self.id), ],limit=1, order='id desc') return { 'name': _('Purchasing Job State'), 'view_mode': 'form', 'res_model': 'purchasing.job.state', 'target': 'new', 'type': 'ir.actions.act_window', 'res_id': states.id, } def init(self): tools.drop_view_if_exists(self.env.cr, self._table) self.env.cr.execute(""" CREATE OR REPLACE VIEW %s AS SELECT pmp.product_id AS id, pmp.product_id, sub.vendor_id, pmp.brand, pmp.item_code, pmp.product, max(pmp.onhand) AS onhand, max(pmp.incoming) AS incoming, max(pmp.outgoing) AS outgoing, pmp.action, max(pjs.status_apo::text) AS status_apo, max(pjs.note::text) AS note, max(pjs.note_detail::text) AS note_detail, max(pjs.date_po::text) AS date_po, pmp.so_number, CASE WHEN pmp.brand IN ('Tekiro', 'RYU', 'Rexco', 'RYU (Sparepart)') THEN 27 WHEN sub.vendor_id = 9688 THEN 397 WHEN sub.vendor_id = 35475 THEN 397 WHEN sub.vendor_id = 29712 THEN 397 ELSE 1036 END AS purchase_representative_id FROM v_procurement_monitoring_by_product pmp LEFT JOIN purchasing_job_state pjs ON pjs.purchasing_job_id = pmp.product_id LEFT JOIN ( SELECT vso.product_id, max(sol.vendor_id) as vendor_id FROM v_sales_outstanding vso LEFT JOIN sale_order_line sol ON sol.id = vso.sale_line_id group by vso.product_id ) sub ON sub.product_id = pmp.product_id WHERE pmp.action = 'kurang'::text AND sub.vendor_id IS NOT NULL GROUP BY pmp.product_id, pmp.brand, pmp.item_code, pmp.product, pmp.action, sub.vendor_id, pmp.so_number; """ % self._table) def open_form_multi_generate_request_po(self): action = self.env['ir.actions.act_window']._for_xml_id('indoteknik_custom.action_purchasing_job_multi_update') action['context'] = { 'product_ids': [x.id for x in self] } return action def generate_request_po(self): # print(1) # TODO create document automatic purchase current_time = datetime.utcnow() automatic_purchase = self.env['automatic.purchase'].create([{ 'apo_type': 'regular', 'date_doc': current_time, }]) count = 0 for job in self: print(job.product_id.name) qty_purchase = job.outgoing - (job.onhand + job.incoming) qty_available = (job.onhand + job.incoming) - job.outgoing domain = [ ('product_id.id', '=', job.product_id.id), ] orderby = 'count_trx_po desc, count_trx_po_vendor desc' purchase_pricelist = self.env['purchase.pricelist'].search(domain, order=orderby, limit=1) vendor_id = purchase_pricelist.vendor_id price, taxes = automatic_purchase._get_valid_purchase_price(purchase_pricelist) last_po_line = self.env['purchase.order.line'].search([('product_id', '=', job.product_id.id), ('order_id.state', '=', 'done')], order='id desc', limit=1) self.env['automatic.purchase.line'].create([{ 'automatic_purchase_id': automatic_purchase.id, 'product_id': job.product_id.id, 'qty_purchase': qty_purchase, 'qty_available': qty_available, 'partner_id': job.vendor_id.id, 'last_price': price, 'taxes_id': taxes, 'subtotal': qty_purchase * price, 'last_order_id': last_po_line.order_id.id, 'last_orderline_id': last_po_line.id, 'brand_id': job.product_id.product_tmpl_id.x_manufacture.id }]) automatic_purchase._create_sales_matching() automatic_purchase._create_sync_purchasing_job(job) count += 1 _logger.info('Create Automatic Purchase Line %s' % job.product_id.name) return automatic_purchase.id class OutstandingSales(models.Model): _name = 'v.sales.outstanding' _auto = False _rec_name = 'move_id' id = fields.Integer() move_id = fields.Many2one('stock.move', string='Move') picking_id = fields.Many2one('stock.picking', string='Picking') product_id = fields.Many2one('product.product', string='Product') sale_id = fields.Many2one('sale.order', string='Sale') sale_line_id = fields.Many2one('sale.order.line', string='Sale Line') 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='Salesperson') origin = fields.Char(string='Origin') salesperson = fields.Char(string='Sales Name') item_code = fields.Char(string='Item Code') product = fields.Char(string='Product') outgoing = fields.Float(string='Outgoing') brand = fields.Char(string='Brand') invoice_partner = fields.Char(string='Invoice Partner') sale_order_create_date = fields.Datetime(string='Sale Order Create Date') def init(self): tools.drop_view_if_exists(self.env.cr, self._table) self.env.cr.execute(""" CREATE OR REPLACE VIEW v_sales_outstanding AS ( select sm.id, sm.id as move_id, sp.id as picking_id, sm.product_id, so.id as sale_id, sol.id as sale_line_id, rp.id as partner_id, so.user_id as salesperson_id, so.partner_invoice_id, sp.origin, rp2.name as salesperson, coalesce(pp.default_code, pt.default_code) as item_code, pt.name as product, sm.product_uom_qty as outgoing, xm.x_name as brand, rp.name as invoice_partner, so.create_date as sale_order_create_date from stock_move sm join stock_picking sp on sp.id = sm.picking_id join sale_order_line sol on sol.id = sm.sale_line_id join sale_order so on so.id = sol.order_id join res_partner rp on rp.id = so.partner_invoice_id join res_users ru on ru.id = so.user_id join res_partner rp2 on rp2.id = ru.partner_id join product_product pp on pp.id = sm.product_id join product_template pt on pt.id = pp.product_tmpl_id left join x_manufactures xm on xm.id = pt.x_manufacture where sp.state in ('draft', 'waiting', 'confirmed', 'assigned') and sm.state in ('draft', 'waiting', 'confirmed', 'partially_available') and sp.name like '%OUT%' ) """) class PurchasingJobSeen(models.Model): _name = 'purchasing.job.seen' _description = 'User Seen SO Snapshot' _rec_name = 'product_id' user_id = fields.Many2one('res.users', required=True, ondelete='cascade') product_id = fields.Many2one('product.product', required=True, ondelete='cascade') so_snapshot = fields.Text("Last Seen SO") seen_date = fields.Datetime(default=fields.Datetime.now) _sql_constraints = [ ('user_product_unique', 'unique(user_id, product_id)', 'User already tracked this product.') ]