| Numéro du ticket | Titre du ticket | |------------------|-----------------| | | | ## Description de la PR ## Modification du .env ## Check list - [x] Pas de régression - [x] TU/TI/TF rédigée - [x] TU/TI/TF OK - [ ] CHANGELOG modifié Reviewed-on: #20 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr>
12 KiB
En-cours d'acquisition « net / brut » — Implementation Plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: Sur l'onglet Congés de la fiche employé, afficher l'en-cours d'acquisition au format {net} / {brut généré à ce jour} pour les non-forfait, afin que la RH voie le total acquis même quand des congés ont été pris en anticipé.
Architecture : Exposition d'une valeur déjà calculée côté backend (generatedDays + generatedSaturdays) via un nouveau champ accruingDaysTotal sur EmployeeLeaveSummary, puis affichage en fraction côté Nuxt. Aucune nouvelle règle métier ; accruingDays (net) reste le numérateur inchangé.
Tech Stack : Backend Symfony / API Platform (State Provider + ApiResource DTO). Frontend Nuxt 4 / Vue 3 / TypeScript. Tests : PHPUnit (backend) ; pas de harnais frontend → vérification manuelle.
Référence spec : docs/superpowers/specs/2026-05-26-en-cours-acquisition-net-brut-design.md
File Structure
src/State/EmployeeLeaveSummaryProvider.php— calculeaccruingDaysTotaldanscomputeYearSummaryet le recopie sur le DTO.src/ApiResource/EmployeeLeaveSummary.php— nouvelle propriété exposéeaccruingDaysTotal.frontend/services/dto/employee-leave-summary.ts— champ TSaccruingDaysTotal.frontend/components/employees/LeaveTab.vue— affichagenet / brut(non-forfait).doc/leave-tab.md+frontend/data/documentation-content.ts— documentation.
Aucun fichier créé ; 6 fichiers modifiés.
Task 1 : Backend — exposer accruingDaysTotal
Files:
-
Modify:
src/State/EmployeeLeaveSummaryProvider.php -
Modify:
src/ApiResource/EmployeeLeaveSummary.php -
Step 1 : Calculer
accruingDaysTotaldans les deux branches decomputeYearSummary
Dans src/State/EmployeeLeaveSummaryProvider.php, branche non-forfait, remplacer :
$acquiredDays = $carryDays;
$accruingDays = $remainingGenerated + $remainingGeneratedSaturdays;
par :
$acquiredDays = $carryDays;
$accruingDays = $remainingGenerated + $remainingGeneratedSaturdays;
// Brut généré à ce jour, AVANT imputation des congés pris en anticipé
// (dénominateur de l'affichage « net / brut » sur l'onglet Congés).
$accruingDaysTotal = $generatedDays + $generatedSaturdays;
Puis, branche forfait, remplacer :
$acquiredDays = $leavePolicy['acquiredDays'];
$accruingDays = 0.0;
par :
$acquiredDays = $leavePolicy['acquiredDays'];
$accruingDays = 0.0;
$accruingDaysTotal = 0.0;
- Step 2 : Ajouter la clé au tableau
targetSummary
Toujours dans computeYearSummary, remplacer :
'accruingDays' => $accruingDays,
par :
'accruingDays' => $accruingDays,
'accruingDaysTotal' => $accruingDaysTotal,
- Step 3 : Déclarer la clé dans le PHPDoc de retour
Dans le bloc @return null|array{ ... } de computeYearSummary, remplacer :
* accruingDays: float,
par :
* accruingDays: float,
* accruingDaysTotal: float,
- Step 4 : Recopier la valeur sur le DTO dans
provide()
Remplacer :
$summary->accruingDays = $yearSummary['accruingDays'];
par :
$summary->accruingDays = $yearSummary['accruingDays'];
$summary->accruingDaysTotal = $yearSummary['accruingDaysTotal'];
- Step 5 : Ajouter la propriété sur l'ApiResource
Dans src/ApiResource/EmployeeLeaveSummary.php, remplacer :
public float $accruingDays = 0.0;
par :
public float $accruingDays = 0.0;
/** Brut généré sur l'exercice à ce jour (= accruingDays + congés pris en anticipé). Dénominateur de l'affichage « net / brut ». */
public float $accruingDaysTotal = 0.0;
- Step 6 : Lancer la suite PHPUnit (non-régression)
Run: docker exec -t -u www-data php-sirh-fpm php vendor/bin/phpunit
Expected: OK (151 tests, ...) — vert. (Le champ est une exposition pure ; aucun test existant ne doit casser. Le service n'est pas unit-testable en isolation à cause des dépôts final, cf. note spec.)
- Step 7 : Vérification sur données réelles (jetable, non commitée)
Créer src/Command/TmpVerifyAccruingCommand.php :
<?php
declare(strict_types=1);
namespace App\Command;
use App\Entity\Employee;
use App\State\EmployeeLeaveSummaryProvider;
use Doctrine\ORM\EntityManagerInterface;
use ReflectionMethod;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
#[AsCommand(name: 'app:tmp-verify-accruing')]
final class TmpVerifyAccruingCommand extends Command
{
public function __construct(
private readonly EntityManagerInterface $em,
private readonly EmployeeLeaveSummaryProvider $provider,
) {
parent::__construct();
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$m = new ReflectionMethod(EmployeeLeaveSummaryProvider::class, 'computeYearSummary');
foreach ($this->em->getRepository(Employee::class)->findAll() as $e) {
$s = $m->invoke($this->provider, $e, 2026, 0.0, null, null);
if (null === $s || 'CDI_CDD_NON_FORFAIT' !== $s['ruleCode']) {
continue;
}
$output->writeln(sprintf(
'#%d %s : en-cours net=%.2f / brut=%.2f',
$e->getId(),
$e->getLastName(),
$s['accruingDays'],
$s['accruingDaysTotal'],
));
}
return Command::SUCCESS;
}
}
Run: docker exec -t php-sirh-fpm php /var/www/html/bin/console app:tmp-verify-accruing --env=dev
Expected: chaque ligne affiche net=… / brut=… avec net ≤ brut. Pour un salarié sans congé anticipé, net == brut ; pour un salarié ayant débordé, net < brut.
Puis supprimer le fichier :
rm src/Command/TmpVerifyAccruingCommand.php
- Step 8 : Commit
git add src/State/EmployeeLeaveSummaryProvider.php src/ApiResource/EmployeeLeaveSummary.php
git commit -m "feat : exposer accruingDaysTotal (brut généré) sur le récap congés
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
Task 2 : Frontend — afficher « net / brut »
Files:
-
Modify:
frontend/services/dto/employee-leave-summary.ts -
Modify:
frontend/components/employees/LeaveTab.vue -
Step 1 : Ajouter le champ au DTO TypeScript
Dans frontend/services/dto/employee-leave-summary.ts, remplacer :
accruingDays: number
par :
accruingDays: number
accruingDaysTotal: number
- Step 2 : Afficher la fraction dans la case « En cours d'acquisition »
Dans frontend/components/employees/LeaveTab.vue, remplacer :
<p class="col-start-4 p-[10px] border-b border-primary-500"><strong class="uppercase font-semibold">En cours d'acquisition :</strong>
{{ formatCount(summary?.accruingDays) }} Jours
</p>
par :
<p class="col-start-4 p-[10px] border-b border-primary-500"><strong class="uppercase font-semibold">En cours d'acquisition :</strong>
<template v-if="!isForfaitRule">{{ formatCount(summary?.accruingDays) }} / {{ formatCount(summary?.accruingDaysTotal) }} Jours</template>
<template v-else>{{ formatCount(summary?.accruingDays) }} Jours</template>
</p>
- Step 3 : Vérification manuelle (dev server)
Run: make dev-nuxt puis ouvrir la fiche d'un employé non-forfait.
Attendu :
- La case « En cours d'acquisition » affiche deux nombres séparés par
/(ex.14,50 / 17,50ou17,50 / 17,50si aucun congé anticipé). - Sur un employé forfait, la case affiche un seul nombre (
0), inchangé.
(Ne pas lancer npm run build.)
- Step 4 : Commit
git add frontend/services/dto/employee-leave-summary.ts frontend/components/employees/LeaveTab.vue
git commit -m "feat : afficher l'en-cours d'acquisition au format net / brut (onglet Congés)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
Task 3 : Documentation
Files:
-
Modify:
doc/leave-tab.md -
Modify:
frontend/data/documentation-content.ts -
Step 1 :
doc/leave-tab.md
Repérer la section décrivant les compteurs du header (recherche : grep -n "acquisition\|En cours\|compteur" doc/leave-tab.md). Ajouter (ou compléter la puce correspondante) avec ce texte :
- **En cours d'acquisition** (non-forfait) : affiché au format `net / brut`.
- `net` (`accruingDays`) : généré de l'exercice restant, déduit des congés posés en anticipé (au-delà du report acquis).
- `brut` (`accruingDaysTotal` = `generatedDays + generatedSaturdays`) : total généré sur l'exercice à ce jour, avant cette déduction.
- La RH voit ainsi le total réellement acquis même si une partie a déjà été consommée en anticipé. Forfait : pas d'en-cours (affiche `0`, sans fraction).
- Step 2 :
frontend/data/documentation-content.ts
Repérer le paragraphe de l'article « Onglet Congés » décrivant les compteurs (recherche : grep -n "en cours d.acquisition\|En cours\|acquis" frontend/data/documentation-content.ts). Ajouter un bloc note dans le tableau blocks de cet article :
{ type: 'note', content: 'La case « En cours d\'acquisition » affiche deux valeurs : à gauche les jours encore à acquérir (déduction faite des congés déjà posés en anticipé), à droite le total brut acquis sur l\'exercice à ce jour. Exemple : « 14,50 / 17,50 » signifie 17,50 jours acquis dont 3 déjà pris en anticipé.' },
Insérer ce bloc juste après le paragraphe qui présente les compteurs de l'exercice de congés (celui mentionnant l'exercice Juin→Mai / les jours acquis). Respecter l'indentation existante (10 espaces) et l'échappement des apostrophes (
\').
- Step 3 : Vérifier la cohérence
Run: grep -rn "accruingDaysTotal\|net / brut\|14,50 / 17,50" doc/leave-tab.md frontend/data/documentation-content.ts
Expected : la doc fonctionnelle mentionne le format net / brut et la doc in-app contient la note d'exemple.
- Step 4 : Commit
git add doc/leave-tab.md frontend/data/documentation-content.ts
git commit -m "docs : en-cours d'acquisition affiché net / brut sur l'onglet Congés
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
Self-Review
1. Couverture de la spec :
- Nouveau champ
accruingDaysTotal=generatedDays + generatedSaturdays(non-forfait),0(forfait) → Task 1 Steps 1-2. ✓ - Exposition DTO PHP + recopie provider → Task 1 Steps 3-5. ✓
- DTO TS → Task 2 Step 1. ✓
- Affichage
net / brutnon-forfait, inchangé forfait → Task 2 Step 2. ✓ - Docs
doc/leave-tab.md+ in-app → Task 3. ✓ - Invariant
accruingDays ≤ accruingDaysTotal→ vérifié en Task 1 Step 7. ✓ - Hors périmètre (RTT, récap, header) → aucun fichier de ces zones touché. ✓
2. Placeholders : aucun « TBD/TODO » ; tout le code est fourni. Les Steps 1-2 de Task 3 demandent un grep pour localiser l'ancre exacte (le texte à insérer est fourni intégralement) car la position dans documentation-content.ts dépend de l'article ; c'est une instruction d'insertion, pas un placeholder de contenu.
3. Cohérence des types/noms : accruingDaysTotal (float PHP / number TS) utilisé identiquement dans le provider, le tableau targetSummary, le PHPDoc, l'ApiResource, le DTO TS et le template. accruingDays (numérateur) reste inchangé. La variable $accruingDaysTotal est définie dans les deux branches avant la construction de targetSummary (comme $accruingDays).