feat(#119): GET /parents/dossier-famille/:numeroDossier - dossier famille complet (admin/gestionnaire)
Made-with: Cursor
This commit is contained in:
parent
5390276ecd
commit
f6fabc521e
@ -0,0 +1,70 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { StatutUtilisateurType } from 'src/entities/users.entity';
|
||||
import { StatutDossierType } from 'src/entities/dossiers.entity';
|
||||
import { StatutEnfantType } from 'src/entities/children.entity';
|
||||
|
||||
/** Parent dans le dossier famille (infos utilisateur + parent) */
|
||||
export class DossierFamilleParentDto {
|
||||
@ApiProperty()
|
||||
user_id: string;
|
||||
@ApiProperty()
|
||||
email: string;
|
||||
@ApiProperty({ required: false })
|
||||
prenom?: string;
|
||||
@ApiProperty({ required: false })
|
||||
nom?: string;
|
||||
@ApiProperty({ required: false })
|
||||
telephone?: string;
|
||||
@ApiProperty({ enum: StatutUtilisateurType })
|
||||
statut: StatutUtilisateurType;
|
||||
@ApiProperty({ required: false, description: 'Id du co-parent si couple' })
|
||||
co_parent_id?: string;
|
||||
}
|
||||
|
||||
/** Enfant dans le dossier famille */
|
||||
export class DossierFamilleEnfantDto {
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
@ApiProperty({ required: false })
|
||||
first_name?: string;
|
||||
@ApiProperty({ required: false })
|
||||
last_name?: string;
|
||||
@ApiProperty({ required: false })
|
||||
birth_date?: Date;
|
||||
@ApiProperty({ required: false })
|
||||
due_date?: Date;
|
||||
@ApiProperty({ enum: StatutEnfantType })
|
||||
status: StatutEnfantType;
|
||||
}
|
||||
|
||||
/** Dossier (parent+enfant) avec presentation */
|
||||
export class DossierFamillePresentationDto {
|
||||
@ApiProperty()
|
||||
id: string;
|
||||
@ApiProperty()
|
||||
id_parent: string;
|
||||
@ApiProperty()
|
||||
id_enfant: string;
|
||||
@ApiProperty({ required: false, description: 'Texte de présentation' })
|
||||
presentation?: string;
|
||||
@ApiProperty({ required: false })
|
||||
type_contrat?: string;
|
||||
@ApiProperty()
|
||||
repas: boolean;
|
||||
@ApiProperty({ required: false })
|
||||
budget?: number;
|
||||
@ApiProperty({ enum: StatutDossierType })
|
||||
statut: StatutDossierType;
|
||||
}
|
||||
|
||||
/** Réponse GET /parents/dossier-famille/:numeroDossier – dossier famille complet. Ticket #119 */
|
||||
export class DossierFamilleCompletDto {
|
||||
@ApiProperty({ example: '2026-000001', description: 'Numéro de dossier famille' })
|
||||
numero_dossier: string;
|
||||
@ApiProperty({ type: [DossierFamilleParentDto] })
|
||||
parents: DossierFamilleParentDto[];
|
||||
@ApiProperty({ type: [DossierFamilleEnfantDto], description: 'Enfants de la famille' })
|
||||
enfants: DossierFamilleEnfantDto[];
|
||||
@ApiProperty({ type: [DossierFamillePresentationDto], description: 'Dossiers (présentation par parent/enfant)' })
|
||||
presentation: DossierFamillePresentationDto[];
|
||||
}
|
||||
@ -20,6 +20,7 @@ import { AuthGuard } from 'src/common/guards/auth.guard';
|
||||
import { RolesGuard } from 'src/common/guards/roles.guard';
|
||||
import { User } from 'src/common/decorators/user.decorator';
|
||||
import { PendingFamilyDto } from './dto/pending-family.dto';
|
||||
import { DossierFamilleCompletDto } from './dto/dossier-famille-complet.dto';
|
||||
|
||||
@ApiTags('Parents')
|
||||
@Controller('parents')
|
||||
@ -39,6 +40,17 @@ export class ParentsController {
|
||||
return this.parentsService.getPendingFamilies();
|
||||
}
|
||||
|
||||
@Get('dossier-famille/:numeroDossier')
|
||||
@Roles(RoleType.SUPER_ADMIN, RoleType.ADMINISTRATEUR, RoleType.GESTIONNAIRE)
|
||||
@ApiOperation({ summary: 'Dossier famille complet par numéro de dossier (Ticket #119)' })
|
||||
@ApiParam({ name: 'numeroDossier', description: 'Numéro de dossier (ex: 2026-000001)' })
|
||||
@ApiResponse({ status: 200, description: 'Dossier famille (numero_dossier, parents, enfants, presentation)', type: DossierFamilleCompletDto })
|
||||
@ApiResponse({ status: 404, description: 'Aucun dossier pour ce numéro' })
|
||||
@ApiResponse({ status: 403, description: 'Accès refusé' })
|
||||
getDossierFamille(@Param('numeroDossier') numeroDossier: string): Promise<DossierFamilleCompletDto> {
|
||||
return this.parentsService.getDossierFamilleByNumero(numeroDossier);
|
||||
}
|
||||
|
||||
@Post(':parentId/valider-dossier')
|
||||
@Roles(RoleType.SUPER_ADMIN, RoleType.ADMINISTRATEUR, RoleType.GESTIONNAIRE)
|
||||
@ApiOperation({ summary: 'Valider tout le dossier famille (les 2 parents en une fois)' })
|
||||
|
||||
@ -5,12 +5,18 @@ import {
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { In, Repository } from 'typeorm';
|
||||
import { Parents } from 'src/entities/parents.entity';
|
||||
import { RoleType, Users } from 'src/entities/users.entity';
|
||||
import { CreateParentDto } from '../user/dto/create_parent.dto';
|
||||
import { UpdateParentsDto } from '../user/dto/update_parent.dto';
|
||||
import { PendingFamilyDto } from './dto/pending-family.dto';
|
||||
import {
|
||||
DossierFamilleCompletDto,
|
||||
DossierFamilleParentDto,
|
||||
DossierFamilleEnfantDto,
|
||||
DossierFamillePresentationDto,
|
||||
} from './dto/dossier-famille-complet.dto';
|
||||
|
||||
@Injectable()
|
||||
export class ParentsService {
|
||||
@ -136,6 +142,79 @@ export class ParentsService {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Dossier famille complet par numéro de dossier. Ticket #119.
|
||||
* Rôles : admin, gestionnaire.
|
||||
* @throws NotFoundException si aucun parent avec ce numéro de dossier
|
||||
*/
|
||||
async getDossierFamilleByNumero(numeroDossier: string): Promise<DossierFamilleCompletDto> {
|
||||
const num = numeroDossier?.trim();
|
||||
if (!num) {
|
||||
throw new NotFoundException('Numéro de dossier requis.');
|
||||
}
|
||||
const firstParent = await this.parentsRepository.findOne({
|
||||
where: { numero_dossier: num },
|
||||
relations: ['user'],
|
||||
});
|
||||
if (!firstParent || !firstParent.user) {
|
||||
throw new NotFoundException('Aucun dossier famille trouvé pour ce numéro.');
|
||||
}
|
||||
const familyUserIds = await this.getFamilyUserIds(firstParent.user_id);
|
||||
const parents = await this.parentsRepository.find({
|
||||
where: { user_id: In(familyUserIds) },
|
||||
relations: ['user', 'co_parent', 'parentChildren', 'parentChildren.child', 'dossiers', 'dossiers.child'],
|
||||
});
|
||||
const enfantsMap = new Map<string, DossierFamilleEnfantDto>();
|
||||
const presentationList: DossierFamillePresentationDto[] = [];
|
||||
for (const p of parents) {
|
||||
// Enfants via parentChildren
|
||||
if (p.parentChildren) {
|
||||
for (const pc of p.parentChildren) {
|
||||
if (pc.child && !enfantsMap.has(pc.child.id)) {
|
||||
enfantsMap.set(pc.child.id, {
|
||||
id: pc.child.id,
|
||||
first_name: pc.child.first_name,
|
||||
last_name: pc.child.last_name,
|
||||
birth_date: pc.child.birth_date,
|
||||
due_date: pc.child.due_date,
|
||||
status: pc.child.status,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
// Dossiers (présentation)
|
||||
if (p.dossiers) {
|
||||
for (const d of p.dossiers) {
|
||||
presentationList.push({
|
||||
id: d.id,
|
||||
id_parent: p.user_id,
|
||||
id_enfant: d.child?.id ?? '',
|
||||
presentation: d.presentation,
|
||||
type_contrat: d.type_contrat,
|
||||
repas: d.meals,
|
||||
budget: d.budget != null ? Number(d.budget) : undefined,
|
||||
statut: d.status,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
const parentsDto: DossierFamilleParentDto[] = parents.map((p) => ({
|
||||
user_id: p.user_id,
|
||||
email: p.user.email,
|
||||
prenom: p.user.prenom,
|
||||
nom: p.user.nom,
|
||||
telephone: p.user.telephone,
|
||||
statut: p.user.statut,
|
||||
co_parent_id: p.co_parent?.id,
|
||||
}));
|
||||
return {
|
||||
numero_dossier: num,
|
||||
parents: parentsDto,
|
||||
enfants: Array.from(enfantsMap.values()),
|
||||
presentation: presentationList,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les user_id de tous les parents de la même famille (co_parent ou enfants partagés).
|
||||
* @throws NotFoundException si parentId n'est pas un parent
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user