leads of sales and inside sales matched
This commit is contained in:
parent
590d716eec
commit
0565053d7a
|
|
@ -15,6 +15,7 @@
|
|||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
'security/record_rules.xml',
|
||||
'data/lead_source_data.xml',
|
||||
'views/menu.xml',
|
||||
'views/sos_inside_sales_leads_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")
|
||||
location = fields.Char(string="Location")
|
||||
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)
|
||||
remarks=fields.Text(string="Remarks")
|
||||
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'),
|
||||
('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')
|
||||
('Product', 'Products'),
|
||||
('Project', 'Projects')
|
||||
|
||||
],
|
||||
string="Product Interested In")
|
||||
source = fields.Selection(
|
||||
string="Service Type",default="Product")
|
||||
project_name= fields.Many2one('sos_projects',string="Project Name")
|
||||
status = fields.Selection(
|
||||
[
|
||||
('website', 'Website'),
|
||||
('expo', 'Expo'),
|
||||
('cold_calls', 'Cold Calls'),
|
||||
('linkedin', 'Linkedin')
|
||||
('Open', 'Open'),
|
||||
('Close', 'Close'),
|
||||
('New', 'New'),
|
||||
('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(
|
||||
[
|
||||
('Online', 'Online'),
|
||||
|
|
@ -52,12 +65,24 @@ class sos_inside_sales_leads(models.Model):
|
|||
],
|
||||
string="Meeting Schedule")
|
||||
expo_name = fields.Char(string="Expo Name")
|
||||
move_to_sales = fields.Many2many('res.users',string="Move Lead to")
|
||||
cc_mail = fields.Many2one('res.users',string="CC 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", 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")
|
||||
line_ids = fields.One2many('sos_inside_sales_activities_line', 'ref_id', string="Action")
|
||||
week = fields.Char(string="Week")
|
||||
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
|
||||
def create(self, vals):
|
||||
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(),
|
||||
'location':self.location,
|
||||
'website_url':self.website_url,
|
||||
'vertical_domain':self.vertical_domain.id,
|
||||
'vertical_domain': [(6, 0, self.vertical_domain.ids)],
|
||||
'linkedin_profile':self.linkedin_profile,
|
||||
'products':self.products,
|
||||
'products_interested':[(6, 0,self.products_interested.ids)],
|
||||
'source':'inside_sales',
|
||||
'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 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
|
||||
return {
|
||||
'type': 'ir.actions.client',
|
||||
|
|
@ -151,6 +191,8 @@ class SOS_Leads_Line(models.Model):
|
|||
email = fields.Char(string="Email Id")
|
||||
mobile_number = fields.Char(string="Contact Number")
|
||||
set_as_primary = fields.Boolean(string="Set Primary")
|
||||
linkedin_profile = fields.Char(string="LinkedIn Profile")
|
||||
remarks = fields.Text(string="Remarks")
|
||||
@api.model
|
||||
def create(self, 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")
|
||||
action_date = fields.Date(string="Action Date")
|
||||
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_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_lead_source,lead_source access,model_lead_source,base.group_user,1,1,1,1
|
||||
|
||||
|
|
|
|||
|
|
|
@ -7,10 +7,12 @@
|
|||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<field name="company_name"/>
|
||||
<field name="status"/>
|
||||
<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="entry_date" string="Lead Generated On"/>
|
||||
<!-- <field name="entry_date" string="Lead Generated On"/> -->
|
||||
<field name="move_div_display" widget="boolean_toggle" readonly="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
|
|
@ -20,17 +22,21 @@
|
|||
<field name="model">sos_inside_sales_leads</field>
|
||||
<field name="arch" type="xml">
|
||||
<search>
|
||||
<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>
|
||||
<searchpanel>
|
||||
|
||||
<field name="sales_type" string="Type" icon="fa-list-ul" enable_counters="1"/>
|
||||
|
||||
</searchpanel>
|
||||
<!-- Add fields to search on -->
|
||||
<field name="company_name" string="Company Name"/>
|
||||
<field name="vertical_domain" string="Domain/Vertical"/>
|
||||
<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>
|
||||
|
|
@ -50,18 +56,24 @@
|
|||
<group>
|
||||
<group>
|
||||
<field name="move_div_display" invisible="1"/>
|
||||
<field name="sales_type"/>
|
||||
<field name="company_name"/>
|
||||
<field name="entry_date"/>
|
||||
<field name="location"/>
|
||||
<field name="vertical_domain"/>
|
||||
<field name="country" invisible="sales_type != 'International'"/>
|
||||
<field name="location" string="City/State"/>
|
||||
<field name="vertical_domain" widget="many2many_tags"/>
|
||||
<field name="status"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="website_url"/>
|
||||
<field name="linkedin_profile"/>
|
||||
<field name="products"/>
|
||||
|
||||
<field name="source"/>
|
||||
<field name="expo_name" invisible="source != 'expo'"/>
|
||||
<field name="service"/>
|
||||
<field name="products_interested"
|
||||
options="{'no_create': True, 'no_edit': True, 'no_create_edit': True}"
|
||||
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="remarks"/>
|
||||
</group>
|
||||
|
|
@ -77,6 +89,8 @@
|
|||
<field name="dept"/>
|
||||
<field name="email"/>
|
||||
<field name="mobile_number"/>
|
||||
<field name="linkedin_profile"/>
|
||||
<field name="remarks"/>
|
||||
|
||||
</tree>
|
||||
</field>
|
||||
|
|
@ -87,6 +101,8 @@
|
|||
<tree editable="bottom">
|
||||
<field name="action_date"/>
|
||||
<field name="remarks"/>
|
||||
<field name="next_action_on"/>
|
||||
|
||||
|
||||
</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_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')
|
||||
def _onchange_batch_size(self):
|
||||
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
|
||||
|
||||
@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):
|
||||
allowed_extensions = ['xlsx', 'xls', 'csv', 'zip', 'pdf']
|
||||
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)
|
||||
if file_name:
|
||||
ext = file_name.split('.')[-1].lower()
|
||||
|
|
|
|||
|
|
@ -13,3 +13,23 @@ class sos_inventory_customers(models.Model):
|
|||
|
||||
customer_name = fields.Char(string="Customer Name")
|
||||
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
|
||||
|
||||
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')
|
||||
def _onchange_wo_no(self):
|
||||
if self.wo_no:
|
||||
|
|
@ -170,7 +170,7 @@ class SOS_IR(models.Model):
|
|||
self.line_ids_sfg = lines
|
||||
|
||||
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')
|
||||
def _onchange_wo_no_inhouse(self):
|
||||
if self.wo_no_inhouse:
|
||||
|
|
@ -186,7 +186,7 @@ class SOS_IR(models.Model):
|
|||
self.line_ids_sfg = lines
|
||||
|
||||
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):
|
||||
|
|
@ -409,6 +409,7 @@ class SOS_IR_Line_Material(models.Model):
|
|||
unit_price = fields.Monetary(string="Unit Price", currency_field='currency_id')
|
||||
test_report = fields.Binary(string="Test Report")
|
||||
test_report_filename=fields.Char(string="Test Report File Name")
|
||||
expiry_date = fields.Date(string="Expiry Date")
|
||||
@api.onchange('component_id')
|
||||
def _onchange_component_id(self):
|
||||
if self.component_id:
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ class SOS_Material(models.Model):
|
|||
domain=[('action', '=', 'in')]
|
||||
)
|
||||
|
||||
shelf_life = fields.Selection([('yes', 'Yes'), ('no', 'No')],default="no", string="Shelf Life",required=True)
|
||||
|
||||
line_ids_out = fields.One2many(
|
||||
'sos_material_transaction_history', 'ref_id',
|
||||
string="Materials History - Out",
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class sos__mon(models.Model):
|
|||
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")
|
||||
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")
|
||||
purpose = fields.Char(string="Purpose")
|
||||
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(
|
||||
'sos_fg',
|
||||
compute='_compute_fg_items',
|
||||
store=False
|
||||
store=True
|
||||
)
|
||||
company_id = fields.Many2one('res.company', store=True, copy=False,
|
||||
string="Company",
|
||||
|
|
@ -70,7 +70,7 @@ class sos__mon(models.Model):
|
|||
related='company_id.currency_id',
|
||||
default=lambda
|
||||
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")
|
||||
active = fields.Boolean(default=True)
|
||||
@api.constrains('indent_ref_no', 'auto_load_fg_items')
|
||||
|
|
@ -189,6 +189,8 @@ class sos__mon(models.Model):
|
|||
|
||||
@api.onchange('auto_load_fg_items')
|
||||
def _onchange_auto_load_fg_items(self):
|
||||
if not self.auto_load_fg_items:
|
||||
return
|
||||
if self.auto_load_fg_items:
|
||||
self.material_option = True
|
||||
self.sfg_option = True
|
||||
|
|
|
|||
|
|
@ -46,7 +46,51 @@ class sos__mrn(models.Model):
|
|||
default=lambda
|
||||
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)
|
||||
@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')
|
||||
def _compute_approx_value(self):
|
||||
for record in self:
|
||||
|
|
@ -115,6 +159,7 @@ class sos__mrn(models.Model):
|
|||
def action_report_esign_btn1(self):
|
||||
sequence_util = self.env['sos_common_scripts']
|
||||
splitted=self.order_type.split(",")
|
||||
customer_return_record = False
|
||||
if self.return_type == "customer":
|
||||
sequence_util = self.env['sos_common_scripts']
|
||||
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 ")
|
||||
qa_comments=fields.Text(string="QA Comments")
|
||||
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')
|
||||
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)
|
||||
|
|
@ -94,10 +95,15 @@ class NCMR_Model(models.Model):
|
|||
string="Rework Action",
|
||||
default="inhouse"
|
||||
)
|
||||
rework_action_by_qc = fields.Boolean(string="Rework")
|
||||
rd_comments=fields.Text(string="Comments")
|
||||
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_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(
|
||||
selection=[
|
||||
('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')
|
||||
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
|
||||
|
||||
|
|
@ -668,6 +675,13 @@ class NCMR_Model(models.Model):
|
|||
'rd_approval_by',
|
||||
'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):
|
||||
if self.action_group:
|
||||
|
|
@ -678,6 +692,20 @@ class NCMR_Model(models.Model):
|
|||
'qa_tested_on',
|
||||
'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":
|
||||
# Email part
|
||||
body_html = f"""
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ class SosTestingParameters(models.Model):
|
|||
_rec_name='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)
|
||||
specification_ids = fields.One2many('sos_specification', 'spec_id', string='Specifications',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_unlink" eval="0"/>
|
||||
</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="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="perm_read" eval="1"/>
|
||||
<field name="perm_write" eval="1"/>
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@
|
|||
</record>
|
||||
|
||||
<!-- 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>
|
||||
</odoo>
|
||||
|
|
|
|||
|
|
@ -119,6 +119,12 @@
|
|||
<br></br>
|
||||
<hr></hr>
|
||||
</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>
|
||||
<templates>
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@
|
|||
<field name="order_qty"/>
|
||||
<field name="qty"/>
|
||||
<field name="unit_price"/>
|
||||
<field name="expiry_date"/>
|
||||
<field name="test_report" widget="binary" filename="test_report_filename"/>
|
||||
<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"/>
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@
|
|||
<field name="description"/>
|
||||
<field name="category"/>
|
||||
<field name="uom"/>
|
||||
<field name="shelf_life"/>
|
||||
<field name="inspection_method" widget="color_picker"/>
|
||||
<field name="qp_no"/>
|
||||
<field name="hsn_code"/>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
<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="rework_action_by_qc" widget="boolean_toggle"/>
|
||||
<field name="write_uid" string="Last Edited By" optional="hide"/>
|
||||
<field name="write_date" string="Last Edited On" optional="hide"/>
|
||||
|
||||
|
|
@ -242,19 +242,27 @@
|
|||
<templates>
|
||||
<div class="container">
|
||||
<div class="row" style="margin-top:100px">
|
||||
<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;">
|
||||
<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>
|
||||
<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" style="color:#fff">To Be Filled By <span style="font-size: 18px;padding: 0px; color: #ffcc00;">QC</span> Team</td></tr>
|
||||
<tr>
|
||||
<td style="padding: 8px;" class="column"><b>QC Comments</b></td>
|
||||
|
||||
<td><field name="comments"/></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<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>
|
||||
</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;">
|
||||
<td style="padding: 8px;" class="column"><b>QC Tested By </b></td>
|
||||
<td>
|
||||
|
|
@ -270,8 +278,8 @@
|
|||
<td><field name="qa_by" readonly="1"/></td>
|
||||
</tr>
|
||||
</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;">
|
||||
<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>
|
||||
<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" style="color:#fff">To Be Filled By <span style="font-size: 18px;padding: 0px; color: #ffcc00;">SCG</span> Team</td></tr>
|
||||
<tr>
|
||||
<td style="padding: 8px;" class="column"><b>Comments</b></td>
|
||||
|
||||
|
|
@ -301,8 +309,8 @@
|
|||
<div class="container">
|
||||
|
||||
<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;">
|
||||
<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>
|
||||
<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" style="color:#fff">To Be Filled By <span style="font-size: 18px;padding: 0px; color: #ffcc00;">Production</span> Team</td></tr>
|
||||
<tr>
|
||||
<td style="padding: 8px;" class="column"><b>Comments</b></td>
|
||||
|
||||
|
|
@ -323,9 +331,9 @@
|
|||
<td><field name="production_approval_by" readonly="1"/></td>
|
||||
</tr>
|
||||
</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>
|
||||
<td style="padding: 8px;" class="column"><b>Comments</b></td>
|
||||
|
||||
|
|
@ -362,8 +370,8 @@
|
|||
<div class="container">
|
||||
|
||||
<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;">
|
||||
<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>
|
||||
<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" style="color:#fff">To Be Filled By <span style="font-size: 18px;padding: 0px; color: #ffcc00;">R&D</span> Team</td></tr>
|
||||
<tr>
|
||||
<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><field name="rd_approval_by" readonly="1"/></td>
|
||||
</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>
|
||||
</templates>
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
<field name="fg_name"/>
|
||||
</group>
|
||||
<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">
|
||||
<tree string="Parameters" editable="bottom">
|
||||
<field name="sequence" widget="handle"/>
|
||||
|
|
@ -115,7 +115,7 @@
|
|||
</record>
|
||||
<!-- Action to open sos_testing_parameters -->
|
||||
<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="view_mode">tree,form</field>
|
||||
<field name="help" type="html">
|
||||
|
|
@ -136,7 +136,7 @@
|
|||
</record>
|
||||
<!-- Menu item to access 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"/>
|
||||
<menuitem id="menu_sos_fir_testing_parameters"
|
||||
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,
|
||||
'customer_name': self.customer_name.id,
|
||||
'action_date': last_record.status_changed_on,
|
||||
'proposal_value': proposal_value
|
||||
'proposal_value': proposal_value,
|
||||
'po_no':self.po_no
|
||||
})
|
||||
|
||||
# Assign signature
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class SOS_Sales_Achievement_Report(models.Model):
|
|||
_sql_constraints = [
|
||||
('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())
|
||||
sales_person = fields.Many2one('res.users', string='Sales person',required=True)
|
||||
overall_target = fields.Float(string="Overall Target")
|
||||
|
|
@ -114,6 +114,11 @@ class SOS_Sales_Achievement_Report(models.Model):
|
|||
'ref_id',
|
||||
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')
|
||||
def _compute_yet_to_billed_april(self):
|
||||
for rec in self:
|
||||
|
|
@ -227,23 +232,23 @@ class SOS_Sales_Achievement_Report(models.Model):
|
|||
'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()
|
||||
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)
|
||||
|
||||
|
|
@ -258,6 +263,45 @@ class SOS_Sales_Achievement_Report(models.Model):
|
|||
'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(
|
||||
|
|
@ -554,17 +598,59 @@ class SOS_Sales_Achievement_Report_Brief(models.Model):
|
|||
_name = 'sos_sales_achievement_report_brief'
|
||||
_description = 'Achievement Brief'
|
||||
_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_record_id = fields.Integer(string="Reference")
|
||||
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(
|
||||
'res.currency',
|
||||
string='Currency',
|
||||
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_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):
|
||||
self.ensure_one()
|
||||
return {
|
||||
|
|
@ -589,7 +675,6 @@ class SOS_Sales_Achievement_Report_Brief(models.Model):
|
|||
# New values
|
||||
new_billed_date = vals.get('billed_date', old_billed_date)
|
||||
new_billed_amount = vals.get('billed_amount', old_billed_amount)
|
||||
|
||||
if isinstance(new_billed_date, str):
|
||||
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
|
||||
})
|
||||
# Optionally create billing collection entry (if needed)
|
||||
if new_billed_amount > 0:
|
||||
self.env['sos_billing_collection'].create({
|
||||
'ref_id': report.id,
|
||||
'customer_name': vals.get('customer_name', rec.customer_name.id),
|
||||
'sales_person': report.sales_person.id,
|
||||
'action_status': 'Billed',
|
||||
'date_of_action': new_billed_date,
|
||||
'value': new_billed_amount
|
||||
})
|
||||
if new_billed_amount > 0:
|
||||
self.env['sos_billing_collection'].create({
|
||||
'ref_id': report.id,
|
||||
'customer_name': vals.get('customer_name', rec.customer_name.id),
|
||||
'sales_person': report.sales_person.id,
|
||||
'action_status': 'Billed',
|
||||
'date_of_action': new_billed_date,
|
||||
'value': new_billed_amount
|
||||
})
|
||||
|
||||
return super(SOS_Sales_Achievement_Report_Brief, self).write(vals)
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
ref_id = vals.get('ref_id')
|
||||
vals['ref_record_id'] = ref_id
|
||||
|
||||
action_date = vals.get('action_date')
|
||||
billed_date = vals.get('billed_date')
|
||||
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):
|
||||
action_date = datetime.strptime(action_date, '%Y-%m-%d').date()
|
||||
if isinstance(billed_date, str):
|
||||
billed_date = datetime.strptime(billed_date, '%Y-%m-%d').date()
|
||||
|
||||
month_name = action_date.strftime('%B').lower()
|
||||
value = vals.get('proposal_value', 0.0)
|
||||
actual_field = f"actual_target_{month_name}"
|
||||
|
||||
ref_id = vals.get('ref_id')
|
||||
if ref_id:
|
||||
if ref_id and action_date:
|
||||
report = self.env['sos_sales_achievement_report'].browse(ref_id)
|
||||
sales_person = report.sales_person
|
||||
if sales_person and hasattr(report, actual_field):
|
||||
current_value = getattr(report, actual_field, 0.0) or 0.0
|
||||
report.write({actual_field: current_value + value})
|
||||
month_name = action_date.strftime('%B').lower()
|
||||
actual_field = f"actual_target_{month_name}"
|
||||
current_date = date.today()
|
||||
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:
|
||||
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': vals.get('billed_amount', 0.0)
|
||||
})
|
||||
|
||||
return super(SOS_Sales_Achievement_Report_Brief, self).create(vals)
|
||||
if vals.get('financial_year') == current_fy:
|
||||
if hasattr(report, actual_field):
|
||||
current_val = getattr(report, actual_field) or 0.0
|
||||
report.write({actual_field: current_val + value})
|
||||
|
||||
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):
|
||||
|
|
@ -780,6 +875,33 @@ class SosBillingCollection(models.Model):
|
|||
start_year = current_date.year if current_date.month >= 4 else current_date.year - 1
|
||||
end_year = start_year + 1
|
||||
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
|
||||
def create(self, vals):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
from odoo import models, fields, api
|
||||
import random
|
||||
|
||||
class sos_sales_leads(models.Model):
|
||||
_name = 'sos_sales_leads'
|
||||
|
|
@ -9,31 +10,43 @@ class sos_sales_leads(models.Model):
|
|||
transferred_on = fields.Date(string="Transferred On")
|
||||
location = fields.Char(string="Location")
|
||||
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")
|
||||
status = fields.Char(string="Status")
|
||||
correspondence_address = fields.Text(string="Correspondence Address")
|
||||
interested_in = fields.Selection(
|
||||
[
|
||||
('products', 'Products'),
|
||||
('projects', 'Projects')
|
||||
('Product', 'Products'),
|
||||
('Project', 'Projects')
|
||||
],
|
||||
string="Interested In",required=True,default="products")
|
||||
project_name = fields.Char(string="Project Name")
|
||||
products = fields.Selection(
|
||||
string="Service Type",required=True,default="Product")
|
||||
sales_type = 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')
|
||||
('Domestic', 'Domestic'),
|
||||
('International', 'International')
|
||||
],
|
||||
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(
|
||||
[
|
||||
('self', 'Self'),
|
||||
|
|
@ -91,16 +104,18 @@ class SOS_Leads_Lines(models.Model):
|
|||
email = fields.Char(string="Email Id")
|
||||
mobile_number = fields.Char(string="Contact Number")
|
||||
set_as_primary = fields.Boolean(string="Set Primary")
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
record = super(SOS_Leads_Lines, self).create(vals)
|
||||
if not self.env['sos_leads_customer_contact_lines'].search([
|
||||
('ref_id', '=', record.ref_id.id),
|
||||
('set_as_primary', '=', True)
|
||||
]):
|
||||
# Set the created record as primary
|
||||
record.set_as_primary = True
|
||||
return record
|
||||
linkedin_profile = fields.Char(string="LinkedIn Profile")
|
||||
remarks = fields.Text(string="Remarks")
|
||||
# @api.model
|
||||
# def create(self, vals):
|
||||
# record = super(SOS_Leads_Lines, self).create(vals)
|
||||
# if not self.env['sos_leads_customer_contact_lines'].search([
|
||||
# ('ref_id', '=', record.ref_id.id),
|
||||
# ('set_as_primary', '=', True)
|
||||
# ]):
|
||||
# # Set the created record as primary
|
||||
# record.set_as_primary = True
|
||||
# return record
|
||||
def write(self, vals):
|
||||
res = super(SOS_Leads_Lines, self).write(vals)
|
||||
if 'set_as_primary' in vals and vals['set_as_primary']:
|
||||
|
|
@ -110,3 +125,21 @@ class SOS_Leads_Lines(models.Model):
|
|||
('id', '!=', record.id)
|
||||
]).write({'set_as_primary': False})
|
||||
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()
|
||||
|
||||
domain = [('financial_year', '=', financial_year)]
|
||||
|
||||
if sales_person_id:
|
||||
domain.append(('sales_person', '=', sales_person_id))
|
||||
|
||||
records = self.env['sos_sales_achievement_report'].search(domain, order="sales_person ASC")
|
||||
|
||||
|
||||
months = [
|
||||
'april', 'may', 'june', 'july', 'august', 'september',
|
||||
'october', 'november', 'december',
|
||||
|
|
@ -39,8 +37,10 @@ class ReportBusinessPerformance(models.AbstractModel):
|
|||
current_month = date.today().month
|
||||
if current_month >= 4:
|
||||
ytd_months = months[:current_month - 4 + 1]
|
||||
current_month_key = months[current_month - 4]
|
||||
else:
|
||||
ytd_months = months[:current_month + 9 + 1]
|
||||
current_month_key = months[current_month + 9]
|
||||
|
||||
records = list(records)
|
||||
|
||||
|
|
@ -54,7 +54,7 @@ class ReportBusinessPerformance(models.AbstractModel):
|
|||
'target': 0.0,
|
||||
'sales': 0.0,
|
||||
'sales_percentage': 0.0,
|
||||
'yet_to_billed':0.0,
|
||||
'yet_to_billed': 0.0,
|
||||
'billed': 0.0,
|
||||
'collected': 0.0,
|
||||
}
|
||||
|
|
@ -77,16 +77,18 @@ class ReportBusinessPerformance(models.AbstractModel):
|
|||
for m in ytd_months:
|
||||
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_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_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']['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']['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
|
||||
doc.ytd_target = "%.2f" % ytd_target
|
||||
doc.ytd_sales = "%.2f" % ytd_sales
|
||||
|
|
@ -104,18 +106,21 @@ class ReportBusinessPerformance(models.AbstractModel):
|
|||
else:
|
||||
summary['ytd']['sales_percentage'] = "0.00"
|
||||
|
||||
# Also convert YTD values in summary to formatted strings
|
||||
for key in ['target', 'sales', 'billed', 'collected']:
|
||||
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 {
|
||||
'doc_ids': [rec.id for rec in records],
|
||||
'doc_model': 'sos_sales_achievement_report',
|
||||
'docs': records,
|
||||
'financial_year': financial_year,
|
||||
'enumerated_months': list(enumerate(months)),
|
||||
'months': months,
|
||||
'month_names': month_names,
|
||||
'summary': summary,
|
||||
'ytd_months': ytd_months,
|
||||
'current_month_index': int(current_month_index),
|
||||
'is_filtered_by_sales_person': bool(sales_person_id)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
<div class="page">
|
||||
<br></br>
|
||||
<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 -->
|
||||
<t t-if="not is_filtered_by_sales_person">
|
||||
|
||||
|
|
@ -64,25 +64,38 @@
|
|||
<td><t t-esc="summary['ytd']['billed']"/></td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="background-color:#e4e0f9"><strong>Yet to Bill</strong></td>
|
||||
<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]"/>
|
||||
<td><t t-esc="'%.2f' % val"/></td>
|
||||
<t t-set="total_yet_billed" t-value="total_billed + val"/>
|
||||
</t>
|
||||
<tr>
|
||||
<td style="background-color:#e4e0f9"><strong>Yet to Bill</strong></td>
|
||||
<t t-set="total_yet_billed" t-value="0"/>
|
||||
|
||||
<t t-foreach="enumerated_months" t-as="item">
|
||||
<t t-set="i" t-value="item[0]"/>
|
||||
<t t-set="m" t-value="item[1]"/>
|
||||
|
||||
<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>
|
||||
<td style="background-color:#e4e0f9"><strong>Collected</strong></td>
|
||||
<t t-set="total_collected" t-value="0"/>
|
||||
<t t-foreach="months" t-as="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>
|
||||
<td><t t-esc="'%.2f' % float(total_collected)"/></td>
|
||||
|
|
@ -186,22 +199,25 @@
|
|||
<td><t t-esc="'%.2f' % float(doc.ytd_billed)"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<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_june)"/></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_august)"/></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_october)"/></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_december)"/></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_february)"/></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_total)"/></td>
|
||||
<td><t t-esc="'%.2f' % float(doc.ytd_yet_to_billed)"/></td>
|
||||
</tr>
|
||||
<td style="background-color:#e4e0f9"><strong>Yet to Bill</strong></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_may) if current_month_index >= 1 else '0.00'"/></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_july) if current_month_index >= 3 else '0.00'"/></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_september) if current_month_index >= 5 else '0.00'"/></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_november) if current_month_index >= 7 else '0.00'"/></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_january) if current_month_index >= 9 else '0.00'"/></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_march) if current_month_index >= 11 else '0.00'"/></td>
|
||||
|
||||
<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>
|
||||
<td style="background-color:#e4e0f9"><strong>Collected</strong></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_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_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>
|
||||
<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>
|
||||
<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><field name="financial_year" style="font-size: 20px; pointer-events: none; color: #793595;"/>
|
||||
</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>
|
||||
<table class="table_custom">
|
||||
<thead>
|
||||
|
|
|
|||
|
|
@ -22,11 +22,11 @@
|
|||
<field name="model">sos_sales_leads</field>
|
||||
<field name="arch" type="xml">
|
||||
<search>
|
||||
<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>
|
||||
|
||||
</searchpanel>
|
||||
<field name="sales_type" string="Type" icon="fa-list-ul" enable_counters="1"/>
|
||||
|
||||
</searchpanel>
|
||||
|
||||
<!-- Add fields to search on -->
|
||||
<field name="company_name" string="Company Name"/>
|
||||
|
|
@ -53,20 +53,25 @@
|
|||
|
||||
<group>
|
||||
<group>
|
||||
<field name="sales_type"/>
|
||||
<field name="lead_generated_by"/>
|
||||
<field name="company_name"/>
|
||||
<field name="convert_to_customer_btn_display" invisible="1"/>
|
||||
<field name="transferred_on" invisible="1"/>
|
||||
<field name="country" invisible="sales_type != 'International'"/>
|
||||
|
||||
<field name="website_url"/>
|
||||
<field name="linkedin_profile"/>
|
||||
<field name="correspondence_address"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="interested_in"/>
|
||||
<field name="project_name" invisible="interested_in == 'products'"/>
|
||||
<field name="products" invisible="interested_in == 'projects'"/>
|
||||
<field name="project_name" invisible="interested_in == 'Product'"/>
|
||||
<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="vertical_domain"/>
|
||||
<field name="vertical_domain" widget="many2many_tags"/>
|
||||
<field name="source"/>
|
||||
<field name="expo_name" invisible="source != 'expo'"/>
|
||||
</group>
|
||||
|
|
@ -82,6 +87,8 @@
|
|||
<field name="dept"/>
|
||||
<field name="email"/>
|
||||
<field name="mobile_number"/>
|
||||
<field name="linkedin_profile"/>
|
||||
<field name="remarks"/>
|
||||
|
||||
</tree>
|
||||
</field>
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,5 +1,29 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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">
|
||||
<field name="name">sos_sales_achievement_report_brief_wizard.form</field>
|
||||
|
|
@ -19,13 +43,18 @@
|
|||
|
||||
<field name="brief_line_ids" nolabel="1">
|
||||
<tree>
|
||||
<field name="financial_year"/>
|
||||
<field name="action_date" string="Date"/>
|
||||
<field name="customer_name"/>
|
||||
<field name="po_no"/>
|
||||
<field name="invoice_no"/>
|
||||
<field name="proposal_value"/>
|
||||
<field name="billed_date"/>
|
||||
<field name="billed_amount"/>
|
||||
<button name="open_line_form" string="Edit"
|
||||
type="object" icon="fa-pencil" invisible="billed_date != False and billed_amount != False"/>
|
||||
<button name="delete_achievement_line" class="btn btn-primary" string="Delete"
|
||||
type="object" icon="fa-times"/>
|
||||
<button name="open_line_form" class="btn btn-primary" string="Edit"
|
||||
type="object" icon="fa-pencil"/>
|
||||
|
||||
</tree>
|
||||
</field>
|
||||
|
|
@ -139,6 +168,8 @@
|
|||
<field name="customer_name"/>
|
||||
<field name="value"/>
|
||||
<field name="invoice_no"/>
|
||||
<button name="delete_form_line" class="btn btn-primary" string="Delete"
|
||||
type="object" icon="fa-times"/>
|
||||
</tree>
|
||||
</field>
|
||||
<footer>
|
||||
|
|
|
|||
Loading…
Reference in New Issue