diff --git a/README.md b/README.md index 31f3009..2e57f6c 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,8 @@ The app exposes the following [gRPC](https://grpc.io/) services : "postalCode": "75000", "country": "France" } - ] + ], + "comment": "I'm flexible with the departure time" } ``` @@ -157,7 +158,8 @@ The app exposes the following [gRPC](https://grpc.io/) services : "postalCode": "75000", "country": "France" } - ] + ], + "comment": "I'm flexible with the departure time" } ``` @@ -207,7 +209,8 @@ The app exposes the following [gRPC](https://grpc.io/) services : "postalCode": "75000", "country": "France" } - ] + ], + "comment": "I'm flexible with the departure time" } ``` @@ -227,6 +230,7 @@ The app exposes the following [gRPC](https://grpc.io/) services : - seatsRequested: number of seats requested as passenger (required if `passenger` is true) - strict (boolean): if set to true, allow matching only with similar frequency ads - waypoints: an array of addresses that represent the waypoints of the journey (only first and last waypoints are used for passenger ads). Note that positions are **required** and **must** be consecutives + - comment: optional freetext comment / description about the ad ## Messages diff --git a/prisma/migrations/20240228132441_added_comment/migration.sql b/prisma/migrations/20240228132441_added_comment/migration.sql new file mode 100644 index 0000000..85650d0 --- /dev/null +++ b/prisma/migrations/20240228132441_added_comment/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "ad" ADD COLUMN "comment" TEXT; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 13cc35a..c7d36f3 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -27,6 +27,7 @@ model Ad { createdAt DateTime @default(now()) updatedAt DateTime @default(now()) @updatedAt waypoints Waypoint[] + comment String? @@map("ad") } diff --git a/src/modules/ad/ad.mapper.ts b/src/modules/ad/ad.mapper.ts index 5c7c014..eb3bf11 100644 --- a/src/modules/ad/ad.mapper.ts +++ b/src/modules/ad/ad.mapper.ts @@ -82,6 +82,7 @@ export class AdMapper })), } : undefined, + comment: copy.comment, }; return record; }; @@ -128,6 +129,7 @@ export class AdMapper }, }, })), + comment: record.comment, }, }); return entity; @@ -193,6 +195,7 @@ export class AdMapper lon: waypoint.address.coordinates.lon, lat: waypoint.address.coordinates.lat, })); + response.comment = props.comment; return response; }; } diff --git a/src/modules/ad/core/application/commands/create-ad/create-ad.command.ts b/src/modules/ad/core/application/commands/create-ad/create-ad.command.ts index 128b4ac..7a939c3 100644 --- a/src/modules/ad/core/application/commands/create-ad/create-ad.command.ts +++ b/src/modules/ad/core/application/commands/create-ad/create-ad.command.ts @@ -15,6 +15,7 @@ export class CreateAdCommand extends Command { readonly seatsRequested?: number; readonly strict: boolean; readonly waypoints: Waypoint[]; + readonly comment?: string; constructor(props: CommandProps) { super(props); @@ -29,5 +30,6 @@ export class CreateAdCommand extends Command { this.seatsRequested = props.seatsRequested; this.strict = props.strict; this.waypoints = props.waypoints; + this.comment = props.comment; } } diff --git a/src/modules/ad/core/application/commands/create-ad/create-ad.service.ts b/src/modules/ad/core/application/commands/create-ad/create-ad.service.ts index b7c8d6d..5d1d30c 100644 --- a/src/modules/ad/core/application/commands/create-ad/create-ad.service.ts +++ b/src/modules/ad/core/application/commands/create-ad/create-ad.service.ts @@ -95,6 +95,7 @@ export class CreateAdService implements ICommandHandler { }, }, })), + comment: command.comment, }); try { diff --git a/src/modules/ad/core/domain/ad.entity.ts b/src/modules/ad/core/domain/ad.entity.ts index 1c4f78c..7381430 100644 --- a/src/modules/ad/core/domain/ad.entity.ts +++ b/src/modules/ad/core/domain/ad.entity.ts @@ -47,6 +47,7 @@ export class AdEntity extends AggregateRoot { lon: waypoint.address.coordinates.lon, lat: waypoint.address.coordinates.lat, })), + comment: props.comment, }), ); return ad; diff --git a/src/modules/ad/core/domain/ad.types.ts b/src/modules/ad/core/domain/ad.types.ts index 64f53e6..85bb2bc 100644 --- a/src/modules/ad/core/domain/ad.types.ts +++ b/src/modules/ad/core/domain/ad.types.ts @@ -15,6 +15,7 @@ export interface AdProps { seatsRequested: number; strict: boolean; waypoints: WaypointProps[]; + comment?: string; } // Properties that are needed for an Ad creation @@ -30,6 +31,7 @@ export interface CreateAdProps { seatsRequested: number; strict: boolean; waypoints: WaypointProps[]; + comment?: string; } export enum Frequency { diff --git a/src/modules/ad/core/domain/events/ad-created.domain-event.ts b/src/modules/ad/core/domain/events/ad-created.domain-event.ts index 8f9a225..50cd191 100644 --- a/src/modules/ad/core/domain/events/ad-created.domain-event.ts +++ b/src/modules/ad/core/domain/events/ad-created.domain-event.ts @@ -12,6 +12,7 @@ export class AdCreatedDomainEvent extends DomainEvent { readonly seatsRequested: number; readonly strict: boolean; readonly waypoints: Waypoint[]; + readonly comment?: string; constructor(props: DomainEventProps) { super(props); @@ -26,6 +27,7 @@ export class AdCreatedDomainEvent extends DomainEvent { this.seatsRequested = props.seatsRequested; this.strict = props.strict; this.waypoints = props.waypoints; + this.comment = props.comment; } } diff --git a/src/modules/ad/infrastructure/ad.repository.ts b/src/modules/ad/infrastructure/ad.repository.ts index 673a036..b5df96f 100644 --- a/src/modules/ad/infrastructure/ad.repository.ts +++ b/src/modules/ad/infrastructure/ad.repository.ts @@ -24,6 +24,7 @@ export type AdBaseModel = { seatsProposed: number; seatsRequested: number; strict: boolean; + comment?: string; }; export type AdReadModel = AdBaseModel & { diff --git a/src/modules/ad/interface/dtos/ad.response.dto.ts b/src/modules/ad/interface/dtos/ad.response.dto.ts index 6c22522..60a301f 100644 --- a/src/modules/ad/interface/dtos/ad.response.dto.ts +++ b/src/modules/ad/interface/dtos/ad.response.dto.ts @@ -28,4 +28,5 @@ export class AdResponseDto extends ResponseBase { lon: number; lat: number; }[]; + comment?: string; } diff --git a/src/modules/ad/interface/grpc-controllers/ad.proto b/src/modules/ad/interface/grpc-controllers/ad.proto index a3e994a..581aa08 100644 --- a/src/modules/ad/interface/grpc-controllers/ad.proto +++ b/src/modules/ad/interface/grpc-controllers/ad.proto @@ -36,6 +36,7 @@ message Ad { int32 seatsRequested = 10; bool strict = 11; repeated Waypoint waypoints = 12; + optional string comment = 13; } message ScheduleItem { diff --git a/src/modules/ad/interface/grpc-controllers/dtos/create-ad.request.dto.ts b/src/modules/ad/interface/grpc-controllers/dtos/create-ad.request.dto.ts index 961cfb6..14122d0 100644 --- a/src/modules/ad/interface/grpc-controllers/dtos/create-ad.request.dto.ts +++ b/src/modules/ad/interface/grpc-controllers/dtos/create-ad.request.dto.ts @@ -3,8 +3,10 @@ import { IsBoolean, IsInt, IsEnum, + IsString, ValidateNested, ArrayMinSize, + Length, IsUUID, IsArray, IsISO8601, @@ -78,4 +80,9 @@ export class CreateAdRequestDto { @HasValidPositionIndexes() @ValidateNested({ each: true }) waypoints: WaypointDto[]; + + @Length(0, 2000) + @IsString() + @IsOptional() + comment?: string; } diff --git a/tests/unit/ad/ad.mapper.spec.ts b/tests/unit/ad/ad.mapper.spec.ts index 47ec4d6..dd71928 100644 --- a/tests/unit/ad/ad.mapper.spec.ts +++ b/tests/unit/ad/ad.mapper.spec.ts @@ -111,6 +111,7 @@ const adReadModel: AdReadModel = { strict: false, seatsProposed: 3, seatsRequested: 1, + comment: '', createdAt: now, updatedAt: now, }; diff --git a/tests/unit/ad/core/ad.entity.spec.ts b/tests/unit/ad/core/ad.entity.spec.ts index e6b3c0f..72bafb7 100644 --- a/tests/unit/ad/core/ad.entity.spec.ts +++ b/tests/unit/ad/core/ad.entity.spec.ts @@ -39,6 +39,7 @@ const baseCreateAdProps = { seatsRequested: 1, strict: false, waypoints: [originWaypointProps, destinationWaypointProps], + comment: "J'accepte les chiens mais pas les chats", }; const punctualCreateAdProps = { fromDate: '2023-06-21', @@ -134,6 +135,9 @@ describe('Ad entity create', () => { expect(punctualPassengerAd.getProps().schedule[0].time).toBe('08:30'); expect(punctualPassengerAd.getProps().driver).toBeFalsy(); expect(punctualPassengerAd.getProps().passenger).toBeTruthy(); + expect(punctualPassengerAd.getProps().comment).toBe( + "J'accepte les chiens mais pas les chats", + ); }); it('should create a new punctual driver ad entity', async () => { const punctualDriverAd: AdEntity = AdEntity.create(