feat : export PDF heures groupé depuis la liste employés + memory_limit 256M
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
- Nouveau endpoint GET /yearly-hours/print-all (admin, par mois uniquement) - Service YearlyHoursExportBuilder extrait du provider existant (logique partagée) - EmployeeYearlyHoursPrintProvider refactorisé pour utiliser le builder - Template print-all.html.twig avec saut de page entre chaque employé - Drawer BulkYearlyHoursDrawer avec loader "Génération en cours..." - Bouton "Export heures" ajouté sur la page liste employés - PHP memory_limit passé de 128M à 256M dans php.ini (nécessaire pour Dompdf multi-employés) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
271
templates/employee-yearly-hours/print-all.html.twig
Normal file
271
templates/employee-yearly-hours/print-all.html.twig
Normal file
@@ -0,0 +1,271 @@
|
||||
<!doctype html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Export heures - {% set months = {
|
||||
1:'Janvier', 2:'Février', 3:'Mars', 4:'Avril', 5:'Mai', 6:'Juin',
|
||||
7:'Juillet', 8:'Août', 9:'Septembre', 10:'Octobre', 11:'Novembre', 12:'Décembre'
|
||||
} %}{% if month %}{{ months[month] }} {{ year }}{% else %}{{ year }}{% endif %}</title>
|
||||
|
||||
<style>
|
||||
@page { size: A4 portrait; margin: 4mm; }
|
||||
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 2mm;
|
||||
font-family: Helvetica, sans-serif;
|
||||
font-size: 9px;
|
||||
}
|
||||
|
||||
.employee-section {
|
||||
page-break-before: always;
|
||||
}
|
||||
|
||||
.employee-section:first-child {
|
||||
page-break-before: auto;
|
||||
}
|
||||
|
||||
.title-bar {
|
||||
position: relative;
|
||||
margin: 0 0 4mm 0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.export-date {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
font-size: 9px;
|
||||
color: #333;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 12px;
|
||||
margin: 4mm 0 2mm 0;
|
||||
padding: 2px 6px;
|
||||
background: #e8e8e8;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: auto;
|
||||
border: 2px solid #0a0a0a;
|
||||
}
|
||||
|
||||
th, td {
|
||||
border: 1px solid #0a0a0a;
|
||||
padding: 2px 4px;
|
||||
vertical-align: middle;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
thead th {
|
||||
text-align: center;
|
||||
font-weight: 700;
|
||||
font-size: 9px;
|
||||
background: #d9e2f3;
|
||||
}
|
||||
|
||||
td { font-size: 9px; }
|
||||
td.date { text-align: left; font-weight: bold; }
|
||||
td.absence { text-align: left; color: #c00; }
|
||||
td.time { text-align: center; }
|
||||
td.presence { text-align: center; }
|
||||
td.total { text-align: center; font-weight: bold; }
|
||||
tr.weekend td { background: #f3f3f3; color: #555; }
|
||||
tr.weekend td.date { color: #333; }
|
||||
|
||||
.signature-footer {
|
||||
page-break-inside: avoid;
|
||||
margin-top: 6mm;
|
||||
}
|
||||
|
||||
.signature-intro {
|
||||
text-align: center;
|
||||
font-weight: 700;
|
||||
margin-bottom: 6mm;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.signature-blocks {
|
||||
display: table;
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
border-collapse: separate;
|
||||
border-spacing: 4mm 0;
|
||||
}
|
||||
|
||||
.signature-block {
|
||||
display: table-cell;
|
||||
border: 1px solid #0a0a0a;
|
||||
padding: 3mm;
|
||||
vertical-align: top;
|
||||
width: 33.33%;
|
||||
}
|
||||
|
||||
.signature-block .title {
|
||||
text-align: center;
|
||||
font-weight: 700;
|
||||
font-size: 11px;
|
||||
margin-bottom: 7mm;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.signature-block .line {
|
||||
margin-bottom: 2mm;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.signature-block .signature-line {
|
||||
margin-top: 6mm;
|
||||
margin-bottom: 18mm;
|
||||
font-size: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
{% set months = {
|
||||
1:'Janvier', 2:'Février', 3:'Mars', 4:'Avril', 5:'Mai', 6:'Juin',
|
||||
7:'Juillet', 8:'Août', 9:'Septembre', 10:'Octobre', 11:'Novembre', 12:'Décembre'
|
||||
} %}
|
||||
|
||||
{% for entry in entries %}
|
||||
<div class="employee-section">
|
||||
<div class="title-bar">
|
||||
<h1>
|
||||
{{ entry.employeeName }}{% if entry.contractLabel %} - {{ entry.contractLabel }}{% endif %}<br>
|
||||
{% if month %}{{ months[month] }} {{ year }}{% else %}{{ year }}{% endif %}
|
||||
</h1>
|
||||
<div class="export-date">Exporté le {{ "now"|date('d/m/Y') }} à {{ "now"|date('H:i:s') }}</div>
|
||||
</div>
|
||||
|
||||
{% for segment in entry.segments %}
|
||||
{% if entry.segments|length > 1 %}
|
||||
<h2>{{ segment.contractName ?? 'Contrat inconnu' }}{% if segment.mode == 'driver' %} (Chauffeur){% endif %}</h2>
|
||||
{% endif %}
|
||||
|
||||
{% if segment.mode == 'presence' %}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Absence</th>
|
||||
<th>Présence matin</th>
|
||||
<th>Présence après-midi</th>
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in segment.rows %}
|
||||
<tr class="{{ row.isWeekend ? 'weekend' : '' }}">
|
||||
<td class="date">{{ row.date }}</td>
|
||||
<td class="absence">{{ row.absenceLabel ?? '' }}</td>
|
||||
<td class="presence">{{ row.presentMorning ? 'X' : '' }}</td>
|
||||
<td class="presence">{{ row.presentAfternoon ? 'X' : '' }}</td>
|
||||
<td class="total">{{ row.total }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% elseif segment.mode == 'driver' %}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Absence</th>
|
||||
<th>Heures jour</th>
|
||||
<th>Heures nuit</th>
|
||||
<th>Heures atelier</th>
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in segment.rows %}
|
||||
<tr class="{{ row.isWeekend ? 'weekend' : '' }}">
|
||||
<td class="date">{{ row.date }}</td>
|
||||
<td class="absence">{{ row.absenceLabel ?? '' }}</td>
|
||||
<td class="time">{{ row.dayHours }}</td>
|
||||
<td class="time">{{ row.nightHours }}</td>
|
||||
<td class="time">{{ row.workshopHours }}</td>
|
||||
<td class="total">{{ row.total }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Absence</th>
|
||||
<th>Début matin</th>
|
||||
<th>Fin matin</th>
|
||||
<th>Début après-midi</th>
|
||||
<th>Fin après-midi</th>
|
||||
<th>Début soir</th>
|
||||
<th>Fin soir</th>
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in segment.rows %}
|
||||
<tr class="{{ row.isWeekend ? 'weekend' : '' }}">
|
||||
<td class="date">{{ row.date }}</td>
|
||||
<td class="absence">{{ row.absenceLabel ?? '' }}</td>
|
||||
<td class="time">{{ row.morningFrom }}</td>
|
||||
<td class="time">{{ row.morningTo }}</td>
|
||||
<td class="time">{{ row.afternoonFrom }}</td>
|
||||
<td class="time">{{ row.afternoonTo }}</td>
|
||||
<td class="time">{{ row.eveningFrom }}</td>
|
||||
<td class="time">{{ row.eveningTo }}</td>
|
||||
<td class="total">{{ row.total }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
<div class="signature-footer">
|
||||
<div class="signature-intro">
|
||||
Nom + Prénom<br>
|
||||
Signature avec mention « bon pour accord »
|
||||
</div>
|
||||
|
||||
<div class="signature-blocks">
|
||||
<div class="signature-block">
|
||||
<p class="title">Direction</p>
|
||||
<p class="line">Nom : ...............</p>
|
||||
<p class="line">Prénom : ...............</p>
|
||||
<p class="line">Mention : ........................................</p>
|
||||
<p class="signature-line">Signature :</p>
|
||||
</div>
|
||||
<div class="signature-block">
|
||||
<p class="title">Responsable usine</p>
|
||||
<p class="line">Nom : ...............</p>
|
||||
<p class="line">Prénom : ...............</p>
|
||||
<p class="line">Mention : ........................................</p>
|
||||
<p class="signature-line">Signature :</p>
|
||||
</div>
|
||||
<div class="signature-block">
|
||||
<p class="title">Salarié</p>
|
||||
<p class="line">Nom : ...............</p>
|
||||
<p class="line">Prénom : ...............</p>
|
||||
<p class="line">Mention : ........................................</p>
|
||||
<p class="signature-line">Signature :</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user