Slink/sos_sales/models/sos_sales_action_plan.py

527 lines
20 KiB
Python
Executable File

from odoo import models, fields, api
from datetime import date
from odoo.exceptions import UserError
from datetime import date, timedelta
from calendar import month_name
class sos_sales_action_plan(models.Model):
_name = 'sos_sales_action_plan'
_description = 'Sosaley Sales Action Plan'
_rec_name="customer_name"
date = fields.Date(string="Action Date",required=True)
customer_name = fields.Many2one(
'sos_customers',
string="Customer Name",
required=True,
domain=lambda self: self._get_customer_domain()
)
end_customer_name = fields.Char(string="End Customer Name")
quote_no = fields.Char(string="Quote/W.O No",help="Fill this if the same customer has different work orders.")
quote_no_selector = fields.Many2one(
'sos_case_diary',
string="End Customer/Quote No",
domain="[('customer_name', '=', customer_name), ('quote_no', '!=', False)]"
)
interested_in = fields.Selection(
[
('Product', 'Products'),
('Project', 'Projects')
],
string="Interested In",required=True,default="Product")
sales_type = fields.Selection(
[
('Domestic', 'Domestic'),
('International', 'International')
],
string="Sales Type",default="Domestic")
project_name= fields.Many2one('sos_projects',string="Project Name")
country = fields.Many2one(
'res.country',
string='Country',
default=lambda self: self.env['res.country'].search([('code', '=', 'IN')], limit=1)
)
ce_product_type = fields.Selection(
[
('Sales', 'Sales'),
('Service', 'Service'),
('Spare', 'Spare'),
('Cloud', 'Cloud')
],
string="Service Type")
product = 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")
location = fields.Char(string="Location")
quantity = fields.Char(string="Quantity")
sales_executive = fields.Many2one(
'res.users',
string='Sales Executive',
default=lambda self: self.env.user,
readonly=True
)
sales_head = fields.Many2one(
'res.users',
string='Sales Head',
default=lambda self: self.env.user,
domain=lambda self: [('groups_id', 'in', self.env.ref('sos_inventory.sos_sales_user').ids + self.env.ref('sos_inventory.sos_ce_head').ids + self.env.ref('sos_inventory.sos_sales_sapl_user').ids)]
)
action_type = fields.Selection([
('Meeting', 'Meeting'),
('Demo', 'Demo'),
('Discussion', 'Discussion'),
('Visit', 'Direct Visit'),
('Negotiation', 'Negotiation'),
('Validation', 'Validation'),
('Proposal', 'Proposal'),
('Email/Call/Video Call', 'Email/Call/Video Call')
], string='Action Type',requierd=True)
current_spenco_status = fields.Selection([
('Suspects', 'Suspects'),
('Prospects', 'Prospects'),
('Engaged', 'Engaged'),
('Negotiation', 'Negotiation'),
('Commercial Order', 'Commercial Order')
], string='Current SPENCO Status')
po_copy = fields.Binary(string='PO Copy', attachment=True)
po_copy_filename = fields.Char(string='PO Copy Filename')
action = fields.Selection(
[
('Generate More Suspects', 'Generate More Suspects'),
('Suspect to Prospects', 'Suspect to Prospects'),
('Prospect to Engaged', 'Prospect to Engaged'),
('Engaged to Negotiation', 'Engaged to Negotiation'),
('Negotiation to Order', 'Negotiation to Order')
],
string="Action Category",required=True)
action_plan = fields.Text(string="Action Plan")
result = fields.Text(string="Result")
status = fields.Selection(
[
('open', 'Open'),
('close', 'Closed without Order'),
('close_order', 'Closed with Order')
],
string="Status",default='open',required=True)
currency_id = fields.Many2one('res.currency', string='Currency')
po_no= fields.Char(string="PO No")
value = fields.Monetary(currency_field='currency_id', string="Value (In Lakhs)")
next_action_date = fields.Date(string="Next Action On")
update_done = fields.Boolean(string="Update Done", default=False)
state = fields.Selection([
('draft', 'Draft'),
('confirmed', 'Confirmed'),
], string='State', default='draft', readonly=True)
is_ce_user_created = fields.Boolean(
compute='_compute_is_ce_user_created',
store=True,
string='Created by CE User'
)
reporting_to = fields.Many2one('res.users',related="sales_executive.reporting_to", string='Reporting To')
@api.depends('create_uid')
def _compute_is_ce_user_created(self):
ce_groups = [
self.env.ref('sos_inventory.sos_ce_user').id
]
for record in self:
record.is_ce_user_created = any(
gid in record.create_uid.groups_id.ids for gid in ce_groups
)
def _get_customer_domain(self):
if (
self.env.user.has_group('sos_inventory.sos_management_user') or
self.env.user.has_group('sos_inventory.sos_ce_head') or
self.env.user.has_group('sos_inventory.sos_ce_user')
):
return [] # no filter, show all
return [('responsible', '=', self.env.uid)]
@api.onchange('quote_no_selector')
def _onchange_quote_no_selector(self):
if self.quote_no_selector:
self.quote_no = self.quote_no_selector.quote_no
self.end_customer_name = self.quote_no_selector.end_customer_name
def action_prev_action_plans(self):
domain = [('customer_name', '=', self.customer_name.id)]
if self.quote_no:
domain.append(('quote_no', '=', self.quote_no))
if self.quote_no:
domain.append(('product', '=', self.product))
prev_action_plans = self.env['sos_sales_action_plan'].search(domain)
return {
'type': 'ir.actions.act_window',
'name': 'Previous Action Plans',
'res_model': 'sos_sales_action_plan',
'view_mode': 'tree',
'views': [(self.env.ref('sos_sales.view_prev_action_plan_tree').id, 'tree')],
'domain': [('id', 'in', prev_action_plans.ids)],
'target': 'new',
}
@api.onchange('quote_no')
def _onchange_quote_no(self):
"""Set products from sos_case_diary if quote_no and customer match"""
if self.customer_name and self.quote_no:
case = self.env['sos_case_diary'].search([
('customer_name', '=', self.customer_name.id),
('quote_no', '=', self.quote_no)
], limit=1)
if case:
self.product = case.products # assuming it's Char or same type
self.location = case.customer_city
self.quantity = case.quantity
else:
self.product = False
self.location = False
self.quantity = False
def write(self, vals):
if 'status' in vals:
for record in self:
domain = [
('customer_name', '=', record.customer_name.customer_name),
('products', '=', record.product),
('sales_person', '=', record.sales_executive.id)
]
if record.quote_no:
domain.append(('quote_no', '=', record.quote_no))
case_diary_records = self.env['sos_case_diary'].search(domain, limit=1)
if case_diary_records:
case_diary_records.write({"status": vals['status']})
return super().write(vals)
def action_view_po(self):
# Check if there is a test report
if not self.po_copy:
raise UserError("No po available for this record.")
# Use `ir.actions.act_url` to open the binary file as a PDF
return {
'type': 'ir.actions.act_url',
'url': '/web/content/{}/{}/{}?download=false'.format(
self._name, self.id, 'po_copy'),
'target': 'new', # This opens the PDF in a new tab
}
@api.onchange('current_spenco_status')
def _onchange_current_spenco_status(self):
if self.current_spenco_status != 'Commercial Order':
self.po_copy = False
def unlink(self):
for record in self:
if record.update_done:
raise UserError("You can't delete the action plan after case diary updation!")
action_plan_date = record.date
sales_executive = record.sales_executive
# Week-wise
week_number = record._compute_week_number(action_plan_date)
record.decrement_summary(
action_plan_date=action_plan_date,
sales_executive=sales_executive,
field_name='week_number',
field_value=week_number,
model_name='sos_action_plan_summary_week_wise'
)
# Month-wise
month_number = record._compute_month_number(action_plan_date)
record.decrement_summary(
action_plan_date=action_plan_date,
sales_executive=sales_executive,
field_name='month_number',
field_value=month_number,
model_name='sos_action_plan_summary_month_wise'
)
# Quarter-wise
quarter_number = record._compute_quarter_number(action_plan_date)
record.decrement_summary(
action_plan_date=action_plan_date,
sales_executive=sales_executive,
field_name='quarter_number',
field_value=quarter_number,
model_name='sos_action_plan_summary_quarter_wise'
)
# Year-wise
year_number = record._compute_year_number(action_plan_date)
record.decrement_summary(
action_plan_date=action_plan_date,
sales_executive=sales_executive,
field_name='year',
field_value=year_number,
model_name='sos_action_plan_summary_year_wise'
)
return super(sos_sales_action_plan, self).unlink()
def decrement_summary(self, action_plan_date, sales_executive, field_name, field_value, model_name):
SummaryModel = self.env[model_name]
record = SummaryModel.search([
('sales_executive', '=', sales_executive.id),
(field_name, '=', field_value),
('action', '=', self.action),
('action_type', '=', self.action_type)
], limit=1)
if record and record.count > 1:
record.write({'count': record.count - 1})
elif record:
record.unlink()
@api.model
def create(self, vals):
record = super(sos_sales_action_plan, self).create(vals)
record.state = 'confirmed'
# Now access fields from the created record
sales_executive = record.sales_executive
action_plan_date = record.date
#week wise
week_number = record._compute_week_number(action_plan_date)
record.update_summary(
action_plan_date=action_plan_date,
sales_executive=sales_executive,
field_name='week_number',
field_value=week_number,
model_name='sos_action_plan_summary_week_wise'
)
#month wise
month_number = record._compute_month_number(action_plan_date)
record.update_summary(
action_plan_date=action_plan_date,
sales_executive=sales_executive,
field_name='month_number',
field_value=month_number,
model_name='sos_action_plan_summary_month_wise'
)
#quarter wise
quarter_number = record._compute_quarter_number(action_plan_date)
record.update_summary(
action_plan_date=action_plan_date,
sales_executive=sales_executive,
field_name='quarter_number',
field_value=quarter_number,
model_name='sos_action_plan_summary_quarter_wise'
)
#year wise
year_number = record._compute_year_number(action_plan_date)
record.update_summary(
action_plan_date=action_plan_date,
sales_executive=sales_executive,
field_name='year',
field_value=year_number,
model_name='sos_action_plan_summary_year_wise'
)
return record
def _compute_year_number(self,action_plan_date):
month_number = action_plan_date.strftime('%B')
month = action_plan_date.month
year = action_plan_date.year
year_number = f"{year}-{year + 1}" if month >= 4 else f"{year - 1}-{year}"
return year_number
def _compute_quarter_number(self,action_plan_date):
month_number = action_plan_date.strftime('%B')
month = action_plan_date.month
quarter_number = (
"Q1" if 4 <= month <= 6 else
"Q2" if 7 <= month <= 9 else
"Q3" if 10 <= month <= 12 else "Q4"
)
return quarter_number
def _compute_month_number(self,action_plan_date):
month_number = action_plan_date.strftime('%B')
return month_number
def _compute_week_number(self,action_plan_date):
start_of_week = action_plan_date - timedelta(days=action_plan_date.weekday())
end_of_week = start_of_week + timedelta(days=5)
return f"{start_of_week.strftime('%b %d')} - {end_of_week.strftime('%b %d')}"
def update_summary(self, action_plan_date, sales_executive, field_name, field_value, model_name):
SummaryModel = self.env[model_name]
record = SummaryModel.search([
('sales_executive', '=', sales_executive.id),
(field_name, '=', field_value),
('action', '=', self.action),
('action_type', '=', self.action_type)
], limit=1)
if record:
record.write({
'count': record.count + 1
})
else:
record = SummaryModel.create({
'sales_executive': sales_executive.id,
field_name: field_value,
'action': self.action,
'action_type': self.action_type,
'entered_date': action_plan_date,
'count': 1
})
return record
def view_casediary(self):
domain = [
('customer_name', '=', self.customer_name.id),
('products', '=', self.product),
('sales_person', '=', self.sales_executive.id)
]
if self.quote_no:
domain.append(('quote_no', '=', self.quote_no))
case_diary_records = self.env['sos_case_diary'].search(domain, limit=1)
if case_diary_records:
return {
'type': 'ir.actions.act_window',
'name': 'Case Diary',
'res_model': 'sos_case_diary',
'view_mode': 'form',
'res_id': case_diary_records.id,
'target': 'current',
}
else:
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'message': "Not Found",
'type': 'danger',
'sticky': False
}
}
def update_casediary(self):
if self.update_done:
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'message': "Already updated!",
'type': 'warning',
'sticky': False
}
}
# Validate mandatory fields
missing_fields = []
if not self.current_spenco_status:
missing_fields.append("Current SPENCO Status")
if not self.next_action_date:
missing_fields.append("Next Action Date")
if not self.result:
missing_fields.append("Result")
if self.value <= 0.00:
if self.current_spenco_status != "Suspects":
missing_fields.append("Value")
if missing_fields:
raise UserError(
f"The following fields are required before updating the Case Diary: {', '.join(missing_fields)}"
)
self.update_done = True
domain = [
('customer_name', '=', self.customer_name.id),
('products', '=', self.product),
('sales_person', '=', self.env.user.id)
]
if self.quote_no:
domain.append(('quote_no', '=', self.quote_no))
if self.end_customer_name:
domain.append(('end_customer_name', '=', self.end_customer_name))
case_diary_records = self.env['sos_case_diary'].search(domain, limit=1)
if case_diary_records:
case_diary_records.write({
'status': self.status,
'po_copy':self.po_copy,
'po_no':self.po_no,
'quantity':self.quantity,
'po_copy_filename':self.po_copy_filename
})
case_diary_records.line_ids.create({
'ref_id': case_diary_records.id,
'action_plan_date': self.date,
'action_plan': self.action_plan,
'action_type': self.action_type,
'notes': self.result,
'next_action_date': self.next_action_date,
'status_changed_on': date.today(),
'spenco_status': self.current_spenco_status,
'current_state_value': self.value,
})
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'message': "Updated",
'type': 'success',
'sticky': False
}
}
else:
interested_in=self.interested_in.lower()+'s'
vals = {
'customer_name': self.customer_name.id,
'end_customer_name': self.end_customer_name,
'customer_city': self.location,
'sales_person': self.sales_executive.id,
'products': self.product,
'proposal_value': self.value,
'status': self.status,
'quote_no': self.quote_no,
'quantity': self.quantity,
'po_no': self.po_no,
'po_copy': self.po_copy,
'po_copy_filename': self.po_copy_filename,
'sales_type':self.sales_type,
'project_name':self.project_name.id,
'interested_in':interested_in,
'country':self.country.id
}
if self.ce_product_type:
vals['ce_product_type'] = self.ce_product_type
casediary_record = self.env['sos_case_diary'].create(vals)
self.env['sos_case_diary_line'].create({
'ref_id': casediary_record.id,
'action_plan_date': self.date,
'action_plan': self.action_plan,
'action_type': self.action_type,
'notes': self.result,
'next_action_date': self.next_action_date,
'status_changed_on': date.today(),
'spenco_status': self.current_spenco_status,
'current_state_value': self.value
})
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'message': "Created New Case Diary",
'type': 'success',
'sticky': False
}
}