1
|
|
|
import { Controller, Inject, Get, UseGuards, Res } from '@nestjs/common'; |
2
|
|
|
import { AuthGuard } from '@nestjs/passport'; |
3
|
|
|
import { ApiCookieAuth } from '@nestjs/swagger'; |
4
|
|
|
import { IQueryBus } from 'src/Application/IQueryBus'; |
5
|
|
|
import { GetUsersElementsQuery } from 'src/Application/HumanResource/Payslip/Query/GetUsersElementsQuery'; |
6
|
|
|
import { UserElementsView } from 'src/Application/HumanResource/Payslip/View/UserElementsView'; |
7
|
|
|
import { Response } from 'express'; |
8
|
|
|
import { format } from 'date-fns'; |
9
|
|
|
import { LeaveRequestSlotView } from 'src/Application/HumanResource/Leave/View/LeaveRequestSlotView'; |
10
|
|
|
|
11
|
|
|
@Controller('payslips.csv') |
12
|
|
|
@ApiCookieAuth() |
13
|
|
|
@UseGuards(AuthGuard('bearer')) |
14
|
|
|
export class GetUsersElementsCsvAction { |
15
|
|
|
constructor( |
16
|
|
|
@Inject('IQueryBus') |
17
|
|
|
private readonly queryBus: IQueryBus |
18
|
|
|
) {} |
19
|
|
|
|
20
|
|
|
private formatNumber(value: number): string { |
21
|
|
|
return value.toLocaleString('fr-FR').replace(/\s/g, ''); |
22
|
|
|
} |
23
|
|
|
|
24
|
|
|
@Get() |
25
|
|
|
public async index(@Res() res: Response) { |
26
|
|
|
res.header('Content-Type', 'text/csv'); |
27
|
|
|
|
28
|
|
|
const date = new Date(); |
29
|
|
|
|
30
|
|
|
const month = date.toISOString().substring(0, 7); |
31
|
|
|
|
32
|
|
|
res.attachment(`Fairness - Éléments de paie - ${month}.csv`); |
33
|
|
|
|
34
|
|
|
const payslips: UserElementsView[] = await this.queryBus.execute( |
35
|
|
|
new GetUsersElementsQuery(date) |
36
|
|
|
); |
37
|
|
|
|
38
|
|
|
const headers = [ |
39
|
|
|
'NOM', |
40
|
|
|
'Prénom', |
41
|
|
|
'Contrat', |
42
|
|
|
"Date d'entrée", |
43
|
|
|
'Salaire annuel brut', |
44
|
|
|
'Salaire mensuel brut', |
45
|
|
|
'Temps de travail', |
46
|
|
|
'Frais de transport', |
47
|
|
|
'Forfait mobilité durable', |
48
|
|
|
'Titres restaurant', |
49
|
|
|
'Mutuelle', |
50
|
|
|
'Congés payés', |
51
|
|
|
'Congés sans solde', |
52
|
|
|
'Congés maladie', |
53
|
|
|
'Congés exceptionnels', |
54
|
|
|
'Notes' |
55
|
|
|
]; |
56
|
|
|
|
57
|
|
|
const paidLeavesIndex = headers.findIndex( |
58
|
|
|
value => value === 'Congés payés' |
59
|
|
|
); |
60
|
|
|
|
61
|
|
|
const rows: string[] = []; |
62
|
|
|
|
63
|
|
|
for (const payslip of payslips) { |
64
|
|
|
const row = [ |
65
|
|
|
payslip.lastName.toUpperCase(), |
66
|
|
|
payslip.firstName, |
67
|
|
|
payslip.contract, |
68
|
|
|
payslip.joiningDate, |
69
|
|
|
this.formatNumber(payslip.annualEarnings), |
70
|
|
|
this.formatNumber(Math.round(payslip.monthlyEarnings * 100) / 100), |
71
|
|
|
payslip.workingTime === 'full_time' ? 'Temps plein' : 'Temps partiel', |
72
|
|
|
this.formatNumber(payslip.transportFee), |
73
|
|
|
this.formatNumber(payslip.sustainableMobilityFee), |
74
|
|
|
payslip.mealTickets, |
75
|
|
|
payslip.healthInsurance === 'yes' ? 'Oui' : 'Non', |
76
|
|
|
this.formatNumber(payslip.paidLeaves.totalDays), |
77
|
|
|
this.formatNumber(payslip.unpaidLeaves.totalDays), |
78
|
|
|
this.formatNumber(payslip.sickLeaves.totalDays), |
79
|
|
|
this.formatNumber(payslip.exceptionalLeaves.totalDays), |
80
|
|
|
'' |
81
|
|
|
]; |
82
|
|
|
|
83
|
|
|
rows.push(row.join(';')); |
84
|
|
|
|
85
|
|
|
for (const leave of payslip.paidLeaves.leaves) { |
86
|
|
|
const leaveRow = row.map((_, index) => |
87
|
|
|
index === paidLeavesIndex ? this.formatLeaves(leave) : '' |
88
|
|
|
); |
89
|
|
|
rows.push(leaveRow.join(';')); |
90
|
|
|
} |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
const csv: string = [headers.join(';'), ...rows].join('\n'); |
94
|
|
|
|
95
|
|
|
return res.send(csv); |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
private formatLeaves(leave: LeaveRequestSlotView): string { |
99
|
|
|
const formatDate = (dateString: string): string => |
100
|
|
|
format(new Date(dateString), 'dd/MM/yyyy'); |
101
|
|
|
|
102
|
|
|
return formatDate(leave.startDate) + ' - ' + formatDate(leave.endDate); |
103
|
|
|
} |
104
|
|
|
} |
105
|
|
|
|