소스 검색

(fix) exposer la compagnie pour les passagers qui ont reservés

Brin AMONKONAN 1 년 전
부모
커밋
3bc7a70b21

+ 9 - 9
app_transport_front/src/views/UserDashboardView.vue

@@ -135,37 +135,37 @@
                   <div class="flex-1">
                     <div class="flex items-center space-x-2 mb-2">
                       <span class="text-lg font-semibold text-gray-900">
-                        {{ reservation.trajet.departAt.station.name }} →
-                        {{ reservation.trajet.arriveAt.station.name }}
+                        {{ reservation.trajet?.departAt?.station?.name || 'N/A' }} →
+                        {{ reservation.trajet?.arriveAt?.station?.name || 'N/A' }}
                       </span>
                       <span
-                        :class="getStatusBadgeClass(reservation.trajet.vehicule.company.name)"
+                        :class="getStatusBadgeClass(reservation.trajet?.vehicule?.company?.name || 'N/A')"
                         class="px-2 py-1 text-xs font-medium rounded-full"
                       >
                       <i class="fas fa-van-shuttle mr-2"></i>
-                        {{ getStatusText(reservation.trajet.vehicule.company.name) }}
+                        {{ getStatusText(reservation.trajet?.vehicule?.company?.name || 'N/A') }}
                       </span>
                       <span
-                        :class="getStatusBadgeClass(reservation.place.isAvailable)"
+                        :class="getStatusBadgeClass(reservation.place?.isAvailable)"
                         class="px-2 py-1 text-xs font-medium rounded-full"
                       >
-                        {{ getStatusText(reservation.place.isAvailable) }} 
+                        {{ getStatusText(reservation.place?.isAvailable) }} 
                       </span>
                     </div>
                     <div class="text-sm text-gray-600 space-y-1">
                       <p>
                         <i class="fas fa-calendar mr-2"></i
-                        >{{ formatDateTime(reservation.trajet.departAt.date) }}
+                        >{{ formatDateTime(reservation.trajet?.departAt?.date) }}
                       </p>
                       <p>
                         <i class="fas fa-chair mr-2"></i
-                        >{{ reservation.place.number }} place(s)
+                        >{{ reservation.place?.number || 'N/A' }} place(s)
                       </p>
                     </div>
                   </div>
                   <div class="text-right">
                     <p class="text-lg font-semibold text-gray-900">
-                      {{ formatCurrency(reservation.trajet.pricePerSeat) }}
+                      {{ formatCurrency(reservation.trajet?.pricePerSeat || 0) }}
                     </p>
                     <button
                       @click="viewReservationDetails(reservation.id)"

+ 110 - 30
node_app/src/infrastructure/mappers/reservation.mapper.ts

@@ -1,6 +1,9 @@
 import { Trajet } from '@prisma/client';
 import { IPrismaMapper } from './prisma-mapper.interface';
-import { Reservation, PaymentMethod } from 'src/domain/entities/reservation.entity';
+import {
+  Reservation,
+  PaymentMethod,
+} from 'src/domain/entities/reservation.entity';
 import { User, UserRole } from 'src/domain/entities/user.entity';
 
 export class ReservationMapper implements IPrismaMapper<any, Reservation> {
@@ -113,35 +116,112 @@ export class ReservationMapper implements IPrismaMapper<any, Reservation> {
       id: reservation.id,
       dateAt: reservation.dateAt,
       paymentMethod: reservation.paymentMethod,
-      place: reservation.place ? {
-        id: reservation.place.id,
-        number: reservation.place.number,
-        isAvailable: reservation.place.isAvailable,
-        vehiculeId: reservation.place.vehiculeId,
-        occupiedAt: reservation.place.occupiedAt,
-      } : undefined,
-      user: reservation.user ? {
-        id: reservation.user.id,
-        name: reservation.user.name,
-        otherName: reservation.user.otherName,
-        email: reservation.user.email,
-        address: reservation.user.address,
-        telephone: reservation.user.telephone,
-        role: reservation.user.role,
-      } : undefined,
-      trajet: reservation.trajet ? {
-        id: reservation.trajet.id,
-        departAt: reservation.trajet.departAt,
-        arriveAt: reservation.trajet.arriveAt,
-        departStationId: reservation.trajet.departStationId,
-        arriveStationId: reservation.trajet.arriveStationId,
-        vehiculeId: reservation.trajet.vehiculeId,
-        companyId: reservation.trajet.companyId,
-        employeeId: reservation.trajet.employeeId,
-        pricePerSeat: reservation.trajet.pricePerSeat,
-        registrationClosed: reservation.trajet.registrationClosed,
-        availableSeats: reservation.trajet.availableSeats,
-      } : undefined,
+      place: reservation.place
+        ? {
+            id: reservation.place.id,
+            number: reservation.place.number,
+            isAvailable: reservation.place.isAvailable,
+            vehiculeId: reservation.place.vehiculeId,
+            occupiedAt: reservation.place.occupiedAt,
+            // Inclure les informations du véhicule si disponibles
+            vehicule: reservation.place.vehicule
+              ? {
+                  id: reservation.place.vehicule.id,
+                  number_places: reservation.place.vehicule.number_places,
+                  color: reservation.place.vehicule.color,
+                  type: reservation.place.vehicule.type,
+                  immatriculation: reservation.place.vehicule.immatriculation,
+                  model: reservation.place.vehicule.model,
+                  companyId: reservation.place.vehicule.companyId,
+                  driverId: reservation.place.vehicule.driverId,
+                  status: reservation.place.vehicule.status,
+                  // Inclure les informations de la compagnie si disponibles
+                  company: reservation.place.vehicule.company
+                    ? {
+                        id: reservation.place.vehicule.company.id,
+                        name: reservation.place.vehicule.company.name,
+                        address: reservation.place.vehicule.company.address,
+                      }
+                    : undefined,
+                }
+              : undefined,
+          }
+        : undefined,
+      user: reservation.user
+        ? {
+            id: reservation.user.id,
+            name: reservation.user.name,
+            otherName: reservation.user.otherName,
+            email: reservation.user.email,
+            address: reservation.user.address,
+            telephone: reservation.user.telephone,
+            role: reservation.user.role,
+          }
+        : undefined,
+      trajet: reservation.trajet
+        ? {
+            id: reservation.trajet.id,
+            departAt: reservation.trajet.departAt,
+            arriveAt: reservation.trajet.arriveAt,
+            departStationId: reservation.trajet.departStationId,
+            arriveStationId: reservation.trajet.arriveStationId,
+            vehiculeId: reservation.trajet.vehiculeId,
+            companyId: reservation.trajet.companyId,
+            employeeId: reservation.trajet.employeeId,
+            pricePerSeat: reservation.trajet.pricePerSeat,
+            registrationClosed: reservation.trajet.registrationClosed,
+            availableSeats: reservation.trajet.availableSeats,
+            // Inclure les informations du véhicule dans le trajet si disponibles
+            vehicule: reservation.trajet.vehicule
+              ? {
+                  id: reservation.trajet.vehicule.id,
+                  number_places: reservation.trajet.vehicule.number_places,
+                  color: reservation.trajet.vehicule.color,
+                  type: reservation.trajet.vehicule.type,
+                  immatriculation: reservation.trajet.vehicule.immatriculation,
+                  model: reservation.trajet.vehicule.model,
+                  companyId: reservation.trajet.vehicule.companyId,
+                  driverId: reservation.trajet.vehicule.driverId,
+                  status: reservation.trajet.vehicule.status,
+                  // Inclure les informations de la compagnie si disponibles
+                  company: reservation.trajet.vehicule.company
+                    ? {
+                        id: reservation.trajet.vehicule.company.id,
+                        name: reservation.trajet.vehicule.company.name,
+                        address: reservation.trajet.vehicule.company.address,
+                      }
+                    : undefined,
+                }
+              : undefined,
+            // Inclure les informations des stations si disponibles
+            departStation: reservation.trajet.departStation
+              ? {
+                  id: reservation.trajet.departStation.id,
+                  name: reservation.trajet.departStation.name,
+                  address: reservation.trajet.departStation.address,
+                  lat: reservation.trajet.departStation.lat,
+                  long: reservation.trajet.departStation.long,
+                  description: reservation.trajet.departStation.description,
+                  city: reservation.trajet.departStation.city,
+                  country: reservation.trajet.departStation.country,
+                  municipality: reservation.trajet.departStation.municipality,
+                }
+              : undefined,
+            arriveStation: reservation.trajet.arriveStation
+              ? {
+                  id: reservation.trajet.arriveStation.id,
+                  name: reservation.trajet.arriveStation.name,
+                  address: reservation.trajet.arriveStation.address,
+                  lat: reservation.trajet.arriveStation.lat,
+                  long: reservation.trajet.arriveStation.long,
+                  description: reservation.trajet.arriveStation.description,
+                  city: reservation.trajet.arriveStation.city,
+                  country: reservation.trajet.arriveStation.country,
+                  municipality: reservation.trajet.arriveStation.municipality,
+                }
+              : undefined,
+          }
+        : undefined,
     };
   }
 }

+ 17 - 5
node_app/src/presentation/controllers/reservation.controller.ts

@@ -62,7 +62,8 @@ export class ReservationController {
   @ApiResponse({ status: 401, description: 'Non autorisé' })
   @Public()
   async create(@Body() createReservationDto: CreateReservationDto) {
-    const reservation = await this.createReservationUseCase.execute(createReservationDto);
+    const reservation =
+      await this.createReservationUseCase.execute(createReservationDto);
     return this.reservationMapper.toResponseDto(reservation);
   }
 
@@ -96,9 +97,14 @@ export class ReservationController {
   })
   @ApiResponse({ status: 401, description: 'Non autorisé' })
   async findAll(@Query('page') page?: number, @Query('limit') limit?: number) {
-    const result = await this.findAllReservationsUseCase.execute(page || 1, limit || 10);
+    const result = await this.findAllReservationsUseCase.execute(
+      page || 1,
+      limit || 10,
+    );
     return {
-      data: result.data.map(reservation => this.reservationMapper.toResponseDto(reservation)),
+      data: result.data.map((reservation) =>
+        this.reservationMapper.toResponseDto(reservation),
+      ),
       total: result.total,
     };
   }
@@ -133,7 +139,10 @@ export class ReservationController {
     @Param('id', ParseIntPipe) id: number,
     @Body() updateReservationDto: UpdateReservationDto,
   ) {
-    const reservation = await this.updateReservationUseCase.execute(id, updateReservationDto);
+    const reservation = await this.updateReservationUseCase.execute(
+      id,
+      updateReservationDto,
+    );
     return this.reservationMapper.toResponseDto(reservation);
   }
 
@@ -192,7 +201,10 @@ export class ReservationController {
     );
 
     return {
-      data: result.data.map(reservation => this.reservationMapper.toResponseDto(reservation)),
+      data: result.data.map((reservation) =>
+        // eslint-disable-next-line @typescript-eslint/no-unsafe-return
+        this.reservationMapper.toResponseDto(reservation),
+      ),
       pagination: {
         page,
         limit,

+ 36 - 58
node_app/src/presentation/controllers/transaction.controller.ts

@@ -1,12 +1,4 @@
-import {
-  Controller,
-  Get,
-  Post,
-  Body,
-  Param,
-  Put,
-  Query,
-} from '@nestjs/common';
+import { Controller, Get, Post, Body, Param, Put, Query } from '@nestjs/common';
 import {
   ApiResponse,
   ApiTags,
@@ -32,7 +24,7 @@ export class CreateTransactionDtoWithExamples {
   amount: number;
 
   @ApiProperty({
-    description: 'ID de l\'utilisateur effectuant la transaction',
+    description: "ID de l'utilisateur effectuant la transaction",
     example: 1,
     type: 'number',
   })
@@ -126,7 +118,7 @@ export class TransactionResponseDtoWithExamples {
   metadata?: any;
 
   @ApiProperty({
-    description: 'ID de l\'utilisateur',
+    description: "ID de l'utilisateur",
     example: 1,
     type: 'number',
   })
@@ -162,14 +154,14 @@ export class TransactionResponseDtoWithExamples {
 @Controller('transactions')
 @ApiSecurity('access-token')
 export class TransactionController {
-  constructor(
-    // Inject use cases here when they are created
-  ) {}
+  constructor() // Inject use cases here when they are created
+  {}
 
   @Post()
-  @ApiOperation({ 
+  @ApiOperation({
     summary: 'Créer une nouvelle transaction',
-    description: 'Crée une nouvelle transaction de paiement pour une réservation'
+    description:
+      'Crée une nouvelle transaction de paiement pour une réservation',
   })
   @ApiResponse({
     status: 201,
@@ -184,16 +176,19 @@ export class TransactionController {
     status: 404,
     description: 'Utilisateur ou réservation non trouvé(e)',
   })
-  async create(@Body() createTransactionDto: CreateTransactionDtoWithExamples): Promise<TransactionResponseDtoWithExamples> {
+  async create(
+    @Body() createTransactionDto: CreateTransactionDtoWithExamples,
+  ): Promise<TransactionResponseDtoWithExamples> {
     // Implementation will be added when use cases are created
     throw new Error('Not implemented yet');
   }
 
   @Get()
   @Roles(UserRole.ADMIN, UserRole.MANAGER)
-  @ApiOperation({ 
+  @ApiOperation({
     summary: 'Récupérer toutes les transactions',
-    description: 'Récupère la liste paginée de toutes les transactions (Admin/Manager uniquement)'
+    description:
+      'Récupère la liste paginée de toutes les transactions (Admin/Manager uniquement)',
   })
   @ApiResponse({
     status: 200,
@@ -204,20 +199,22 @@ export class TransactionController {
     status: 403,
     description: 'Accès refusé - Rôle insuffisant',
   })
-  async findAll(@Query() paginationDto: PaginationDto): Promise<PaginatedResponseDto<TransactionResponseDtoWithExamples>> {
+  async findAll(
+    @Query() paginationDto: PaginationDto,
+  ): Promise<PaginatedResponseDto<TransactionResponseDtoWithExamples>> {
     // Implementation will be added when use cases are created
     throw new Error('Not implemented yet');
   }
 
   @Get(':id')
-  @ApiOperation({ 
+  @ApiOperation({
     summary: 'Récupérer une transaction par ID',
-    description: 'Récupère les détails d\'une transaction spécifique'
+    description: "Récupère les détails d'une transaction spécifique",
   })
-  @ApiParam({ 
-    name: 'id', 
+  @ApiParam({
+    name: 'id',
     description: 'Identifiant unique de la transaction',
-    example: 'txn_123456789'
+    example: 'txn_123456789',
   })
   @ApiResponse({
     status: 200,
@@ -228,44 +225,23 @@ export class TransactionController {
     status: 404,
     description: 'Transaction non trouvée',
   })
-  async findOne(@Param('id') id: string): Promise<TransactionResponseDtoWithExamples> {
-    // Implementation will be added when use cases are created
-    throw new Error('Not implemented yet');
-  }
-
-  @Get('user/:userId')
-  @ApiOperation({ 
-    summary: 'Récupérer les transactions d\'un utilisateur',
-    description: 'Récupère toutes les transactions effectuées par un utilisateur spécifique'
-  })
-  @ApiParam({ 
-    name: 'userId', 
-    description: 'Identifiant de l\'utilisateur',
-    example: 1
-  })
-  @ApiResponse({
-    status: 200,
-    description: 'Transactions de l\'utilisateur récupérées avec succès',
-    type: [TransactionResponseDtoWithExamples],
-  })
-  @ApiResponse({
-    status: 404,
-    description: 'Utilisateur non trouvé',
-  })
-  async findByUser(@Param('userId') userId: number): Promise<TransactionResponseDtoWithExamples[]> {
+  async findOne(
+    @Param('id') id: string,
+  ): Promise<TransactionResponseDtoWithExamples> {
     // Implementation will be added when use cases are created
     throw new Error('Not implemented yet');
   }
 
   @Get('reservation/:reservationId')
-  @ApiOperation({ 
-    summary: 'Récupérer la transaction d\'une réservation',
-    description: 'Récupère la transaction associée à une réservation spécifique'
+  @ApiOperation({
+    summary: "Récupérer la transaction d'une réservation",
+    description:
+      'Récupère la transaction associée à une réservation spécifique',
   })
-  @ApiParam({ 
-    name: 'reservationId', 
+  @ApiParam({
+    name: 'reservationId',
     description: 'Identifiant de la réservation',
-    example: 123
+    example: 123,
   })
   @ApiResponse({
     status: 200,
@@ -276,8 +252,10 @@ export class TransactionController {
     status: 404,
     description: 'Réservation ou transaction non trouvée',
   })
-  async findByReservation(@Param('reservationId') reservationId: number): Promise<TransactionResponseDtoWithExamples> {
+  async findByReservation(
+    @Param('reservationId') reservationId: number,
+  ): Promise<TransactionResponseDtoWithExamples> {
     // Implementation will be added when use cases are created
     throw new Error('Not implemented yet');
   }
-}
+}