Initial commit
This commit is contained in:
3
fusion_payroll/controllers/__init__.py
Normal file
3
fusion_payroll/controllers/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import payroll_report
|
||||
249
fusion_payroll/controllers/payroll_report.py
Normal file
249
fusion_payroll/controllers/payroll_report.py
Normal file
@@ -0,0 +1,249 @@
|
||||
# -*- 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()}
|
||||
Reference in New Issue
Block a user