Explorar o código

(feat) des driver et des vehicules dans la reponse api

Brin AMONKONAN hai 1 ano
pai
achega
fe49c3dfdb

+ 4 - 0
node_app/src/app.module.ts

@@ -36,6 +36,8 @@ import { AuthController } from './presentation/controllers/auth.controller';
 import { AuthService } from './infrastructure/services/auth.service';
 import { APP_GUARD } from '@nestjs/core';
 import { AuthGuard } from './presentation/guards/auth.guard';
+import { FindUniqueCompanyByManagerUseCase } from './application/use-cases/company/find-unique-company-by-manager.use-case';
+import { FindCompanyByIdUseCase } from './application/use-cases/company/find-company-by-id.use-case';
 
 @Module({
   imports: [
@@ -79,6 +81,8 @@ import { AuthGuard } from './presentation/guards/auth.guard';
     // Company related providers
     CreateCompanyUseCase,
     FindAllCompaniesUseCase,
+    FindUniqueCompanyByManagerUseCase,
+    FindCompanyByIdUseCase,
     UpdateCompanyUseCase,
     CompanyMapper,
     {

+ 5 - 1
node_app/src/application/interfaces/i-auth.service.ts

@@ -1,5 +1,9 @@
 export interface IAuthService {
   validateUser(email: string, password: string): Promise<any>;
-  generateToken(user: any): Promise<string>;
+  generateToken(
+    user: any,
+    companyId?: number,
+    driverId?: number,
+  ): Promise<string>;
   verifyToken(token: string): Promise<any>;
 }

+ 15 - 0
node_app/src/application/use-cases/company/find-company-by-id.use-case.ts

@@ -0,0 +1,15 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { CompanyRepository } from '../../../infrastructure/database/repositories/company.repository';
+import { Company } from '../../../domain/entities/company.entity';
+
+@Injectable()
+export class FindCompanyByIdUseCase {
+  constructor(
+    @Inject('CompanyRepository')
+    private readonly companyRepository: CompanyRepository,
+  ) {}
+
+  async execute(id: number): Promise<Company | null> {
+    return this.companyRepository.findById(id);
+  }
+}

+ 21 - 0
node_app/src/application/use-cases/company/find-unique-company-by-manager.use-case.ts

@@ -0,0 +1,21 @@
+import { Injectable, Inject } from '@nestjs/common';
+import { CompanyRepository } from '../../../infrastructure/database/repositories/company.repository';
+import { Company } from '../../../domain/entities/company.entity';
+
+@Injectable()
+export class FindUniqueCompanyByManagerUseCase {
+  constructor(
+    @Inject('CompanyRepository')
+    private readonly companyRepository: CompanyRepository,
+  ) {}
+
+  async execute(managerId: number): Promise<Company | null> {
+    const company = await this.companyRepository.findByManagerId(managerId);
+
+    if (!company) {
+      return null;
+    }
+    console.log(company);
+    return company;
+  }
+}

+ 12 - 0
node_app/src/infrastructure/database/repositories/company.repository.ts

@@ -51,6 +51,18 @@ export class CompanyRepository implements IBaseRepository<Company> {
     return prismaCompany ? this.companyMapper.toDomain(prismaCompany) : null;
   }
 
+  async findByManagerId(userId: number): Promise<Company | null> {
+    const prismaCompany = await this.prisma.company.findUnique({
+      where: { managerId: userId },
+      include: {
+        vehicules: true,
+        drivers: true,
+        manager: true,
+      },
+    });
+    return prismaCompany ? this.companyMapper.toDomain(prismaCompany) : null;
+  }
+
   async findAll(): Promise<Company[]> {
     const companies = await this.prisma.company.findMany({
       include: {

+ 8 - 1
node_app/src/infrastructure/mappers/company.mapper.ts

@@ -5,11 +5,18 @@ import { Company as PrismaCompany } from '@prisma/client';
 import { Company } from 'src/domain/entities/company.entity';
 
 export class CompanyMapper implements IPrismaMapper<PrismaCompany, Company> {
-  toDomain(prismaCompany: Partial<PrismaCompany>): Company {
+  toDomain(
+    prismaCompany: Partial<PrismaCompany> & {
+      drivers?: any[];
+      vehicules?: any[];
+    },
+  ): Company {
     return new Company({
       id: prismaCompany.id,
       name: prismaCompany.name,
       address: prismaCompany.address,
+      drivers: prismaCompany.drivers ?? [],
+      vehicules: prismaCompany.vehicules ?? [],
     });
   }
   toPrisma(company: Company): PrismaCompany {

+ 12 - 2
node_app/src/infrastructure/services/auth.service.ts

@@ -24,9 +24,19 @@ export class AuthService implements IAuthService {
     return null;
   }
 
-  async generateToken(user: User): Promise<string> {
+  async generateToken(
+    user: User,
+    companyId?: number,
+    driverId?: number,
+  ): Promise<string> {
     return new Promise<string>((resolve) => {
-      const payload = { email: user.email, sub: user.id, userRole: user.role };
+      const payload = {
+        email: user.email,
+        sub: user.id,
+        userRole: user.role,
+        companyId: companyId,
+        driverId: driverId,
+      };
       const token = this.jwtService.sign(payload);
       resolve(token);
     });

+ 9 - 11
node_app/src/presentation/controllers/auth.controller.ts

@@ -21,6 +21,7 @@ import { UserResponseDto } from '../../application/dto/responses/user-response.d
 import { User } from 'src/domain/entities/user.entity';
 import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
 import { Public } from '../decorators/public.decorator';
+import { FindUniqueCompanyByManagerUseCase } from 'src/application/use-cases/company/find-unique-company-by-manager.use-case';
 
 export class LoginDto {
   @ApiProperty({
@@ -38,15 +39,6 @@ export class LoginDto {
   @IsString({ message: 'Le mot de passe doit être une chaîne de caractères' })
   @IsNotEmpty({ message: 'Le mot de passe est requis' })
   password: string;
-
-  // @ApiProperty({
-  //   example: 'USER',
-  //   description:
-  //     "Rôle de l'utilisateur (USER, ADMIN, DRIVER, MANAGER, EMPLOYEE)",
-  // })
-  // @IsString({ message: 'Le rôle doit être une chaîne de caractères' })
-  // @IsNotEmpty({ message: 'Le rôle est requis' })
-  // userRole: string;
 }
 
 @ApiTags('Authentification')
@@ -55,6 +47,7 @@ export class AuthController {
   constructor(
     @Inject('IAuthService')
     private readonly authService: IAuthService,
+    private readonly findUniqueCompanyByUser: FindUniqueCompanyByManagerUseCase, // Inject the company service
   ) {}
 
   @Post('login')
@@ -73,8 +66,8 @@ export class AuthController {
     if (!user) {
       throw new UnauthorizedException('Identifiants invalides');
     }
-
-    const token = await this.authService.generateToken(user);
+    const companyId = await this.getCompanyId(user.id);
+    const token = await this.authService.generateToken(user, companyId);
 
     // Retourner les informations de l'utilisateur sans le mot de passe
     const userResponse = UserResponseDto.fromEntity(user);
@@ -85,6 +78,11 @@ export class AuthController {
     };
   }
 
+  async getCompanyId(userId: number): Promise<number | undefined> {
+    const company = await this.findUniqueCompanyByUser.execute(userId);
+    return company?.id;
+  }
+
   @Post('logout')
   @UseGuards(AuthGuard)
   @HttpCode(HttpStatus.OK)

+ 52 - 1
node_app/src/presentation/controllers/company.controller.ts

@@ -20,6 +20,11 @@ import { UpdateCompanyDto } from '../../application/dto/update-company.dto';
 import { FindAllCompaniesUseCase } from '../../application/use-cases/company/find-all-companies.use-case';
 import { CompanyResponseDto } from 'src/application/dto/responses/company-response.dto';
 import { CreateCompanyUseCase } from '../../application/use-cases/company/create-company.use-case';
+import { Roles } from '../decorators/roles.decorator';
+import { UserRole } from 'src/domain/entities/user.entity';
+import { FindCompanyByIdUseCase } from '../../application/use-cases/company/find-company-by-id.use-case';
+import { NotFoundException } from '@nestjs/common';
+import { FindUniqueCompanyByManagerUseCase } from 'src/application/use-cases/company/find-unique-company-by-manager.use-case';
 
 @ApiTags('companies')
 @Controller('companies')
@@ -28,6 +33,8 @@ export class CompanyController {
   constructor(
     private readonly findAllCompaniesUseCase: FindAllCompaniesUseCase,
     private readonly createCompanyUseCase: CreateCompanyUseCase,
+    private readonly findCompanyByIdUseCase: FindCompanyByIdUseCase,
+    private readonly findCompanyByManager: FindUniqueCompanyByManagerUseCase,
   ) {}
 
   @Post()
@@ -47,6 +54,7 @@ export class CompanyController {
   }
 
   @Get()
+  @Roles(UserRole.ADMIN)
   @ApiOperation({ summary: 'Récupérer toutes les entreprises' })
   @ApiResponse({
     status: 200,
@@ -58,6 +66,7 @@ export class CompanyController {
   }
 
   @Get(':id')
+  @Roles(UserRole.ADMIN, UserRole.MANAGER, UserRole.USER)
   @ApiOperation({ summary: 'Récupérer une entreprise par son ID' })
   @ApiParam({ name: 'id', description: "ID de l'entreprise" })
   @ApiResponse({
@@ -67,7 +76,49 @@ export class CompanyController {
   })
   @ApiResponse({ status: 404, description: 'Entreprise non trouvée' })
   async findOne(@Param('id') id: string) {
-    // TODO: Implement get company by id use case
+    try {
+      const company = await this.findCompanyByIdUseCase.execute(
+        parseInt(id, 10),
+      );
+
+      if (!company) {
+        throw new NotFoundException(`Entreprise avec l'ID ${id} non trouvée`);
+      }
+
+      return company;
+    } catch (error) {
+      if (error instanceof NotFoundException) {
+        throw error;
+      }
+      throw new NotFoundException(`Entreprise avec l'ID ${id} non trouvée`);
+    }
+  }
+
+  @Get('/manager/:id')
+  @Roles(UserRole.ADMIN, UserRole.MANAGER, UserRole.USER)
+  @ApiOperation({ summary: 'Récupérer une entreprise par son ID' })
+  @ApiParam({ name: 'id', description: 'ID de du manager' })
+  @ApiResponse({
+    status: 200,
+    description: "L'entreprise a été trouvée",
+    type: CompanyResponseDto,
+  })
+  @ApiResponse({ status: 404, description: 'Entreprise non trouvée' })
+  async findOneByManaderId(@Param('id') id: string) {
+    try {
+      const company = await this.findCompanyByManager.execute(parseInt(id, 10));
+
+      if (!company) {
+        throw new NotFoundException(`Entreprise avec l'ID ${id} non trouvée`);
+      }
+
+      return company;
+    } catch (error) {
+      if (error instanceof NotFoundException) {
+        throw error;
+      }
+      throw new NotFoundException(`Entreprise avec l'ID ${id} non trouvée`);
+    }
   }
 
   @Put(':id')

+ 2 - 1
node_app/src/presentation/controllers/user.controller.ts

@@ -26,6 +26,7 @@ import { DeleteUserUseCase } from '../../application/use-cases/delete-user.use-c
 import { FindAllUsersUseCase } from '../../application/use-cases/find-all-users.use-case';
 import { Public } from '../decorators/public.decorator';
 import { Roles } from '../decorators/roles.decorator';
+import { UserRole } from 'src/domain/entities/user.entity';
 
 @Controller('users')
 @UseInterceptors(BodyParserInterceptor)
@@ -57,7 +58,7 @@ export class UserController {
 
   @Get(':id')
   // Route protégée - nécessite une authentification
-  @Roles('ADMIN', 'MANAGER')
+  @Roles(UserRole.ADMIN, UserRole.MANAGER, UserRole.USER)
   @ApiOperation({ description: 'Récupérer un utilisateur par son ID' })
   @ApiResponse({ status: 200, description: 'Utilisateur trouvé' })
   @ApiResponse({ status: 404, description: 'Utilisateur non trouvé' })