Files
Odoo-Modules/fusion_payroll/controllers/payroll_report.py
2026-02-22 01:22:18 -05:00

250 lines
8.7 KiB
Python

# -*- coding: utf-8 -*-
"""
Payroll Report Controller
=========================
Handles AJAX requests for payroll reports:
- Loading report data
- Exporting PDF/Excel
- Updating filters
"""
import base64
import json
from datetime import date
from odoo import http
from odoo.http import request, content_disposition
class PayrollReportController(http.Controller):
"""Controller for payroll report endpoints."""
@http.route('/payroll/report/get_report_data', type='jsonrpc', auth='user')
def get_report_data(self, report_model, options=None):
"""
Get report data for the given report model.
Args:
report_model: The report model name (e.g., 'payroll.report.paycheque.history')
options: Filter options dictionary
Returns:
dict: Report data with columns, lines, and options
"""
try:
# Check if model exists
if report_model not in request.env.registry:
return {'error': f'Report model {report_model} not found in registry'}
# Get the model class (works for abstract models)
report = request.env[report_model]
# Build options
if options:
if isinstance(options, str):
options = json.loads(options)
final_options = report._get_options(options)
# Get report data
columns = report._get_columns()
lines = report._get_lines(final_options)
return {
'report_name': report.report_name,
'report_code': report.report_code,
'options': final_options,
'columns': columns,
'lines': lines,
'date_filter_options': report.DATE_FILTER_OPTIONS,
'filter_date_range': report.filter_date_range,
'filter_employee': report.filter_employee,
'filter_department': report.filter_department,
}
except KeyError as e:
return {'error': f'Report model {report_model} not found: {str(e)}'}
except AttributeError as e:
return {'error': f'Report model {report_model} missing required attribute: {str(e)}'}
except Exception as e:
import traceback
import logging
_logger = logging.getLogger(__name__)
_logger.error(f"Error in get_report_data: {str(e)}\n{traceback.format_exc()}")
return {'error': str(e), 'traceback': traceback.format_exc()}
@http.route('/payroll/report/get_lines', type='jsonrpc', auth='user')
def get_lines(self, report_model, options):
"""
Get report lines with current options.
"""
try:
if report_model not in request.env:
return {'error': f'Report model {report_model} not found'}
report = request.env[report_model]
if isinstance(options, str):
options = json.loads(options)
final_options = report._get_options(options)
return {
'lines': report._get_lines(final_options),
'options': final_options,
}
except Exception as e:
import traceback
return {'error': str(e), 'traceback': traceback.format_exc()}
@http.route('/payroll/report/get_detail_lines', type='jsonrpc', auth='user')
def get_detail_lines(self, report_model, line_id, options):
"""
Get expanded detail lines for a specific line.
Used for drill-down functionality.
"""
try:
if report_model not in request.env:
return {'error': f'Report model {report_model} not found'}
report = request.env[report_model]
if isinstance(options, str):
options = json.loads(options)
# Parse line_id to get record id
if '_' in str(line_id):
parts = line_id.split('_')
record_id = int(parts[-1])
else:
record_id = int(line_id)
if hasattr(report, '_get_detail_lines'):
return {
'detail_lines': report._get_detail_lines(record_id, options)
}
return {'detail_lines': []}
except Exception as e:
import traceback
return {'error': str(e), 'traceback': traceback.format_exc()}
@http.route('/payroll/report/export_xlsx', type='http', auth='user')
def export_xlsx(self, report_model, options, **kw):
"""
Export report to Excel format.
"""
report = request.env[report_model]
if isinstance(options, str):
options = json.loads(options)
final_options = report._get_options(options)
try:
xlsx_data = report.get_xlsx(final_options)
filename = f"{report.report_code}_{date.today().strftime('%Y%m%d')}.xlsx"
return request.make_response(
xlsx_data,
headers=[
('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'),
('Content-Disposition', content_disposition(filename)),
('Content-Length', len(xlsx_data)),
],
)
except Exception as e:
return request.make_response(
json.dumps({'error': str(e)}),
headers=[('Content-Type', 'application/json')],
status=500,
)
@http.route('/payroll/report/export_pdf', type='http', auth='user')
def export_pdf(self, report_model, options, **kw):
"""
Export report to PDF format.
"""
report = request.env[report_model]
if isinstance(options, str):
options = json.loads(options)
final_options = report._get_options(options)
try:
pdf_data = report.get_pdf(final_options)
filename = f"{report.report_code}_{date.today().strftime('%Y%m%d')}.pdf"
return request.make_response(
pdf_data,
headers=[
('Content-Type', 'application/pdf'),
('Content-Disposition', content_disposition(filename)),
('Content-Length', len(pdf_data)),
],
)
except Exception as e:
return request.make_response(
json.dumps({'error': str(e)}),
headers=[('Content-Type', 'application/json')],
status=500,
)
@http.route('/payroll/report/get_employees', type='jsonrpc', auth='user')
def get_employees(self, search_term=''):
"""
Get employees for filter dropdown.
"""
try:
domain = [('company_id', '=', request.env.company.id)]
if search_term:
domain.append(('name', 'ilike', search_term))
employees = request.env['hr.employee'].search(domain, limit=50, order='name')
return [
{'id': emp.id, 'name': emp.name, 'department': emp.department_id.name or ''}
for emp in employees
]
except Exception as e:
import traceback
return {'error': str(e), 'traceback': traceback.format_exc()}
@http.route('/payroll/report/get_departments', type='jsonrpc', auth='user')
def get_departments(self):
"""
Get departments for filter dropdown.
"""
try:
departments = request.env['hr.department'].search([
('company_id', '=', request.env.company.id),
], order='name')
return [
{'id': dept.id, 'name': dept.name}
for dept in departments
]
except Exception as e:
import traceback
return {'error': str(e), 'traceback': traceback.format_exc()}
@http.route('/payroll/report/action_open_record', type='jsonrpc', auth='user')
def action_open_record(self, model, res_id):
"""
Get action to open a specific record.
"""
try:
return {
'type': 'ir.actions.act_window',
'res_model': model,
'res_id': res_id,
'view_mode': 'form',
'target': 'current',
}
except Exception as e:
import traceback
return {'error': str(e), 'traceback': traceback.format_exc()}