Cas CP-019 : Configuration par pays : jours fériés + mise en cache + validation¶
Module
: plan de contrôle Tranche
: tranche 6b de l'architecture (dissociée de CP-006) Contexte de marque
: [LES DEUX] Papillon HR Suite + ALTARYS ENTERPRISE HR Suite Priorité
: 6 (après CP-006) Dépend de
: CP-006 Complexité estimée
: S
Objectif¶
Étendre le moteur de configuration par pays avec les jours fériés, les grilles salariales par secteur, la mise en cache Caffeine pour toutes les requêtes de configuration par pays et la validation des codes pays. Cette tranche ajoute les entités PublicHoliday et CountrySectorSalaryGrid, leurs endpoints, la mise en cache pour toutes les méthodes CountryConfigService (y compris celles de CP-006) et rejette les codes pays invalides.
Portée du backend¶
Entités et enregistrements¶
Entité PublicHoliday (base de données de la plateforme) :
| Field | Type | Constraints |
|---|---|---|
| id | UUID v7 | PK |
| country_code | String(2) | NOT NULL |
| year | int | NOT NULL |
| date | LocalDate | NOT NULL |
| name | String | NOT NULL |
Entity « CountrySectorSalaryGrid » (base de données de la plateforme) :
| Field | Type | Constraints |
|---|---|---|
| id | UUID v7 | PK |
| country_code | String(2) | NOT NULL |
| sector_code | String(10) | NOT NULL (COM, BTP, IND, SVC, AGR) |
| sector_name | String | NOT NULL |
| category_code | String(10) | NOT NULL |
| minimum_salary_monthly | BigDecimal | NOT NULL |
| effective_date | LocalDate | NOT NULL |
| Secteurs : Commerce (COM), BTP, Industrie (IND), Services (SVC), Agriculture (AGR) |
Couche de référentiel¶
PublicHolidayRepository.java— Portée : plateforme :findByCountryCodeAndYear(String, int) → List<PUBLICHOLIDAY>CountrySectorSalaryGridRepository.java— Portée plateforme :findByCountryCodeAndSectorCode(String, String) → List<CountrySectorSalaryGrid>
Couche de service¶
CountryConfigService.java (extension de CP-006) :
- getPublicHolidays(String countryCode, int year) → List<PublicHoliday> — NOUVELLE méthode
- getSalaryGrids(String countryCode, String sectorCode) → List<CountrySectorSalaryGrid> — NOUVELLE méthode
- Ajouter la mise en cache Caffeine à TOUTES les méthodes (TTL : 1 heure, invalidée lors de la mise à jour) :
- getTaxBrackets (de CP-006) — ajouter @Cacheable
- getSocialContributions (de CP-006) — ajouter @Cacheable
- getPublicHolidays — ajouter @Cacheable
- getSalaryGrids — ajouter @Cacheable
- Ajouter la validation du code pays : rejeter tout code ne figurant pas dans la liste prise en charge (MVP : uniquement « CI »). Renvoyer un code HTTP 400 avec le message « Code pays non pris en charge » (Code pays non pris en charge).
| Method | Path | Request Body | Response | Auth |
|---|---|---|---|---|
| GET | /api/v1/country-config/{countryCode}/holidays/{year} | — | List |
Any authenticated |
| GET | /api/v1/country-config/{countryCode}/salary-grids?sectorCode={s} | — | List |
Any authenticated |
| Endpoints CRUD d'administration (destinés à l'administrateur de la plateforme — utilisés par la console d'administration CP-012) : |
| Method | Path | Auth |
|---|---|---|
| PUT | /api/v1/admin/country-config/{countryCode}/holidays/{year} | PLATFORM_ADMIN |
Règles de validation¶
country_code: code ISO 3166-1 alpha-2 valide (MVP : seul « CI » est accepté). Codes non valides → HTTP 400.year: >= 2020, <= année en cours + 2sector_code: doit être l'un des codes suivants : COM, BTP, IND, SVC, AGR- Tous les champs monétaires : BigDecimal, >= 0, zéro décimale (XOF)
Considérations multi-tenant¶
- La configuration du pays se trouve dans la base de données de la plateforme — partagée entre tous les tenants
- NE S'APPLIQUE PAS au niveau du tenant (les mêmes jours fériés s'appliquent à tous les tenants de ce pays)
- Endpoints en lecture accessibles à tout utilisateur authentifié
- Endpoints en écriture réservés au rôle PLATFORM_ADMIN
- Le cache est partagé entre tous les tenants (les données de référence sont identiques)
Migration Flyway¶
V004__create_country_config_holidays_grids.sql— Base de données de la plateforme : tables PublicHoliday + CountrySectorSalaryGrid + jours fériés CI de référence 2026-2027 + espaces réservés pour les grilles salariales
Aucune interface utilisateur destinée aux tenants dans cette tranche. La configuration du pays est constituée de données de référence en lecture seule pour les tenants. La console d'administration (CP-012) fournit l'interface utilisateur de l'éditeur.
Pages et routes¶
Sans objet pour l'interface utilisateur des tenants. L'éditeur de la console d'administration se trouve dans CP-012.
États de l'interface utilisateur (TOUS OBLIGATOIRES)¶
N/A — Tranche réservée au backend pour le côté client. Interface utilisateur d'administration dans CP-012.
Comportement réactif¶
N/A
Interactions¶
N/A
Critères d'acceptation¶
AC-048: Get CI public holidays
Given CI holidays are seeded for 2026
When I call GET /api/v1/country-config/CI/holidays/2026
Then I receive all CI public holidays for 2026
AC-050: Country config caching
Given tax brackets have been fetched once
When the same request is made within 1 hour
Then the response is served from Caffeine cache (no DB query)
AC-051: Invalid country code rejected
Given country code "XX" does not exist
When I call GET /api/v1/country-config/XX/tax-brackets?fiscalYear=2026
Then I receive HTTP 400 with message "Country code not supported"
OHADA et règles réglementaires¶
- Jours fériés en Côte d'Ivoire : jours fériés fixes (Fête du Travail, Fête de l'Indépendance, etc.) et fêtes islamiques variables. La liste des jours fériés doit pouvoir être mise à jour chaque année sans redéploiement.
- Grilles salariales sectorielles : la CCI définit les salaires minimums par catégorie et par secteur. Des valeurs par défaut sont fournies ; les valeurs définitives doivent être fournies avant le traitement de la paie.
- BigDecimal UNIQUEMENT : toutes les valeurs monétaires utilisent BigDecimal. Jamais pas de double/float pour les données financières.
Normes et conventions¶
docs/standards/java-Spring-guidelines.md— §Entités, §Mise en cache Caffeine, §BigDecimal pour les données financièresdocs/standards/database-guidelines.md— §Données de référence de la base de données de la plateforme, §Données de départ dans les migrationsdocs/standards/api-guidelines.md— §Endpoints de référence en lecture seule, §Endpoints d'écriture réservés à l'administration- CountryConfigService : recherche des jours fériés par pays + année
- CountryConfigService : recherche des grilles salariales par pays + secteur
- CountryConfigService : cache (hit/miss/invalidation) (les 4 méthodes)
- Validation : rejet des codes pays invalides
Tests d'intégration¶
- Endpoints GET pour les jours fériés et les grilles salariales
- Vérification des données d'amorçage : les jours fériés CI correspondent aux valeurs attendues
- Invalidation du cache lors d'une mise à jour par l'administrateur
- Code pays « XX » → 400 (sur tous les endpoints, y compris les tranches d'imposition et les cotisations sociales de CP-006)
- Autorisation : l'utilisateur du tenant peut lire, mais ne peut pas écrire (403)
Ce que l'assurance qualité va valider¶
- N/A pour l'interface utilisateur du tenant (backend uniquement pour les tenants)
- La console d'administration (CP-012) validera l'interface utilisateur de l'éditeur
Hors du périmètre¶
- Interface utilisateur de l'éditeur de la console d'administration — CP-012
- Pays autres que CI — Post-MVP (l'architecture prend en charge plusieurs pays dès le premier jour)
- API d'importation automatique des jours fériés — Backlog OQ-CP-06
- Plan comptable SYSCOHADA — Pré-remplissage lors de la migration, le module comptable complet l'utilise ultérieurement
- Données de référence sur les types de congés — Pré-remplies ici, détaillées dans le PRD de gestion des absences
Définition de « Terminé »¶
- [ ] Tous les endpoints backend sont implémentés et renvoient des réponses correctes
- [ ] Toutes les pages frontend s'affichent correctement à 360px, 768px, 1024px — N/A
- [ ] Les 5 états de l'interface utilisateur sont tous implémentés — N/A (back-end uniquement pour le côté locataire)
- [ ] Les micro-textes en français correspondent exactement aux spécifications de conception — N/A
- [ ] Tous les critères d'acceptation sont satisfaits manuellement
- [ ] Les tests unitaires sont écrits et réussis
- [ ] Les tests d'intégration sont écrits et réussis
- [ ] L'isolation multi-tenant est vérifiée — N/A (les données de référence sont partagées)
- [ ] L'écriture et la synchronisation hors ligne fonctionnent — N/A
- [ ] Pas de
anyen TypeScript — N/A - [ ] Pas de types bruts en Java — tous les génériques sont explicites
- [ ] Les réponses API respectent le format d'enveloppe standard
- [ ] Entrées de piste d'audit créées pour chaque mutation de données — Les mises à jour de configuration par l'administrateur génèrent des entrées d'audit