leads of sales and inside sales matched
This commit is contained in:
parent
590d716eec
commit
0565053d7a
|
|
@ -15,6 +15,7 @@
|
||||||
'data': [
|
'data': [
|
||||||
'security/ir.model.access.csv',
|
'security/ir.model.access.csv',
|
||||||
'security/record_rules.xml',
|
'security/record_rules.xml',
|
||||||
|
'data/lead_source_data.xml',
|
||||||
'views/menu.xml',
|
'views/menu.xml',
|
||||||
'views/sos_inside_sales_leads_view.xml',
|
'views/sos_inside_sales_leads_view.xml',
|
||||||
'views/sos_target_tracker_view.xml',
|
'views/sos_target_tracker_view.xml',
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
<odoo>
|
||||||
|
<data noupdate="1">
|
||||||
|
<record id="lead_source_website" model="lead_source">
|
||||||
|
<field name="name">Website</field>
|
||||||
|
</record>
|
||||||
|
<record id="lead_source_expo" model="lead_source">
|
||||||
|
<field name="name">Expo</field>
|
||||||
|
</record>
|
||||||
|
<record id="lead_source_cold_calls" model="lead_source">
|
||||||
|
<field name="name">Cold Calls</field>
|
||||||
|
</record>
|
||||||
|
<record id="lead_source_linkedin" model="lead_source">
|
||||||
|
<field name="name">Linkedin</field>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
Binary file not shown.
|
|
@ -20,31 +20,44 @@ class sos_inside_sales_leads(models.Model):
|
||||||
moved_on = fields.Date(string="Moved On")
|
moved_on = fields.Date(string="Moved On")
|
||||||
location = fields.Char(string="Location")
|
location = fields.Char(string="Location")
|
||||||
website_url = fields.Char(string="Website URL")
|
website_url = fields.Char(string="Website URL")
|
||||||
vertical_domain = fields.Many2one('sos_vertical_domain',string="Domain / Industry", ondelete="cascade")
|
vertical_domain = fields.Many2many('sos_vertical_domain',string="Domain / Industry", ondelete="cascade")
|
||||||
line_ids_contacts = fields.One2many('sos_leads_contact_lines', 'ref_id', string="Contact Details",copy=True)
|
line_ids_contacts = fields.One2many('sos_leads_contact_lines', 'ref_id', string="Contact Details",copy=True)
|
||||||
remarks=fields.Text(string="Remarks")
|
remarks=fields.Text(string="Remarks")
|
||||||
linkedin_profile = fields.Char(string="Linkedin profile")
|
linkedin_profile = fields.Char(string="Linkedin profile")
|
||||||
products = fields.Selection(
|
# products = fields.Selection(
|
||||||
|
# [
|
||||||
|
# ('BHMS 1.2V', 'BHMS 1.2V'),
|
||||||
|
# ('BHMS 2V', 'BHMS 2V'),
|
||||||
|
# ('BHMS 12V', 'BHMS 12V'),
|
||||||
|
# ('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 Interested In")
|
||||||
|
products_interested = fields.Many2many('sos_products',string="Product Interested In")
|
||||||
|
service = fields.Selection(
|
||||||
[
|
[
|
||||||
('BHMS 1.2V', 'BHMS 1.2V'),
|
('Product', 'Products'),
|
||||||
('BHMS 2V', 'BHMS 2V'),
|
('Project', 'Projects')
|
||||||
('BHMS 12V', 'BHMS 12V'),
|
|
||||||
('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 Interested In")
|
string="Service Type",default="Product")
|
||||||
source = fields.Selection(
|
project_name= fields.Many2one('sos_projects',string="Project Name")
|
||||||
|
status = fields.Selection(
|
||||||
[
|
[
|
||||||
('website', 'Website'),
|
('Open', 'Open'),
|
||||||
('expo', 'Expo'),
|
('Close', 'Close'),
|
||||||
('cold_calls', 'Cold Calls'),
|
('New', 'New'),
|
||||||
('linkedin', 'Linkedin')
|
('In-Progress', 'In-Progress'),
|
||||||
|
('Qualified', 'Qualified'),
|
||||||
|
('Unqualified', 'Unqualified')
|
||||||
|
|
||||||
],
|
],
|
||||||
string="Source")
|
string="Status",default="New")
|
||||||
|
new_source = fields.Many2one('lead_source', string="Source")
|
||||||
meeting_scheduled = fields.Selection(
|
meeting_scheduled = fields.Selection(
|
||||||
[
|
[
|
||||||
('Online', 'Online'),
|
('Online', 'Online'),
|
||||||
|
|
@ -52,12 +65,24 @@ class sos_inside_sales_leads(models.Model):
|
||||||
],
|
],
|
||||||
string="Meeting Schedule")
|
string="Meeting Schedule")
|
||||||
expo_name = fields.Char(string="Expo Name")
|
expo_name = fields.Char(string="Expo Name")
|
||||||
move_to_sales = fields.Many2many('res.users',string="Move Lead to")
|
move_to_sales = fields.Many2many('res.users',string="Move Lead to", domain=lambda self: [('groups_id', 'in', self.env.ref('sos_inventory.sos_sales_user').ids + self.env.ref('sos_inventory.sos_ce_head').ids)])
|
||||||
cc_mail = fields.Many2one('res.users',string="CC to")
|
cc_mail = fields.Many2one('res.users',string="CC to", domain=lambda self: [('groups_id', 'in', self.env.ref('sos_inventory.sos_sales_user').ids + self.env.ref('sos_inventory.sos_ce_head').ids)])
|
||||||
move_div_display = fields.Boolean(default=False,string="Moved to Sales")
|
move_div_display = fields.Boolean(default=False,string="Moved to Sales")
|
||||||
line_ids = fields.One2many('sos_inside_sales_activities_line', 'ref_id', string="Action")
|
line_ids = fields.One2many('sos_inside_sales_activities_line', 'ref_id', string="Action")
|
||||||
week = fields.Char(string="Week")
|
week = fields.Char(string="Week")
|
||||||
reporting_to = fields.Many2one('res.users', string='Reporting To')
|
reporting_to = fields.Many2one('res.users', string='Reporting To')
|
||||||
|
sales_type = fields.Selection(
|
||||||
|
[
|
||||||
|
('Domestic', 'Domestic'),
|
||||||
|
('International', 'International')
|
||||||
|
],
|
||||||
|
string="Sales Type",default="Domestic")
|
||||||
|
country = fields.Many2one(
|
||||||
|
'res.country',
|
||||||
|
string='Country',
|
||||||
|
default=lambda self: self.env['res.country'].search([('code', '=', 'IN')], limit=1)
|
||||||
|
)
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def create(self, vals):
|
def create(self, vals):
|
||||||
create_uid = vals.get('create_uid', self.env.uid)
|
create_uid = vals.get('create_uid', self.env.uid)
|
||||||
|
|
@ -122,14 +147,29 @@ class sos_inside_sales_leads(models.Model):
|
||||||
'transferred_on': fields.Date.today(),
|
'transferred_on': fields.Date.today(),
|
||||||
'location':self.location,
|
'location':self.location,
|
||||||
'website_url':self.website_url,
|
'website_url':self.website_url,
|
||||||
'vertical_domain':self.vertical_domain.id,
|
'vertical_domain': [(6, 0, self.vertical_domain.ids)],
|
||||||
'linkedin_profile':self.linkedin_profile,
|
'linkedin_profile':self.linkedin_profile,
|
||||||
'products':self.products,
|
'products_interested':[(6, 0,self.products_interested.ids)],
|
||||||
'source':'inside_sales',
|
'source':'inside_sales',
|
||||||
'expo_name':self.expo_name,
|
'expo_name':self.expo_name,
|
||||||
'lead_generated_by':self.env.user.id
|
'lead_generated_by':self.env.user.id,
|
||||||
|
'sales_type':self.sales_type,
|
||||||
|
'interested_in':self.service,
|
||||||
|
'project_name':self.project_name.id
|
||||||
})
|
})
|
||||||
if new_record:
|
if new_record:
|
||||||
|
if self.line_ids_contacts:
|
||||||
|
for contact in self.line_ids_contacts:
|
||||||
|
self.env['sos_leads_customer_contact_lines'].create({
|
||||||
|
'ref_id': new_record.id,
|
||||||
|
'name': contact.name,
|
||||||
|
'dept': contact.dept,
|
||||||
|
'email': contact.email,
|
||||||
|
'mobile_number': contact.mobile_number,
|
||||||
|
'set_as_primary': contact.set_as_primary,
|
||||||
|
'linkedin_profile': contact.linkedin_profile,
|
||||||
|
'remarks': contact.remarks
|
||||||
|
})
|
||||||
self.move_div_display = True
|
self.move_div_display = True
|
||||||
return {
|
return {
|
||||||
'type': 'ir.actions.client',
|
'type': 'ir.actions.client',
|
||||||
|
|
@ -151,6 +191,8 @@ class SOS_Leads_Line(models.Model):
|
||||||
email = fields.Char(string="Email Id")
|
email = fields.Char(string="Email Id")
|
||||||
mobile_number = fields.Char(string="Contact Number")
|
mobile_number = fields.Char(string="Contact Number")
|
||||||
set_as_primary = fields.Boolean(string="Set Primary")
|
set_as_primary = fields.Boolean(string="Set Primary")
|
||||||
|
linkedin_profile = fields.Char(string="LinkedIn Profile")
|
||||||
|
remarks = fields.Text(string="Remarks")
|
||||||
@api.model
|
@api.model
|
||||||
def create(self, vals):
|
def create(self, vals):
|
||||||
record = super(SOS_Leads_Line, self).create(vals)
|
record = super(SOS_Leads_Line, self).create(vals)
|
||||||
|
|
@ -176,4 +218,11 @@ class sos_inside_sales_activities_lines(models.Model):
|
||||||
|
|
||||||
ref_id = fields.Many2one('sos_inside_sales_leads', ondelete="cascade")
|
ref_id = fields.Many2one('sos_inside_sales_leads', ondelete="cascade")
|
||||||
action_date = fields.Date(string="Action Date")
|
action_date = fields.Date(string="Action Date")
|
||||||
remarks = fields.Text(string="Remarks")
|
next_action_on = fields.Date(string="Next Action On")
|
||||||
|
remarks = fields.Text(string="Remarks")
|
||||||
|
|
||||||
|
class LeadSource(models.Model):
|
||||||
|
_name = 'lead_source'
|
||||||
|
_description = 'Lead Source Master'
|
||||||
|
|
||||||
|
name = fields.Char(string="Source Name", required=True)
|
||||||
|
|
|
||||||
|
|
@ -4,3 +4,5 @@ access_sos_inside_sales_activities_line,sos_inside_sales_activities_line access,
|
||||||
access_sos_target_tracker,sos_target_tracker access,model_sos_target_tracker,base.group_user,1,1,1,1
|
access_sos_target_tracker,sos_target_tracker access,model_sos_target_tracker,base.group_user,1,1,1,1
|
||||||
access_sos_leads_contact_lines,sos_leads_contact_lines access,model_sos_leads_contact_lines,base.group_user,1,1,1,1
|
access_sos_leads_contact_lines,sos_leads_contact_lines access,model_sos_leads_contact_lines,base.group_user,1,1,1,1
|
||||||
access_action_leads_report_wizard,action_leads_report_wizard access,model_action_leads_report_wizard,base.group_user,1,1,1,1
|
access_action_leads_report_wizard,action_leads_report_wizard access,model_action_leads_report_wizard,base.group_user,1,1,1,1
|
||||||
|
access_lead_source,lead_source access,model_lead_source,base.group_user,1,1,1,1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
|
@ -7,10 +7,12 @@
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree>
|
<tree>
|
||||||
<field name="company_name"/>
|
<field name="company_name"/>
|
||||||
|
<field name="status"/>
|
||||||
<field name="location"/>
|
<field name="location"/>
|
||||||
<field name="vertical_domain"/>
|
<field name="products_interested" string="Products" widget="many2many_tags" options="{'color_field': 'color'}"/>
|
||||||
|
<field name="project_name"/>
|
||||||
<field name="lead_generated_by"/>
|
<field name="lead_generated_by"/>
|
||||||
<field name="entry_date" string="Lead Generated On"/>
|
<!-- <field name="entry_date" string="Lead Generated On"/> -->
|
||||||
<field name="move_div_display" widget="boolean_toggle" readonly="1"/>
|
<field name="move_div_display" widget="boolean_toggle" readonly="1"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
|
|
@ -20,17 +22,21 @@
|
||||||
<field name="model">sos_inside_sales_leads</field>
|
<field name="model">sos_inside_sales_leads</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<search>
|
<search>
|
||||||
<searchpanel>
|
|
||||||
<field name="products" string="Products Interested In" icon="fa-list-ul" enable_counters="1"/>
|
<searchpanel>
|
||||||
<field name="vertical_domain" string="Vertical/Domain" icon="fa-pie-chart" enable_counters="1"/>
|
|
||||||
|
|
||||||
</searchpanel>
|
<field name="sales_type" string="Type" icon="fa-list-ul" enable_counters="1"/>
|
||||||
|
|
||||||
|
</searchpanel>
|
||||||
<!-- Add fields to search on -->
|
<!-- Add fields to search on -->
|
||||||
<field name="company_name" string="Company Name"/>
|
<field name="company_name" string="Company Name"/>
|
||||||
<field name="vertical_domain" string="Domain/Vertical"/>
|
<field name="vertical_domain" string="Domain/Vertical"/>
|
||||||
<field name="lead_generated_by" string="Lead Generated By"/>
|
<field name="lead_generated_by" string="Lead Generated By"/>
|
||||||
|
<field name="products_interested"/>
|
||||||
|
|
||||||
|
<filter name="product_filter"
|
||||||
|
string="Product"
|
||||||
|
domain="[('products_interested', 'in', products_interested)]"/>
|
||||||
|
|
||||||
|
|
||||||
</search>
|
</search>
|
||||||
|
|
@ -50,18 +56,24 @@
|
||||||
<group>
|
<group>
|
||||||
<group>
|
<group>
|
||||||
<field name="move_div_display" invisible="1"/>
|
<field name="move_div_display" invisible="1"/>
|
||||||
|
<field name="sales_type"/>
|
||||||
<field name="company_name"/>
|
<field name="company_name"/>
|
||||||
<field name="entry_date"/>
|
<field name="entry_date"/>
|
||||||
<field name="location"/>
|
<field name="country" invisible="sales_type != 'International'"/>
|
||||||
<field name="vertical_domain"/>
|
<field name="location" string="City/State"/>
|
||||||
|
<field name="vertical_domain" widget="many2many_tags"/>
|
||||||
|
<field name="status"/>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="website_url"/>
|
<field name="website_url"/>
|
||||||
<field name="linkedin_profile"/>
|
<field name="linkedin_profile"/>
|
||||||
<field name="products"/>
|
<field name="service"/>
|
||||||
|
<field name="products_interested"
|
||||||
<field name="source"/>
|
options="{'no_create': True, 'no_edit': True, 'no_create_edit': True}"
|
||||||
<field name="expo_name" invisible="source != 'expo'"/>
|
widget="many2many_tags" invisible="service != 'Product'"/>
|
||||||
|
<field name="project_name" invisible="service != 'Project'"/>
|
||||||
|
<field name="new_source"/>
|
||||||
|
<field name="expo_name" invisible="new_source != 2"/>
|
||||||
<field name="meeting_scheduled"/>
|
<field name="meeting_scheduled"/>
|
||||||
<field name="remarks"/>
|
<field name="remarks"/>
|
||||||
</group>
|
</group>
|
||||||
|
|
@ -77,6 +89,8 @@
|
||||||
<field name="dept"/>
|
<field name="dept"/>
|
||||||
<field name="email"/>
|
<field name="email"/>
|
||||||
<field name="mobile_number"/>
|
<field name="mobile_number"/>
|
||||||
|
<field name="linkedin_profile"/>
|
||||||
|
<field name="remarks"/>
|
||||||
|
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
|
|
@ -87,6 +101,8 @@
|
||||||
<tree editable="bottom">
|
<tree editable="bottom">
|
||||||
<field name="action_date"/>
|
<field name="action_date"/>
|
||||||
<field name="remarks"/>
|
<field name="remarks"/>
|
||||||
|
<field name="next_action_on"/>
|
||||||
|
|
||||||
|
|
||||||
</tree>
|
</tree>
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -63,6 +63,9 @@ class FIR_Only(models.Model):
|
||||||
|
|
||||||
cloud_data = fields.Binary("Cloud Data", required=False, attachment=True)
|
cloud_data = fields.Binary("Cloud Data", required=False, attachment=True)
|
||||||
cloud_data_filename = fields.Char("Cloud Data Filename")
|
cloud_data_filename = fields.Char("Cloud Data Filename")
|
||||||
|
|
||||||
|
firmware_data = fields.Binary("Firmware Data", required=False, attachment=True)
|
||||||
|
firmware_data_filename = fields.Char("Firmware Data Filename")
|
||||||
@api.onchange('batch_size')
|
@api.onchange('batch_size')
|
||||||
def _onchange_batch_size(self):
|
def _onchange_batch_size(self):
|
||||||
if self._origin and self.batch_size is not False:
|
if self._origin and self.batch_size is not False:
|
||||||
|
|
@ -75,11 +78,11 @@ class FIR_Only(models.Model):
|
||||||
]
|
]
|
||||||
self.testing_parameter_line_ids = line_values
|
self.testing_parameter_line_ids = line_values
|
||||||
|
|
||||||
@api.constrains('test_log_filename', 'sd_card_data_filename', 'cloud_data_filename')
|
@api.constrains('test_log_filename', 'sd_card_data_filename', 'cloud_data_filename', 'firmware_data_filename')
|
||||||
def _check_file_extension(self):
|
def _check_file_extension(self):
|
||||||
allowed_extensions = ['xlsx', 'xls', 'csv', 'zip', 'pdf']
|
allowed_extensions = ['xlsx', 'xls', 'csv', 'zip', 'pdf']
|
||||||
for record in self:
|
for record in self:
|
||||||
for field_name in ['test_log_filename', 'sd_card_data_filename', 'cloud_data_filename']:
|
for field_name in ['test_log_filename', 'sd_card_data_filename', 'cloud_data_filename','firmware_data_filename']:
|
||||||
file_name = getattr(record, field_name)
|
file_name = getattr(record, field_name)
|
||||||
if file_name:
|
if file_name:
|
||||||
ext = file_name.split('.')[-1].lower()
|
ext = file_name.split('.')[-1].lower()
|
||||||
|
|
|
||||||
|
|
@ -13,3 +13,23 @@ class sos_inventory_customers(models.Model):
|
||||||
|
|
||||||
customer_name = fields.Char(string="Customer Name")
|
customer_name = fields.Char(string="Customer Name")
|
||||||
customer_location = fields.Char(string="Location")
|
customer_location = fields.Char(string="Location")
|
||||||
|
@api.model
|
||||||
|
def create(self, vals):
|
||||||
|
new_name = (vals.get('customer_name') or '').lower()
|
||||||
|
|
||||||
|
if new_name and len(new_name) >= 5:
|
||||||
|
existing_customers = self.search([])
|
||||||
|
|
||||||
|
for customer in existing_customers:
|
||||||
|
existing_name = (customer.customer_name or '').lower()
|
||||||
|
|
||||||
|
# Check all substrings of length 5 or more
|
||||||
|
for i in range(len(new_name) - 4):
|
||||||
|
substring = new_name[i:i+5]
|
||||||
|
if substring in existing_name:
|
||||||
|
raise UserError(
|
||||||
|
f"A customer with a similar name already exists: '{customer.customer_name}' "
|
||||||
|
f"(matched substring: '{substring}')"
|
||||||
|
)
|
||||||
|
|
||||||
|
return super(sos_inventory_customers, self).create(vals)
|
||||||
|
|
@ -154,7 +154,7 @@ class SOS_IR(models.Model):
|
||||||
self.line_ids_material = lines
|
self.line_ids_material = lines
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
_logger.error("Error processing po_no: %s", str(e))
|
print("Error processing po_no: %s", str(e))
|
||||||
@api.onchange('wo_no')
|
@api.onchange('wo_no')
|
||||||
def _onchange_wo_no(self):
|
def _onchange_wo_no(self):
|
||||||
if self.wo_no:
|
if self.wo_no:
|
||||||
|
|
@ -170,7 +170,7 @@ class SOS_IR(models.Model):
|
||||||
self.line_ids_sfg = lines
|
self.line_ids_sfg = lines
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
_logger.error("Error processing po_no: %s", str(e))
|
print("Error processing po_no: %s", str(e))
|
||||||
@api.onchange('wo_no_inhouse')
|
@api.onchange('wo_no_inhouse')
|
||||||
def _onchange_wo_no_inhouse(self):
|
def _onchange_wo_no_inhouse(self):
|
||||||
if self.wo_no_inhouse:
|
if self.wo_no_inhouse:
|
||||||
|
|
@ -186,7 +186,7 @@ class SOS_IR(models.Model):
|
||||||
self.line_ids_sfg = lines
|
self.line_ids_sfg = lines
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
_logger.error("Error processing po_no: %s", str(e))
|
print("Error processing po_no: %s", str(e))
|
||||||
|
|
||||||
|
|
||||||
def action_report_ir_btn(self):
|
def action_report_ir_btn(self):
|
||||||
|
|
@ -409,6 +409,7 @@ class SOS_IR_Line_Material(models.Model):
|
||||||
unit_price = fields.Monetary(string="Unit Price", currency_field='currency_id')
|
unit_price = fields.Monetary(string="Unit Price", currency_field='currency_id')
|
||||||
test_report = fields.Binary(string="Test Report")
|
test_report = fields.Binary(string="Test Report")
|
||||||
test_report_filename=fields.Char(string="Test Report File Name")
|
test_report_filename=fields.Char(string="Test Report File Name")
|
||||||
|
expiry_date = fields.Date(string="Expiry Date")
|
||||||
@api.onchange('component_id')
|
@api.onchange('component_id')
|
||||||
def _onchange_component_id(self):
|
def _onchange_component_id(self):
|
||||||
if self.component_id:
|
if self.component_id:
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,8 @@ class SOS_Material(models.Model):
|
||||||
string="Materials History - In",
|
string="Materials History - In",
|
||||||
domain=[('action', '=', 'in')]
|
domain=[('action', '=', 'in')]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
shelf_life = fields.Selection([('yes', 'Yes'), ('no', 'No')],default="no", string="Shelf Life",required=True)
|
||||||
|
|
||||||
line_ids_out = fields.One2many(
|
line_ids_out = fields.One2many(
|
||||||
'sos_material_transaction_history', 'ref_id',
|
'sos_material_transaction_history', 'ref_id',
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ class sos__mon(models.Model):
|
||||||
mon_date = fields.Date(string="MON/SON/FON Date", required=True, default=fields.Date.today)
|
mon_date = fields.Date(string="MON/SON/FON Date", required=True, default=fields.Date.today)
|
||||||
min_no = fields.Many2one('sos_min',string="MIN/SIN/FIN No")
|
min_no = fields.Many2one('sos_min',string="MIN/SIN/FIN No")
|
||||||
filled_by = fields.Many2one('res.users', string='Filled By', readonly=True,required=True,default=lambda self: self.env.user)
|
filled_by = fields.Many2one('res.users', string='Filled By', readonly=True,required=True,default=lambda self: self.env.user)
|
||||||
logged_inuser_group=fields.Boolean(string='Group Name',compute='compute_user_grp')
|
logged_inuser_group=fields.Boolean(string='Group Name',compute='compute_user_grp',store=True)
|
||||||
dept = fields.Many2one('sos_departments',string="Department")
|
dept = fields.Many2one('sos_departments',string="Department")
|
||||||
purpose = fields.Char(string="Purpose")
|
purpose = fields.Char(string="Purpose")
|
||||||
product_name = fields.Many2one('sos_fg', string='Material/Product Name & No')
|
product_name = fields.Many2one('sos_fg', string='Material/Product Name & No')
|
||||||
|
|
@ -61,7 +61,7 @@ class sos__mon(models.Model):
|
||||||
auto_load_fg_item_ids = fields.Many2many(
|
auto_load_fg_item_ids = fields.Many2many(
|
||||||
'sos_fg',
|
'sos_fg',
|
||||||
compute='_compute_fg_items',
|
compute='_compute_fg_items',
|
||||||
store=False
|
store=True
|
||||||
)
|
)
|
||||||
company_id = fields.Many2one('res.company', store=True, copy=False,
|
company_id = fields.Many2one('res.company', store=True, copy=False,
|
||||||
string="Company",
|
string="Company",
|
||||||
|
|
@ -70,7 +70,7 @@ class sos__mon(models.Model):
|
||||||
related='company_id.currency_id',
|
related='company_id.currency_id',
|
||||||
default=lambda
|
default=lambda
|
||||||
self: self.env.user.company_id.currency_id.id)
|
self: self.env.user.company_id.currency_id.id)
|
||||||
approx_value = fields.Monetary(compute='_compute_approx_value', string="Approximate Value", currency_field='currency_id', readonly=True)
|
approx_value = fields.Monetary(compute='_compute_approx_value', string="Approximate Value", currency_field='currency_id', readonly=True,store=True)
|
||||||
status = fields.Selection([ ('open', 'Open'),('close', 'Closed')], default='open' , string="Status")
|
status = fields.Selection([ ('open', 'Open'),('close', 'Closed')], default='open' , string="Status")
|
||||||
active = fields.Boolean(default=True)
|
active = fields.Boolean(default=True)
|
||||||
@api.constrains('indent_ref_no', 'auto_load_fg_items')
|
@api.constrains('indent_ref_no', 'auto_load_fg_items')
|
||||||
|
|
@ -189,6 +189,8 @@ class sos__mon(models.Model):
|
||||||
|
|
||||||
@api.onchange('auto_load_fg_items')
|
@api.onchange('auto_load_fg_items')
|
||||||
def _onchange_auto_load_fg_items(self):
|
def _onchange_auto_load_fg_items(self):
|
||||||
|
if not self.auto_load_fg_items:
|
||||||
|
return
|
||||||
if self.auto_load_fg_items:
|
if self.auto_load_fg_items:
|
||||||
self.material_option = True
|
self.material_option = True
|
||||||
self.sfg_option = True
|
self.sfg_option = True
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,51 @@ class sos__mrn(models.Model):
|
||||||
default=lambda
|
default=lambda
|
||||||
self: self.env.user.company_id.currency_id.id)
|
self: self.env.user.company_id.currency_id.id)
|
||||||
approx_value = fields.Monetary(compute='_compute_approx_value', string="Approximate Value", currency_field='currency_id', readonly=True)
|
approx_value = fields.Monetary(compute='_compute_approx_value', string="Approximate Value", currency_field='currency_id', readonly=True)
|
||||||
|
@api.onchange('min_no')
|
||||||
|
def _onchange_min_no(self):
|
||||||
|
if self.min_no:
|
||||||
|
self.material_option = self.min_no.material_option
|
||||||
|
self.sfg_option = self.min_no.sfg_option
|
||||||
|
self.fg_option = self.min_no.fg_option
|
||||||
|
#materials
|
||||||
|
self.line_ids_material = [(5, 0, 0)]
|
||||||
|
material_lines = []
|
||||||
|
for material in self.min_no.line_ids_material:
|
||||||
|
line_vals = {
|
||||||
|
'mrn_id': self.id,
|
||||||
|
'component_id': material.component_id,
|
||||||
|
'qp_no': material.qp_no,
|
||||||
|
'uom': material.uom,
|
||||||
|
'quantity': material.quantity
|
||||||
|
}
|
||||||
|
material_lines.append((0, 0, line_vals))
|
||||||
|
|
||||||
|
self.line_ids_material = material_lines
|
||||||
|
#sfg
|
||||||
|
self.line_ids_sfg = [(5, 0, 0)]
|
||||||
|
sfg_lines = []
|
||||||
|
for sfg in self.min_no.line_ids_sfg:
|
||||||
|
line_vals_sfg = {
|
||||||
|
'mrn_id': self.id,
|
||||||
|
'component_id': sfg.component_id,
|
||||||
|
'qp_no': sfg.qp_no,
|
||||||
|
'quantity': sfg.quantity
|
||||||
|
}
|
||||||
|
sfg_lines.append((0, 0, line_vals_sfg))
|
||||||
|
|
||||||
|
self.line_ids_sfg = sfg_lines
|
||||||
|
#sfg
|
||||||
|
self.line_ids_fg = [(5, 0, 0)]
|
||||||
|
fg_lines = []
|
||||||
|
for fg in self.min_no.line_ids_fg:
|
||||||
|
line_vals_fg = {
|
||||||
|
'mrn_id': self.id,
|
||||||
|
'component_id': fg.component_id,
|
||||||
|
'quantity': fg.quantity
|
||||||
|
}
|
||||||
|
fg_lines.append((0, 0, line_vals_fg))
|
||||||
|
|
||||||
|
self.line_ids_fg = fg_lines
|
||||||
@api.depends('line_ids_material.total_cost')
|
@api.depends('line_ids_material.total_cost')
|
||||||
def _compute_approx_value(self):
|
def _compute_approx_value(self):
|
||||||
for record in self:
|
for record in self:
|
||||||
|
|
@ -115,6 +159,7 @@ class sos__mrn(models.Model):
|
||||||
def action_report_esign_btn1(self):
|
def action_report_esign_btn1(self):
|
||||||
sequence_util = self.env['sos_common_scripts']
|
sequence_util = self.env['sos_common_scripts']
|
||||||
splitted=self.order_type.split(",")
|
splitted=self.order_type.split(",")
|
||||||
|
customer_return_record = False
|
||||||
if self.return_type == "customer":
|
if self.return_type == "customer":
|
||||||
sequence_util = self.env['sos_common_scripts']
|
sequence_util = self.env['sos_common_scripts']
|
||||||
tc_no = sequence_util.generate_sequence('sos_transfer_challan_return_from_customer','TC', 'tc_no')
|
tc_no = sequence_util.generate_sequence('sos_transfer_challan_return_from_customer','TC', 'tc_no')
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ class NCMR_Model(models.Model):
|
||||||
comments_on_capa = fields.Html(string="Comments on Corrective / Preventive Action ")
|
comments_on_capa = fields.Html(string="Comments on Corrective / Preventive Action ")
|
||||||
qa_comments=fields.Text(string="QA Comments")
|
qa_comments=fields.Text(string="QA Comments")
|
||||||
qa_done_on = fields.Date(string="Verified On")
|
qa_done_on = fields.Date(string="Verified On")
|
||||||
|
rework_responsible_rd_user = fields.Many2one('res.users',string='R&D User')
|
||||||
rd_user = fields.Many2many('res.users',string='R&D User', relation='sos_ncmr_rd_user_rel')
|
rd_user = fields.Many2many('res.users',string='R&D User', relation='sos_ncmr_rd_user_rel')
|
||||||
qa_by = fields.Many2one('res.users',string='QC In-Charge',readonly=True)
|
qa_by = fields.Many2one('res.users',string='QC In-Charge',readonly=True)
|
||||||
qa_sign = fields.Image(related="qa_by.signature_image",string='QC In-Charge',readonly=True)
|
qa_sign = fields.Image(related="qa_by.signature_image",string='QC In-Charge',readonly=True)
|
||||||
|
|
@ -94,10 +95,15 @@ class NCMR_Model(models.Model):
|
||||||
string="Rework Action",
|
string="Rework Action",
|
||||||
default="inhouse"
|
default="inhouse"
|
||||||
)
|
)
|
||||||
|
rework_action_by_qc = fields.Boolean(string="Rework")
|
||||||
rd_comments=fields.Text(string="Comments")
|
rd_comments=fields.Text(string="Comments")
|
||||||
rd_approval_by = fields.Many2one('res.users',string='R&D In-Charge',readonly=True)
|
rd_approval_by = fields.Many2one('res.users',string='R&D In-Charge',readonly=True)
|
||||||
rd_approval_sign = fields.Image(related="rd_approval_by.signature_image",string='R&D In-Charge',readonly=True)
|
rd_approval_sign = fields.Image(related="rd_approval_by.signature_image",string='R&D In-Charge',readonly=True)
|
||||||
rd_approval_on = fields.Datetime(string="Approved On")
|
rd_approval_on = fields.Datetime(string="Approved On")
|
||||||
|
rework_rd_approval_by = fields.Many2one('res.users',string='Rework - R&D In-Charge',readonly=True)
|
||||||
|
rework_rd_approval_sign = fields.Image(related="rework_rd_approval_by.signature_image",string='Rework - R&D In-Charge',readonly=True)
|
||||||
|
rework_rd_approval_on = fields.Datetime(string="Approved On")
|
||||||
|
|
||||||
combined_incoming_doc_ref = fields.Reference(
|
combined_incoming_doc_ref = fields.Reference(
|
||||||
selection=[
|
selection=[
|
||||||
('sos_iqi', 'IQI Ref No'),
|
('sos_iqi', 'IQI Ref No'),
|
||||||
|
|
@ -244,7 +250,8 @@ class NCMR_Model(models.Model):
|
||||||
|
|
||||||
open_count = sum(1 for rec in line.defective_status_ids if rec.status == 'open')
|
open_count = sum(1 for rec in line.defective_status_ids if rec.status == 'open')
|
||||||
closed_count = sum(1 for rec in line.defective_status_ids if rec.status == 'closed')
|
closed_count = sum(1 for rec in line.defective_status_ids if rec.status == 'closed')
|
||||||
closure_rate = ((closed_count/required_ncmr)*100)
|
closure_rate = (closed_count / required_ncmr) * 100 if required_ncmr else 0.0
|
||||||
|
|
||||||
|
|
||||||
ppm = None
|
ppm = None
|
||||||
|
|
||||||
|
|
@ -668,6 +675,13 @@ class NCMR_Model(models.Model):
|
||||||
'rd_approval_by',
|
'rd_approval_by',
|
||||||
'rd_approval_on'
|
'rd_approval_on'
|
||||||
)
|
)
|
||||||
|
def action_rework_rd_esign_btn(self):
|
||||||
|
send_email = self.env['sos_common_scripts']
|
||||||
|
send_email.action_assign_signature(
|
||||||
|
self,
|
||||||
|
'rework_rd_approval_by',
|
||||||
|
'rework_rd_approval_on'
|
||||||
|
)
|
||||||
|
|
||||||
def action_qa_esign_btn(self):
|
def action_qa_esign_btn(self):
|
||||||
if self.action_group:
|
if self.action_group:
|
||||||
|
|
@ -678,6 +692,20 @@ class NCMR_Model(models.Model):
|
||||||
'qa_tested_on',
|
'qa_tested_on',
|
||||||
'sos_inventory.sos_qc_user'
|
'sos_inventory.sos_qc_user'
|
||||||
)
|
)
|
||||||
|
if self.rework_action_by_qc:
|
||||||
|
# Email part
|
||||||
|
body_html = f"""
|
||||||
|
<p>Below <b>NCMR</b> is waiting for your Action</p>
|
||||||
|
"""
|
||||||
|
send_email = self.env['sos_common_scripts']
|
||||||
|
send_email.send_direct_email(
|
||||||
|
self.env,
|
||||||
|
"sos_ncmr",
|
||||||
|
self.id,
|
||||||
|
self.rework_responsible_rd_user.login,
|
||||||
|
"NCMR Rework Action Request",
|
||||||
|
body_html
|
||||||
|
)
|
||||||
if self.action_group == "rd":
|
if self.action_group == "rd":
|
||||||
# Email part
|
# Email part
|
||||||
body_html = f"""
|
body_html = f"""
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ class SosTestingParameters(models.Model):
|
||||||
_rec_name='fg_name'
|
_rec_name='fg_name'
|
||||||
|
|
||||||
fg_name = fields.Many2one('sos_fg',string="FG Name")
|
fg_name = fields.Many2one('sos_fg',string="FG Name")
|
||||||
parameter_ids = fields.One2many('sos_parameter', 'testing_id', string= 'BRR Testing Parameters',copy=True)
|
parameter_ids = fields.One2many('sos_parameter', 'testing_id', string= 'In-Process/BRR Testing Parameters',copy=True)
|
||||||
fir_parameter_ids = fields.One2many('sos_parameter_fir', 'testing_id', string= 'FIR Testing Parameters',copy=True)
|
fir_parameter_ids = fields.One2many('sos_parameter_fir', 'testing_id', string= 'FIR Testing Parameters',copy=True)
|
||||||
specification_ids = fields.One2many('sos_specification', 'spec_id', string='Specifications',copy=True)
|
specification_ids = fields.One2many('sos_specification', 'spec_id', string='Specifications',copy=True)
|
||||||
deliverables_ids = fields.One2many('sos_deliverables', 'accessory_id', string='Deliverables',copy=True)
|
deliverables_ids = fields.One2many('sos_deliverables', 'accessory_id', string='Deliverables',copy=True)
|
||||||
|
|
|
||||||
|
|
@ -44,11 +44,10 @@
|
||||||
<field name="perm_create" eval="1"/>
|
<field name="perm_create" eval="1"/>
|
||||||
<field name="perm_unlink" eval="0"/>
|
<field name="perm_unlink" eval="0"/>
|
||||||
</record>
|
</record>
|
||||||
|
<record id="sos_ncmr_all_records_rule" model="ir.rule">
|
||||||
<record id="sos_ncmr_all_records_rule" model="ir.rule">
|
|
||||||
<field name="name">Sos NCMR: All Records - Read Access</field>
|
<field name="name">Sos NCMR: All Records - Read Access</field>
|
||||||
<field name="model_id" ref="model_sos_ncmr"/>
|
<field name="model_id" ref="model_sos_ncmr"/>
|
||||||
<field name="domain_force">[('rd_user', '=', user.id)]</field>
|
<field name="domain_force">[('rd_user', '=', user.id), ('rework_responsible_rd_user', '=', user.id)]</field>
|
||||||
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
||||||
<field name="perm_read" eval="1"/>
|
<field name="perm_read" eval="1"/>
|
||||||
<field name="perm_write" eval="1"/>
|
<field name="perm_write" eval="1"/>
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,7 @@
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- Menuitem -->
|
<!-- Menuitem -->
|
||||||
<menuitem id="menu_sos_fir_brr" sequence="3" name="Batch Realease Report (BRR)" parent="mop_forms_menu_root" action="action_sos_fir_brr" groups="sos_inventory.sos_healthcare_user,sos_inventory.sos_scg_group_user,sos_inventory.sos_qc_user,sos_inventory.sos_management_user"/>
|
<menuitem id="menu_sos_fir_brr" sequence="3" name="In-Process Inspection / Batch Realease Report (BRR)" parent="mop_forms_menu_root" action="action_sos_fir_brr" groups="sos_inventory.sos_healthcare_user,sos_inventory.sos_scg_group_user,sos_inventory.sos_qc_user,sos_inventory.sos_management_user"/>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,12 @@
|
||||||
<br></br>
|
<br></br>
|
||||||
<hr></hr>
|
<hr></hr>
|
||||||
</page>
|
</page>
|
||||||
|
<page string="Firmware Data">
|
||||||
|
<field name="firmware_data" filename="firmware_data_filename"/>
|
||||||
|
<field name="firmware_data_filename" invisible="1"/>
|
||||||
|
<br></br>
|
||||||
|
<hr></hr>
|
||||||
|
</page>
|
||||||
</notebook>
|
</notebook>
|
||||||
<templates>
|
<templates>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,7 @@
|
||||||
<field name="order_qty"/>
|
<field name="order_qty"/>
|
||||||
<field name="qty"/>
|
<field name="qty"/>
|
||||||
<field name="unit_price"/>
|
<field name="unit_price"/>
|
||||||
|
<field name="expiry_date"/>
|
||||||
<field name="test_report" widget="binary" filename="test_report_filename"/>
|
<field name="test_report" widget="binary" filename="test_report_filename"/>
|
||||||
<field name="test_report_filename" column_invisible="1"/>
|
<field name="test_report_filename" column_invisible="1"/>
|
||||||
<button name="action_view_pdf" invisible="not test_report" type="object" string="View" class="btn-primary" icon="fa-eye"/>
|
<button name="action_view_pdf" invisible="not test_report" type="object" string="View" class="btn-primary" icon="fa-eye"/>
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,7 @@
|
||||||
<field name="description"/>
|
<field name="description"/>
|
||||||
<field name="category"/>
|
<field name="category"/>
|
||||||
<field name="uom"/>
|
<field name="uom"/>
|
||||||
|
<field name="shelf_life"/>
|
||||||
<field name="inspection_method" widget="color_picker"/>
|
<field name="inspection_method" widget="color_picker"/>
|
||||||
<field name="qp_no"/>
|
<field name="qp_no"/>
|
||||||
<field name="hsn_code"/>
|
<field name="hsn_code"/>
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
<field name="forward_by" string="QA Approval" widget="many2one_avatar_user"/>
|
<field name="forward_by" string="QA Approval" widget="many2one_avatar_user"/>
|
||||||
|
|
||||||
<field name="status" widget="badge" decoration-success="status == 'closed'" decoration-danger="status == 'open'"/>
|
<field name="status" widget="badge" decoration-success="status == 'closed'" decoration-danger="status == 'open'"/>
|
||||||
|
<field name="rework_action_by_qc" widget="boolean_toggle"/>
|
||||||
<field name="write_uid" string="Last Edited By" optional="hide"/>
|
<field name="write_uid" string="Last Edited By" optional="hide"/>
|
||||||
<field name="write_date" string="Last Edited On" optional="hide"/>
|
<field name="write_date" string="Last Edited On" optional="hide"/>
|
||||||
|
|
||||||
|
|
@ -242,19 +242,27 @@
|
||||||
<templates>
|
<templates>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row" style="margin-top:100px">
|
<div class="row" style="margin-top:100px">
|
||||||
<div class="col-6">
|
<div class="col-6" style="padding: 0px;box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;background-color: #fff;border: solid 4px #9689c1;">
|
||||||
<table class="table_custom" style="box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;background-color: #fff;border: solid 4px #9689c1;">
|
<table class="table_custom" >
|
||||||
<tr><td colspan="2" class="table_custom_header">To Be Filled By <span style="font-size: 18px;padding: 0px; color: #ffcc00;">QC</span> Team</td></tr>
|
<tr><td colspan="2" class="table_custom_header" style="color:#fff">To Be Filled By <span style="font-size: 18px;padding: 0px; color: #ffcc00;">QC</span> Team</td></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="padding: 8px;" class="column"><b>QC Comments</b></td>
|
<td style="padding: 8px;" class="column"><b>QC Comments</b></td>
|
||||||
|
|
||||||
<td><field name="comments"/></td>
|
<td><field name="comments"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td style="padding: 8px;" class="column"><b>Action to be taken By</b></td>
|
<td style="padding: 8px;" class="column"><b>Action to be taken By</b></td>
|
||||||
|
|
||||||
<td><field name="action_group"/><field name="rd_user" widget="many2many_tags" invisible="action_group != 'rd'"/></td>
|
<td><field name="action_group"/><field name="rd_user" widget="many2many_tags" invisible="action_group != 'rd'"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="padding: 8px;" class="column"><b>Rework Decision</b></td>
|
||||||
|
|
||||||
|
<td><field name="rework_action_by_qc" widget="boolean_toggle"/>
|
||||||
|
<field name="rework_responsible_rd_user" invisible="rework_action_by_qc != True"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr style="border-bottom: solid 1px #ccc;">
|
<tr style="border-bottom: solid 1px #ccc;">
|
||||||
<td style="padding: 8px;" class="column"><b>QC Tested By </b></td>
|
<td style="padding: 8px;" class="column"><b>QC Tested By </b></td>
|
||||||
<td>
|
<td>
|
||||||
|
|
@ -270,8 +278,8 @@
|
||||||
<td><field name="qa_by" readonly="1"/></td>
|
<td><field name="qa_by" readonly="1"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table></div>
|
</table></div>
|
||||||
<div class="col-6"><table class="table_custom" style="box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;background-color: #fff;border: solid 4px #9689c1;">
|
<div class="col-6" style="padding: 0px;box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;background-color: #fff;border: solid 4px #9689c1;"><table class="table_custom" >
|
||||||
<tr><td colspan="2" class="table_custom_header">To Be Filled By <span style="font-size: 18px;padding: 0px; color: #ffcc00;">SCG</span> Team</td></tr>
|
<tr><td colspan="2" class="table_custom_header" style="color:#fff">To Be Filled By <span style="font-size: 18px;padding: 0px; color: #ffcc00;">SCG</span> Team</td></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="padding: 8px;" class="column"><b>Comments</b></td>
|
<td style="padding: 8px;" class="column"><b>Comments</b></td>
|
||||||
|
|
||||||
|
|
@ -301,8 +309,8 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-6" invisible="rework_action == 'outsourcing_vendor'"><table class="table_custom" style="box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;background-color: #fff;border: solid 4px #9689c1;">
|
<div class="col-6" style="padding: 0px;box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;background-color: #fff;border: solid 4px #9689c1;" invisible="rework_action == 'outsourcing_vendor'"><table class="table_custom" >
|
||||||
<tr><td colspan="2" class="table_custom_header">To Be Filled By <span style="font-size: 18px;padding: 0px; color: #ffcc00;">Production</span> Team</td></tr>
|
<tr><td colspan="2" class="table_custom_header" style="color:#fff">To Be Filled By <span style="font-size: 18px;padding: 0px; color: #ffcc00;">Production</span> Team</td></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="padding: 8px;" class="column"><b>Comments</b></td>
|
<td style="padding: 8px;" class="column"><b>Comments</b></td>
|
||||||
|
|
||||||
|
|
@ -323,9 +331,9 @@
|
||||||
<td><field name="production_approval_by" readonly="1"/></td>
|
<td><field name="production_approval_by" readonly="1"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table></div>
|
</table></div>
|
||||||
<div class="col-6"> <table class="table_custom" style="box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;background-color: #fff;border: solid 4px #9689c1;">
|
<div class="col-6" style="padding: 0px;box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;background-color: #fff;border: solid 4px #9689c1;"> <table class="table_custom" >
|
||||||
|
|
||||||
<tr><td colspan="2" class="table_custom_header">To Be Filled By <span style="font-size: 18px;padding: 0px; color: #ffcc00;">QA</span> Team</td></tr>
|
<tr><td colspan="2" class="table_custom_header" style="color:#fff">To Be Filled By <span style="font-size: 18px;padding: 0px; color: #ffcc00;">QA</span> Team</td></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="padding: 8px;" class="column"><b>Comments</b></td>
|
<td style="padding: 8px;" class="column"><b>Comments</b></td>
|
||||||
|
|
||||||
|
|
@ -362,8 +370,8 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-6" invisible="action_group != 'rd'"><table class="table_custom" style="box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;background-color: #fff;border: solid 4px #9689c1;">
|
<div class="col-6" style="padding: 0px;box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;background-color: #fff;border: solid 4px #9689c1;" invisible="action_group != 'rd'"><table class="table_custom" >
|
||||||
<tr><td colspan="2" class="table_custom_header">To Be Filled By <span style="font-size: 18px;padding: 0px; color: #ffcc00;">R&D</span> Team</td></tr>
|
<tr><td colspan="2" class="table_custom_header" style="color:#fff">To Be Filled By <span style="font-size: 18px;padding: 0px; color: #ffcc00;">R&D</span> Team</td></tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="padding: 8px;" class="column"><b>Comments</b></td>
|
<td style="padding: 8px;" class="column"><b>Comments</b></td>
|
||||||
|
|
||||||
|
|
@ -383,7 +391,27 @@
|
||||||
<td style="padding: 8px;" class="column"><b>Approved By</b></td>
|
<td style="padding: 8px;" class="column"><b>Approved By</b></td>
|
||||||
<td><field name="rd_approval_by" readonly="1"/></td>
|
<td><field name="rd_approval_by" readonly="1"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table></div></div>
|
</table></div>
|
||||||
|
<div class="col-6" style="padding: 0px;box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;background-color: #fff;border: solid 4px #9689c1;" invisible="rework_action_by_qc != True"><table class="table_custom" >
|
||||||
|
<tr><td colspan="2" class="table_custom_header" style="color:#fff">To Be Filled By <span style="font-size: 18px;padding: 0px; color: #ffcc00;">R&D</span> Team(Rework)</td></tr>
|
||||||
|
<tr style="border-bottom: solid 1px #ccc;">
|
||||||
|
<td style="padding: 8px;" class="column"><b>Approved By </b></td>
|
||||||
|
<td>
|
||||||
|
<button string="Approve" invisible="rework_rd_approval_sign" class="btn-primary custom_btn" type="object" name="action_rework_rd_esign_btn"></button>
|
||||||
|
<field name="rework_rd_approval_sign" widget="image"/></td>
|
||||||
|
</tr>
|
||||||
|
<tr invisible="rework_rd_approval_sign == False">
|
||||||
|
<td style="padding: 8px;" class="column"><b>Approved On</b></td>
|
||||||
|
<td><field name="rework_rd_approval_on" readonly="1"/></td>
|
||||||
|
</tr>
|
||||||
|
<tr invisible="rework_rd_approval_sign == False">
|
||||||
|
<td style="padding: 8px;" class="column"><b>Approved By</b></td>
|
||||||
|
<td><field name="rework_rd_approval_by" readonly="1"/></td>
|
||||||
|
</tr>
|
||||||
|
</table></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</templates>
|
</templates>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
<field name="fg_name"/>
|
<field name="fg_name"/>
|
||||||
</group>
|
</group>
|
||||||
<notebook>
|
<notebook>
|
||||||
<page string="BRR Testing Parameters" groups="sos_inventory.sos_qc_user,sos_inventory.sos_qa_user">
|
<page string="In-Process/BRR Testing Parameters" groups="sos_inventory.sos_qc_user,sos_inventory.sos_qa_user">
|
||||||
<field name="parameter_ids">
|
<field name="parameter_ids">
|
||||||
<tree string="Parameters" editable="bottom">
|
<tree string="Parameters" editable="bottom">
|
||||||
<field name="sequence" widget="handle"/>
|
<field name="sequence" widget="handle"/>
|
||||||
|
|
@ -115,7 +115,7 @@
|
||||||
</record>
|
</record>
|
||||||
<!-- Action to open sos_testing_parameters -->
|
<!-- Action to open sos_testing_parameters -->
|
||||||
<record id="action_sos_testing_parameters" model="ir.actions.act_window">
|
<record id="action_sos_testing_parameters" model="ir.actions.act_window">
|
||||||
<field name="name">FG Configurations</field>
|
<field name="name">In-Process Configurations</field>
|
||||||
<field name="res_model">sos_testing_parameters</field>
|
<field name="res_model">sos_testing_parameters</field>
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
<field name="help" type="html">
|
<field name="help" type="html">
|
||||||
|
|
@ -136,7 +136,7 @@
|
||||||
</record>
|
</record>
|
||||||
<!-- Menu item to access sos_testing_parameters -->
|
<!-- Menu item to access sos_testing_parameters -->
|
||||||
<menuitem id="menu_sos_testing_parameters"
|
<menuitem id="menu_sos_testing_parameters"
|
||||||
name="FG Configurations"
|
name="In-Process Configurations"
|
||||||
parent="settings_root_menu" action="action_sos_testing_parameters" groups="sos_inventory.sos_qc_user,sos_inventory.sos_qa_user,sos_inventory.sos_ce_user,sos_inventory.sos_production_user,sos_inventory.sos_management_user"/>
|
parent="settings_root_menu" action="action_sos_testing_parameters" groups="sos_inventory.sos_qc_user,sos_inventory.sos_qa_user,sos_inventory.sos_ce_user,sos_inventory.sos_production_user,sos_inventory.sos_management_user"/>
|
||||||
<menuitem id="menu_sos_fir_testing_parameters"
|
<menuitem id="menu_sos_fir_testing_parameters"
|
||||||
name="FIR Parameters Configurations"
|
name="FIR Parameters Configurations"
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -152,7 +152,8 @@ class sos_case_diary(models.Model):
|
||||||
'ref_id': ref_id,
|
'ref_id': ref_id,
|
||||||
'customer_name': self.customer_name.id,
|
'customer_name': self.customer_name.id,
|
||||||
'action_date': last_record.status_changed_on,
|
'action_date': last_record.status_changed_on,
|
||||||
'proposal_value': proposal_value
|
'proposal_value': proposal_value,
|
||||||
|
'po_no':self.po_no
|
||||||
})
|
})
|
||||||
|
|
||||||
# Assign signature
|
# Assign signature
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ class SOS_Sales_Achievement_Report(models.Model):
|
||||||
_sql_constraints = [
|
_sql_constraints = [
|
||||||
('unique_financial_year_sales_person', 'UNIQUE(financial_year, sales_person)', 'The combination of Financial Year and Sales Person must be unique.')
|
('unique_financial_year_sales_person', 'UNIQUE(financial_year, sales_person)', 'The combination of Financial Year and Sales Person must be unique.')
|
||||||
]
|
]
|
||||||
|
display_name = fields.Char(string="Name", compute='_compute_display_name', store=True)
|
||||||
financial_year = fields.Char(string="Financial Year", default=lambda self: self._get_financial_year())
|
financial_year = fields.Char(string="Financial Year", default=lambda self: self._get_financial_year())
|
||||||
sales_person = fields.Many2one('res.users', string='Sales person',required=True)
|
sales_person = fields.Many2one('res.users', string='Sales person',required=True)
|
||||||
overall_target = fields.Float(string="Overall Target")
|
overall_target = fields.Float(string="Overall Target")
|
||||||
|
|
@ -114,6 +114,11 @@ class SOS_Sales_Achievement_Report(models.Model):
|
||||||
'ref_id',
|
'ref_id',
|
||||||
string="Billing Collection Lines"
|
string="Billing Collection Lines"
|
||||||
)
|
)
|
||||||
|
@api.depends('financial_year', 'sales_person')
|
||||||
|
def _compute_display_name(self):
|
||||||
|
for record in self:
|
||||||
|
record.display_name = f"{record.financial_year or ''} / {record.sales_person.name or ''}"
|
||||||
|
|
||||||
@api.depends('opening_balance', 'actual_target_april', 'billed_target_april')
|
@api.depends('opening_balance', 'actual_target_april', 'billed_target_april')
|
||||||
def _compute_yet_to_billed_april(self):
|
def _compute_yet_to_billed_april(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
|
|
@ -226,24 +231,24 @@ class SOS_Sales_Achievement_Report(models.Model):
|
||||||
'target': 'new',
|
'target': 'new',
|
||||||
'res_id': wizard.id,
|
'res_id': wizard.id,
|
||||||
}
|
}
|
||||||
|
|
||||||
def action_view_brief_lines(self):
|
# def action_view_brief_lines_acc(self):
|
||||||
|
# return {
|
||||||
|
# 'name': "Action",
|
||||||
|
# 'type': 'ir.actions.act_window',
|
||||||
|
# 'res_model': 'sos_sales_achievement_report_brief',
|
||||||
|
# 'view_mode': 'form',
|
||||||
|
# 'view_id': self.env.ref('sos_sales.view_form_sos_sales_achievement_acc').id,
|
||||||
|
# 'target': 'new',
|
||||||
|
# 'context': {
|
||||||
|
# 'ref_record_id': self.id
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
def action_view_brief_lines_acc(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
domain = [('ref_id', '=', self.id)]
|
domain = [('ref_record_id', '=', self.id)]
|
||||||
|
|
||||||
# Extract year from 'FY 2025-2026'
|
|
||||||
match = re.search(r'FY\s*(\d{4})', self.financial_year or '')
|
|
||||||
if match:
|
|
||||||
year = int(match.group(1))
|
|
||||||
else:
|
|
||||||
raise ValueError(f"Unable to extract year from financial year: {self.financial_year}")
|
|
||||||
|
|
||||||
# Filter by month if present
|
|
||||||
month = int(self.env.context.get('month', 0))
|
|
||||||
if month:
|
|
||||||
domain.append(('action_date', '>=', f'{year}-{month:02d}-01'))
|
|
||||||
last_day = calendar.monthrange(year, month)[1]
|
|
||||||
domain.append(('action_date', '<=', f'{year}-{month:02d}-{last_day:02d}'))
|
|
||||||
|
|
||||||
brief_lines = self.env['sos_sales_achievement_report_brief'].search(domain)
|
brief_lines = self.env['sos_sales_achievement_report_brief'].search(domain)
|
||||||
|
|
||||||
|
|
@ -258,6 +263,45 @@ class SOS_Sales_Achievement_Report(models.Model):
|
||||||
'default_parent_id': self.id,
|
'default_parent_id': self.id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
def action_view_brief_lines(self):
|
||||||
|
self.ensure_one()
|
||||||
|
domain = [('ref_id', '=', self.id)]
|
||||||
|
|
||||||
|
# Extract starting year from 'FY 2025-2026'
|
||||||
|
match = re.search(r'FY\s*(\d{4})', self.financial_year or '')
|
||||||
|
if match:
|
||||||
|
year = int(match.group(1))
|
||||||
|
else:
|
||||||
|
raise ValueError(f"Unable to extract year from financial year: {self.financial_year}")
|
||||||
|
|
||||||
|
month = int(self.env.context.get('month', 0))
|
||||||
|
|
||||||
|
if month:
|
||||||
|
# Filter specific month
|
||||||
|
domain.append(('action_date', '>=', f'{year}-{month:02d}-01'))
|
||||||
|
last_day = calendar.monthrange(year, month)[1]
|
||||||
|
domain.append(('action_date', '<=', f'{year}-{month:02d}-{last_day:02d}'))
|
||||||
|
else:
|
||||||
|
# Filter for entire financial year (April to March)
|
||||||
|
start_date = f'{year}-04-01'
|
||||||
|
end_date = f'{year + 1}-03-31'
|
||||||
|
domain.append(('action_date', '>=', start_date))
|
||||||
|
domain.append(('action_date', '<=', end_date))
|
||||||
|
|
||||||
|
brief_lines = self.env['sos_sales_achievement_report_brief'].search(domain)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'name': 'Achievement Brief Lines',
|
||||||
|
'type': 'ir.actions.act_window',
|
||||||
|
'res_model': 'sos_sales_achievement_report_brief_wizard',
|
||||||
|
'view_mode': 'form',
|
||||||
|
'target': 'new',
|
||||||
|
'context': {
|
||||||
|
'default_brief_line_ids': [(6, 0, brief_lines.ids)],
|
||||||
|
'default_parent_id': self.id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@api.depends(
|
@api.depends(
|
||||||
|
|
@ -554,17 +598,59 @@ class SOS_Sales_Achievement_Report_Brief(models.Model):
|
||||||
_name = 'sos_sales_achievement_report_brief'
|
_name = 'sos_sales_achievement_report_brief'
|
||||||
_description = 'Achievement Brief'
|
_description = 'Achievement Brief'
|
||||||
_order = 'action_date desc'
|
_order = 'action_date desc'
|
||||||
|
def get_financial_year_selection(self):
|
||||||
|
current_date = date.today()
|
||||||
|
start_year = 2024 # starting from FY 2024-2025
|
||||||
|
current_year = current_date.year if current_date.month >= 4 else current_date.year - 1
|
||||||
|
end_year = current_year + 1
|
||||||
|
|
||||||
|
selection = []
|
||||||
|
for y in range(start_year, current_year + 1):
|
||||||
|
fy = f"FY {y}-{y+1}"
|
||||||
|
selection.append((fy, fy))
|
||||||
|
return selection
|
||||||
ref_id = fields.Many2one('sos_sales_achievement_report', string="Financial Year", ondelete="cascade")
|
ref_id = fields.Many2one('sos_sales_achievement_report', string="Financial Year", ondelete="cascade")
|
||||||
|
ref_record_id = fields.Integer(string="Reference")
|
||||||
customer_name = fields.Many2one('sos_customers',string="Customer Name", required=True)
|
customer_name = fields.Many2one('sos_customers',string="Customer Name", required=True)
|
||||||
action_date = fields.Date(string="Date")
|
action_date = fields.Date(string="PO Date")
|
||||||
currency_id = fields.Many2one(
|
currency_id = fields.Many2one(
|
||||||
'res.currency',
|
'res.currency',
|
||||||
string='Currency',
|
string='Currency',
|
||||||
default=lambda self: self.env['res.currency'].search([('name', '=', 'INR')], limit=1).id or False
|
default=lambda self: self.env['res.currency'].search([('name', '=', 'INR')], limit=1).id or False
|
||||||
)
|
)
|
||||||
proposal_value = fields.Monetary(currency_field='currency_id',string="PO Received(In Lakhs)")
|
financial_year = fields.Selection(
|
||||||
|
selection=get_financial_year_selection,
|
||||||
|
string="Financial Year",
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
sales_person = fields.Many2one('res.users', string='Sales person',related="ref_id.sales_person",store=True)
|
||||||
|
po_no = fields.Char(string="PO No")
|
||||||
|
invoice_no = fields.Char(string="Invoice No")
|
||||||
|
proposal_value = fields.Monetary(currency_field='currency_id',string="PO Value(In Lakhs)")
|
||||||
billed_date = fields.Date(string="Billed Date")
|
billed_date = fields.Date(string="Billed Date")
|
||||||
billed_amount = fields.Monetary(currency_field='currency_id',string="Billed Value(In Lakhs)")
|
billed_amount = fields.Monetary(currency_field='currency_id',string="Billed Value(In Lakhs)")
|
||||||
|
# def view_lines_acc(self):
|
||||||
|
# self.ensure_one()
|
||||||
|
# return {
|
||||||
|
# 'name': 'Achievement Brief Lines',
|
||||||
|
# 'type': 'ir.actions.act_window',
|
||||||
|
# 'res_model': 'sos_sales_achievement_report_brief',
|
||||||
|
# 'view_mode': 'tree',
|
||||||
|
# 'domain': [('ref_record_id', '=', self.id)],
|
||||||
|
# 'context': {
|
||||||
|
# 'default_ref_record_id': self.id
|
||||||
|
# },
|
||||||
|
# 'target': 'current',
|
||||||
|
# }
|
||||||
|
def delete_achievement_line(self):
|
||||||
|
self.unlink()
|
||||||
|
def unlink(self):
|
||||||
|
for record in self:
|
||||||
|
report = self.env['sos_sales_achievement_report'].browse(record.ref_id.id)
|
||||||
|
if report and hasattr(report, 'opening_balance'):
|
||||||
|
report.write({'opening_balance': report.opening_balance - record.proposal_value})
|
||||||
|
return super(SOS_Sales_Achievement_Report_Brief, self).unlink()
|
||||||
|
|
||||||
def open_line_form(self):
|
def open_line_form(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
return {
|
return {
|
||||||
|
|
@ -589,7 +675,6 @@ class SOS_Sales_Achievement_Report_Brief(models.Model):
|
||||||
# New values
|
# New values
|
||||||
new_billed_date = vals.get('billed_date', old_billed_date)
|
new_billed_date = vals.get('billed_date', old_billed_date)
|
||||||
new_billed_amount = vals.get('billed_amount', old_billed_amount)
|
new_billed_amount = vals.get('billed_amount', old_billed_amount)
|
||||||
|
|
||||||
if isinstance(new_billed_date, str):
|
if isinstance(new_billed_date, str):
|
||||||
new_billed_date = datetime.strptime(new_billed_date, '%Y-%m-%d').date()
|
new_billed_date = datetime.strptime(new_billed_date, '%Y-%m-%d').date()
|
||||||
|
|
||||||
|
|
@ -609,53 +694,63 @@ class SOS_Sales_Achievement_Report_Brief(models.Model):
|
||||||
new_field_billed: (getattr(report, new_field_billed, 0.0) or 0.0) + new_billed_amount
|
new_field_billed: (getattr(report, new_field_billed, 0.0) or 0.0) + new_billed_amount
|
||||||
})
|
})
|
||||||
# Optionally create billing collection entry (if needed)
|
# Optionally create billing collection entry (if needed)
|
||||||
if new_billed_amount > 0:
|
if new_billed_amount > 0:
|
||||||
self.env['sos_billing_collection'].create({
|
self.env['sos_billing_collection'].create({
|
||||||
'ref_id': report.id,
|
'ref_id': report.id,
|
||||||
'customer_name': vals.get('customer_name', rec.customer_name.id),
|
'customer_name': vals.get('customer_name', rec.customer_name.id),
|
||||||
'sales_person': report.sales_person.id,
|
'sales_person': report.sales_person.id,
|
||||||
'action_status': 'Billed',
|
'action_status': 'Billed',
|
||||||
'date_of_action': new_billed_date,
|
'date_of_action': new_billed_date,
|
||||||
'value': new_billed_amount
|
'value': new_billed_amount
|
||||||
})
|
})
|
||||||
|
|
||||||
return super(SOS_Sales_Achievement_Report_Brief, self).write(vals)
|
return super(SOS_Sales_Achievement_Report_Brief, self).write(vals)
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def create(self, vals):
|
def create(self, vals):
|
||||||
|
ref_id = vals.get('ref_id')
|
||||||
|
vals['ref_record_id'] = ref_id
|
||||||
|
|
||||||
action_date = vals.get('action_date')
|
action_date = vals.get('action_date')
|
||||||
billed_date = vals.get('billed_date')
|
billed_date = vals.get('billed_date')
|
||||||
customer_name = vals.get('customer_name')
|
customer_name = vals.get('customer_name')
|
||||||
|
value = vals.get('proposal_value', 0.0)
|
||||||
|
billed_value = vals.get('billed_amount', 0.0)
|
||||||
|
ref_id = vals.get('ref_id')
|
||||||
|
|
||||||
if isinstance(action_date, str):
|
if isinstance(action_date, str):
|
||||||
action_date = datetime.strptime(action_date, '%Y-%m-%d').date()
|
action_date = datetime.strptime(action_date, '%Y-%m-%d').date()
|
||||||
if isinstance(billed_date, str):
|
if isinstance(billed_date, str):
|
||||||
billed_date = datetime.strptime(billed_date, '%Y-%m-%d').date()
|
billed_date = datetime.strptime(billed_date, '%Y-%m-%d').date()
|
||||||
|
|
||||||
month_name = action_date.strftime('%B').lower()
|
if ref_id and action_date:
|
||||||
value = vals.get('proposal_value', 0.0)
|
|
||||||
actual_field = f"actual_target_{month_name}"
|
|
||||||
|
|
||||||
ref_id = vals.get('ref_id')
|
|
||||||
if ref_id:
|
|
||||||
report = self.env['sos_sales_achievement_report'].browse(ref_id)
|
report = self.env['sos_sales_achievement_report'].browse(ref_id)
|
||||||
sales_person = report.sales_person
|
month_name = action_date.strftime('%B').lower()
|
||||||
if sales_person and hasattr(report, actual_field):
|
actual_field = f"actual_target_{month_name}"
|
||||||
current_value = getattr(report, actual_field, 0.0) or 0.0
|
current_date = date.today()
|
||||||
report.write({actual_field: current_value + value})
|
start_year = current_date.year if current_date.month >= 4 else current_date.year - 1
|
||||||
|
end_year = start_year + 1
|
||||||
|
current_fy = f"FY {start_year}-{end_year}"
|
||||||
|
if vals.get('financial_year') != current_fy:
|
||||||
|
report.write({'opening_balance': report.opening_balance + value})
|
||||||
|
|
||||||
# Instead of also summing billed_value here, just create billing line
|
|
||||||
if billed_date:
|
if vals.get('financial_year') == current_fy:
|
||||||
self.env['sos_billing_collection'].create({
|
if hasattr(report, actual_field):
|
||||||
'ref_id': report.id,
|
current_val = getattr(report, actual_field) or 0.0
|
||||||
'customer_name': customer_name,
|
report.write({actual_field: current_val + value})
|
||||||
'sales_person': report.sales_person.id,
|
|
||||||
'action_status': 'Billed',
|
|
||||||
'date_of_action': billed_date,
|
|
||||||
'value': vals.get('billed_amount', 0.0)
|
|
||||||
})
|
|
||||||
|
|
||||||
return super(SOS_Sales_Achievement_Report_Brief, self).create(vals)
|
if billed_date:
|
||||||
|
self.env['sos_billing_collection'].create({
|
||||||
|
'ref_id': report.id,
|
||||||
|
'customer_name': customer_name,
|
||||||
|
'sales_person': report.sales_person.id,
|
||||||
|
'action_status': 'Billed',
|
||||||
|
'date_of_action': billed_date,
|
||||||
|
'value': billed_value
|
||||||
|
})
|
||||||
|
new_record = super(SOS_Sales_Achievement_Report_Brief, self).create(vals)
|
||||||
|
return new_record
|
||||||
|
|
||||||
|
|
||||||
class SOS_Sales_Achievement_Report_Brief_Wizard(models.TransientModel):
|
class SOS_Sales_Achievement_Report_Brief_Wizard(models.TransientModel):
|
||||||
|
|
@ -780,6 +875,33 @@ class SosBillingCollection(models.Model):
|
||||||
start_year = current_date.year if current_date.month >= 4 else current_date.year - 1
|
start_year = current_date.year if current_date.month >= 4 else current_date.year - 1
|
||||||
end_year = start_year + 1
|
end_year = start_year + 1
|
||||||
return f"FY {start_year}-{end_year}"
|
return f"FY {start_year}-{end_year}"
|
||||||
|
def delete_form_line(self):
|
||||||
|
self.unlink()
|
||||||
|
|
||||||
|
def unlink(self):
|
||||||
|
for record in self:
|
||||||
|
|
||||||
|
if record.date_of_action:
|
||||||
|
fy = self._get_financial_year(record.date_of_action)
|
||||||
|
month_name = record.date_of_action.strftime('%B').lower()
|
||||||
|
else:
|
||||||
|
fy = False
|
||||||
|
month_name = False
|
||||||
|
|
||||||
|
if fy and month_name:
|
||||||
|
actual_field_name = f"{record.action_status.lower()}_target_{month_name}"
|
||||||
|
|
||||||
|
# Fetch related record where field update should happen (example logic)
|
||||||
|
report = self.env['sos_sales_achievement_report'].search([
|
||||||
|
('financial_year', '=', fy),
|
||||||
|
('sales_person', '=', record.sales_person.id)
|
||||||
|
], limit=1)
|
||||||
|
|
||||||
|
if report and hasattr(report, actual_field_name):
|
||||||
|
current_val = getattr(report, actual_field_name, 0.0)
|
||||||
|
setattr(report, actual_field_name, current_val - record.value)
|
||||||
|
|
||||||
|
return super(SosBillingCollection, self).unlink()
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def create(self, vals):
|
def create(self, vals):
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
from odoo import models, fields, api
|
from odoo import models, fields, api
|
||||||
|
import random
|
||||||
|
|
||||||
class sos_sales_leads(models.Model):
|
class sos_sales_leads(models.Model):
|
||||||
_name = 'sos_sales_leads'
|
_name = 'sos_sales_leads'
|
||||||
|
|
@ -9,31 +10,43 @@ class sos_sales_leads(models.Model):
|
||||||
transferred_on = fields.Date(string="Transferred On")
|
transferred_on = fields.Date(string="Transferred On")
|
||||||
location = fields.Char(string="Location")
|
location = fields.Char(string="Location")
|
||||||
website_url = fields.Char(string="Website URL")
|
website_url = fields.Char(string="Website URL")
|
||||||
vertical_domain = fields.Many2one('sos_vertical_domain',string="Domain / Industry", ondelete="cascade")
|
vertical_domain = fields.Many2many('sos_vertical_domain',string="Domain / Industry", ondelete="cascade")
|
||||||
linkedin_profile = fields.Char(string="Linkedin profile")
|
linkedin_profile = fields.Char(string="Linkedin profile")
|
||||||
status = fields.Char(string="Status")
|
status = fields.Char(string="Status")
|
||||||
correspondence_address = fields.Text(string="Correspondence Address")
|
correspondence_address = fields.Text(string="Correspondence Address")
|
||||||
interested_in = fields.Selection(
|
interested_in = fields.Selection(
|
||||||
[
|
[
|
||||||
('products', 'Products'),
|
('Product', 'Products'),
|
||||||
('projects', 'Projects')
|
('Project', 'Projects')
|
||||||
],
|
],
|
||||||
string="Interested In",required=True,default="products")
|
string="Service Type",required=True,default="Product")
|
||||||
project_name = fields.Char(string="Project Name")
|
sales_type = fields.Selection(
|
||||||
products = fields.Selection(
|
|
||||||
[
|
[
|
||||||
('BHMS 1.2V', 'BHMS 1.2V'),
|
('Domestic', 'Domestic'),
|
||||||
('BHMS 2V', 'BHMS 2V'),
|
('International', 'International')
|
||||||
('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="Products")
|
string="Sales Type",default="Domestic")
|
||||||
|
project_name= fields.Many2one('sos_projects',string="Project Name")
|
||||||
|
products_interested = fields.Many2many('sos_products',string="Product Interested In")
|
||||||
|
# products = 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="Products")
|
||||||
|
country = fields.Many2one(
|
||||||
|
'res.country',
|
||||||
|
string='Country',
|
||||||
|
default=lambda self: self.env['res.country'].search([('code', '=', 'IN')], limit=1)
|
||||||
|
)
|
||||||
source = fields.Selection(
|
source = fields.Selection(
|
||||||
[
|
[
|
||||||
('self', 'Self'),
|
('self', 'Self'),
|
||||||
|
|
@ -91,16 +104,18 @@ class SOS_Leads_Lines(models.Model):
|
||||||
email = fields.Char(string="Email Id")
|
email = fields.Char(string="Email Id")
|
||||||
mobile_number = fields.Char(string="Contact Number")
|
mobile_number = fields.Char(string="Contact Number")
|
||||||
set_as_primary = fields.Boolean(string="Set Primary")
|
set_as_primary = fields.Boolean(string="Set Primary")
|
||||||
@api.model
|
linkedin_profile = fields.Char(string="LinkedIn Profile")
|
||||||
def create(self, vals):
|
remarks = fields.Text(string="Remarks")
|
||||||
record = super(SOS_Leads_Lines, self).create(vals)
|
# @api.model
|
||||||
if not self.env['sos_leads_customer_contact_lines'].search([
|
# def create(self, vals):
|
||||||
('ref_id', '=', record.ref_id.id),
|
# record = super(SOS_Leads_Lines, self).create(vals)
|
||||||
('set_as_primary', '=', True)
|
# if not self.env['sos_leads_customer_contact_lines'].search([
|
||||||
]):
|
# ('ref_id', '=', record.ref_id.id),
|
||||||
# Set the created record as primary
|
# ('set_as_primary', '=', True)
|
||||||
record.set_as_primary = True
|
# ]):
|
||||||
return record
|
# # Set the created record as primary
|
||||||
|
# record.set_as_primary = True
|
||||||
|
# return record
|
||||||
def write(self, vals):
|
def write(self, vals):
|
||||||
res = super(SOS_Leads_Lines, self).write(vals)
|
res = super(SOS_Leads_Lines, self).write(vals)
|
||||||
if 'set_as_primary' in vals and vals['set_as_primary']:
|
if 'set_as_primary' in vals and vals['set_as_primary']:
|
||||||
|
|
@ -109,4 +124,22 @@ class SOS_Leads_Lines(models.Model):
|
||||||
('ref_id', '=', record.ref_id.id),
|
('ref_id', '=', record.ref_id.id),
|
||||||
('id', '!=', record.id)
|
('id', '!=', record.id)
|
||||||
]).write({'set_as_primary': False})
|
]).write({'set_as_primary': False})
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
class ProductInterest(models.Model):
|
||||||
|
_name = 'sos_products'
|
||||||
|
_description = 'Product Interest'
|
||||||
|
|
||||||
|
name = fields.Char(string="Product Name", required=True)
|
||||||
|
color = fields.Integer(string="Colour")
|
||||||
|
@api.model
|
||||||
|
def create(self, vals):
|
||||||
|
if 'color' not in vals:
|
||||||
|
vals['color'] = random.randint(1, 11)
|
||||||
|
return super(ProductInterest, self).create(vals)
|
||||||
|
|
||||||
|
class ProjectMaster(models.Model):
|
||||||
|
_name = 'sos_projects'
|
||||||
|
_description = 'Projects'
|
||||||
|
|
||||||
|
name = fields.Char(string="Project Name", required=True)
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -17,13 +17,11 @@ class ReportBusinessPerformance(models.AbstractModel):
|
||||||
financial_year = self._get_financial_year()
|
financial_year = self._get_financial_year()
|
||||||
|
|
||||||
domain = [('financial_year', '=', financial_year)]
|
domain = [('financial_year', '=', financial_year)]
|
||||||
|
|
||||||
if sales_person_id:
|
if sales_person_id:
|
||||||
domain.append(('sales_person', '=', sales_person_id))
|
domain.append(('sales_person', '=', sales_person_id))
|
||||||
|
|
||||||
records = self.env['sos_sales_achievement_report'].search(domain, order="sales_person ASC")
|
records = self.env['sos_sales_achievement_report'].search(domain, order="sales_person ASC")
|
||||||
|
|
||||||
|
|
||||||
months = [
|
months = [
|
||||||
'april', 'may', 'june', 'july', 'august', 'september',
|
'april', 'may', 'june', 'july', 'august', 'september',
|
||||||
'october', 'november', 'december',
|
'october', 'november', 'december',
|
||||||
|
|
@ -39,8 +37,10 @@ class ReportBusinessPerformance(models.AbstractModel):
|
||||||
current_month = date.today().month
|
current_month = date.today().month
|
||||||
if current_month >= 4:
|
if current_month >= 4:
|
||||||
ytd_months = months[:current_month - 4 + 1]
|
ytd_months = months[:current_month - 4 + 1]
|
||||||
|
current_month_key = months[current_month - 4]
|
||||||
else:
|
else:
|
||||||
ytd_months = months[:current_month + 9 + 1]
|
ytd_months = months[:current_month + 9 + 1]
|
||||||
|
current_month_key = months[current_month + 9]
|
||||||
|
|
||||||
records = list(records)
|
records = list(records)
|
||||||
|
|
||||||
|
|
@ -54,7 +54,7 @@ class ReportBusinessPerformance(models.AbstractModel):
|
||||||
'target': 0.0,
|
'target': 0.0,
|
||||||
'sales': 0.0,
|
'sales': 0.0,
|
||||||
'sales_percentage': 0.0,
|
'sales_percentage': 0.0,
|
||||||
'yet_to_billed':0.0,
|
'yet_to_billed': 0.0,
|
||||||
'billed': 0.0,
|
'billed': 0.0,
|
||||||
'collected': 0.0,
|
'collected': 0.0,
|
||||||
}
|
}
|
||||||
|
|
@ -77,16 +77,18 @@ class ReportBusinessPerformance(models.AbstractModel):
|
||||||
for m in ytd_months:
|
for m in ytd_months:
|
||||||
ytd_target += round(getattr(doc, f'planned_target_{m}', 0.0), 2)
|
ytd_target += round(getattr(doc, f'planned_target_{m}', 0.0), 2)
|
||||||
ytd_sales += round(getattr(doc, f'actual_target_{m}', 0.0), 2)
|
ytd_sales += round(getattr(doc, f'actual_target_{m}', 0.0), 2)
|
||||||
ytd_yet_to_billed += round(getattr(doc, f'yet_to_billed_target_{m}', 0.0), 2)
|
|
||||||
ytd_billed += round(getattr(doc, f'billed_target_{m}', 0.0), 2)
|
ytd_billed += round(getattr(doc, f'billed_target_{m}', 0.0), 2)
|
||||||
ytd_collected += round(getattr(doc, f'collected_target_{m}', 0.0), 2)
|
ytd_collected += round(getattr(doc, f'collected_target_{m}', 0.0), 2)
|
||||||
|
|
||||||
summary['ytd']['target'] += round(getattr(doc, f'planned_target_{m}', 0.0), 2)
|
summary['ytd']['target'] += round(getattr(doc, f'planned_target_{m}', 0.0), 2)
|
||||||
summary['ytd']['sales'] += round(getattr(doc, f'actual_target_{m}', 0.0), 2)
|
summary['ytd']['sales'] += round(getattr(doc, f'actual_target_{m}', 0.0), 2)
|
||||||
summary['ytd']['yet_to_billed'] += round(getattr(doc, f'yet_to_billed_target_{m}', 0.0), 2)
|
|
||||||
summary['ytd']['billed'] += round(getattr(doc, f'billed_target_{m}', 0.0), 2)
|
summary['ytd']['billed'] += round(getattr(doc, f'billed_target_{m}', 0.0), 2)
|
||||||
summary['ytd']['collected'] += round(getattr(doc, f'collected_target_{m}', 0.0), 2)
|
summary['ytd']['collected'] += round(getattr(doc, f'collected_target_{m}', 0.0), 2)
|
||||||
|
|
||||||
|
# Override YTD "yet_to_billed" with only current month value
|
||||||
|
ytd_yet_to_billed = round(getattr(doc, f'yet_to_billed_target_{current_month_key}', 0.0), 2)
|
||||||
|
summary['ytd']['yet_to_billed'] += ytd_yet_to_billed
|
||||||
|
|
||||||
# Assign as formatted string with 2 decimal places
|
# Assign as formatted string with 2 decimal places
|
||||||
doc.ytd_target = "%.2f" % ytd_target
|
doc.ytd_target = "%.2f" % ytd_target
|
||||||
doc.ytd_sales = "%.2f" % ytd_sales
|
doc.ytd_sales = "%.2f" % ytd_sales
|
||||||
|
|
@ -104,18 +106,21 @@ class ReportBusinessPerformance(models.AbstractModel):
|
||||||
else:
|
else:
|
||||||
summary['ytd']['sales_percentage'] = "0.00"
|
summary['ytd']['sales_percentage'] = "0.00"
|
||||||
|
|
||||||
# Also convert YTD values in summary to formatted strings
|
|
||||||
for key in ['target', 'sales', 'billed', 'collected']:
|
for key in ['target', 'sales', 'billed', 'collected']:
|
||||||
summary['ytd'][key] = "%.2f" % summary['ytd'][key]
|
summary['ytd'][key] = "%.2f" % summary['ytd'][key]
|
||||||
|
summary['ytd']['yet_to_billed'] = "%.2f" % summary['ytd']['yet_to_billed']
|
||||||
|
current_month_index = months.index(current_month_key) if current_month_key in months else 0
|
||||||
return {
|
return {
|
||||||
'doc_ids': [rec.id for rec in records],
|
'doc_ids': [rec.id for rec in records],
|
||||||
'doc_model': 'sos_sales_achievement_report',
|
'doc_model': 'sos_sales_achievement_report',
|
||||||
'docs': records,
|
'docs': records,
|
||||||
'financial_year': financial_year,
|
'financial_year': financial_year,
|
||||||
|
'enumerated_months': list(enumerate(months)),
|
||||||
'months': months,
|
'months': months,
|
||||||
'month_names': month_names,
|
'month_names': month_names,
|
||||||
'summary': summary,
|
'summary': summary,
|
||||||
'ytd_months': ytd_months,
|
'ytd_months': ytd_months,
|
||||||
|
'current_month_index': int(current_month_index),
|
||||||
'is_filtered_by_sales_person': bool(sales_person_id)
|
'is_filtered_by_sales_person': bool(sales_person_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
<div class="page">
|
<div class="page">
|
||||||
<br></br>
|
<br></br>
|
||||||
<h4 style="text-align: center;">Business Performance Report- <t t-esc="financial_year"/></h4>
|
<h4 style="text-align: center;">Business Performance Report- <t t-esc="financial_year"/></h4>
|
||||||
|
<span style="float: right;font-weight: bold;">Note : Rupees(In Lakhs)</span>
|
||||||
<!-- ✅ SUMMARY TABLE -->
|
<!-- ✅ SUMMARY TABLE -->
|
||||||
<t t-if="not is_filtered_by_sales_person">
|
<t t-if="not is_filtered_by_sales_person">
|
||||||
|
|
||||||
|
|
@ -64,25 +64,38 @@
|
||||||
<td><t t-esc="summary['ytd']['billed']"/></td>
|
<td><t t-esc="summary['ytd']['billed']"/></td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="background-color:#e4e0f9"><strong>Yet to Bill</strong></td>
|
<td style="background-color:#e4e0f9"><strong>Yet to Bill</strong></td>
|
||||||
<t t-set="total_yet_billed" t-value="0"/>
|
<t t-set="total_yet_billed" t-value="0"/>
|
||||||
<t t-foreach="months" t-as="m">
|
|
||||||
<t t-set="val" t-value="summary['yet_to_billed'][m]"/>
|
<t t-foreach="enumerated_months" t-as="item">
|
||||||
<td><t t-esc="'%.2f' % val"/></td>
|
<t t-set="i" t-value="item[0]"/>
|
||||||
<t t-set="total_yet_billed" t-value="total_billed + val"/>
|
<t t-set="m" t-value="item[1]"/>
|
||||||
</t>
|
|
||||||
|
<t t-if="i <= current_month_index">
|
||||||
|
<t t-set="val" t-value="summary['yet_to_billed'][m] or 0.0"/>
|
||||||
|
<td><t t-esc="'%.2f' % val"/></td>
|
||||||
|
<t t-set="total_yet_billed" t-value="total_yet_billed + val"/>
|
||||||
|
</t>
|
||||||
|
<t t-else="">
|
||||||
|
<td>0.00</td>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
|
||||||
|
<td><t t-esc="summary['ytd']['yet_to_billed']"/></td>
|
||||||
|
<td><t t-esc="summary['ytd']['yet_to_billed']"/></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<td><t t-esc="'%.2f' % float(total_yet_billed)"/></td>
|
|
||||||
<td><t t-esc="summary['ytd']['yet_to_billed']"/></td>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td style="background-color:#e4e0f9"><strong>Collected</strong></td>
|
<td style="background-color:#e4e0f9"><strong>Collected</strong></td>
|
||||||
<t t-set="total_collected" t-value="0"/>
|
<t t-set="total_collected" t-value="0"/>
|
||||||
<t t-foreach="months" t-as="m">
|
<t t-foreach="months" t-as="m">
|
||||||
<t t-set="val" t-value="summary['collected'][m]"/>
|
<t t-set="val" t-value="summary['collected'][m]"/>
|
||||||
<td><t t-esc="val"/></td>
|
<td><t t-esc="'%.2f' % val"/></td>
|
||||||
<t t-set="total_collected" t-value="total_collected + val"/>
|
<t t-set="total_collected" t-value="total_collected + val"/>
|
||||||
</t>
|
</t>
|
||||||
<td><t t-esc="'%.2f' % float(total_collected)"/></td>
|
<td><t t-esc="'%.2f' % float(total_collected)"/></td>
|
||||||
|
|
@ -186,22 +199,25 @@
|
||||||
<td><t t-esc="'%.2f' % float(doc.ytd_billed)"/></td>
|
<td><t t-esc="'%.2f' % float(doc.ytd_billed)"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td style="background-color:#e4e0f9"><strong>Yet to Bill</strong></td>
|
<td style="background-color:#e4e0f9"><strong>Yet to Bill</strong></td>
|
||||||
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_april)"/></td>
|
|
||||||
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_may)"/></td>
|
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_april) if current_month_index >= 0 else '0.00'"/></td>
|
||||||
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_june)"/></td>
|
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_may) if current_month_index >= 1 else '0.00'"/></td>
|
||||||
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_july)"/></td>
|
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_june) if current_month_index >= 2 else '0.00'"/></td>
|
||||||
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_august)"/></td>
|
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_july) if current_month_index >= 3 else '0.00'"/></td>
|
||||||
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_september)"/></td>
|
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_august) if current_month_index >= 4 else '0.00'"/></td>
|
||||||
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_october)"/></td>
|
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_september) if current_month_index >= 5 else '0.00'"/></td>
|
||||||
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_november)"/></td>
|
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_october) if current_month_index >= 6 else '0.00'"/></td>
|
||||||
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_december)"/></td>
|
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_november) if current_month_index >= 7 else '0.00'"/></td>
|
||||||
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_january)"/></td>
|
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_december) if current_month_index >= 8 else '0.00'"/></td>
|
||||||
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_february)"/></td>
|
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_january) if current_month_index >= 9 else '0.00'"/></td>
|
||||||
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_march)"/></td>
|
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_february) if current_month_index >= 10 else '0.00'"/></td>
|
||||||
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_total)"/></td>
|
<td><t t-esc="'%.2f' % float(doc.yet_to_billed_target_march) if current_month_index >= 11 else '0.00'"/></td>
|
||||||
<td><t t-esc="'%.2f' % float(doc.ytd_yet_to_billed)"/></td>
|
|
||||||
</tr>
|
<td><t t-esc="'%.2f' % float(doc.ytd_yet_to_billed)"/></td>
|
||||||
|
<td><t t-esc="'%.2f' % float(doc.ytd_yet_to_billed)"/></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td style="background-color:#e4e0f9"><strong>Collected</strong></td>
|
<td style="background-color:#e4e0f9"><strong>Collected</strong></td>
|
||||||
<td><t t-esc="'%.2f' % float(doc.collected_target_april)"/></td>
|
<td><t t-esc="'%.2f' % float(doc.collected_target_april)"/></td>
|
||||||
|
|
|
||||||
|
|
@ -61,5 +61,7 @@ access_sos_sales_achievement_report_brief_wizard,sos_sales_achievement_report_br
|
||||||
access_sos_billing_collection,sos_billing_collection access,model_sos_billing_collection,base.group_user,1,1,1,1
|
access_sos_billing_collection,sos_billing_collection access,model_sos_billing_collection,base.group_user,1,1,1,1
|
||||||
access_sos_billed_collection_wizard,sos_billed_collection_wizard access,model_sos_billed_collection_wizard,base.group_user,1,1,1,1
|
access_sos_billed_collection_wizard,sos_billed_collection_wizard access,model_sos_billed_collection_wizard,base.group_user,1,1,1,1
|
||||||
access_sos_business_performance_wizard,sos_business_performance_wizard access,model_sos_business_performance_wizard,base.group_user,1,1,1,1
|
access_sos_business_performance_wizard,sos_business_performance_wizard access,model_sos_business_performance_wizard,base.group_user,1,1,1,1
|
||||||
|
access_sos_products,sos_products access,model_sos_products,base.group_user,1,1,1,1
|
||||||
|
access_sos_projects,sos_projects access,model_sos_projects,base.group_user,1,1,1,1
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
|
@ -13,13 +13,23 @@ name="action_report_achievement_btn"><i class="fa fa-print"></i> Print Report</b
|
||||||
<sheet>
|
<sheet>
|
||||||
<h2 style="text-align: center;text-transform: uppercase;text-shadow: 1px 1p 1px #140718;color: #65407c;padding:5px;">Sales Achievements Report</h2><hr></hr><br></br>
|
<h2 style="text-align: center;text-transform: uppercase;text-shadow: 1px 1p 1px #140718;color: #65407c;padding:5px;">Sales Achievements Report</h2><hr></hr><br></br>
|
||||||
<group>
|
<group>
|
||||||
<field name="financial_year" style="font-size: 20px; pointer-events: none; color: #793595;"/>
|
<group><field name="financial_year" style="font-size: 20px; pointer-events: none; color: #793595;"/>
|
||||||
|
|
||||||
<field name="sales_person" />
|
|
||||||
<field name="overall_target" />
|
|
||||||
<field name="opening_balance" groups="sos_inventory.sos_finance_user,sos_inventory.sos_management_user"/>
|
|
||||||
|
|
||||||
</group>
|
</group>
|
||||||
|
<group><field name="sales_person" /></group>
|
||||||
|
<group><field name="overall_target" /></group>
|
||||||
|
<table style="margin-left: 15px;"><tr>
|
||||||
|
<td><group><field name="opening_balance" groups="sos_inventory.sos_finance_user,sos_inventory.sos_management_user"/>
|
||||||
|
</group></td>
|
||||||
|
<td><button name="action_view_brief_lines_acc"
|
||||||
|
type="object"
|
||||||
|
string="📊"
|
||||||
|
class="btn-link"
|
||||||
|
context="{'month': 0}"
|
||||||
|
style="padding: 0; border: none; background: none; font-size: 18px; box-shadow: 4px 5px 5px #e3e2e2;"/>
|
||||||
|
</td>
|
||||||
|
</tr></table>
|
||||||
|
</group>
|
||||||
|
|
||||||
<br></br>
|
<br></br>
|
||||||
<table class="table_custom">
|
<table class="table_custom">
|
||||||
<thead>
|
<thead>
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,11 @@
|
||||||
<field name="model">sos_sales_leads</field>
|
<field name="model">sos_sales_leads</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<search>
|
<search>
|
||||||
<searchpanel>
|
<searchpanel>
|
||||||
<field name="products" string="Products Interested In" icon="fa-list-ul" enable_counters="1"/>
|
|
||||||
<field name="vertical_domain" string="Vertical/Domain" icon="fa-pie-chart" enable_counters="1"/>
|
|
||||||
|
|
||||||
</searchpanel>
|
<field name="sales_type" string="Type" icon="fa-list-ul" enable_counters="1"/>
|
||||||
|
|
||||||
|
</searchpanel>
|
||||||
|
|
||||||
<!-- Add fields to search on -->
|
<!-- Add fields to search on -->
|
||||||
<field name="company_name" string="Company Name"/>
|
<field name="company_name" string="Company Name"/>
|
||||||
|
|
@ -53,20 +53,25 @@
|
||||||
|
|
||||||
<group>
|
<group>
|
||||||
<group>
|
<group>
|
||||||
|
<field name="sales_type"/>
|
||||||
<field name="lead_generated_by"/>
|
<field name="lead_generated_by"/>
|
||||||
<field name="company_name"/>
|
<field name="company_name"/>
|
||||||
<field name="convert_to_customer_btn_display" invisible="1"/>
|
<field name="convert_to_customer_btn_display" invisible="1"/>
|
||||||
<field name="transferred_on" invisible="1"/>
|
<field name="transferred_on" invisible="1"/>
|
||||||
|
<field name="country" invisible="sales_type != 'International'"/>
|
||||||
|
|
||||||
<field name="website_url"/>
|
<field name="website_url"/>
|
||||||
<field name="linkedin_profile"/>
|
<field name="linkedin_profile"/>
|
||||||
<field name="correspondence_address"/>
|
<field name="correspondence_address"/>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="interested_in"/>
|
<field name="interested_in"/>
|
||||||
<field name="project_name" invisible="interested_in == 'products'"/>
|
<field name="project_name" invisible="interested_in == 'Product'"/>
|
||||||
<field name="products" invisible="interested_in == 'projects'"/>
|
<field name="products_interested"
|
||||||
|
options="{'no_create': True, 'no_edit': True, 'no_create_edit': True}"
|
||||||
|
widget="many2many_tags" invisible="interested_in != 'Product'"/>
|
||||||
<field name="location"/>
|
<field name="location"/>
|
||||||
<field name="vertical_domain"/>
|
<field name="vertical_domain" widget="many2many_tags"/>
|
||||||
<field name="source"/>
|
<field name="source"/>
|
||||||
<field name="expo_name" invisible="source != 'expo'"/>
|
<field name="expo_name" invisible="source != 'expo'"/>
|
||||||
</group>
|
</group>
|
||||||
|
|
@ -82,6 +87,8 @@
|
||||||
<field name="dept"/>
|
<field name="dept"/>
|
||||||
<field name="email"/>
|
<field name="email"/>
|
||||||
<field name="mobile_number"/>
|
<field name="mobile_number"/>
|
||||||
|
<field name="linkedin_profile"/>
|
||||||
|
<field name="remarks"/>
|
||||||
|
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -1,5 +1,29 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<odoo>
|
<odoo>
|
||||||
|
<record id="view_form_sos_sales_achievement_acc" model="ir.ui.view">
|
||||||
|
<field name="name">sos.sales.achievement.report.brief.form</field>
|
||||||
|
<field name="model">sos_sales_achievement_report_brief</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Achievement Brief">
|
||||||
|
<sheet>
|
||||||
|
<group>
|
||||||
|
<field name="ref_id" invisible="1"/>
|
||||||
|
<field name="financial_year"/>
|
||||||
|
<field name="sales_person"/>
|
||||||
|
<field name="customer_name"/>
|
||||||
|
<field name="invoice_no"/>
|
||||||
|
<field name="action_date"/>
|
||||||
|
|
||||||
|
<field name="po_no"/>
|
||||||
|
<field name="proposal_value"/>
|
||||||
|
<field name="billed_date"/>
|
||||||
|
<field name="billed_amount"/>
|
||||||
|
<field name="currency_id" invisible="1"/>
|
||||||
|
</group>
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
<record id="view_sos_sales_achievement_brief_wizard_form" model="ir.ui.view">
|
<record id="view_sos_sales_achievement_brief_wizard_form" model="ir.ui.view">
|
||||||
<field name="name">sos_sales_achievement_report_brief_wizard.form</field>
|
<field name="name">sos_sales_achievement_report_brief_wizard.form</field>
|
||||||
|
|
@ -19,13 +43,18 @@
|
||||||
|
|
||||||
<field name="brief_line_ids" nolabel="1">
|
<field name="brief_line_ids" nolabel="1">
|
||||||
<tree>
|
<tree>
|
||||||
|
<field name="financial_year"/>
|
||||||
<field name="action_date" string="Date"/>
|
<field name="action_date" string="Date"/>
|
||||||
<field name="customer_name"/>
|
<field name="customer_name"/>
|
||||||
|
<field name="po_no"/>
|
||||||
|
<field name="invoice_no"/>
|
||||||
<field name="proposal_value"/>
|
<field name="proposal_value"/>
|
||||||
<field name="billed_date"/>
|
<field name="billed_date"/>
|
||||||
<field name="billed_amount"/>
|
<field name="billed_amount"/>
|
||||||
<button name="open_line_form" string="Edit"
|
<button name="delete_achievement_line" class="btn btn-primary" string="Delete"
|
||||||
type="object" icon="fa-pencil" invisible="billed_date != False and billed_amount != False"/>
|
type="object" icon="fa-times"/>
|
||||||
|
<button name="open_line_form" class="btn btn-primary" string="Edit"
|
||||||
|
type="object" icon="fa-pencil"/>
|
||||||
|
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
|
|
@ -139,6 +168,8 @@
|
||||||
<field name="customer_name"/>
|
<field name="customer_name"/>
|
||||||
<field name="value"/>
|
<field name="value"/>
|
||||||
<field name="invoice_no"/>
|
<field name="invoice_no"/>
|
||||||
|
<button name="delete_form_line" class="btn btn-primary" string="Delete"
|
||||||
|
type="object" icon="fa-times"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
<footer>
|
<footer>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue