# -*- coding: utf-8 -*- from odoo import models, fields, api import re import math class sos__wo(models.Model): _name = 'sos_wo' _description = 'Work Order' _rec_name = 'wo_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.Many2one('sos_fg_plan',string="Indent No") supplier_name = fields.Many2one('sos_service_providers',string="Service Provider Name") supplier_address = fields.Char(related='supplier_name.address',string="Service Provider Address") wo_no = fields.Char(string="W.O No", readonly= True, required= True, default=lambda self: self._generate_id()) wo_date = fields.Datetime(string="W.O Date", help="You can choose the date," " Otherwise sets to current 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.service_provider_code',string="SARF No") Contact_details = fields.Char(string="Contact Person Name & Mobile No") terms_conditions = fields.Html( string="Terms and Conditions", default="""

Terms and Conditions:


1. This Work Order is valid up to …………………………….
2. Payment: ................. from the date of receipt of the Invoice.
3. Invoice and Material Final Inspection Report should be provided with all the Supplies made.
4. Sosaley W.O. No. should be mentioned in your Delivery challan / Invoice.
5. All the products shall be supplied with closed boxes/containers and labelled.
6. All the boxes/containers shall be numbered (1 of 3, 2 of 3, etc.) """ ) currency_id = fields.Many2one('res.currency', string='Currency') line_ids = fields.One2many('sos_wo_line', 'wo_id', string="Components") gross_value = fields.Monetary(compute='_compute_gross_value', string="Gross Value", currency_field='currency_id', readonly=True) total_value = fields.Monetary(compute='_compute_total_value', string="Total Value", currency_field='currency_id', readonly=True) approval_status=fields.Selection([('Approved', 'Approve'),('Rejected', 'Reject')],string="Approval Status") indent_id = fields.Integer(String="Integer") total_qty = fields.Integer(string='Total Line Items Count', compute='_compute_total_qty', store=True) received_qty = fields.Integer(string='Received Line Items Count', store=True) payment_method=fields.Selection([('neft', 'NEFT'),('credit', 'Credit'),('credit_card', 'Credit Card')],string="Payment Method") wo_status = fields.Selection([ ('amend', 'Amended'),('open', 'Open'),('close', 'Closed')], default='open' , string="Status") progress = fields.Float(string="Completion Percentage", compute='_compute_progress', store=True) dc_no = fields.Many2one('sos_dc',string="DC Reference No", readonly= True) stores_approved_by = fields.Many2one('res.users', string='Manager Approval By') stores_approved_image = fields.Image(related="stores_approved_by.signature_image",string='Top Management Approval Sign',readonly=True) stores_approved_on = fields.Datetime(string="Approved On") wo_planned_at = fields.Selection([('inhouse', 'In-House'),('outsource', 'Out-Sourcing')],default="outsource",string="W.O Planned at") stores_manager_approved_by = fields.Many2one('res.users', string='Manager Approval By') stores_manager_approved_image = fields.Image(related="stores_manager_approved_by.signature_image",string='Top Management Approval Sign',readonly=True) stores_manager_approved_on = fields.Datetime(string="Approved On") remarks = fields.Text(string="Remarks") top_management_approved_by = fields.Many2one('res.users', string='Top Management Approver') top_management_approval_image = fields.Image(related="top_management_approved_by.signature_image",string='Top Management Approval',readonly=True) top_management_approved_on = fields.Datetime(string="Approved On") rounded_total_value = fields.Float(string="Total Value", compute="_compute_total_value", store=True) adjustment_value = fields.Float(string="Round-off", compute="_compute_total_value", store=True) nre_charges = fields.Monetary(string="NRE Charges", currency_field='currency_id') nre_tax = fields.Integer(default=18,string="Tax (%)") nre_tax_amount = fields.Float(string="NRE Tax Value", store=True,readonly=True, compute="_compute_nretax") nre_total_value = fields.Float(string="Total", store=True) @api.depends('nre_charges', 'nre_tax') def _compute_nretax(self): for record in self: if record.nre_charges: nre_tax_amount = round((record.nre_tax * record.nre_charges) / 100, 2) exact_total = round(record.nre_charges + nre_tax_amount, 2) if math.isnan(exact_total) or exact_total is None: record.total_value = 0.00 record.nre_total_value = 0.00 else: rounded_total = round(exact_total) record.nre_total_value = exact_total record.nre_tax_amount = nre_tax_amount else: record.nre_total_value = 0.00 record.nre_tax_amount = 0.00 def action_amend(self): active_ids = self.env.context.get('active_ids', []) records = self.browse(active_ids) for record in records: record.wo_status = 'amend' return { 'type': 'ir.actions.client', 'tag': 'display_notification', 'params': { 'title': 'Amended', 'message': 'The selected record(s) have been amended.', 'sticky': False, } } def action_esign_btn(self): sequence_util = self.env['sos_common_scripts'] sequence_util.action_assign_signature( self, 'stores_approved_by', 'stores_approved_on', 'sos_inventory.sos_scg_group_user' ) # Email part body_html = f"""

Below WO is waiting for your Approval

""" send_email = self.env['sos_common_scripts'] send_email.send_group_email(self.env,"sos_wo",self.id,"deenalaura.m@sosaley.in","WO 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 WO is waiting for your Approval

""" subject = f"Work Order Approval Request - {self.wo_no}" send_email = self.env['sos_common_scripts'] send_email.send_direct_email(self.env,"sos_wo",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'] return sequence_util.action_assign_signature( self, 'top_management_approved_by', 'top_management_approved_on', 'sos_inventory.sos_management_user' ) @api.depends('line_ids.status') def _compute_progress(self): for record in self: line_count = len(record.line_ids) if line_count == 0: record.progress = 0 record.wo_status = 'open' else: progress_sum = 0 for line in record.line_ids: if line.status == 2: progress_sum += 1 elif line.status == 1: progress_sum += 0.5 record.progress = (progress_sum / line_count) * 100 record.wo_status = 'close' if record.progress == 100 else 'open' @api.onchange('progress') def _onchange_progress_status(self): for record in self: if record.progress == 100: record.wo_status = 'close' else: record.wo_status = 'open' # @api.depends('total_qty', 'received_qty') # def _compute_progress(self): # print(self.received_qty,self.total_qty) # for po in self: # if po.total_qty > 0: # print(po.received_qty,po.total_qty) # percentage = (po.received_qty / po.total_qty) * 100 # po.progress = percentage # if percentage >= 100: # po.progress = 100 # po.wo_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_wo','WO', 'wo_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('gross_value','nre_total_value') def _compute_total_value(self): for record in self: if record.wo_planned_at != "inhouse": if record.gross_value: exact_total = round(record.nre_total_value + record.gross_value, 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 else: record.total_value = 0.00 record.rounded_total_value = 0.00 record.adjustment_value = 0.00 else: record.total_value = 0.00 record.rounded_total_value = 0.00 record.adjustment_value = 0.00 def action_report_wo_btn(self): try: action = self.env.ref("sos_inventory.action_report_wo").report_action(self) return action except ValueError as e: print(f"Failed to find report action: {e}") def action_approve_wo_btn(self): for record in self: record.approval_status = "Approved" return { 'type':'ir.actions.client', 'tag':'display_notification', 'params':{ 'message':'Approved' } } class Wo_Line(models.Model): _name = 'sos_wo_line' _description = 'WO Material Lines' wo_id = fields.Many2one('sos_wo', string="Materials", ondelete="cascade") wo_planned_at = fields.Selection([('inhouse', 'In-House'),('outsource', 'Out-Sourcing')],default="outsource",string="W.O Planned at",related='wo_id.wo_planned_at') component_id = fields.Many2one('sos_sfg', string="SFG Name", required=True) 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") last_received_quantity = fields.Integer(string="Last Received Qty") quantity = fields.Integer(string="Qty", required=True, default=1) currency_id = fields.Many2one('res.currency', string='Currency') total_price = fields.Monetary(compute='_compute_total_cost', string="Total Price (Tax Inclusive)", currency_field='currency_id') status = fields.Integer(string="Status",default=0,compute='_compute_status') tax = fields.Selection( [ ('6', '6%'), ('12', '12%'), ('18', '18%'), ('28', '28%') ], string="Tax (%)" ) @api.depends('last_received_quantity', 'quantity') def _compute_status(self): for record in self: if record.last_received_quantity and record.last_received_quantity >= record.quantity: record.status = 2 elif record.last_received_quantity: record.status = 1 else: record.status = 0 @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 @api.depends('unit_price', 'quantity','tax') def _compute_total_cost(self): for record in self: gross_value = record.unit_price * record.quantity tax_amount = round((int(record.tax) * gross_value) / 100, 2) record.total_price = tax_amount + gross_value