105 lines
3.9 KiB
Python
Executable File
105 lines
3.9 KiB
Python
Executable File
from odoo import models, api
|
|
from collections import defaultdict
|
|
from datetime import datetime, timedelta, date
|
|
|
|
# Constants
|
|
PRODUCTION_LEAD_DAYS = {
|
|
'BHMS 1.2V': 60,
|
|
'BHMS 2V': 30,
|
|
'BHMS 12V': 30,
|
|
'BHMS 48V': 30,
|
|
'BMS-LV 100A': 30,
|
|
'BMS-LV 40A': 30,
|
|
'MC 250W': 45,
|
|
'HeartTarang': 30,
|
|
}
|
|
|
|
MONTH_NAMES = [
|
|
'April', 'May', 'June', 'July', 'August', 'September',
|
|
'October', 'November', 'December', 'January', 'February', 'March'
|
|
]
|
|
|
|
class ReportBillingTarget(models.AbstractModel):
|
|
_name = 'report.sos_sales.report_billing_target'
|
|
_description = 'Billing Target Report'
|
|
|
|
def get_month_start_dates(self, fy_start_year):
|
|
dates = {}
|
|
for i, name in enumerate(MONTH_NAMES):
|
|
month = i + 4 if i < 9 else i - 8
|
|
year = fy_start_year if i < 9 else fy_start_year + 1
|
|
dates[name] = datetime(year, month, 1)
|
|
return dates
|
|
|
|
@api.model
|
|
def _get_report_values(self, docids, data=None):
|
|
fy_start_year = 2024 # Change to dynamic year if needed
|
|
month_start_dates = self.get_month_start_dates(fy_start_year)
|
|
|
|
today = date.today()
|
|
fy_year = today.year if today.month >= 4 else today.year - 1
|
|
current_fy = f"FY {fy_year}-{fy_year + 1}"
|
|
|
|
result = defaultdict(lambda: defaultdict(lambda: defaultdict(float)))
|
|
records = self.env['sos_sales_plan_target'].search([
|
|
('financial_year', '=', current_fy)
|
|
])
|
|
|
|
for rec in records:
|
|
exec_name = rec.sales_executive.name
|
|
for line in rec.line_ids:
|
|
product = line.product
|
|
if not product:
|
|
continue
|
|
lead_days = PRODUCTION_LEAD_DAYS.get(product, 0)
|
|
|
|
for month in MONTH_NAMES:
|
|
short = month.lower()[:3]
|
|
value = getattr(line, f"{short}_value", 0.0)
|
|
if value:
|
|
source_start = month_start_dates[month]
|
|
next_month = source_start.replace(day=28) + timedelta(days=4)
|
|
last_day_of_month = next_month.replace(day=1) - timedelta(days=1)
|
|
|
|
billed_date = last_day_of_month + timedelta(days=lead_days)
|
|
|
|
|
|
# Match billed_date to one of the financial year months
|
|
for name, start_date in month_start_dates.items():
|
|
if start_date.month == billed_date.month and start_date.year == billed_date.year:
|
|
billed_month = name
|
|
break
|
|
else:
|
|
billed_month = None
|
|
|
|
if billed_month in MONTH_NAMES:
|
|
result[exec_name][billed_month][product] += value
|
|
|
|
|
|
# Step 2: Filter products and compute totals
|
|
filtered_products_by_exec = defaultdict(set)
|
|
display_totals = defaultdict(lambda: defaultdict(float))
|
|
|
|
for exec_name, month_data in result.items():
|
|
for month, prod_data in month_data.items():
|
|
for product, val in prod_data.items():
|
|
if val > 0:
|
|
filtered_products_by_exec[exec_name].add(product)
|
|
display_totals[exec_name][month] += val
|
|
overall_monthly_totals = defaultdict(float)
|
|
|
|
for exec_name, month_totals in display_totals.items():
|
|
for month, value in month_totals.items():
|
|
overall_monthly_totals[month] += value
|
|
grand_total = sum(overall_monthly_totals.values())
|
|
return {
|
|
'doc_ids': docids,
|
|
'doc_model': 'sos_sales_plan_target',
|
|
'billing_data': result,
|
|
'month_names': MONTH_NAMES,
|
|
'filtered_products_by_exec': filtered_products_by_exec,
|
|
'monthly_totals': display_totals,
|
|
'overall_monthly_totals': overall_monthly_totals,
|
|
'grand_total': grand_total,
|
|
}
|