# -*- coding: utf-8 -*- from odoo import models, fields, api import re class sos__dc(models.Model): _name = 'sos_dc' _description = 'Delivery Challan' _rec_name = 'dc_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 dc_no = fields.Char(string="D.C No", readonly= True, required= True, default=lambda self: self._generate_id()) dock_audit_no = fields.Many2one('sos_dock_audit',string="Fill Challan against Dock Audit") dc_date = fields.Datetime(string="D.C Date",required=True) dispatch_mode=fields.Selection([('By Courier', 'By Courier'),('By Hand', 'By Hand'),('By Direct Delivery', 'By Direct Delivery')],string="Mode of Dispatch") from_station = fields.Char(string="From Station",default="Sosaley Technologies Private Limited,Chennai") to_station = fields.Char(string="To Station") sosaley_gst_no = fields.Char(string="Sosaley GST No",default="33AACCJ0045R1ZI") customer_gst_no = fields.Char(string="Customer GST No") purpose = fields.Char(string="Remarks") purpose_remarks=fields.Selection([('Outsourcing', 'Outsourcing'),('Sales', 'Sales'),('I&C / Service', 'I&C / Service'),('Demo', 'Demo'),('Validation', 'Validation'),('Warranty', 'Warranty')],string="Purpose") indent_no = fields.Many2one('sos_fg_plan', string='Ref No') po_no = fields.Char(string="PO No") invoice_no = fields.Char(string="Invoice No") carried_by = fields.Many2one('res.users', string='Carried By') billing_address = fields.Text(string="Billing Address") to_address = fields.Text(string="Shipping Address") approval_name = fields.Many2one('res.users', string='Prepared By') approval_image = fields.Image(related="approval_name.signature_image",string='Authorised Signatory',readonly=True) approved_on = fields.Datetime(string="Approved On") line_ids = fields.One2many('sos_dc_line', 'dc_id') line_ids_miscellaneous = fields.One2many('sos_dc_line_miscellaneous', 'dc_id') line_ids_materials = fields.One2many('sos_dc_line_material', 'dc_id') line_ids_sfg = fields.One2many('sos_dc_line_sfg', 'dc_id') line_ids_fg = fields.One2many('sos_dc_line_fg', 'dc_id') dc_type = fields.Selection([ ('others', 'Others'),('out_souce_return', 'Outsourcing / Returnable'),('out_souce_noreturn', 'Outsourcing / Non-Returnable'),('customer_return', 'Customer / Returnable'),('customer_noreturn', 'Customer / Non-Returnable')], default='customer_return' , string="Type") wo_no = fields.Many2one('sos_wo', string="W.O No", domain="[('wo_status', '=', 'open')]") auto_load_sfg_items = fields.Many2many('sos_sfg', string='SFG Name') auto_load_sfg_items_domain = fields.Char(compute='_compute_auto_load_sfg_items_domain') order_qty = fields.Integer(string="Order Quantity",default=1) service_provider_name = fields.Many2one('sos_service_providers',string="Service Provider Name") top_management_name = fields.Many2one('res.users', string='Top Management Approver') top_management_approval_image = fields.Image(related="top_management_name.signature_image",string='Top Management Approval',readonly=True) top_management_approved_on = fields.Datetime(string="Approved On") dept_in_charge_name = fields.Many2one('res.users', string='Department In-Charge') dept_in_charge_image = fields.Image(related="dept_in_charge_name.signature_image",string='Department In-Charge Sign',readonly=True) dept_in_charge_approved_on = fields.Datetime(string="Approved On") remarks = fields.Text(string="Remarks") @api.onchange('dock_audit_no') def _onchange_dock_audit_no(self): if self.dock_audit_no: self.billing_address = self.dock_audit_no.billing_address self.to_address = self.dock_audit_no.shipping_address self.po_no = self.dock_audit_no.customer_po_no self.purpose = self.dock_audit_no.purpose self.invoice_no = self.dock_audit_no.invoice_no self.customer_gst_no = self.dock_audit_no.gst_no self.line_ids_materials = [(5, 0, 0)] self.line_ids_materials = [ (0, 0, { 'component_id': line.component_id, 'uom': line.uom, 'qty': line.quantity }) for line in self.dock_audit_no.line_ids_material ] self.line_ids_materials = [ (0, 0, { 'component_id': line.component_id, 'uom': line.uom, 'qty': line.quantity }) for line in self.dock_audit_no.line_ids_installation_kit ] self.line_ids_sfg = [(5, 0, 0)] self.line_ids_sfg = [ (0, 0, { 'component_id': line.component_id, 'uom': line.uom, 'qty': line.quantity }) for line in self.dock_audit_no.line_ids_sfg ] self.line_ids_fg = [(5, 0, 0)] self.line_ids_fg = [ (0, 0, { 'component_id': line.component_id, 'uom': line.uom, 'qty': line.quantity }) for line in self.dock_audit_no.line_ids_fg ] self.line_ids_miscellaneous = [(5, 0, 0)] self.line_ids_miscellaneous = [ (0, 0, { 'description': line.name, 'qty': line.quantity }) for line in self.dock_audit_no.line_ids_miscellaneous ] @api.onchange('service_provider_name') def _onchange_service_provider_name(self): if self.service_provider_name and (self.dc_type == 'out_souce_return' or self.dc_type == 'out_souce_noreturn'): if self.service_provider_name.address: self.to_address = self.service_provider_name.address self.to_station = self.service_provider_name.service_provider_name else: self.to_address = False self.to_station = False else: self.to_address = False self.to_station = False @api.onchange('order_qty') def _onchange_order_qty(self): if self.auto_load_sfg_items: self.line_ids = [(5, 0, 0)] for sfg_item in self.auto_load_sfg_items: sfg_record = self.env['sos_sfg_bom'].search([('name', '=', sfg_item.name)], limit=1) if sfg_record: sfg_materials = self.env['sos_sfg_bom_line'].search([('bom_id', '=', sfg_record.id)]) material_lines = [] for material in sfg_materials: line_vals = { 'component_id': material.primary_component_id.id, 'uom': material.primary_component_id.uom, 'req_qty': material.quantity * self.order_qty, 'given_qty': material.quantity * self.order_qty, 'uom': 'Nos' } material_lines.append((0, 0, line_vals)) self.line_ids = material_lines else: print(f"No matching BOM found for the selected SFG item: {sfg_item.name}") @api.depends('wo_no') def _compute_auto_load_sfg_items_domain(self): for record in self: if record.wo_no: component_ids = record.wo_no.line_ids.mapped('component_id.id') record.auto_load_sfg_items_domain = [('id', 'in', component_ids)] else: record.auto_load_sfg_items_domain = [] @api.onchange('auto_load_sfg_items') def _onchange_auto_load_sfg_items(self): if self.auto_load_sfg_items: # Clear existing lines first self.line_ids = [(5, 0, 0)] # This clears the existing lines # Loop through each selected item in the Many2many field for sfg_item in self.auto_load_sfg_items: # Search for the SFG record sfg_record = self.env['sos_sfg_bom'].search([('name', '=', sfg_item.name)], limit=1) if sfg_record: # Get all materials related to the selected SFG sfg_materials = self.env['sos_sfg_bom_line'].search([('bom_id', '=', sfg_record.id)]) # Loop through the materials and prepare the data material_lines = [] for material in sfg_materials: line_vals = { 'component_id': material.primary_component_id.id, 'uom': material.primary_component_id.uom, # Ensure the UOM field is correctly referenced 'req_qty': material.quantity, 'given_qty': material.quantity, 'uom': 'Nos' # Update UOM if needed } # Append the material lines as a tuple (0, 0, line_vals) material_lines.append((0, 0, line_vals)) # Assign the new lines to the line_ids field self.line_ids = material_lines else: print(f"No matching BOM found for the selected SFG item: {sfg_item.name}") def _generate_id(self): sequence_util = self.env['sos_common_scripts'] return sequence_util.generate_sequence('sos_dc','DC', 'dc_no') def action_report_dc_btn(self): try: action = self.env.ref("sos_inventory.action_report_dc").report_action(self) return action except ValueError as e: print(f"Failed to find report action: {e}") def approved_by_sign_btn(self): # Email part body_html = f"""Below DC is waiting for your Approval
""" subject = f"Delivery Challan Approval Request - {self.dc_no}" sequence_util = self.env['sos_common_scripts'] sequence_util.send_mon_min_email(self.env,"sos_dc",self.id,"deenalaura.m@sosaley.in",subject,body_html,"user") sequence_util.action_assign_signature( self, 'approval_name', 'approved_on' ) def deptincharge_sign_btn(self): # Email part body_html = f"""Below DC is waiting for your Approval
""" subject = f"Delivery Challan Approval Request - {self.dc_no}" send_email = self.env['sos_common_scripts'] send_email.send_direct_email(self.env,"sos_dc",self.id,"ramachandran.r@sosaley.in",subject,body_html) # Email part ends sequence_util = self.env['sos_common_scripts'] sequence_util.action_assign_signature( self, 'dept_in_charge_name', 'dept_in_charge_approved_on' ) def action_top_esign(self): if self.wo_no: sos_dc_record = self.env['sos_wo'].search([('id', '=', self.wo_no.id)], limit=1) if sos_dc_record: sos_dc_record.write({'dc_no': self.id}) sequence_util = self.env['sos_common_scripts'] sequence_util.action_assign_signature( self, 'top_management_name', 'top_management_approved_on', 'sos_inventory.sos_management_user' ) # Email part body_html = f"""Below DC was Approved
""" send_email = self.env['sos_common_scripts'] send_email.send_direct_email(self.env,"sos_dc",self.id,self.approval_name.login,"Delivery Challan Approved",body_html) # Email part ends class DC_Line(models.Model): _name = 'sos_dc_line' _description = 'DC Lines' dc_id = fields.Many2one('sos_dc', ondelete="cascade") description = fields.Char(string="Description") qty = fields.Integer(string="Quantity") uom = fields.Selection([('Nos', 'Nos'),('litre', 'litre'), ('meters', 'Meters'), ('Strips', 'Strips'), ('Packs', 'Packs')], string="Uom", default='Nos') component_id = fields.Many2one('sos_material', string="Material Part No") req_qty = fields.Integer(string="Required Quantity") given_qty = fields.Integer(string="Given Quantity") display_name = fields.Char(string="Material Name", compute="_compute_display_name", store=True) @api.depends('component_id') def _compute_display_name(self): for record in self: if record.component_id: record.display_name = record.component_id.name or record.component_id.part_no else: record.display_name = False # or an empty string '' class DC_Line_miscellaneous(models.Model): _name = 'sos_dc_line_miscellaneous' _description = 'DC Lines Miscellaneous' dc_id = fields.Many2one('sos_dc', ondelete="cascade") description = fields.Char(string="Description") qty = fields.Integer(string="Quantity") uom = fields.Selection([('Nos', 'Nos'),('litre', 'litre'), ('meters', 'Meters'), ('Strips', 'Strips')], string="Uom", default='Nos') class DC_Line_Materials(models.Model): _name = 'sos_dc_line_material' _description = 'DC Lines Material' dc_id = fields.Many2one('sos_dc', ondelete="cascade") qty = fields.Integer(string="Quantity") uom = fields.Selection([('Nos', 'Nos'),('litre', 'litre'), ('meters', 'Meters'), ('Strips', 'Strips')], string="Uom", default='Nos') component_id = fields.Many2one('sos_material', string="Material Part No") display_name = fields.Char(string="Material Name", compute="_compute_display_name", store=True) @api.depends('component_id') def _compute_display_name(self): for record in self: if record.component_id: record.display_name = record.component_id.name or record.component_id.part_no else: record.display_name = False # or an empty string '' class DC_Line_SFG(models.Model): _name = 'sos_dc_line_sfg' _description = 'DC Lines SFG' dc_id = fields.Many2one('sos_dc', ondelete="cascade") qty = fields.Integer(string="Quantity") uom = fields.Selection([('Nos', 'Nos'),('set', 'Set')], string="Uom", default='Nos') component_id = fields.Many2one('sos_sfg', string="SFG Name") class DC_Line_FG(models.Model): _name = 'sos_dc_line_fg' _description = 'DC Lines FG' dc_id = fields.Many2one('sos_dc', ondelete="cascade") qty = fields.Integer(string="Quantity") uom = fields.Selection([('Nos', 'Nos'),('set', 'Set')], string="Uom", default='Nos') component_id = fields.Many2one('sos_fg', string="FG Name") serial_no = fields.Char(string="Serial No")