feat: pending-families ajoute parents[] (email/tel/ville/cp) + ordre stable
Made-with: Cursor
This commit is contained in:
parent
cc3639b19a
commit
0e6e473e84
@ -42,14 +42,12 @@ export class DossiersService {
|
|||||||
relations: ['user'],
|
relations: ['user'],
|
||||||
});
|
});
|
||||||
if (am?.user) {
|
if (am?.user) {
|
||||||
const bio = am.biography;
|
|
||||||
const dossier: DossierAmCompletDto = {
|
const dossier: DossierAmCompletDto = {
|
||||||
numero_dossier: num,
|
numero_dossier: num,
|
||||||
user: this.toDossierAmUserDto(am.user),
|
user: this.toDossierAmUserDto(am.user),
|
||||||
numero_agrement: am.approval_number,
|
numero_agrement: am.approval_number,
|
||||||
nir: am.nir,
|
nir: am.nir,
|
||||||
texte_motivation: bio,
|
biographie: am.biography,
|
||||||
biographie: bio,
|
|
||||||
disponible: am.available,
|
disponible: am.available,
|
||||||
ville_residence: am.residence_city,
|
ville_residence: am.residence_city,
|
||||||
date_agrement: am.agreement_date,
|
date_agrement: am.agreement_date,
|
||||||
|
|||||||
@ -39,9 +39,6 @@ export class DossierAmCompletDto {
|
|||||||
numero_agrement?: string;
|
numero_agrement?: string;
|
||||||
@ApiProperty({ required: false })
|
@ApiProperty({ required: false })
|
||||||
nir?: string;
|
nir?: string;
|
||||||
/** Même contenu que biographie — alias pour aligner le front avec le dossier famille (texte_motivation). */
|
|
||||||
@ApiProperty({ required: false, description: 'Texte de présentation / motivation (alias biographie)' })
|
|
||||||
texte_motivation?: string;
|
|
||||||
@ApiProperty({ required: false })
|
@ApiProperty({ required: false })
|
||||||
biographie?: string;
|
biographie?: string;
|
||||||
@ApiProperty({ required: false })
|
@ApiProperty({ required: false })
|
||||||
|
|||||||
@ -1,5 +1,22 @@
|
|||||||
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||||
|
|
||||||
|
export class ParentPendingSummaryDto {
|
||||||
|
@ApiProperty({ description: 'UUID utilisateur' })
|
||||||
|
id: string;
|
||||||
|
|
||||||
|
@ApiProperty()
|
||||||
|
email: string;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ nullable: true })
|
||||||
|
telephone?: string | null;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ nullable: true })
|
||||||
|
code_postal?: string | null;
|
||||||
|
|
||||||
|
@ApiPropertyOptional({ nullable: true })
|
||||||
|
ville?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
export class PendingFamilyDto {
|
export class PendingFamilyDto {
|
||||||
@ApiProperty({ example: 'Famille Dupont', description: 'Libellé affiché pour la famille' })
|
@ApiProperty({ example: 'Famille Dupont', description: 'Libellé affiché pour la famille' })
|
||||||
libelle: string;
|
libelle: string;
|
||||||
@ -37,4 +54,10 @@ export class PendingFamilyDto {
|
|||||||
description: 'Emails des parents du groupe (ordre stable : nom, prénom)',
|
description: 'Emails des parents du groupe (ordre stable : nom, prénom)',
|
||||||
})
|
})
|
||||||
emails?: string[];
|
emails?: string[];
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
type: [ParentPendingSummaryDto],
|
||||||
|
description: 'Résumé des parents (ordre stable, aligné sur parentIds/emails)',
|
||||||
|
})
|
||||||
|
parents?: ParentPendingSummaryDto[];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -94,6 +94,7 @@ export class ParentsService {
|
|||||||
date_soumission: Date | string | null;
|
date_soumission: Date | string | null;
|
||||||
nombre_enfants: string | number | null;
|
nombre_enfants: string | number | null;
|
||||||
emails: unknown;
|
emails: unknown;
|
||||||
|
parents: unknown;
|
||||||
}[];
|
}[];
|
||||||
try {
|
try {
|
||||||
raw = await this.parentsRepository.query(`
|
raw = await this.parentsRepository.query(`
|
||||||
@ -121,7 +122,7 @@ export class ParentsService {
|
|||||||
)
|
)
|
||||||
SELECT
|
SELECT
|
||||||
'Famille ' || string_agg(u.nom, ' - ' ORDER BY u.nom, u.prenom) AS libelle,
|
'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.id_utilisateur ORDER BY u.nom, u.prenom, u.id) AS "parentIds",
|
||||||
(array_agg(p.numero_dossier))[1] AS numero_dossier,
|
(array_agg(p.numero_dossier))[1] AS numero_dossier,
|
||||||
MIN(u.cree_le) AS date_soumission,
|
MIN(u.cree_le) AS date_soumission,
|
||||||
COALESCE((
|
COALESCE((
|
||||||
@ -131,7 +132,17 @@ export class ParentsService {
|
|||||||
SELECT frx.id FROM family_rep frx WHERE frx.rep = fr.rep
|
SELECT frx.id FROM family_rep frx WHERE frx.rep = fr.rep
|
||||||
)
|
)
|
||||||
), 0) AS nombre_enfants,
|
), 0) AS nombre_enfants,
|
||||||
array_agg(u.email ORDER BY u.nom, u.prenom) AS emails
|
array_agg(u.email ORDER BY u.nom, u.prenom, u.id) AS emails,
|
||||||
|
json_agg(
|
||||||
|
json_build_object(
|
||||||
|
'id', u.id::text,
|
||||||
|
'email', u.email,
|
||||||
|
'telephone', u.telephone,
|
||||||
|
'code_postal', u.code_postal,
|
||||||
|
'ville', u.ville
|
||||||
|
)
|
||||||
|
ORDER BY u.nom, u.prenom, u.id
|
||||||
|
) AS parents
|
||||||
FROM family_rep fr
|
FROM family_rep fr
|
||||||
JOIN parents p ON p.id_utilisateur = fr.id
|
JOIN parents p ON p.id_utilisateur = fr.id
|
||||||
JOIN utilisateurs u ON u.id = p.id_utilisateur
|
JOIN utilisateurs u ON u.id = p.id_utilisateur
|
||||||
@ -150,6 +161,7 @@ export class ParentsService {
|
|||||||
date_soumission: this.toIsoDateTimeOrNull(r.date_soumission),
|
date_soumission: this.toIsoDateTimeOrNull(r.date_soumission),
|
||||||
nombre_enfants: this.normalizeNombreEnfants(r.nombre_enfants),
|
nombre_enfants: this.normalizeNombreEnfants(r.nombre_enfants),
|
||||||
emails: this.normalizeEmails(r.emails),
|
emails: this.normalizeEmails(r.emails),
|
||||||
|
parents: this.normalizeParents(r.parents),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,6 +187,27 @@ export class ParentsService {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private normalizeParents(parents: unknown): { id: string; email: string; telephone: string | null; code_postal: string | null; ville: string | null }[] {
|
||||||
|
if (Array.isArray(parents)) {
|
||||||
|
return parents.map((p: any) => ({
|
||||||
|
id: String(p?.id ?? ''),
|
||||||
|
email: String(p?.email ?? ''),
|
||||||
|
telephone: p?.telephone != null ? String(p.telephone) : null,
|
||||||
|
code_postal: p?.code_postal != null ? String(p.code_postal) : null,
|
||||||
|
ville: p?.ville != null ? String(p.ville) : null,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
if (typeof parents === 'string') {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(parents);
|
||||||
|
return this.normalizeParents(parsed);
|
||||||
|
} catch {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
/** Convertit parentIds (array ou chaîne PG) en string[] pour éviter 500 si le driver renvoie une chaîne. */
|
/** Convertit parentIds (array ou chaîne PG) en string[] pour éviter 500 si le driver renvoie une chaîne. */
|
||||||
private normalizeParentIds(parentIds: unknown): string[] {
|
private normalizeParentIds(parentIds: unknown): string[] {
|
||||||
if (Array.isArray(parentIds)) return parentIds.map(String);
|
if (Array.isArray(parentIds)) return parentIds.map(String);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user