698 lines
32 KiB
Python
Executable File
698 lines
32 KiB
Python
Executable File
|
|
from odoo import models, fields, api
|
|
from datetime import date
|
|
from decimal import Decimal, ROUND_HALF_UP
|
|
from datetime import date, timedelta,datetime
|
|
from odoo.exceptions import UserError
|
|
|
|
class sos_case_diary(models.Model):
|
|
_name = 'sos_case_diary'
|
|
_description = 'Sosaley Case Diary'
|
|
_rec_name="display_name"
|
|
|
|
_sql_constraints = [
|
|
('unique_customer_casediary', 'unique(customer_name, quote_no)',
|
|
'A customer with the same quote no already exists!')
|
|
]
|
|
display_name = fields.Char(string='Display Name', compute='_compute_display_name', store=True)
|
|
customer_name = fields.Many2one('sos_customers',string="Customer Name")
|
|
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.")
|
|
line_ids_contacts = fields.One2many(related="customer_name.line_ids_contacts", string="Contact Details",copy=True)
|
|
customer_city = fields.Char(string="City")
|
|
correspondence_address = fields.Text(string="Correspondence Address",related="customer_name.correspondence_address")
|
|
lead_generated_by = fields.Selection([('Self','Self'),('Inside Sales','Inside Sales'),('Expo Directory','Expo Directory'),('Expo Exhibitors','Expo Exhibitors'),('Associations','Associations'),('Website','Website'),('Linkedin','Linkedin'),('Conference','Conference'),('Others','Others')],string='Lead Generated By')
|
|
lead_generated_by_others = fields.Char(string="Lead Generated By - Others")
|
|
inside_sales_person = fields.Many2one('res.users', string='Inside Sales person')
|
|
sales_person = fields.Many2one(
|
|
'res.users',
|
|
string='Sales Executive',
|
|
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)])
|
|
currency_id = fields.Many2one(
|
|
'res.currency',
|
|
string='Currency',
|
|
default=lambda self: self.env['res.currency'].search([('name', '=', 'INR')], limit=1).id or False
|
|
)
|
|
account_start_date = fields.Date(string="Account Start Date")
|
|
proposal_value = fields.Monetary(currency_field='currency_id',string="Proposal Value(In Lakhs)")
|
|
quantity = fields.Char(string="Quantity")
|
|
interested_in = fields.Selection(
|
|
[
|
|
('products', 'Products'),
|
|
('projects', 'Projects')
|
|
],
|
|
string="Interested In",required=True,default="products")
|
|
project_name = fields.Char(string="Project Name")
|
|
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")
|
|
ce_product_type = fields.Selection(
|
|
[
|
|
('Sales', 'Sales'),
|
|
('Service', 'Service'),
|
|
('Spare', 'Spare'),
|
|
('Cloud', 'Cloud')
|
|
],
|
|
string="Service Type")
|
|
line_ids = fields.One2many('sos_case_diary_line', 'ref_id', string="Action")
|
|
status = fields.Selection([('open', 'Open'),
|
|
('close', 'Closed without Order'),
|
|
('close_order', 'Closed with Order') ],default='open',string='Status')
|
|
spenco_status = fields.Selection([('Suspects','Suspects'),('Prospects','Prospects'),('Engaged','Engaged'),('Negotiation','Negotiation'),('Commercial Order','Commercial Order')],string='Current State',compute='_compute_is_latest',store=True)
|
|
dept_incharge_name = fields.Many2one('res.users', string='Dept-Incharge Approver')
|
|
dept_incharge_approval_image = fields.Image(related="dept_incharge_name.signature_image",string='Top Management Approval',readonly=True)
|
|
dept_incharge_approved_on = fields.Datetime(string="Approved On")
|
|
reporting_to = fields.Many2one('res.users', string='Reporting To')
|
|
transfer_history_ids = fields.One2many('sos_case_transfer_history', 'case_diary_id', string="Transfer History")
|
|
po_no= fields.Char(string="PO No")
|
|
po_copy = fields.Binary(string="PO Copy")
|
|
po_copy_filename=fields.Char(string="PO DocumentFile Name")
|
|
order_expected_on = fields.Date(string="Order Expected On")
|
|
|
|
@api.depends('end_customer_name', 'quote_no')
|
|
def _compute_display_name(self):
|
|
for rec in self:
|
|
end_customer = rec.end_customer_name.strip() if rec.end_customer_name else '-'
|
|
quote = rec.quote_no.strip() if rec.quote_no else '-'
|
|
rec.display_name = f"{end_customer} / {quote}"
|
|
|
|
|
|
def action_transfer_sales_person(self):
|
|
""" Opens a wizard to transfer sales person """
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': 'Transfer Sales Person',
|
|
'res_model': 'sos_case_transfer_wizard',
|
|
'view_mode': 'form',
|
|
'target': 'new',
|
|
'context': {'default_case_diary_id': self.id}
|
|
}
|
|
def _get_financial_year(self):
|
|
current_date = date.today()
|
|
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}"
|
|
@api.model
|
|
def create(self, vals):
|
|
create_uid = vals.get('create_uid', self.env.uid)
|
|
create_user = self.env['res.users'].browse(create_uid)
|
|
vals['reporting_to'] = create_user.reporting_to.id
|
|
return super(sos_case_diary, self).create(vals)
|
|
def action_deptincharge_esign_btn(self):
|
|
fy = self._get_financial_year()
|
|
|
|
if not self.line_ids:
|
|
raise UserError("No lines found to process.")
|
|
|
|
# Get the last record from line_ids
|
|
last_record = self.line_ids[-1]
|
|
|
|
if not last_record.status_changed_on:
|
|
raise UserError("Status changed date is not set on the last line.")
|
|
|
|
month_name = last_record.status_changed_on.strftime('%B').lower()
|
|
actual_field = f"actual_target_{month_name}"
|
|
|
|
# Get or create the sales achievement record
|
|
sales_achievement = self.env['sos_sales_achievement_report'].search([
|
|
('financial_year', '=', fy),
|
|
('sales_person', '=', last_record.ref_id.sales_person.id)
|
|
], limit=1)
|
|
|
|
# Calculate new achieved target
|
|
if sales_achievement:
|
|
current_achieved_target = getattr(sales_achievement, actual_field, 0.0) or 0.0
|
|
new_achieved_target = current_achieved_target + last_record.current_state_value
|
|
sales_achievement.write({actual_field: new_achieved_target})
|
|
ref_id = sales_achievement.id
|
|
proposal_value = last_record.current_state_value
|
|
else:
|
|
new_record = self.env['sos_sales_achievement_report'].create({
|
|
'financial_year': fy,
|
|
'sales_person': last_record.ref_id.sales_person.id,
|
|
actual_field: last_record.current_state_value
|
|
})
|
|
ref_id = new_record.id
|
|
proposal_value = last_record.current_state_value
|
|
|
|
# Log brief entry
|
|
self.env['sos_sales_achievement_report_brief'].create({
|
|
'ref_id': ref_id,
|
|
'customer_name': self.customer_name.id,
|
|
'action_date': last_record.status_changed_on,
|
|
'proposal_value': proposal_value
|
|
})
|
|
|
|
# Assign signature
|
|
self.env['sos_common_scripts'].action_assign_signature(
|
|
self,
|
|
'dept_incharge_name',
|
|
'dept_incharge_approved_on'
|
|
)
|
|
|
|
@api.onchange('customer_name')
|
|
def _onchange_customer_name(self):
|
|
for record in self:
|
|
primary_record = self.env['sos_customers_line'].search(
|
|
[('ref_id', '=', record.customer_name.id),
|
|
('set_as_primary', '=', True)],
|
|
order="id desc",
|
|
limit=1
|
|
)
|
|
record.customer_city = primary_record.ref_id.customer_city
|
|
record.correspondence_address = primary_record.ref_id.correspondence_address
|
|
@api.depends('line_ids')
|
|
def _compute_is_latest(self):
|
|
for record in self:
|
|
latest_record = self.env['sos_case_diary_line'].search(
|
|
[('ref_id', '=', record.id)],
|
|
order="id desc",
|
|
limit=1
|
|
)
|
|
self.spenco_status = latest_record.spenco_status
|
|
if latest_record.spenco_status == "Commercial Order":
|
|
users = self.env['res.users'].browse(self.env.user.id)
|
|
|
|
if users.reporting_to:
|
|
reporting_user = self.env['res.users'].browse(users.reporting_to.id)
|
|
reporting_to = reporting_user.login
|
|
|
|
if reporting_to:
|
|
# Email part
|
|
body_html = f"""
|
|
<p>Below Commercial Order is waiting for your Acknowledgement</p>
|
|
"""
|
|
subject = f"Commercial Order Received - {self.customer_name.customer_name}"
|
|
sequence_util = self.env['sos_common_scripts']
|
|
sequence_util.send_direct_email(self.env, "sos_case_diary", self.id, reporting_to, subject, body_html)
|
|
|
|
def action_report_pipeline_btn(self, sales_person_id=None, from_date=None, to_date=None):
|
|
try:
|
|
domain = [('status', '!=', 'close')]
|
|
if sales_person_id:
|
|
domain.append(('sales_person', '=', sales_person_id))
|
|
if from_date:
|
|
domain.append(('order_expected_on', '>=', from_date))
|
|
if to_date:
|
|
domain.append(('order_expected_on', '<=', to_date))
|
|
|
|
records = self.env['sos_case_diary'].search(domain, order="order_expected_on asc")
|
|
|
|
if records:
|
|
# Prepare month-year formatted data
|
|
data_by_month = {}
|
|
totals_by_month = {}
|
|
for record in records:
|
|
order_month_year = record.order_expected_on.strftime('%B %Y') # E.g., "May 2025"
|
|
|
|
if order_month_year not in data_by_month:
|
|
data_by_month[order_month_year] = []
|
|
totals_by_month[order_month_year] = 0.0
|
|
|
|
data_by_month[order_month_year].append({
|
|
'record_id': record.id,
|
|
'quote_no': record.quote_no,
|
|
'customer_name': record.customer_name.customer_name,
|
|
'end_customer_name':record.end_customer_name,
|
|
'customer_city':record.customer_city,
|
|
'sales_person': record.sales_person.name,
|
|
'order_expected_on': record.order_expected_on,
|
|
'proposal_value':record.proposal_value,
|
|
'products':record.products
|
|
})
|
|
totals_by_month[order_month_year] += record.proposal_value or 0.0
|
|
action = self.env.ref("sos_sales.action_report_pipeline").with_context(landscape=True).report_action(
|
|
self, data={'data_by_month': data_by_month,'totals_by_month': totals_by_month}
|
|
)
|
|
return action
|
|
else:
|
|
return {
|
|
'type': 'ir.actions.client',
|
|
'tag': 'display_notification',
|
|
'params': {
|
|
'message': "No Records Found",
|
|
'type': 'danger',
|
|
'sticky': False
|
|
}
|
|
}
|
|
except ValueError as e:
|
|
print(f"Failed to find report action: {e}")
|
|
def action_report_action_plan_btn(self, sales_person_id=None, from_date=None, to_date=None):
|
|
try:
|
|
domain = []
|
|
if sales_person_id:
|
|
domain.append(('sales_executive', '=', sales_person_id))
|
|
if from_date:
|
|
domain.append(('date', '>=', from_date))
|
|
if to_date:
|
|
domain.append(('date', '<=', to_date))
|
|
|
|
records = self.env['sos_sales_action_plan'].search(domain, order="date asc")
|
|
|
|
if records:
|
|
return self.env.ref("sos_sales.action_report_action_plan").with_context(landscape=True).report_action(records)
|
|
else:
|
|
return {
|
|
'type': 'ir.actions.client',
|
|
'tag': 'display_notification',
|
|
'params': {
|
|
'message': "No Records Found",
|
|
'type': 'danger',
|
|
'sticky': False
|
|
}
|
|
}
|
|
except ValueError as e:
|
|
print(f"Failed to find report action: {e}")
|
|
|
|
def action_report_spenco_btn(self, sales_person_id=None, from_date=None, to_date=None, customer=None):
|
|
try:
|
|
# Filter records based on sales_person_id if provided
|
|
domain = [('status', '!=', 'close')]
|
|
if customer:
|
|
domain.append(('customer_name', '=', customer.id))
|
|
if sales_person_id:
|
|
domain.append(('sales_person', '=', sales_person_id))
|
|
|
|
if to_date:
|
|
domain.append(('line_ids.status_changed_on', '<=', to_date))
|
|
domain.append(('spenco_status', 'not in', ('Suspects', '', False, None)))
|
|
records = self.env['sos_case_diary'].search(domain)
|
|
if records:
|
|
|
|
action = self.env.ref("sos_sales.action_report_spenco").with_context(landscape=True).report_action(
|
|
self, data={
|
|
'sales_person_id': sales_person_id,
|
|
'from_date': from_date,
|
|
'to_date': to_date,
|
|
'customer_id': customer.id if customer else None,
|
|
}
|
|
)
|
|
return action
|
|
else:
|
|
return {
|
|
'type': 'ir.actions.client',
|
|
'tag': 'display_notification',
|
|
'params': {
|
|
'message': "No Records Found",
|
|
'type': 'danger',
|
|
'sticky': False
|
|
}
|
|
}
|
|
except ValueError as e:
|
|
print(f"Failed to find report action: {e}")
|
|
|
|
|
|
|
|
class SosCaseDiaryLine(models.Model):
|
|
_name = 'sos_case_diary_line'
|
|
_description = 'Sosaley Case Diary Actions'
|
|
|
|
ref_id = fields.Many2one('sos_case_diary', ondelete="cascade")
|
|
spenco_status = fields.Selection([
|
|
('Suspects', 'Suspects'),
|
|
('Prospects', 'Prospects'),
|
|
('Engaged', 'Engaged'),
|
|
('Negotiation', 'Negotiation'),
|
|
('Commercial Order', 'Commercial Order')
|
|
], string='Status')
|
|
|
|
action_plan_date = fields.Date(string="Action Date",required=True)
|
|
currency_id = fields.Many2one(
|
|
'res.currency',
|
|
string='Currency',
|
|
default=lambda self: self.env['res.currency'].search([('name', '=', 'INR')], limit=1).id or False
|
|
)
|
|
current_state_value = fields.Monetary(currency_field='currency_id', string="Value (In Lakhs)")
|
|
action_plan = fields.Text(string="Action Plan")
|
|
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')
|
|
next_action_date = fields.Date(string="Next Action On")
|
|
status_changed_on = fields.Date(string="Status Changed On")
|
|
notes = fields.Text(string="Remarks")
|
|
@api.model
|
|
def check_expired_status(self):
|
|
today = date.today()
|
|
threshold_date = today - timedelta(days=30)
|
|
|
|
records = self.search([
|
|
('status_changed_on', '<=', threshold_date),
|
|
('spenco_status', 'in', ['Prospects', 'Engaged']),
|
|
])
|
|
if records:
|
|
sequence_util = self.env['sos_common_scripts']
|
|
for record in records:
|
|
ref = record.ref_id
|
|
sales_person = ref.sales_person
|
|
if ref and sales_person:
|
|
body_html = f"""
|
|
<p>The SPENCO status of the following case diary has been downgraded due to no activity in past 30 Days.</p>
|
|
"""
|
|
|
|
sequence_util.send_direct_email(
|
|
self.env,
|
|
"sos_case_diary",
|
|
ref.id,
|
|
sales_person.login,
|
|
"SPENCO Status Downgrade",
|
|
body_html,
|
|
"ramachandran.r@sosaley.in"
|
|
)
|
|
|
|
for rec in records:
|
|
original_status = rec.spenco_status
|
|
if rec.spenco_status == 'Prospects':
|
|
rec.write({'spenco_status': 'Suspects'})
|
|
elif rec.spenco_status == 'Engaged':
|
|
rec.write({'spenco_status': 'Prospects'})
|
|
|
|
@api.onchange('spenco_status')
|
|
def _onchange_spenco_status(self):
|
|
if self.spenco_status and self.ref_id:
|
|
domain = [
|
|
('ref_id', '=', self.ref_id.id),
|
|
('spenco_status', '=', self.spenco_status)
|
|
]
|
|
|
|
if self.id:
|
|
domain.append(('id', '!=', self.id))
|
|
|
|
old_record = self.env['sos_case_diary_line'].search(domain, order="status_changed_on desc", limit=1)
|
|
if old_record and old_record.status_changed_on:
|
|
self.status_changed_on = old_record.status_changed_on
|
|
else:
|
|
self.status_changed_on = fields.Date.today() # Set today's date for the first record
|
|
|
|
def write(self, vals):
|
|
if not self.env.context.get('prevent_recursion'):
|
|
result = super(SosCaseDiaryLine, self).write(vals)
|
|
self.with_context(prevent_recursion=True)._update_current_state_values()
|
|
return result
|
|
return super(SosCaseDiaryLine, self).write(vals)
|
|
|
|
def _update_current_state_values(self):
|
|
""" Ensures that the most recent entry keeps its value, and previous entries are set to 0. """
|
|
for record in self:
|
|
lines = self.search([('ref_id', '=', record.ref_id.id)], order='id desc')
|
|
if lines:
|
|
# Keep the most recent entry's value, reset all others
|
|
first_entry = lines[0] # The latest entry retains its value
|
|
for line in lines[1:]:
|
|
line.with_context(prevent_recursion=True).write({'current_state_value': 0.00})
|
|
|
|
@api.model
|
|
def create(self, vals):
|
|
is_first_record = False
|
|
if 'spenco_status' in vals and 'ref_id' in vals:
|
|
last_record = self.env['sos_case_diary_line'].search([
|
|
('ref_id', '=', vals['ref_id'])
|
|
], order="id desc", limit=1)
|
|
if last_record:
|
|
previous_spenco_status = last_record.spenco_status
|
|
previous_state_value = last_record.current_state_value
|
|
else:
|
|
previous_spenco_status = 'Suspects'
|
|
previous_state_value = 0.00
|
|
is_first_record = True
|
|
else:
|
|
previous_spenco_status = 'Suspects'
|
|
previous_state_value = 0.00
|
|
is_first_record = True
|
|
|
|
record = super(SosCaseDiaryLine, self).create(vals)
|
|
if record.spenco_status:
|
|
sales_executive = record.ref_id.sales_person
|
|
action_plan_date = record.action_plan_date
|
|
#week wise
|
|
week_number = record._compute_week_number(action_plan_date)
|
|
record.update_summary(
|
|
previous_spenco_status = previous_spenco_status,
|
|
previous_state_value=previous_state_value,
|
|
action_plan_date=action_plan_date,
|
|
sales_executive=sales_executive,
|
|
field_name='week_number',
|
|
field_value=week_number,
|
|
model_name='sos_spenco_summary_week_wise',
|
|
is_first_record=is_first_record
|
|
)
|
|
#month wise
|
|
month_number = record._compute_month_number(action_plan_date)
|
|
record.update_summary(
|
|
previous_spenco_status = previous_spenco_status,
|
|
previous_state_value=previous_state_value,
|
|
action_plan_date=action_plan_date,
|
|
sales_executive=sales_executive,
|
|
field_name='month_number',
|
|
field_value=month_number,
|
|
model_name='sos_spenco_summary_month_wise',
|
|
is_first_record=is_first_record
|
|
)
|
|
#quarter wise
|
|
quarter_number = record._compute_quarter_number(action_plan_date)
|
|
record.update_summary(
|
|
previous_spenco_status = previous_spenco_status,
|
|
previous_state_value=previous_state_value,
|
|
action_plan_date=action_plan_date,
|
|
sales_executive=sales_executive,
|
|
field_name='quarter_number',
|
|
field_value=quarter_number,
|
|
model_name='sos_spenco_summary_quarter_wise',
|
|
is_first_record=is_first_record
|
|
)
|
|
#year wise
|
|
year_number = record._compute_year_number(action_plan_date)
|
|
record.update_summary(
|
|
previous_spenco_status = previous_spenco_status,
|
|
previous_state_value=previous_state_value,
|
|
action_plan_date=action_plan_date,
|
|
sales_executive=sales_executive,
|
|
field_name='year',
|
|
field_value=year_number,
|
|
model_name='sos_spenco_summary_year_wise',
|
|
is_first_record=is_first_record
|
|
)
|
|
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 _compute_previous_week_number(self, action_plan_date):
|
|
prev_week_date = action_plan_date - timedelta(days=7)
|
|
start_of_week = prev_week_date - timedelta(days=prev_week_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 _compute_previous_month_number(self, action_date):
|
|
prev_month_date = (action_date.replace(day=1) - timedelta(days=1))
|
|
return prev_month_date.strftime('%B')
|
|
|
|
def _compute_previous_quarter_number(self, action_date):
|
|
month = action_date.month
|
|
year = action_date.year
|
|
if 4 <= month <= 6:
|
|
return "Q4"
|
|
elif 7 <= month <= 9:
|
|
return "Q1"
|
|
elif 10 <= month <= 12:
|
|
return "Q2"
|
|
else: # Jan-Mar
|
|
return "Q3"
|
|
|
|
def _compute_previous_year_number(self, action_date):
|
|
month = action_date.month
|
|
year = action_date.year
|
|
return f"{year - 1}-{year}" if month >= 4 else f"{year - 2}-{year - 1}"
|
|
|
|
def update_summary(self, previous_spenco_status, previous_state_value, action_plan_date, sales_executive, field_name, field_value, model_name, is_first_record=False):
|
|
SummaryModel = self.env[model_name]
|
|
current_spenco_status = self.spenco_status
|
|
|
|
def update_all_status(SummaryModel, sales_executive_id, field_name, prev_field_value):
|
|
for all_status in ['Suspects', 'Prospects', 'Engaged', 'Negotiation', 'Commercial Order']:
|
|
status_record = SummaryModel.search([
|
|
('sales_executive', '=', sales_executive_id),
|
|
(field_name, '=', prev_field_value),
|
|
('spenco_status', '=', all_status)
|
|
], limit=1)
|
|
if status_record:
|
|
closing_count_status = (
|
|
(status_record.opening_cases_count or 0)
|
|
- (status_record.downgrade_cases_count or 0)
|
|
- (status_record.upgrade_cases_count or 0)
|
|
+ (status_record.new_cases_count or 0)
|
|
)
|
|
closing_value_status = (
|
|
(status_record.opening_cases_value or 0.0)
|
|
- (status_record.downgrade_cases_value or 0.0)
|
|
- (status_record.upgrade_cases_value or 0.0)
|
|
+ (status_record.new_cases_value or 0.0)
|
|
)
|
|
status_record.write({
|
|
'closing_cases_count': closing_count_status,
|
|
'closing_cases_value': closing_value_status,
|
|
})
|
|
|
|
# Compute previous field value once
|
|
prev_field_value = None
|
|
if field_name == 'week_number':
|
|
prev_field_value = self._compute_previous_week_number(action_plan_date)
|
|
elif field_name == 'month_number':
|
|
prev_field_value = self._compute_previous_month_number(action_plan_date)
|
|
elif field_name == 'quarter_number':
|
|
prev_field_value = self._compute_previous_quarter_number(action_plan_date)
|
|
elif field_name == 'year':
|
|
prev_field_value = self._compute_previous_year_number(action_plan_date)
|
|
|
|
# Update all status closing fields from previous period
|
|
update_all_status(SummaryModel, sales_executive.id, field_name, prev_field_value)
|
|
|
|
def get_or_create_status_record(status):
|
|
record = SummaryModel.search([
|
|
('sales_executive', '=', sales_executive.id),
|
|
(field_name, '=', field_value),
|
|
('spenco_status', '=', status)
|
|
], limit=1)
|
|
if not record:
|
|
old_record = SummaryModel.search([
|
|
('sales_executive', '=', sales_executive.id),
|
|
(field_name, '=', prev_field_value),
|
|
('spenco_status', '=', status)
|
|
], limit=1) if prev_field_value else None
|
|
|
|
vals = {
|
|
'sales_executive': sales_executive.id,
|
|
field_name: field_value,
|
|
'spenco_status': status,
|
|
'entered_date': action_plan_date,
|
|
}
|
|
if old_record:
|
|
closing_count = (
|
|
(old_record.opening_cases_count or 0)
|
|
- (old_record.downgrade_cases_count or 0)
|
|
- (old_record.upgrade_cases_count or 0)
|
|
+ (old_record.new_cases_count or 0)
|
|
)
|
|
closing_value = (
|
|
(old_record.opening_cases_value or 0.0)
|
|
- (old_record.downgrade_cases_value or 0.0)
|
|
- (old_record.upgrade_cases_value or 0.0)
|
|
+ (old_record.new_cases_value or 0.0)
|
|
)
|
|
old_record.write({
|
|
'closing_cases_count': closing_count,
|
|
'closing_cases_value': closing_value,
|
|
})
|
|
vals.update({
|
|
'opening_cases_count': closing_count,
|
|
'opening_cases_value': closing_value,
|
|
})
|
|
|
|
record = SummaryModel.create(vals)
|
|
return record
|
|
|
|
# Now process previous/current statuses
|
|
prev_component = get_or_create_status_record(previous_spenco_status)
|
|
current_component = get_or_create_status_record(current_spenco_status)
|
|
|
|
if is_first_record:
|
|
current_component.write({
|
|
'new_cases_count': max(0, (current_component.new_cases_count or 0)) + 1,
|
|
'new_cases_value': max(0.0, (current_component.new_cases_value or 0.0)) + (self.current_state_value or 0.0),
|
|
})
|
|
return True
|
|
|
|
if previous_spenco_status != current_spenco_status:
|
|
spenco_order = ['Suspects', 'Prospects', 'Engaged', 'Negotiation', 'Commercial Order']
|
|
try:
|
|
prev_index = spenco_order.index(previous_spenco_status)
|
|
curr_index = spenco_order.index(current_spenco_status)
|
|
except ValueError:
|
|
return True # Skip if invalid
|
|
|
|
if curr_index > prev_index:
|
|
# Upgrade
|
|
prev_component.write({
|
|
'upgrade_cases_count': max(0, (prev_component.upgrade_cases_count or 0)) + 1,
|
|
'upgrade_cases_value': max(0.0, (prev_component.upgrade_cases_value or 0.0)) + (previous_state_value or 0.0),
|
|
})
|
|
current_component.write({
|
|
'new_cases_count': max(0, (current_component.new_cases_count or 0)) + 1,
|
|
'new_cases_value': max(0.0, (current_component.new_cases_value or 0.0)) + (self.current_state_value or 0.0),
|
|
})
|
|
elif curr_index < prev_index:
|
|
# Downgrade
|
|
prev_component.write({
|
|
'downgrade_cases_count': max(0, (prev_component.downgrade_cases_count or 0)) + 1,
|
|
'downgrade_cases_value': max(0.0, (prev_component.downgrade_cases_value or 0.0)) + (previous_state_value or 0.0),
|
|
})
|
|
current_component.write({
|
|
'new_cases_count': max(0, (current_component.new_cases_count or 0)) + 1,
|
|
'new_cases_value': max(0.0, (current_component.new_cases_value or 0.0)) + (self.current_state_value or 0.0),
|
|
})
|
|
|
|
return True
|
|
|
|
|
|
class SosCaseTransferHistory(models.Model):
|
|
_name = 'sos_case_transfer_history'
|
|
_description = 'Case Transfer History'
|
|
_order = 'id desc'
|
|
|
|
case_diary_id = fields.Many2one('sos_case_diary', string="Case Diary", required=True, ondelete='cascade')
|
|
previous_sales_person = fields.Many2one('res.users', string="Transferred From", readonly=True)
|
|
new_sales_person = fields.Many2one('res.users', string="Transferred To", readonly=True)
|
|
transfer_date = fields.Datetime(string="Transfer Date", default=fields.Datetime.now, readonly=True)
|
|
status = fields.Text(string="Status")
|
|
top_management_name = fields.Many2one('res.users', string='Top Management Approver')
|
|
top_management_approval_image = fields.Image(related="top_management_name.signature_image",string='Top Management Approval',readonly=True)
|
|
top_management_approved_on = fields.Datetime(string="Approved On")
|
|
def action_top_esign_btn(self):
|
|
self.status = "Approved"
|
|
self.case_diary_id.sales_person = self.new_sales_person
|
|
self.case_diary_id.customer_name.responsible = self.new_sales_person #Customers change
|
|
sequence_util = self.env['sos_common_scripts']
|
|
sequence_util.action_assign_signature(
|
|
self,
|
|
'top_management_name',
|
|
'top_management_approved_on',
|
|
'sos_inventory.sos_management_user'
|
|
)
|
|
return {'type': 'ir.actions.act_window_close'}
|
|
|