# -*- coding: utf-8 -*- from odoo import models, fields, api import time from odoo.exceptions import UserError class sos_deliverables_boq(models.Model): _name = 'sos_deliverables_boq' _description = 'Deliverables/BOQ' _rec_name = 'sales_id' _order = 'id desc' sales_id = fields.Many2one('sos_sales_order',string="Sales Order Id") fg_name = fields.Selection( [ ('BHMS 1.2V', 'BHMS 1.2V'), ('BHMS 2V', 'BHMS 2V'), ('BHMS 12V', 'BHMS 12V'), ('BHMS 48V', 'BHMS 48V'), ('BMS-HV', 'BMS-HV'), ('BMS-LV 100A', 'BMS-LV 100A'), ('BMS-LV 40A', 'BMS-LV 40A'), ('SBMS 55A', 'SBMS 55A'), ('MC 250W', 'MC 250W'), ('HeartTarang', 'HeartTarang') ], string="Product Name",required=True) quantity = fields.Integer(string="Quantity") master_quantity = fields.Integer(string="Master Quantity") slave_quantity = fields.Integer(string="Slave Quantity") show_ev_fields = fields.Boolean(string="Show BMS Fields", compute="_compute_show_bms_fields", store=True) customer_name = fields.Char(string="Customer Name") customer_location = fields.Char(string="Customer Location") lead_time = fields.Datetime(string="Lead Time") scg_comments = fields.Text(string="Comments") rd_comments = fields.Text(string="Comments") production_comments = fields.Text(string="Comments") qc_comments = fields.Text(string="Comments") qa_comments = fields.Text(string="Comments") customer_po_no = fields.Char(string="PO No") customer_po_date = fields.Datetime(string="PO Date") line_ids_material = fields.One2many('sos_deliverables_line_material', 'ref_id', string="Materials",copy=True) line_ids_sfg = fields.One2many('sos_deliverables_line_sfg', 'ref_id', string="Semi-Finished Goods",copy=True) line_ids_fg = fields.One2many('sos_deliverables_line_fg', 'ref_id', string="Finished Goods",copy=True) line_ids_miscellaneous = fields.One2many('sos_deliverables_miscellaneous_items', 'ref_id',string="") line_ids_installation_kit = fields.One2many('sos_deliverables_line_material_installation', 'ref_id',string="") scg_reviewed_by = fields.Many2one('res.users', string='Prepared by') scg_reviewed_by_image = fields.Image(related="scg_reviewed_by.signature_image",string='Reviewed by Sign',readonly=True) scg_reviewed_on = fields.Datetime(string="Approved On") rd_reviewed_by = fields.Many2one('res.users', string='Prepared by') rd_reviewed_by_image = fields.Image(related="rd_reviewed_by.signature_image",string='Reviewed by Sign',readonly=True) rd_reviewed_on = fields.Datetime(string="Approved On") production_reviewed_by = fields.Many2one('res.users', string='Prepared by') production_reviewed_by_image = fields.Image(related="production_reviewed_by.signature_image",string='Reviewed by Sign',readonly=True) production_reviewed_on = fields.Datetime(string="Approved On") qc_reviewed_by = fields.Many2one('res.users', string='Prepared by') qc_reviewed_by_image = fields.Image(related="qc_reviewed_by.signature_image",string='Reviewed by Sign',readonly=True) qc_reviewed_on = fields.Datetime(string="Approved On") qa_reviewed_by = fields.Many2one('res.users', string='Prepared by') qa_reviewed_by_image = fields.Image(related="qa_reviewed_by.signature_image",string='Reviewed by Sign',readonly=True) qa_reviewed_on = fields.Datetime(string="Approved On") prepared_by = fields.Many2one('res.users', string='Prepared by') prepared_by_image = fields.Image(related="prepared_by.signature_image",string='Prepared by Sign',readonly=True) prepared_on = fields.Datetime(string="Prepared On") verified_by = fields.Many2one('res.users', string='Prepared by') verified_by_image = fields.Image(related="verified_by.signature_image",string='Prepared by Sign',readonly=True) verified_on = fields.Datetime(string="Prepared On") ce_verified_by = fields.Many2one('res.users', string='CE Verified by') ce_verified_by_image = fields.Image(related="ce_verified_by.signature_image",string='CE Verified by Sign',readonly=True) ce_verified_on = fields.Datetime(string="CE Head Verified On") scg_head_verified_by = fields.Many2one('res.users', string='SCG Verified by') scg_head_verified_by_image = fields.Image(related="scg_head_verified_by.signature_image",string='SCG Verified by Sign',readonly=True) scg_head_verified_on = fields.Datetime(string="SCG Head Verified On") batter_or_cells=fields.Integer(string="Battery/Cells") def action_report_boq(self): try: action = self.env.ref("sos_inventory.action_sos_deliverables_boq").report_action(self) return action except ValueError as e: print(f"Failed to find report action: {e}") def action_print_labels_btn(self): try: action = self.env.ref("sos_inventory.action_report_labels").report_action(self) return action except ValueError as e: print(f"Failed to find report action: {e}") @api.depends('fg_name') def _compute_show_bms_fields(self): for record in self: record.show_ev_fields = record.fg_name.startswith('BHMS') if record.fg_name else False @api.onchange('fg_name') def _onchange_fg_name(self): if self.fg_name: self.line_ids_fg = [(5, 0, 0)] self.line_ids_sfg = [(5, 0, 0)] self.line_ids_material = [(5, 0, 0)] self.line_ids_installation_kit = [(5, 0, 0)] self.line_ids_miscellaneous = [(5, 0, 0)] record = self.env['sos_deliverables_config'].search([('fg_name', '=', self.fg_name)], limit=1) if record: for field_name, source_field in [ ('line_ids_fg', record.fg_ids), ('line_ids_sfg', record.sfg_ids), ('line_ids_material', record.material_ids), ('line_ids_installation_kit', record.installation_kit_ids), ('line_ids_miscellaneous', record.miscellaneous_ids) ]: lines = [] if field_name != 'line_ids_miscellaneous': for line_id in source_field: line_vals = { 'ref_id': self.id, 'component_id': line_id.component_id.id, 'unit_price': line_id.component_id.unit_price, 'uom': line_id.uom, 'singet_set_qty': line_id.quantity, } if field_name == 'line_ids_sfg': line_vals['assembling_charges'] = line_id.component_id.assembling_charges lines.append((0, 0, line_vals)) else: for line_id in source_field: line_vals = { 'ref_id': self.id, 'name': line_id.name, 'quantity': line_id.quantity, } lines.append((0, 0, line_vals)) setattr(self, field_name, lines) def action_verified_esign_btn(self): sequence_util = self.env['sos_common_scripts'] return sequence_util.action_assign_signature( self, 'verified_by', 'verified_on' ) def action_prepared_esign_btn(self): sequence_util = self.env['sos_common_scripts'] # Email part body_html = f"""
Below Deliverables/BOQ is waiting for your Approval
""" sequence_util.send_group_email(self.env,'sos_deliverables_boq',self.id,"deenalaura.m@sosaley.in","Deliverables/BOQ Approval Request",body_html,'sos_inventory.sos_ce_head') # Email part ends return sequence_util.action_assign_signature( self, 'prepared_by', 'prepared_on' ) def action_ce_verified_esign_btn(self): sequence_util = self.env['sos_common_scripts'] # Email part body_html = f"""Below Deliverables/BOQ is waiting for your Approval
""" sequence_util.send_group_email(self.env,'sos_deliverables_boq',self.id,"deenalaura.m@sosaley.in","Deliverables/BOQ Approval Request",body_html,'sos_inventory.sos_scg_group_manager') # Email part ends return sequence_util.action_assign_signature( self, 'ce_verified_by', 'ce_verified_on' ) def action_scg_head_verified_esign_btn(self): sequence_util = self.env['sos_common_scripts'] # Email part body_html = f"""Below Deliverables/BOQ is waiting for your Approval
""" sequence_util.send_group_email(self.env,'sos_deliverables_boq',self.id,"deenalaura.m@sosaley.in","Deliverables/BOQ Approval Request",body_html,'sos_inventory.sos_qa_user') # Email part ends return sequence_util.action_assign_signature( self, 'scg_head_verified_by', 'scg_head_verified_on' ) def action_scg_esign_btn(self): sequence_util = self.env['sos_common_scripts'] return sequence_util.action_assign_signature( self, 'scg_reviewed_by', 'scg_reviewed_on' ) def action_rd_esign_btn(self): sequence_util = self.env['sos_common_scripts'] return sequence_util.action_assign_signature( self, 'rd_reviewed_by', 'rd_reviewed_on' ) def action_production_esign_btn(self): sequence_util = self.env['sos_common_scripts'] return sequence_util.action_assign_signature( self, 'production_reviewed_by', 'production_reviewed_on' ) def action_qc_esign_btn(self): sequence_util = self.env['sos_common_scripts'] return sequence_util.action_assign_signature( self, 'qc_reviewed_by', 'qc_reviewed_on' ) def action_qa_esign_btn(self): sos_order_delivery_plan_line = self.env['sos_order_delivery_plan'].create({ 'sales_id':self.sales_id.id, 'fg_name':self.fg_name, 'quantity':self.quantity, 'customer_name':self.customer_name, 'lead_time':self.lead_time, 'deliverables_boq_id':self.id, 'customer_po_no':self.customer_po_no, 'customer_po_date':self.customer_po_date }) sequence_util = self.env['sos_common_scripts'] return sequence_util.action_assign_signature( self, 'qa_reviewed_by', 'qa_reviewed_on' ) class sos_deliverables_boq_Line_Material(models.Model): _name = 'sos_deliverables_line_material' _description = 'Material Lines' ref_id = fields.Many2one('sos_deliverables_boq', string="Materials", ondelete="cascade") component_id = fields.Many2one('sos_material', string="Material Name", required=True) display_name = fields.Char(string="Display Name", related="component_id.name", store=True) uom = fields.Selection([('meters', 'Meters'),('Nos', 'Nos'),('coils', 'Coils'), ('litre', 'litre'), ('kg', 'Kilogram')], default="Nos",string="Uom") currency_id = fields.Many2one('res.currency', string='Currency') material_code = fields.Char(related="component_id.material_code",string="Material Code") material_name = fields.Char(related="component_id.part_no",string="Material Name") singet_set_qty = fields.Integer(string="Single Set Quantity",default=1) total_set = fields.Integer(string="Total Set",default=1) quantity = fields.Integer(string="Quantity",compute="_compute_set_wise",store=True) unit_price = fields.Monetary(currency_field='currency_id',string="Unit Price",related="component_id.unit_price") total_price = fields.Monetary(string="Total",compute="_compute_total_price") is_spare = fields.Boolean(string="Spare") add_production_cost = fields.Boolean(string="Include in Costing",default=True) @api.onchange('component_id') def _onchange_component_id(self): """ Set the initial value of `unit_price` when `component_id` is changed. """ for record in self: if record.component_id: record.unit_price = record.component_id.unit_price @api.depends('singet_set_qty','total_set') def _compute_set_wise(self): for record in self: record.quantity = record.singet_set_qty * record.total_set @api.depends('unit_price','quantity') def _compute_total_price(self): for record in self: record.total_price = record.unit_price * record.quantity class sos_deliverables_boq_Line_sfg(models.Model): _name = 'sos_deliverables_line_sfg' _description = 'SFG Order Lines' ref_id = fields.Many2one('sos_deliverables_boq', string="Materials", ondelete="cascade") currency_id = fields.Many2one('res.currency', string='Currency') component_id = fields.Many2one('sos_sfg', string="SFG Name", required=True) uom = fields.Selection([('meters', 'Meters'),('Nos', 'Nos'),('coils', 'Coils'), ('litre', 'litre'), ('kg', 'Kilogram')], default="Nos",string="Uom") sfg_code = fields.Char(related="component_id.sfg_code",string="SFG Code") sfg_name = fields.Char(related="component_id.name",string="SFG Name") singet_set_qty = fields.Integer(string="Single Set Quantity",default=1) total_set = fields.Integer(string="Total Set",default=1) quantity = fields.Integer(string="Quantity",compute="_compute_set_wise",store=True) unit_price = fields.Monetary(currency_field='currency_id',string="Unit Price",related="component_id.unit_price") assembling_charges = fields.Monetary(string="Assembling cost per unit",related="component_id.assembling_charges") total_price = fields.Monetary(string="Total",compute="_compute_total_price") is_spare = fields.Boolean(string="Spare") add_production_cost = fields.Boolean(string="Include in Costing",default=True) @api.onchange('component_id') def _onchange_component_id(self): """ Set the initial value of `unit_price` when `component_id` is changed. """ for record in self: if record.component_id: record.unit_price = record.component_id.unit_price record.assembling_charges = record.component_id.assembling_charges @api.depends('singet_set_qty','total_set') def _compute_set_wise(self): for record in self: record.quantity = record.singet_set_qty * record.total_set @api.depends('unit_price','quantity') def _compute_total_price(self): for record in self: record.total_price = (record.unit_price + record.assembling_charges) * record.quantity class sos_deliverables_boq_Line_fg(models.Model): _name = 'sos_deliverables_line_fg' _description = 'FG Order Lines' ref_id = fields.Many2one('sos_deliverables_boq', string="Materials", ondelete="cascade") currency_id = fields.Many2one('res.currency', string='Currency') component_id = fields.Many2one('sos_fg',string="FG Name", required=True) uom = fields.Selection([('meters', 'Meters'),('Nos', 'Nos'),('coils', 'Coils'), ('litre', 'litre'), ('kg', 'Kilogram')], default="Nos",string="Uom") fg_code = fields.Char(related="component_id.fg_code",string="FG Code") fg_name = fields.Char(related="component_id.name",string="FG Name") quantity = fields.Integer(string="Quantity",compute="_compute_set_wise", store=True) singet_set_qty = fields.Integer(string="Single Set Quantity",default=1) total_set = fields.Integer(string="Total Set",default=1) unit_price = fields.Monetary(currency_field='currency_id',string="Unit Price",related="component_id.unit_price") total_price = fields.Monetary(string="Total",compute="_compute_total_price") is_spare = fields.Boolean(string="Spare") add_production_cost = fields.Boolean(string="Include in Costing",default=True) @api.onchange('component_id') def _onchange_component_id(self): for record in self: if record.component_id: record.unit_price = record.component_id.unit_price @api.depends('singet_set_qty','total_set') def _compute_set_wise(self): for record in self: record.quantity = record.singet_set_qty * record.total_set @api.depends('unit_price','quantity') def _compute_total_price(self): for record in self: record.total_price = record.unit_price * record.quantity class sos_deliverables_MiscellaneousCost(models.Model): _name = 'sos_deliverables_miscellaneous_items' _description = 'Miscellaneous Items' ref_id = fields.Many2one('sos_deliverables_boq', string="Miscellaneous", ondelete="cascade") name = fields.Char(string='Name') cost = fields.Float(string='Cost') quantity = fields.Integer(string="Quantity") currency_id = fields.Many2one('res.currency', string='Currency') total_price = fields.Monetary(string="Total", currency_field='currency_id',compute="_compute_total_price") @api.depends('cost','quantity') def _compute_total_price(self): for record in self: record.total_price = record.cost * record.quantity class sos_deliverables_Material_installationkit(models.Model): _name = 'sos_deliverables_line_material_installation' _description = 'Installation Kit Lines' ref_id = fields.Many2one('sos_deliverables_boq', string="Materials", ondelete="cascade") component_id = fields.Many2one('sos_material', string="Material Name", required=True) display_name = fields.Char(string="Display Name", related="component_id.name", store=True) uom = fields.Selection([('meters', 'Meters'),('Nos', 'Nos'),('coils', 'Coils'), ('litre', 'litre'), ('kg', 'Kilogram'), ('Packs', 'Packs')], default="Nos",string="Uom") currency_id = fields.Many2one('res.currency', string='Currency') material_code = fields.Char(related="component_id.material_code",string="Material Code") material_name = fields.Char(related="component_id.part_no",string="Material Name") singet_set_qty = fields.Integer(string="Single Set Quantity",default=1) total_set = fields.Integer(string="Total Set",default=1) quantity = fields.Integer(string="Quantity",compute="_compute_set_wise",readonly=False) unit_price = fields.Monetary(currency_field='currency_id',string="Unit Price",related="component_id.unit_price") total_price = fields.Monetary(string="Total",compute="_compute_total_price") @api.onchange('component_id') def _onchange_component_id(self): """ Set the initial value of `unit_price` when `component_id` is changed. """ for record in self: if record.component_id: record.unit_price = record.component_id.unit_price @api.depends('singet_set_qty','total_set') def _compute_set_wise(self): for record in self: record.quantity = record.singet_set_qty * record.total_set @api.depends('unit_price','quantity') def _compute_total_price(self): for record in self: record.total_price = record.unit_price * record.quantity