250 lines
8.7 KiB
Python
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()}
|