This commit is contained in:
gsinghpal
2026-02-27 14:32:32 -05:00
parent b649246e81
commit b925766966
80 changed files with 7831 additions and 1041 deletions

View File

@@ -182,6 +182,84 @@ class FusionClockReport(models.Model):
else:
_logger.warning("Fusion Clock: Mail template not found for report %s", self.id)
def action_export_csv(self):
"""Export the report data as a CSV file for payroll."""
import csv
import io
self.ensure_one()
if not self.attendance_ids:
self._collect_attendance_records()
ICP = self.env['ir.config_parameter'].sudo()
mapping_raw = ICP.get_param('fusion_clock.csv_column_mapping', '')
import json as json_mod
try:
col_map = json_mod.loads(mapping_raw) if mapping_raw else {}
except Exception:
col_map = {}
default_cols = {
'employee': 'Employee',
'date': 'Date',
'clock_in': 'Clock In',
'clock_out': 'Clock Out',
'worked_hours': 'Worked Hours',
'net_hours': 'Net Hours',
'break_min': 'Break (min)',
'overtime': 'Overtime (h)',
'penalties': 'Penalties',
'location': 'Location',
}
for k in default_cols:
if k in col_map:
default_cols[k] = col_map[k]
output = io.StringIO()
writer = csv.writer(output)
writer.writerow(list(default_cols.values()))
for att in self.attendance_ids.sorted(key=lambda a: a.check_in):
date_str = att.check_in.strftime('%Y-%m-%d') if att.check_in else ''
in_str = att.check_in.strftime('%H:%M') if att.check_in else ''
out_str = att.check_out.strftime('%H:%M') if att.check_out else ''
penalties = self.env['fusion.clock.penalty'].search_count([
('attendance_id', '=', att.id),
])
writer.writerow([
att.employee_id.name or '',
date_str,
in_str,
out_str,
round(att.worked_hours or 0, 2),
round(att.x_fclk_net_hours or 0, 2),
round(att.x_fclk_break_minutes or 0, 0),
round(att.x_fclk_overtime_hours or 0, 2),
penalties,
att.x_fclk_location_id.name or '',
])
csv_data = output.getvalue().encode('utf-8')
output.close()
filename = f"clock_export_{self.date_start}_{self.date_end}"
if self.employee_id:
filename += f"_{self.employee_id.name.replace(' ', '_')}"
filename += ".csv"
attachment = self.env['ir.attachment'].create({
'name': filename,
'type': 'binary',
'datas': base64.b64encode(csv_data),
'mimetype': 'text/csv',
})
return {
'type': 'ir.actions.act_url',
'url': f'/web/content/{attachment.id}/{filename}?download=true',
'target': 'new',
}
@api.model
def _cron_generate_period_reports(self):
"""Cron: Generate reports when a pay period ends."""