feat(admin): onglet À valider, dossier unifié et modales de validation
- Onglet « À valider » (AM + familles), pending-families et détail dossier par numéro. - Wizards validation AM et famille, modale commune, chargement via GET /dossiers/:num. - UI : cartes enfants, photo AM (cadre uniforme, ratio), NIR affiché formaté (espaces autour du tiret). - Backend : DTO / routes parents pending ; scripts de test et mise à jour issue Gitea. Tickets #107, #119. Made-with: Cursor
This commit is contained in:
@@ -17,4 +17,22 @@ export class PendingFamilyDto {
|
||||
description: 'Numéro de dossier famille (format AAAA-NNNNNN)',
|
||||
})
|
||||
numero_dossier: string | null;
|
||||
|
||||
@ApiProperty({ nullable: true, example: 'parent@mail.fr', description: 'Email du premier parent (ordre nom/prénom)' })
|
||||
email: string | null;
|
||||
|
||||
@ApiProperty({ nullable: true, description: 'Date de création du compte la plus ancienne (famille)' })
|
||||
cree_le: Date | string | null;
|
||||
|
||||
@ApiProperty({ nullable: true, example: '0612345678' })
|
||||
telephone: string | null;
|
||||
|
||||
@ApiProperty({ nullable: true, example: '75001' })
|
||||
code_postal: string | null;
|
||||
|
||||
@ApiProperty({ nullable: true, example: 'Paris' })
|
||||
ville: string | null;
|
||||
|
||||
@ApiProperty({ example: 2, description: 'Nombre d’enfants liés à la famille' })
|
||||
nombre_enfants: number;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,12 @@ export class ParentsController {
|
||||
@Get('pending-families')
|
||||
@Roles(RoleType.SUPER_ADMIN, RoleType.ADMINISTRATEUR, RoleType.GESTIONNAIRE)
|
||||
@ApiOperation({ summary: 'Liste des familles en attente (une entrée par famille)' })
|
||||
@ApiResponse({ status: 200, description: 'Liste des familles (libellé, parentIds, numero_dossier)', type: [PendingFamilyDto] })
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description:
|
||||
'Liste des familles (libellé, parentIds, numero_dossier, email, cree_le, téléphone, CP, ville, nombre_enfants)',
|
||||
type: [PendingFamilyDto],
|
||||
})
|
||||
@ApiResponse({ status: 403, description: 'Accès refusé' })
|
||||
getPendingFamilies(): Promise<PendingFamilyDto[]> {
|
||||
return this.parentsService.getPendingFamilies();
|
||||
|
||||
@@ -105,7 +105,17 @@ export class ParentsService {
|
||||
SELECT
|
||||
'Famille ' || string_agg(u.nom, ' - ' ORDER BY u.nom, u.prenom) AS libelle,
|
||||
array_agg(DISTINCT p.id_utilisateur ORDER BY p.id_utilisateur) AS "parentIds",
|
||||
(array_agg(p.numero_dossier))[1] AS numero_dossier
|
||||
(array_agg(p.numero_dossier))[1] AS numero_dossier,
|
||||
(array_agg(u.email ORDER BY u.nom, u.prenom))[1] AS email,
|
||||
MIN(u.cree_le) AS cree_le,
|
||||
(array_agg(u.telephone ORDER BY u.nom, u.prenom))[1] AS telephone,
|
||||
(array_agg(u.code_postal ORDER BY u.nom, u.prenom))[1] AS code_postal,
|
||||
(array_agg(u.ville ORDER BY u.nom, u.prenom))[1] AS ville,
|
||||
(
|
||||
SELECT COUNT(DISTINCT ep.id_enfant)::int
|
||||
FROM enfants_parents ep
|
||||
WHERE ep.id_parent IN (SELECT fr2.id FROM family_rep fr2 WHERE fr2.rep = fr.rep)
|
||||
) AS nombre_enfants
|
||||
FROM family_rep fr
|
||||
JOIN parents p ON p.id_utilisateur = fr.id
|
||||
JOIN utilisateurs u ON u.id = p.id_utilisateur
|
||||
@@ -113,11 +123,30 @@ export class ParentsService {
|
||||
GROUP BY fr.rep
|
||||
ORDER BY libelle
|
||||
`);
|
||||
return raw.map((r: { libelle: string; parentIds: unknown; numero_dossier: string | null }) => ({
|
||||
libelle: r.libelle,
|
||||
parentIds: Array.isArray(r.parentIds) ? r.parentIds.map(String) : [],
|
||||
numero_dossier: r.numero_dossier ?? null,
|
||||
}));
|
||||
return raw.map(
|
||||
(r: {
|
||||
libelle: string;
|
||||
parentIds: unknown;
|
||||
numero_dossier: string | null;
|
||||
email: string | null;
|
||||
cree_le: Date | string | null;
|
||||
telephone: string | null;
|
||||
code_postal: string | null;
|
||||
ville: string | null;
|
||||
nombre_enfants: string | number | null;
|
||||
}) => ({
|
||||
libelle: r.libelle,
|
||||
parentIds: Array.isArray(r.parentIds) ? r.parentIds.map(String) : [],
|
||||
numero_dossier: r.numero_dossier ?? null,
|
||||
email: r.email ?? null,
|
||||
cree_le: r.cree_le ?? null,
|
||||
telephone: r.telephone ?? null,
|
||||
code_postal: r.code_postal ?? null,
|
||||
ville: r.ville ?? null,
|
||||
nombre_enfants:
|
||||
r.nombre_enfants == null ? 0 : Number(r.nombre_enfants),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user