From 7fc2b3358799f1deb59ed8e83b495af5cfab40f9 Mon Sep 17 00:00:00 2001
From: Nessar
Date: Sat, 17 Oct 2026 11:05:51 +0200
Subject: [PATCH] refactor(planning): remove the unused remaining-balance
mirror
The summary and details already read the displayed plan's remaining
balances, so the writable mirror, its legacy conversion and the VacDay
classification/reason fields it alone populated are removed.
Refs #274
Co-Authored-By: Claude Opus 5.5
---
.../calendar-year-planning.spec.ts | 27 ++++---------------
.../components/calendar-year/calendar-year.ts | 18 -------------
src/app/services/calendar-service.ts | 4 ---
src/app/services/user-input-service.ts | 1 -
4 files changed, 5 insertions(+), 45 deletions(-)
diff --git a/src/app/components/calendar-year/calendar-year-planning.spec.ts b/src/app/components/calendar-year/calendar-year-planning.spec.ts
index baa9d1c..c7a4c99 100644
--- a/src/app/components/calendar-year/calendar-year-planning.spec.ts
+++ b/src/app/components/calendar-year/calendar-year-planning.spec.ts
@@ -474,7 +474,7 @@ describe('CalendarYear planning outcome boundary', () => {
fixture.detectChanges();
const before = {
balances: structuredClone(input.vacationNumberSignal()),
- remaining: structuredClone(input.remainingVacationDaysSignal()),
+ displayed: structuredClone(input.displayedPlanSignal()),
declarations: structuredClone(input.declaredDaysSignal()),
rules: structuredClone(rules.rules),
};
@@ -508,7 +508,7 @@ describe('CalendarYear planning outcome boundary', () => {
expect(dialog.textContent?.includes('Partial plan')).toBe(partial);
expect(input.planningOutcomeSignal()).toBe(outcome);
expect(input.vacationNumberSignal()).toEqual(before.balances);
- expect(input.remainingVacationDaysSignal()).toEqual(before.remaining);
+ expect(input.displayedPlanSignal()).toEqual(before.displayed);
expect(input.declaredDaysSignal()).toEqual(before.declarations);
expect(rules.rules).toEqual(before.rules);
expect(calendar.createPlanningCalculation).toHaveBeenCalledOnce();
@@ -2164,19 +2164,11 @@ describe('CalendarYear planning outcome boundary', () => {
],
}).compileComponents();
const userInput = TestBed.inject(UserInputService);
- userInput.remainingVacationDaysSignal.set([
- {
- id: 'stale',
- type: SelectableDayType.CP,
- numberOfDays: 1,
- expiryDate: new Date('2025-01-01'),
- },
- ]);
const fixture: ComponentFixture = TestBed.createComponent(CalendarYear);
fixture.detectChanges();
await fixture.whenStable();
- expect(userInput.remainingVacationDaysSignal()).toEqual([]);
+ expect(userInput.displayedPlanSignal()).toBeUndefined();
});
it('keeps and summarizes a returned result', async () => {
@@ -2189,13 +2181,12 @@ describe('CalendarYear planning outcome boundary', () => {
],
}).compileComponents();
const userInput = TestBed.inject(UserInputService);
- userInput.remainingVacationDaysSignal.set([]);
const fixture = TestBed.createComponent(CalendarYear);
fixture.detectChanges();
await fixture.whenStable();
await new Promise((resolve) => setTimeout(resolve, 0));
fixture.detectChanges();
- expect(userInput.remainingVacationDaysSignal()).toEqual([]);
+ expect(userInput.displayedPlanSignal()?.remainingBalances).toEqual(plan.remainingBalances);
const summaryValues = Array.from(
fixture.nativeElement.querySelectorAll('.plan-summary dd') as NodeListOf,
).map((element) => element.textContent?.trim());
@@ -2969,14 +2960,6 @@ describe('CalendarYear planning outcome boundary', () => {
],
}).compileComponents();
const userInput = TestBed.inject(UserInputService);
- userInput.remainingVacationDaysSignal.set([
- {
- id: 'stale',
- type: SelectableDayType.CP,
- numberOfDays: 1,
- expiryDate: new Date('2025-01-01'),
- },
- ]);
const fixture = TestBed.createComponent(CalendarYear);
fixture.detectChanges();
await fixture.whenStable();
@@ -2988,6 +2971,6 @@ describe('CalendarYear planning outcome boundary', () => {
if (outcome?.kind === 'PlanningIncomplete')
expect(outcome.reasons[0].code).toBe('planner-error');
expect(fixture.componentInstance['isLoading']()).toBe(false);
- expect(userInput.remainingVacationDaysSignal()).toEqual([]);
+ expect(userInput.displayedPlanSignal()).toBeUndefined();
});
});
diff --git a/src/app/components/calendar-year/calendar-year.ts b/src/app/components/calendar-year/calendar-year.ts
index d1d7a2a..7ae5169 100644
--- a/src/app/components/calendar-year/calendar-year.ts
+++ b/src/app/components/calendar-year/calendar-year.ts
@@ -37,8 +37,6 @@ import {
CalendarService,
calendarProjectionHorizon,
SelectedDates,
- SelectableDayType,
- VacDay,
} from '../../services/calendar-service';
import { TranslationService } from '../../services/translation-service';
import { UserInputService } from '../../services/user-input-service';
@@ -50,7 +48,6 @@ import {
LeaveType,
DeclaredNonWorkingDay,
PlanExplanation,
- PlanOutcome,
PlanningCalculationContext,
PlanningExplanation,
PlanningObjective,
@@ -467,7 +464,6 @@ export class CalendarYear {
this.planDetailsOpen.set(false);
this.clearCounterfactual();
this.selectedDates.set(this.calendarService.getSelectedDatesForHorizon(horizon));
- this.userInput.remainingVacationDaysSignal.set([]);
}
private loadArtifacts(calculation: PlanningCalculationContext): void {
@@ -517,13 +513,11 @@ export class CalendarYear {
if (plan) {
this.planningHorizon.set(plan.horizon);
this.selectedDates.set(this.calendarService.selectedDatesForPlan(plan));
- this.userInput.remainingVacationDaysSignal.set(this.toLegacyBalances(plan));
return;
}
this.selectedDates.set(
this.calendarService.getSelectedDatesForHorizon(this.planningHorizon()!),
);
- this.userInput.remainingVacationDaysSignal.set([]);
}
protected formatStatistic(value: number | null): string {
@@ -1078,16 +1072,4 @@ export class CalendarYear {
if (stage === 'dates') return 98;
return this.loadingProgress();
}
-
- private toLegacyBalances(plan: PlanOutcome): VacDay[] {
- return plan.remainingBalances.map((balance) => ({
- id: balance.id,
- type: balance.type as SelectableDayType,
- numberOfDays: balance.quantity,
- availableDate: new Date(`${balance.availableFrom}T00:00:00`),
- expiryDate: new Date(`${balance.expiryDate}T00:00:00`),
- classification: balance.classification,
- reason: balance.reason,
- }));
- }
}
diff --git a/src/app/services/calendar-service.ts b/src/app/services/calendar-service.ts
index b3a658f..abc85a4 100644
--- a/src/app/services/calendar-service.ts
+++ b/src/app/services/calendar-service.ts
@@ -10,9 +10,7 @@ import {
planLeave as planLeaveOperation,
LeaveType,
PlanOutcome,
- PlanningReason,
PlanningStateSnapshot,
- RemainingClassification,
} from './leave-planner.service';
import { addPlanningDays, addPlanningYears, planningDateInParis } from './planning-date';
@@ -255,8 +253,6 @@ export type VacDay = {
/** Legacy balances omit this value; the planner then uses the horizon start. */
availableDate?: Date;
expiryDate: Date;
- classification?: RemainingClassification;
- reason?: PlanningReason;
};
export type Week = (Date | null)[];
diff --git a/src/app/services/user-input-service.ts b/src/app/services/user-input-service.ts
index e0bdc67..0fcb093 100644
--- a/src/app/services/user-input-service.ts
+++ b/src/app/services/user-input-service.ts
@@ -161,7 +161,6 @@ export class UserInputService {
readonly vacationNumberSignal = signal(
this.getSavedValues() ?? this.getInitialValues(),
);
- readonly remainingVacationDaysSignal = signal([]);
readonly planningOutcomeSignal = signal(null);
readonly planningSnapshotSignal = signal(null);
readonly displayedPlanSignal = computed(() => {