diff --git a/backend/Dockerfile b/backend/Dockerfile index c41f409..b1d64fd 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -32,6 +32,9 @@ COPY --from=builder /app/dist ./dist RUN addgroup -g 1001 -S nodejs RUN adduser -S nestjs -u 1001 +# Créer le dossier uploads et donner les permissions +RUN mkdir -p /app/uploads/photos && chown -R nestjs:nodejs /app/uploads + USER nestjs EXPOSE 3000 diff --git a/backend/src/routes/enfants/dto/create_enfants.dto.ts b/backend/src/routes/enfants/dto/create_enfants.dto.ts index 7b55282..3ede09d 100644 --- a/backend/src/routes/enfants/dto/create_enfants.dto.ts +++ b/backend/src/routes/enfants/dto/create_enfants.dto.ts @@ -29,10 +29,10 @@ export class CreateEnfantsDto { @MaxLength(100) last_name?: string; - @ApiProperty({ enum: GenreType, required: false }) - @IsOptional() + @ApiProperty({ enum: GenreType }) @IsEnum(GenreType) - gender?: GenreType; + @IsNotEmpty() + gender: GenreType; @ApiProperty({ example: '2018-06-24', required: false }) @ValidateIf(o => o.status !== StatutEnfantType.A_NAITRE) diff --git a/backend/src/routes/enfants/enfants.controller.ts b/backend/src/routes/enfants/enfants.controller.ts index c76dcd5..e112972 100644 --- a/backend/src/routes/enfants/enfants.controller.ts +++ b/backend/src/routes/enfants/enfants.controller.ts @@ -8,8 +8,13 @@ import { Patch, Post, UseGuards, + UseInterceptors, + UploadedFile, } from '@nestjs/common'; -import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +import { FileInterceptor } from '@nestjs/platform-express'; +import { ApiBearerAuth, ApiTags, ApiConsumes } from '@nestjs/swagger'; +import { diskStorage } from 'multer'; +import { extname } from 'path'; import { EnfantsService } from './enfants.service'; import { CreateEnfantsDto } from './dto/create_enfants.dto'; import { UpdateEnfantsDto } from './dto/update_enfants.dto'; @@ -28,8 +33,34 @@ export class EnfantsController { @Roles(RoleType.PARENT) @Post() - create(@Body() dto: CreateEnfantsDto, @User() currentUser: Users) { - return this.enfantsService.create(dto, currentUser); + @ApiConsumes('multipart/form-data') + @UseInterceptors( + FileInterceptor('photo', { + storage: diskStorage({ + destination: './uploads/photos', + filename: (req, file, cb) => { + const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9); + const ext = extname(file.originalname); + cb(null, `enfant-${uniqueSuffix}${ext}`); + }, + }), + fileFilter: (req, file, cb) => { + if (!file.mimetype.match(/\/(jpg|jpeg|png|gif)$/)) { + return cb(new Error('Seules les images sont autorisées'), false); + } + cb(null, true); + }, + limits: { + fileSize: 5 * 1024 * 1024, + }, + }), + ) + create( + @Body() dto: CreateEnfantsDto, + @UploadedFile() photo: Express.Multer.File, + @User() currentUser: Users, + ) { + return this.enfantsService.create(dto, currentUser, photo); } @Roles(RoleType.ADMINISTRATEUR, RoleType.GESTIONNAIRE, RoleType.SUPER_ADMIN) diff --git a/backend/src/routes/enfants/enfants.service.ts b/backend/src/routes/enfants/enfants.service.ts index 952f2b1..bfefedb 100644 --- a/backend/src/routes/enfants/enfants.service.ts +++ b/backend/src/routes/enfants/enfants.service.ts @@ -24,10 +24,11 @@ export class EnfantsService { private readonly parentsChildrenRepository: Repository, ) { } - // Création d’un enfant - async create(dto: CreateEnfantsDto, currentUser: Users): Promise { + // Création d'un enfant + async create(dto: CreateEnfantsDto, currentUser: Users, photoFile?: Express.Multer.File): Promise { const parent = await this.parentsRepository.findOne({ where: { user_id: currentUser.id }, + relations: ['co_parent'], }); if (!parent) throw new NotFoundException('Parent introuvable'); @@ -46,17 +47,34 @@ export class EnfantsService { }); if (exist) throw new ConflictException('Cet enfant existe déjà'); + // Gestion de la photo uploadée + if (photoFile) { + dto.photo_url = `/uploads/photos/${photoFile.filename}`; + if (dto.consent_photo) { + dto.consent_photo_at = new Date().toISOString(); + } + } + // Création const child = this.childrenRepository.create(dto); await this.childrenRepository.save(child); - // Lien parent-enfant + // Lien parent-enfant (Parent 1) const parentLink = this.parentsChildrenRepository.create({ parentId: parent.user_id, enfantId: child.id, }); await this.parentsChildrenRepository.save(parentLink); + // Rattachement automatique au co-parent s'il existe + if (parent.co_parent) { + const coParentLink = this.parentsChildrenRepository.create({ + parentId: parent.co_parent.id, + enfantId: child.id, + }); + await this.parentsChildrenRepository.save(coParentLink); + } + return this.findOne(child.id, currentUser); }