[#SIRH-32] Ajouter l'exercice 2026/2027 dans les congés/RTT (#20)
Auto Tag Develop / tag (push) Successful in 9s
Auto Tag Develop / tag (push) Successful in 9s
| 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>
This commit was merged in pull request #20.
This commit is contained in:
@@ -0,0 +1,321 @@
|
||||
# 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` — calcule `accruingDaysTotal` dans `computeYearSummary` et le recopie sur le DTO.
|
||||
- `src/ApiResource/EmployeeLeaveSummary.php` — nouvelle propriété exposée `accruingDaysTotal`.
|
||||
- `frontend/services/dto/employee-leave-summary.ts` — champ TS `accruingDaysTotal`.
|
||||
- `frontend/components/employees/LeaveTab.vue` — affichage `net / 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 `accruingDaysTotal` dans les deux branches de `computeYearSummary`**
|
||||
|
||||
Dans `src/State/EmployeeLeaveSummaryProvider.php`, branche non-forfait, remplacer :
|
||||
|
||||
```php
|
||||
$acquiredDays = $carryDays;
|
||||
$accruingDays = $remainingGenerated + $remainingGeneratedSaturdays;
|
||||
```
|
||||
|
||||
par :
|
||||
|
||||
```php
|
||||
$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 :
|
||||
|
||||
```php
|
||||
$acquiredDays = $leavePolicy['acquiredDays'];
|
||||
$accruingDays = 0.0;
|
||||
```
|
||||
|
||||
par :
|
||||
|
||||
```php
|
||||
$acquiredDays = $leavePolicy['acquiredDays'];
|
||||
$accruingDays = 0.0;
|
||||
$accruingDaysTotal = 0.0;
|
||||
```
|
||||
|
||||
- [ ] **Step 2 : Ajouter la clé au tableau `targetSummary`**
|
||||
|
||||
Toujours dans `computeYearSummary`, remplacer :
|
||||
|
||||
```php
|
||||
'accruingDays' => $accruingDays,
|
||||
```
|
||||
|
||||
par :
|
||||
|
||||
```php
|
||||
'accruingDays' => $accruingDays,
|
||||
'accruingDaysTotal' => $accruingDaysTotal,
|
||||
```
|
||||
|
||||
- [ ] **Step 3 : Déclarer la clé dans le PHPDoc de retour**
|
||||
|
||||
Dans le bloc `@return null|array{ ... }` de `computeYearSummary`, remplacer :
|
||||
|
||||
```php
|
||||
* accruingDays: float,
|
||||
```
|
||||
|
||||
par :
|
||||
|
||||
```php
|
||||
* accruingDays: float,
|
||||
* accruingDaysTotal: float,
|
||||
```
|
||||
|
||||
- [ ] **Step 4 : Recopier la valeur sur le DTO dans `provide()`**
|
||||
|
||||
Remplacer :
|
||||
|
||||
```php
|
||||
$summary->accruingDays = $yearSummary['accruingDays'];
|
||||
```
|
||||
|
||||
par :
|
||||
|
||||
```php
|
||||
$summary->accruingDays = $yearSummary['accruingDays'];
|
||||
$summary->accruingDaysTotal = $yearSummary['accruingDaysTotal'];
|
||||
```
|
||||
|
||||
- [ ] **Step 5 : Ajouter la propriété sur l'ApiResource**
|
||||
|
||||
Dans `src/ApiResource/EmployeeLeaveSummary.php`, remplacer :
|
||||
|
||||
```php
|
||||
public float $accruingDays = 0.0;
|
||||
```
|
||||
|
||||
par :
|
||||
|
||||
```php
|
||||
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
|
||||
<?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 :
|
||||
|
||||
```bash
|
||||
rm src/Command/TmpVerifyAccruingCommand.php
|
||||
```
|
||||
|
||||
- [ ] **Step 8 : Commit**
|
||||
|
||||
```bash
|
||||
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 :
|
||||
|
||||
```ts
|
||||
accruingDays: number
|
||||
```
|
||||
|
||||
par :
|
||||
|
||||
```ts
|
||||
accruingDays: number
|
||||
accruingDaysTotal: number
|
||||
```
|
||||
|
||||
- [ ] **Step 2 : Afficher la fraction dans la case « En cours d'acquisition »**
|
||||
|
||||
Dans `frontend/components/employees/LeaveTab.vue`, remplacer :
|
||||
|
||||
```vue
|
||||
<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 :
|
||||
|
||||
```vue
|
||||
<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,50` ou `17,50 / 17,50` si aucun congé anticipé).
|
||||
- Sur un employé **forfait**, la case affiche un seul nombre (`0`), inchangé.
|
||||
|
||||
(Ne pas lancer `npm run build`.)
|
||||
|
||||
- [ ] **Step 4 : Commit**
|
||||
|
||||
```bash
|
||||
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 :
|
||||
|
||||
```markdown
|
||||
- **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 :
|
||||
|
||||
```ts
|
||||
{ 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**
|
||||
|
||||
```bash
|
||||
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 / brut` non-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`).
|
||||
@@ -0,0 +1,267 @@
|
||||
# Exercice suivant dans les sélecteurs Congés et RTT — 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:** Faire apparaître toujours l'exercice **suivant** (exercice courant + 1) dans les sélecteurs d'exercice des onglets Congés et RTT de la fiche employé, pour une phase de contrat ouverte.
|
||||
|
||||
**Architecture :** Changement **frontend uniquement**. Le backend calcule déjà l'exercice suivant pour une phase ouverte (`clampYearToPhase` ne plafonne pas vers le haut quand `phase.endDate` est nul). On déplace la borne haute (`maxYear`) des deux `computed` `availableLeaveYears` / `availableRttYears` de « exercice courant » à « exercice courant + 1 » lorsque la phase est ouverte ; la borne reste l'exercice de fin de phase pour une phase clôturée. La borne basse, la sélection par défaut (exercice courant) et le verrouillage des éditions (`isHistoricalYear`) sont inchangés.
|
||||
|
||||
**Tech Stack :** Nuxt 4 / Vue 3 / TypeScript (composables). Backend Symfony inchangé (les tests PHPUnit doivent rester verts). Pas de harnais de test frontend dans le projet → vérification manuelle via `make dev-nuxt`.
|
||||
|
||||
**Référence spec :** `docs/superpowers/specs/2026-05-26-exercice-suivant-conges-rtt-design.md`
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
- `frontend/composables/useEmployeeLeave.ts` — borne haute du sélecteur Congés (`availableLeaveYears`).
|
||||
- `frontend/composables/useEmployeeRtt.ts` — borne haute du sélecteur RTT (`availableRttYears`).
|
||||
- `doc/leave-tab.md` — doc fonctionnelle, section « Sélecteur d'année ».
|
||||
- `doc/rtt-tab.md` — doc fonctionnelle, section « Sélecteur d'année ».
|
||||
- `CLAUDE.md` — bullets « Sélecteur d'année » des sections Congés et RTT.
|
||||
- `frontend/data/documentation-content.ts` — documentation in-app (2 paragraphes).
|
||||
|
||||
Aucun fichier créé ; 6 fichiers modifiés.
|
||||
|
||||
---
|
||||
|
||||
### Task 1 : Borne haute = exercice suivant sur les deux composables
|
||||
|
||||
**Files:**
|
||||
- Modify: `frontend/composables/useEmployeeLeave.ts` (computed `availableLeaveYears`)
|
||||
- Modify: `frontend/composables/useEmployeeRtt.ts` (computed `availableRttYears`)
|
||||
|
||||
- [ ] **Step 1 : Modifier `availableLeaveYears` dans `useEmployeeLeave.ts`**
|
||||
|
||||
Remplacer ce bloc (déclaration de `phaseEndYear`) :
|
||||
|
||||
```ts
|
||||
// Plage = exercices intersectant la phase.
|
||||
const phaseStartYear = computeLeaveYearForDate(new Date(`${phase.startDate}T00:00:00`))
|
||||
const phaseEndYear = phase.endDate
|
||||
? computeLeaveYearForDate(new Date(`${phase.endDate}T00:00:00`))
|
||||
: currentLeaveYear.value
|
||||
```
|
||||
|
||||
par :
|
||||
|
||||
```ts
|
||||
// Plage = exercices intersectant la phase.
|
||||
const phaseStartYear = computeLeaveYearForDate(new Date(`${phase.startDate}T00:00:00`))
|
||||
// Borne haute : fin de phase si clôturée ; sinon l'exercice SUIVANT (courant + 1),
|
||||
// pour pouvoir consulter en avance les congés posés sur l'exercice à venir.
|
||||
const maxYear = phase.endDate
|
||||
? computeLeaveYearForDate(new Date(`${phase.endDate}T00:00:00`))
|
||||
: currentLeaveYear.value + 1
|
||||
```
|
||||
|
||||
Puis, plus bas, supprimer la ligne devenue redondante en remplaçant :
|
||||
|
||||
```ts
|
||||
const minYear = dataFloor !== null ? Math.max(phaseStartYear, dataFloor) : phaseStartYear
|
||||
const maxYear = phaseEndYear
|
||||
```
|
||||
|
||||
par :
|
||||
|
||||
```ts
|
||||
const minYear = dataFloor !== null ? Math.max(phaseStartYear, dataFloor) : phaseStartYear
|
||||
```
|
||||
|
||||
(La variable `maxYear` est désormais déclarée plus haut ; la boucle `for (let y = maxYear; ...)` qui suit est inchangée.)
|
||||
|
||||
- [ ] **Step 2 : Modifier `availableRttYears` dans `useEmployeeRtt.ts`**
|
||||
|
||||
Remplacer ce bloc :
|
||||
|
||||
```ts
|
||||
// Plage = exercices intersectant la phase.
|
||||
const phaseStartYear = computeRttYearForDate(new Date(`${phase.startDate}T00:00:00`))
|
||||
const phaseEndYear = phase.endDate
|
||||
? computeRttYearForDate(new Date(`${phase.endDate}T00:00:00`))
|
||||
: currentRttYear.value
|
||||
```
|
||||
|
||||
par :
|
||||
|
||||
```ts
|
||||
// Plage = exercices intersectant la phase.
|
||||
const phaseStartYear = computeRttYearForDate(new Date(`${phase.startDate}T00:00:00`))
|
||||
// Borne haute : fin de phase si clôturée ; sinon l'exercice SUIVANT (courant + 1),
|
||||
// pour rester cohérent avec le sélecteur de l'onglet Congés.
|
||||
const maxYear = phase.endDate
|
||||
? computeRttYearForDate(new Date(`${phase.endDate}T00:00:00`))
|
||||
: currentRttYear.value + 1
|
||||
```
|
||||
|
||||
Puis remplacer :
|
||||
|
||||
```ts
|
||||
const minYear = dataFloor !== null ? Math.max(phaseStartYear, dataFloor) : phaseStartYear
|
||||
const maxYear = phaseEndYear
|
||||
```
|
||||
|
||||
par :
|
||||
|
||||
```ts
|
||||
const minYear = dataFloor !== null ? Math.max(phaseStartYear, dataFloor) : phaseStartYear
|
||||
```
|
||||
|
||||
- [ ] **Step 3 : Vérifier qu'il ne reste aucune référence à `phaseEndYear`**
|
||||
|
||||
Run: `grep -rn "phaseEndYear" frontend/composables/`
|
||||
Expected: aucune sortie (la variable a été supprimée des deux fichiers).
|
||||
|
||||
- [ ] **Step 4 : Vérification manuelle dans le dev server**
|
||||
|
||||
Run: `make dev-nuxt` puis, dans le navigateur, ouvrir la fiche d'un employé **non-forfait avec phase courante ouverte**.
|
||||
|
||||
Attendu :
|
||||
- Onglet **Congés** → le menu déroulant en pied de calendrier propose l'exercice **suivant** en première position (ex. aujourd'hui exercice `Juin 2025 → Mai 2026` → l'option `Juin 2026 → Mai 2027` est présente), et l'onglet s'ouvre **par défaut** sur l'exercice courant.
|
||||
- Onglet **RTT** → idem, l'exercice suivant est proposé.
|
||||
- Sélectionner l'exercice suivant : les boutons **Jours fractionnés** / **Année N-1 payés** (Congés) et **+ Payer les RTT** (RTT) sont **désactivés** (car `isHistoricalYear` = vrai), et aucun bandeau « Vous consultez l'historique » n'apparaît (ce bandeau dépend de la phase, pas de l'année).
|
||||
- Ouvrir la fiche d'un employé ayant une **phase clôturée** (sélecteur « Vue contrat ») : le sélecteur d'exercice de cette phase **ne propose pas** d'exercice au-delà de la fin de phase (comportement inchangé).
|
||||
|
||||
- [ ] **Step 5 : Commit**
|
||||
|
||||
```bash
|
||||
git add frontend/composables/useEmployeeLeave.ts frontend/composables/useEmployeeRtt.ts
|
||||
git commit -m "feat : proposer l'exercice suivant dans les sélecteurs Congés et RTT
|
||||
|
||||
Sur une phase de contrat ouverte, la borne haute des sélecteurs d'exercice
|
||||
(availableLeaveYears / availableRttYears) passe de l'exercice courant à
|
||||
l'exercice suivant (courant + 1), pour consulter en avance les congés/RTT
|
||||
posés sur l'exercice à venir. Phase clôturée : borne inchangée (fin de phase).
|
||||
Sélection par défaut et verrouillage des éditions inchangés.
|
||||
|
||||
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
|
||||
```
|
||||
|
||||
(Le hook pre-commit lance PHPUnit ; les 151 tests doivent rester verts — aucun changement backend.)
|
||||
|
||||
---
|
||||
|
||||
### Task 2 : Mettre à jour la documentation
|
||||
|
||||
**Files:**
|
||||
- Modify: `doc/leave-tab.md` (section « Sélecteur d'année »)
|
||||
- Modify: `doc/rtt-tab.md` (section « Sélecteur d'année »)
|
||||
- Modify: `CLAUDE.md` (bullets sélecteur Congés et RTT)
|
||||
- Modify: `frontend/data/documentation-content.ts` (2 paragraphes)
|
||||
|
||||
- [ ] **Step 1 : `doc/leave-tab.md`**
|
||||
|
||||
Dans la section « ## Sélecteur d'année » (vers la ligne 26 « Plage proposée : »), remplacer la première puce :
|
||||
|
||||
```markdown
|
||||
- du plus récent (= exercice courant) au plus ancien ;
|
||||
```
|
||||
|
||||
> Remarque : si cette puce n'existe pas telle quelle dans ce fichier, ajouter à la place, juste après la ligne `Plage proposée :`, la puce ci-dessous.
|
||||
|
||||
par :
|
||||
|
||||
```markdown
|
||||
- du plus récent au plus ancien. La borne haute est l'exercice **suivant** (exercice courant + 1) lorsque la phase de contrat est ouverte, afin de consulter en avance les congés posés sur l'exercice à venir ; pour une phase clôturée, la borne haute reste l'exercice de fin de phase ;
|
||||
```
|
||||
|
||||
- [ ] **Step 2 : `doc/rtt-tab.md`**
|
||||
|
||||
Dans la section « ## Sélecteur d'année », remplacer la puce (ligne 24) :
|
||||
|
||||
```markdown
|
||||
- du plus récent (= exercice courant) au plus ancien ;
|
||||
```
|
||||
|
||||
par :
|
||||
|
||||
```markdown
|
||||
- du plus récent au plus ancien. La borne haute est l'exercice **suivant** (exercice courant + 1) sur une phase ouverte (cohérent avec l'onglet Congés) ; pour une phase clôturée, elle reste l'exercice de fin de phase ;
|
||||
```
|
||||
|
||||
- [ ] **Step 3 : `CLAUDE.md` — section Onglet Congés (ligne 76)**
|
||||
|
||||
Remplacer le segment :
|
||||
|
||||
```
|
||||
Plage : de l'exercice courant jusqu'à `max(floor_contrat, floor_data_start_date)`
|
||||
```
|
||||
|
||||
par :
|
||||
|
||||
```
|
||||
Plage : de l'exercice **suivant** (exercice courant + 1 sur une phase ouverte ; exercice de fin de phase si clôturée) jusqu'à `max(floor_contrat, floor_data_start_date)`
|
||||
```
|
||||
|
||||
- [ ] **Step 4 : `CLAUDE.md` — section Onglet RTT (ligne 83)**
|
||||
|
||||
Remplacer la phrase :
|
||||
|
||||
```
|
||||
Même mécanique que l'onglet Congés (double plancher) : `max(floor_contrat, floor_rttStartDate)`.
|
||||
```
|
||||
|
||||
par :
|
||||
|
||||
```
|
||||
Même mécanique que l'onglet Congés : borne haute = exercice suivant (courant + 1) sur phase ouverte, double plancher `max(floor_contrat, floor_rttStartDate)`.
|
||||
```
|
||||
|
||||
- [ ] **Step 5 : `frontend/data/documentation-content.ts` — paragraphe Congés (ligne 483)**
|
||||
|
||||
Remplacer le contenu du paragraphe :
|
||||
|
||||
```ts
|
||||
{ type: 'paragraph', content: 'Un sélecteur d\'année est disponible en bas du calendrier (zone scrollable, à gauche). Il permet de consulter les exercices passés. La plage proposée part de l\'exercice courant et remonte jusqu\'au plus récent entre (a) le premier exercice où l\'employé avait un contrat ouvert et (b) l\'exercice de mise en service du logiciel — il est inutile de remonter plus loin, aucune donnée n\'a été saisie avant.' },
|
||||
```
|
||||
|
||||
par :
|
||||
|
||||
```ts
|
||||
{ type: 'paragraph', content: 'Un sélecteur d\'année est disponible en bas du calendrier (zone scrollable, à gauche). Il permet de consulter l\'exercice suivant ainsi que les exercices passés. La plage proposée part de l\'exercice suivant (l\'exercice à venir, pour consulter en avance les congés déjà posés) et remonte jusqu\'au plus récent entre (a) le premier exercice où l\'employé avait un contrat ouvert et (b) l\'exercice de mise en service du logiciel — il est inutile de remonter plus loin, aucune donnée n\'a été saisie avant.' },
|
||||
```
|
||||
|
||||
- [ ] **Step 6 : `frontend/data/documentation-content.ts` — paragraphe RTT (ligne 539)**
|
||||
|
||||
Remplacer le contenu du paragraphe :
|
||||
|
||||
```ts
|
||||
{ type: 'paragraph', content: 'Un sélecteur d\'exercice est disponible en bas du tableau RTT (zone scrollable, à gauche). Il permet de consulter les exercices passés (Juin → Mai). La plage proposée part de l\'exercice courant et remonte jusqu\'au plus récent entre (a) le premier exercice où l\'employé avait un contrat ouvert et (b) l\'exercice de mise en service du logiciel.' },
|
||||
```
|
||||
|
||||
par :
|
||||
|
||||
```ts
|
||||
{ type: 'paragraph', content: 'Un sélecteur d\'exercice est disponible en bas du tableau RTT (zone scrollable, à gauche). Il permet de consulter l\'exercice suivant ainsi que les exercices passés (Juin → Mai). La plage proposée part de l\'exercice suivant et remonte jusqu\'au plus récent entre (a) le premier exercice où l\'employé avait un contrat ouvert et (b) l\'exercice de mise en service du logiciel.' },
|
||||
```
|
||||
|
||||
- [ ] **Step 7 : Vérifier la cohérence des chaînes éditées**
|
||||
|
||||
Run: `grep -n "exercice suivant" frontend/data/documentation-content.ts doc/leave-tab.md doc/rtt-tab.md CLAUDE.md`
|
||||
Expected: les 6 emplacements modifiés ci-dessus apparaissent (2 dans documentation-content.ts, 1 dans chaque doc, 2 dans CLAUDE.md).
|
||||
|
||||
- [ ] **Step 8 : Commit**
|
||||
|
||||
```bash
|
||||
git add doc/leave-tab.md doc/rtt-tab.md CLAUDE.md frontend/data/documentation-content.ts
|
||||
git commit -m "docs : sélecteurs Congés/RTT proposent l'exercice suivant
|
||||
|
||||
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Self-Review
|
||||
|
||||
**1. Couverture de la spec :**
|
||||
- « Borne haute = exercice courant + 1 sur phase ouverte, fin de phase si clôturée » → Task 1, Steps 1-2. ✓
|
||||
- « Forfait (année civile) et non-forfait » → le `+1` porte sur le numéro d'exercice produit par `computeLeaveYearForDate`/`computeRttYearForDate`, donc valable pour les deux règles. ✓
|
||||
- « Sélection par défaut inchangée » → aucun changement à `initSelected*Year` ; vérifié en Step 4. ✓
|
||||
- « Verrouillage des éditions / pas de bandeau passé » → aucun changement à `isHistoricalYear` ; vérifié en Step 4. ✓
|
||||
- « Périmètre Congés + RTT » → Task 1 touche les deux composables. ✓
|
||||
- « Docs : leave-tab.md, rtt-tab.md, CLAUDE.md, documentation-content.ts » → Task 2. ✓
|
||||
- « Tests backend restent verts » → hook pre-commit, Task 1 Step 5. ✓
|
||||
|
||||
**2. Placeholders :** aucun « TBD/TODO » ; tout le code et toutes les chaînes sont fournis. La Step 1 de Task 2 prévoit le cas où l'ancre exacte diffère (instruction de repli explicite).
|
||||
|
||||
**3. Cohérence des types/noms :** la variable `maxYear` est désormais déclarée en amont dans les deux composables ; la ligne `const maxYear = phaseEndYear` est supprimée ; `phaseEndYear` n'existe plus (vérifié Step 3). La boucle `for (let y = maxYear; y >= minYear; ...)` reste valide.
|
||||
Reference in New Issue
Block a user