# -*- coding: utf-8 -*- from odoo import models, fields, api import re import math class sos__po(models.Model): _name = 'sos_po' _description = 'Purchase Order' _rec_name = 'po_no' _order = 'id desc' def _default_invoicing_address(self): html_content = self.env.company.company_details if not isinstance(html_content, str): html_content = str(html_content) clean_text = re.sub(r'
', '\n', html_content) clean_text = re.sub(r'<[^>]+>', '', clean_text) lines = clean_text.split('\n') for line in lines: if line.strip(): line.strip() return clean_text plan_ref_no = fields.Char( string='Indent No' ) supplier_name = fields.Many2one('sos_suppliers',string="Supplier Name", required= True) supplier_address = fields.Text(related='supplier_name.address',string="Supplier Address") po_no = fields.Char(string="P.O No", readonly= True, required= True, default=lambda self: self._generate_id()) po_date = fields.Datetime(string="P.O Date",required=True) quotation_no = fields.Char(string="Quotation No") quotation_date = fields.Date(string="Quotation Date") material_delivery_required_date = fields.Date(string="Material Delivery Required Date") supplier_gst_no = fields.Char(related='supplier_name.gst_no', string="Supplier GST No", readonly=False) sosaley_gst_no = fields.Char(string="Sosaley GST No",default="33AACCJ0045R1ZI") invoicing_address = fields.Text(string="Invoicing Address",default= _default_invoicing_address) delivery_address = fields.Text(string="Delivery Address",default= _default_invoicing_address) sarf_no = fields.Char(related='supplier_name.supplier_code',string="SARF No") Contact_details = fields.Char(string="Contact Person Name & Mobile No") terms_conditions = fields.Html( string="Terms and Conditions", default="""Below PO is waiting for your Approval
""" send_email = self.env['sos_common_scripts'] send_email.send_group_email(self.env,"sos_po",self.id,"deenalaura.m@sosaley.in","PO Approval Request",body_html,'sos_inventory.sos_scg_group_manager') # Email part ends def action_head_esign_btn(self): # Email part body_html = f"""Below PO is waiting for your Approval
""" subject = f"Purchase Order Approval Request - {self.po_no}" send_email = self.env['sos_common_scripts'] send_email.send_direct_email(self.env,"sos_po",self.id,"ramachandran.r@sosaley.in",subject,body_html) # Email part ends sequence_util = self.env['sos_common_scripts'] return sequence_util.action_assign_signature( self, 'stores_manager_approved_by', 'stores_manager_approved_on' ) def action_top_esign_btn(self): sequence_util = self.env['sos_common_scripts'] sequence_util.action_assign_signature( self, 'top_management_approved_by', 'top_management_approved_on', 'sos_inventory.sos_management_user' ) body_html = f"""Below PO is Approved
""" send_email = self.env['sos_common_scripts'] send_email.send_direct_email(self.env,"sos_po",self.id,"accounts@sosaley.in","PO Approved",body_html) if self.stores_approved_by and self.stores_approved_by.login: send_email.send_direct_email(self.env,"sos_po",self.id,self.stores_approved_by.login,"PO Approved",body_html) @api.depends('total_qty', 'received_qty', 'line_ids.prev_received_qty', 'line_ids.quantity') # ✅ Added 'line_ids.quantity' def _compute_progress(self): for record in self: total_quantity = sum(record.line_ids.mapped('quantity')) prev_received_quantity = sum(record.line_ids.mapped('prev_received_qty')) if total_quantity > 0: percentage = int((prev_received_quantity / total_quantity) * 100) else: percentage = 0 record.progress = percentage if percentage >= 100: record.progress = 100 record.po_status = "close" else: record.po_status = "open" # @api.depends('total_qty', 'received_qty') # def _compute_progress(self): # for po in self: # if po.total_qty > 0: # percentage = (po.received_qty / po.total_qty) * 100 # po.progress = percentage # if percentage >= 100: # po.progress = 100 # po.po_status = "close" # else: # po.progress = 0 @api.depends('line_ids') def _compute_total_qty(self): for po in self: po.total_qty = len(po.line_ids) def _generate_id(self): sequence_util = self.env['sos_common_scripts'] return sequence_util.generate_sequence('sos_po','PO', 'po_no') @api.depends('line_ids.total_price') def _compute_gross_value(self): for record in self: record.gross_value = round(sum(line.total_price for line in record.line_ids), 2) @api.depends('delivery_charges', 'delivery_tax') def _compute_deliverytax(self): for record in self: if record.delivery_charges: delivery_tax_amount = round((record.delivery_tax * record.delivery_charges) / 100, 2) exact_total = round(record.delivery_charges + delivery_tax_amount, 2) if math.isnan(exact_total) or exact_total is None: record.total_value = 0.00 record.delivery_total_value = 0.00 else: rounded_total = round(exact_total) record.delivery_total_value = exact_total record.delivery_tax_amount = delivery_tax_amount else: record.delivery_total_value = 0.00 record.delivery_tax_amount = 0.00 @api.depends('gross_value', 'tax','delivery_total_value') def _compute_total_value(self): for record in self: if record.gross_value: tax_amount = round((int(record.tax) * record.gross_value) / 100, 2) exact_total = round(record.delivery_total_value + record.gross_value + tax_amount, 2) if math.isnan(exact_total) or exact_total is None: record.total_value = 0.00 record.rounded_total_value = 0.00 record.adjustment_value = 0.00 else: rounded_total = round(exact_total) adjustment = round(rounded_total - exact_total, 2) record.total_value = exact_total record.rounded_total_value = rounded_total record.adjustment_value = adjustment record.tax_amount = tax_amount else: record.total_value = 0.00 record.rounded_total_value = 0.00 record.adjustment_value = 0.00 record.tax_amount = 0.00 def action_report_po_btn(self): try: action = self.env.ref("sos_inventory.action_report_po").report_action(self) return action except ValueError as e: print(f"Failed to find report action: {e}") def action_approve_po_btn(self): for record in self: record.approval_status = "Approved" return { 'type':'ir.actions.client', 'tag':'display_notification', 'params':{ 'message':'Approved' } } class Po_Line(models.Model): _name = 'sos_po_line' _description = 'PO Material Lines' po_id = fields.Many2one('sos_po', string="Materials", ondelete="cascade") component_id = fields.Many2one('sos_material', string="Material Name", required=True) material_code = fields.Char(related='component_id.material_code',string="Material Code") qp = fields.Char(related='component_id.qp_no',string="QP #") hsn_code = fields.Char(related='component_id.hsn_code',string="HSN Code #") unit_price = fields.Monetary(string="Unit Price") quantity = fields.Integer(string="Qty", required=True, default=1) prev_received_qty = fields.Integer() currency_id = fields.Many2one('res.currency', string='Currency') total_price = fields.Monetary(compute='_compute_total_cost', string="Total Price", currency_field='currency_id') status = fields.Integer(string="Status",default=0) @api.onchange('prev_received_qty') def _onchange_prev_received_qty(self): if self.prev_received_qty >= self.quantity: self.status = 2 @api.onchange('component_id') def _onchange_component_id(self): if self.component_id: self.unit_price = self.component_id.unit_price else: self.unit_price = 0.0 # Default value when no component is selected @api.depends('unit_price', 'quantity') def _compute_total_cost(self): for record in self: record.total_price = record.unit_price * record.quantity