from odoo import fields, models, api, _ from odoo.exceptions import AccessError, UserError, ValidationError from datetime import datetime, timedelta import logging _logger = logging.getLogger(__name__) class PurchaseOrder(models.Model): _inherit = 'purchase.order' 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([ ('terproses', 'Terproses'), ('sebagian', 'Sebagian Diproses'), ('menunggu', 'Menunggu Diproses'), ]) approval_status = fields.Selection([ ('pengajuan1', 'Approval Manager'), #siapa? darren - 11 ('pengajuan2', 'Approval Pimpinan'), #akbar - 7 temporary not used ('approved', 'Approved'), ], string='Approval Status', readonly=True, copy=False, index=True, tracking=3) delivery_amount = fields.Float('Delivery Amount', compute='compute_delivery_amount') total_margin = fields.Float( 'Margin', compute='compute_total_margin', help="Total Margin in Sales Order Header") total_percent_margin = fields.Float( 'Margin%', compute='compute_total_margin', help="Total % Margin in Sales Order Header") total_so_margin = fields.Float( 'SO Margin', compute='compute_total_margin', help="Total Margin in Sales Order Header") total_so_percent_margin = fields.Float( 'SO Margin%', compute='compute_total_margin', help="Total % Margin in Sales Order Header") amount_total_without_service = fields.Float('AmtTotalWithoutService', compute='compute_amt_total_without_service') summary_qty_po = fields.Float('Total Qty', compute='_compute_summary_qty') summary_qty_receipt = fields.Float('Summary Qty Receipt', compute='_compute_summary_qty') count_line_product = fields.Float('Total Item', compute='compute_count_line_product') note_description = fields.Char(string='Note', help='bisa diisi sebagai informasi indent barang tertentu atau apapun') def _compute_date_planned(self): for order in self: if order.date_approve: current_time = order.date_approve delta_time = current_time + timedelta(days=2) delta_time = delta_time.strftime('%Y-%m-%d %H:%M:%S') order.date_planned = delta_time else: order.date_planned = False def action_create_invoice(self): res = super(PurchaseOrder, self).action_create_invoice() if not self.env.user.is_accounting: raise UserError('Hanya Accounting yang bisa membuat Bill') return res def calculate_line_no(self): line_no = 0 for line in self.order_line: if line.product_id.type == 'product': line_no += 1 line.line_no = line_no # _logger.info('Calculate PO Line No %s' % line.id) def calculate_po_status_beginning(self): purchases = self.env['purchase.order'].search([ ('po_status', '=', False), '|', ('state', '=', 'purchase'), ('state', '=', 'done') ]) for order in purchases: sum_qty_received = sum_qty_po = 0 for po_line in order.order_line: sum_qty_po += po_line.product_uom_qty sum_qty_received += po_line.qty_received if order.summary_qty_po == order.summary_qty_receipt: order.po_status = 'terproses' elif order.summary_qty_po > order.summary_qty_receipt > 0: order.po_status = 'sebagian' else: order.po_status = 'menunggu' _logger.info("Calculate PO Status %s" % order.id) def calculate_po_status(self): purchases = self.env['purchase.order'].search([ ('po_status', '!=', 'terproses'), # ('id', '=', 213), ]) for order in purchases: sum_qty_received = sum_qty_po = 0 have_outstanding_pick = False for pick in order.picking_ids: if pick.state == 'draft' or pick.state == 'assigned' or pick.state == 'confirmed' or pick.state == 'waiting': have_outstanding_pick = True for po_line in order.order_line: sum_qty_po += po_line.product_uom_qty sum_qty_received += po_line.qty_received if have_outstanding_pick: # if order.summary_qty_po == order.summary_qty_receipt: # order.po_status = 'terproses' if order.summary_qty_po > order.summary_qty_receipt > 0: order.po_status = 'sebagian' else: order.po_status = 'menunggu' else: order.po_status = 'terproses' _logger.info("Calculate PO Status %s" % order.id) def _compute_summary_qty(self): for order in self: sum_qty_po = sum_qty_receipt = 0 for line in order.order_line: sum_qty_po += line.product_uom_qty sum_qty_receipt += line.qty_received order.summary_qty_po = sum_qty_po order.summary_qty_receipt = sum_qty_receipt def get_procurement_status(self): for purchase_order in self: # product_uom_qty = sum_qty_received = 0 # # for order_line in purchase_order.order_line: # product_uom_qty += order_line.product_uom_qty # sum_qty_received += order_line.qty_received if purchase_order.summary_qty_po == purchase_order.summary_qty_receipt: status = 'Terproses' elif purchase_order.summary_qty_po > purchase_order.summary_qty_receipt > 0: status = 'Sebagian Diproses' else: status = 'Menunggu Diproses' purchase_order.procurement_status = status def sale_order_sync(self): if not self.sale_order_id: return purchase_orders = self.search(['&', ('sale_order_id', '=', self.sale_order_id.id), ('id', '!=', self.id)]) products_exception = [] for purchase_order in purchase_orders: for order_line in purchase_order.order_line: products_exception.append(order_line.product_id.id) self.order_line.unlink() for order_line in self.sale_order_id.order_line: if order_line.product_id.id and order_line.product_id.id not in products_exception: qty_available = order_line.product_id.qty_onhand_bandengan + order_line.product_id.qty_incoming_bandengan - order_line.product_id.outgoing_qty suggest = 'harus beli' if qty_available > order_line.product_qty: suggest = 'masih cukup' values = { 'order_id': self.id, 'product_id': order_line.product_id.id, 'name': order_line.product_id.display_name, 'product_qty': order_line.product_qty, 'qty_available_store': qty_available, 'suggest': suggest, } self.order_line.create(values) def compute_count_line_product(self): for order in self: count = 0 for line in order.order_line: if line.product_id.type == 'product': count += 1 if count == 0: order.count_line_product = 1 else: order.count_line_product = count def compute_delivery_amount(self): for order in self: amount = 0 for line in order.order_line: if line.product_id.type == 'service': amount += line.price_total order.delivery_amount = amount def button_confirm(self): res = super(PurchaseOrder, self).button_confirm() if self.total_percent_margin < self.total_so_percent_margin and not self.env.user.is_purchasing_manager and not self.env.user.is_leader: raise UserError("Beda Margin dengan Sales, harus approval Manager") if not self.sale_order_id and not self.env.user.is_purchasing_manager and not self.env.user.is_leader: raise UserError("Tidak ada link dengan SO, harus approval Manager") for line in self.order_line: if not line.product_id.purchase_ok: raise UserError("Terdapat barang yang tidak bisa di proses") self.approval_status = 'approved' self.po_status = 'menunggu' self.calculate_line_no() # override date planned added with two days current_time = datetime.now() delta_time = current_time + timedelta(days=2) delta_time = delta_time.strftime('%Y-%m-%d %H:%M:%S') self.date_planned = delta_time return res def po_approve(self): if self.env.user.is_leader or self.env.user.is_purchasing_manager: raise UserError("Bisa langsung Confirm") elif self.total_percent_margin == self.total_so_percent_margin and self.sale_order_id: raise UserError("Bisa langsung Confirm") else: self.approval_status = 'pengajuan1' def re_calculate(self): for line in self.order_line: sale_order_line = self.env['sale.order.line'].search([ ('product_id', '=', line.product_id.id), ('order_id', '=', line.order_id.sale_order_id.id) ], limit=1, order='price_reduce_taxexcl') for so_line in sale_order_line: unit_price = line.price_unit so_line.purchase_price = unit_price def button_cancel(self): res = super(PurchaseOrder, self).button_cancel() self.approval_status = False return res def compute_total_margin(self): sum_so_margin = sum_sales_price = sum_margin = 0 for line in self.order_line: sale_order_line = self.env['sale.order.line'].search( [('product_id', '=', line.product_id.id), ('order_id', '=', line.order_id.sale_order_id.id)], limit=1, order='price_reduce_taxexcl') sum_so_margin += sale_order_line.item_margin sales_price = sale_order_line.price_reduce_taxexcl * sale_order_line.product_uom_qty if sale_order_line.order_id.shipping_cost_covered == 'indoteknik': sales_price -= sale_order_line.delivery_amt_line if sale_order_line.order_id.fee_third_party > 0: sales_price -= sale_order_line.fee_third_party_line sum_sales_price += sales_price purchase_price = line.price_subtotal if line.order_id.delivery_amount > 0: purchase_price += line.delivery_amt_line real_item_margin = sales_price - purchase_price sum_margin += real_item_margin if sum_so_margin != 0 and sum_sales_price != 0 and sum_margin != 0: self.total_so_margin = sum_so_margin self.total_so_percent_margin = round((sum_so_margin / sum_sales_price), 2) * 100 self.total_margin = sum_margin self.total_percent_margin = round((sum_margin / sum_sales_price), 2) * 100 else: self.total_margin = 0 self.total_percent_margin = 0 self.total_so_margin = 0 self.total_so_percent_margin = 0 def compute_amt_total_without_service(self): for order in self: sum_price_total = 0 for line in order.order_line: if line.product_id.type == 'product': sum_price_total += line.price_total order.amount_total_without_service = sum_price_total