from odoo import models, fields, api
from datetime import date
from odoo.exceptions import ValidationError
from collections import defaultdict
class sos_sales_plan_target(models.Model):
_name = 'sos_sales_plan_target'
_description = 'Sosaley Sales Target'
_rec_name='financial_year'
financial_year = fields.Char(string="Financial Year", default=lambda self: self._get_financial_year())
line_ids = fields.One2many('sos_sales_plan_target_lines', 'ref_id', string="Sales Target Lines",copy=True)
sales_executive = fields.Many2one(
'res.users',
string='Sales Executive',
default=lambda self: self.env.user,
readonly=True
)
total_april_value = fields.Float(string="April Target", compute="_compute_monthly_totals", store=True)
total_may_value = fields.Float(string="May Target", compute="_compute_monthly_totals", store=True)
total_june_value = fields.Float(string="June Target", compute="_compute_monthly_totals", store=True)
total_july_value = fields.Float(string="July Target", compute="_compute_monthly_totals", store=True)
total_august_value = fields.Float(string="August Target", compute="_compute_monthly_totals", store=True)
total_september_value = fields.Float(string="September Target", compute="_compute_monthly_totals", store=True)
total_october_value = fields.Float(string="October Target", compute="_compute_monthly_totals", store=True)
total_november_value = fields.Float(string="November Target", compute="_compute_monthly_totals", store=True)
total_december_value = fields.Float(string="December Target", compute="_compute_monthly_totals", store=True)
total_january_value = fields.Float(string="January Target", compute="_compute_monthly_totals", store=True)
total_february_value = fields.Float(string="February Target", compute="_compute_monthly_totals", store=True)
total_march_value = fields.Float(string="March Target", compute="_compute_monthly_totals", store=True)
total_annual_value = fields.Float(string="Annual Target", compute="_compute_total_annual_value", store=True)
total_q1_value = fields.Float(string="Q1 Target", compute="_compute_q1_value", store=True)
total_q2_value = fields.Float(string="Q2 Target", compute="_compute_q2_value", store=True)
total_q3_value = fields.Float(string="Q3 Target", compute="_compute_q3_value", store=True)
total_q4_value = fields.Float(string="Q4 Target", compute="_compute_q4_value", store=True)
product_summary = fields.Html(string="Product-wise Summary", compute="_compute_product_summary")
def _compute_product_summary(self):
for rec in self:
totals = defaultdict(float)
for line in rec.line_ids:
total = sum([
line.apr_value, line.may_value, line.jun_value, line.jul_value,
line.aug_value, line.sep_value, line.oct_value, line.nov_value,
line.dec_value, line.jan_value, line.feb_value, line.mar_value
])
totals[line.product] += total
rows = "".join(f"
| {prod} | ₹ {amt:.2f} |
" for prod, amt in totals.items())
rec.product_summary = f"""
| Product Wise Target (Rupees In Lakhs) |
| Product | Total |
{rows}
"""
def action_report_sales_plan_btn(self):
try:
action = self.env.ref("sos_sales.action_report_sales_plan").with_context(landscape=True).report_action(self)
return action
except ValueError as e:
print(f"Failed to find report action: {e}")
@api.model
def create(self, vals):
month_map = {
'total_april_value': 'apr_value',
'total_may_value': 'may_value',
'total_june_value': 'jun_value',
'total_july_value': 'jul_value',
'total_august_value': 'aug_value',
'total_september_value': 'sep_value',
'total_october_value': 'oct_value',
'total_november_value': 'nov_value',
'total_december_value': 'dec_value',
'total_january_value': 'jan_value',
'total_february_value': 'feb_value',
'total_march_value': 'mar_value',
}
monthly_totals = {key: 0.0 for key in month_map}
line_items = vals.get('line_ids', [])
for command in line_items:
if isinstance(command, (list, tuple)) and command[0] == 0: # create command
line_vals = command[2]
for field_name, month_key in month_map.items():
monthly_totals[field_name] += line_vals.get(month_key, 0.0)
# Assign calculated values into vals
vals.update(monthly_totals)
# Also calculate total_annual_value from monthly values
total = sum(monthly_totals.values())
vals['total_annual_value'] = total
sales_achievement_records = self.env['sos_sales_achievement_report'].search([
('financial_year', '=', vals['financial_year']),
('sales_person', '=', self.env.user.id)
], limit=1)
if sales_achievement_records:
sales_achievement_records.write({
'overall_target':total,
'planned_target_april':vals['total_april_value'],
'planned_target_may':vals['total_may_value'],
'planned_target_june':vals['total_june_value'],
'planned_target_july':vals['total_july_value'],
'planned_target_august':vals['total_august_value'],
'planned_target_september':vals['total_september_value'],
'planned_target_october':vals['total_october_value'],
'planned_target_november':vals['total_november_value'],
'planned_target_december':vals['total_december_value'],
'planned_target_january':vals['total_january_value'],
'planned_target_february':vals['total_february_value'],
'planned_target_march':vals['total_march_value']
})
else:
self.env['sos_sales_achievement_report'].create({
'financial_year': vals['financial_year'],
'sales_person': self.env.user.id,
'overall_target':vals['total_annual_value'],
'planned_target_april':vals['total_april_value'],
'planned_target_may':vals['total_may_value'],
'planned_target_june':vals['total_june_value'],
'planned_target_july':vals['total_july_value'],
'planned_target_august':vals['total_august_value'],
'planned_target_september':vals['total_september_value'],
'planned_target_october':vals['total_october_value'],
'planned_target_november':vals['total_november_value'],
'planned_target_december':vals['total_december_value'],
'planned_target_january':vals['total_january_value'],
'planned_target_february':vals['total_february_value'],
'planned_target_march':vals['total_march_value']
})
return super(sos_sales_plan_target, self).create(vals)
def write(self, vals):
res = super(sos_sales_plan_target, self).write(vals) # Perform the write first
for rec in self:
achievement = self.env['sos_sales_achievement_report'].search([
('financial_year', '=', rec.financial_year),
('sales_person', '=', rec.sales_executive.id)
], limit=1)
vals_to_write = {
'overall_target': rec.total_annual_value,
'planned_target_april': rec.total_april_value,
'planned_target_may': rec.total_may_value,
'planned_target_june': rec.total_june_value,
'planned_target_july': rec.total_july_value,
'planned_target_august': rec.total_august_value,
'planned_target_september': rec.total_september_value,
'planned_target_october': rec.total_october_value,
'planned_target_november': rec.total_november_value,
'planned_target_december': rec.total_december_value,
'planned_target_january': rec.total_january_value,
'planned_target_february': rec.total_february_value,
'planned_target_march': rec.total_march_value,
}
if achievement:
achievement.write(vals_to_write)
else:
vals_to_write.update({
'financial_year': rec.financial_year,
'sales_person': rec.sales_executive.id,
})
self.env['sos_sales_achievement_report'].create(vals_to_write)
return res
@api.constrains('financial_year', 'sales_executive')
def check_unique_values(self):
for record in self:
existing_records = self.search([
('sales_executive', '=', record.sales_executive.id),
('financial_year', '=', record.financial_year),
('id', '!=', record.id) # Exclude self
])
print(existing_records)
if existing_records:
raise ValidationError("Target of the financial year must be unique.")
@api.depends('line_ids.apr_value', 'line_ids.may_value', 'line_ids.jun_value',
'line_ids.jul_value', 'line_ids.aug_value', 'line_ids.sep_value',
'line_ids.oct_value', 'line_ids.nov_value', 'line_ids.dec_value',
'line_ids.jan_value', 'line_ids.feb_value', 'line_ids.mar_value')
def _compute_total_annual_value(self):
for rec in self:
rec.total_annual_value = sum(
line.apr_value + line.may_value + line.jun_value + line.jul_value +
line.aug_value + line.sep_value + line.oct_value + line.nov_value +
line.dec_value + line.jan_value + line.feb_value + line.mar_value
for line in rec.line_ids
)
@api.depends('line_ids.apr_value', 'line_ids.may_value', 'line_ids.jun_value')
def _compute_q1_value(self):
for rec in self:
rec.total_q1_value = sum(
line.apr_value + line.may_value + line.jun_value
for line in rec.line_ids
)
@api.depends('line_ids.jul_value', 'line_ids.aug_value', 'line_ids.sep_value')
def _compute_q2_value(self):
for rec in self:
rec.total_q2_value = sum(
line.jul_value + line.aug_value + line.sep_value
for line in rec.line_ids
)
@api.depends('line_ids.oct_value', 'line_ids.nov_value', 'line_ids.dec_value')
def _compute_q3_value(self):
for rec in self:
rec.total_q3_value = sum(
line.oct_value + line.nov_value + line.dec_value
for line in rec.line_ids
)
@api.depends('line_ids.jan_value', 'line_ids.feb_value', 'line_ids.mar_value')
def _compute_q4_value(self):
for rec in self:
rec.total_q4_value = sum(
line.jan_value + line.feb_value + line.mar_value
for line in rec.line_ids
)
@api.depends(
'line_ids.apr_value', 'line_ids.may_value', 'line_ids.jun_value',
'line_ids.jul_value', 'line_ids.aug_value', 'line_ids.sep_value',
'line_ids.oct_value', 'line_ids.nov_value', 'line_ids.dec_value',
'line_ids.jan_value', 'line_ids.feb_value', 'line_ids.mar_value'
)
def _compute_monthly_totals(self):
for rec in self:
rec.total_april_value = sum(line.apr_value for line in rec.line_ids)
rec.total_may_value = sum(line.may_value for line in rec.line_ids)
rec.total_june_value = sum(line.jun_value for line in rec.line_ids)
rec.total_july_value = sum(line.jul_value for line in rec.line_ids)
rec.total_august_value = sum(line.aug_value for line in rec.line_ids)
rec.total_september_value = sum(line.sep_value for line in rec.line_ids)
rec.total_october_value = sum(line.oct_value for line in rec.line_ids)
rec.total_november_value = sum(line.nov_value for line in rec.line_ids)
rec.total_december_value = sum(line.dec_value for line in rec.line_ids)
rec.total_january_value = sum(line.jan_value for line in rec.line_ids)
rec.total_february_value = sum(line.feb_value for line in rec.line_ids)
rec.total_march_value = sum(line.mar_value for line in rec.line_ids)
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}"
class sos_sales_plan_target_Line(models.Model):
_name = 'sos_sales_plan_target_lines'
_description = 'Sosaley Sales Target Lines'
ref_id = fields.Many2one('sos_sales_plan_target', string="Sales Target")
region = fields.Char(string="Region / Vertical")
customer_name = fields.Many2one('sos_customers',string="Customer Name",domain=lambda self: [('responsible', '=', self.env.uid)])
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")
date_billed = fields.Date(string="Date (Billed)")
apr_qty = fields.Integer(string="April Qty")
apr_value = fields.Float(string="April Value", digits=(12, 2))
may_qty = fields.Integer(string="May Qty")
may_value = fields.Float(string="May Value", digits=(12, 2))
jun_qty = fields.Integer(string="June Qty")
jun_value = fields.Float(string="June Value", digits=(12, 2))
jul_qty = fields.Integer(string="July Qty")
jul_value = fields.Float(string="July Value", digits=(12, 2))
aug_qty = fields.Integer(string="August Qty")
aug_value = fields.Float(string="August Value", digits=(12, 2))
sep_qty = fields.Integer(string="September Qty")
sep_value = fields.Float(string="September Value", digits=(12, 2))
oct_qty = fields.Integer(string="October Qty")
oct_value = fields.Float(string="October Value", digits=(12, 2))
nov_qty = fields.Integer(string="November Qty")
nov_value = fields.Float(string="November Value", digits=(12, 2))
dec_qty = fields.Integer(string="December Qty")
dec_value = fields.Float(string="December Value", digits=(12, 2))
jan_qty = fields.Integer(string="January Qty")
jan_value = fields.Float(string="January Value", digits=(12, 2))
feb_qty = fields.Integer(string="February Qty")
feb_value = fields.Float(string="February Value", digits=(12, 2))
mar_qty = fields.Integer(string="March Qty")
mar_value = fields.Float(string="March Value", digits=(12, 2))
@api.onchange('customer_name')
def _onchange_customer_name(self):
if self.customer_name:
self.location = self.customer_name.customer_city or ''