functional ad insert

This commit is contained in:
sbriat
2023-08-24 14:08:49 +02:00
parent 39cebda0b9
commit 9799f78bd2
24 changed files with 1390 additions and 2108 deletions

View File

@@ -1,16 +1,17 @@
import { Mapper } from '@mobicoop/ddd-library';
import { Inject, Injectable } from '@nestjs/common';
import { AdEntity } from './core/domain/ad.entity';
import {
AdWriteModel,
AdReadModel,
ScheduleItemModel,
AdUnsupportedWriteModel,
} from './infrastructure/ad.repository';
import { Frequency } from './core/domain/ad.types';
import { v4 } from 'uuid';
import { ScheduleItemProps } from './core/domain/value-objects/schedule-item.value-object';
import { DirectionEncoderPort } from '@modules/geography/core/application/ports/direction-encoder.port';
import { AD_DIRECTION_ENCODER } from './ad.di-tokens';
import { ExtendedMapper } from '@mobicoop/ddd-library';
/**
* Mapper constructs objects that are used in different layers:
@@ -21,7 +22,14 @@ import { AD_DIRECTION_ENCODER } from './ad.di-tokens';
@Injectable()
export class AdMapper
implements Mapper<AdEntity, AdReadModel, AdWriteModel, undefined>
implements
ExtendedMapper<
AdEntity,
AdReadModel,
AdWriteModel,
AdUnsupportedWriteModel,
undefined
>
{
constructor(
@Inject(AD_DIRECTION_ENCODER)
@@ -61,8 +69,6 @@ export class AdMapper
driverDistance: copy.driverDistance,
passengerDuration: copy.passengerDuration,
passengerDistance: copy.passengerDistance,
waypoints: this.directionEncoder.encode(copy.waypoints),
direction: this.directionEncoder.encode(copy.points),
fwdAzimuth: copy.fwdAzimuth,
backAzimuth: copy.backAzimuth,
createdAt: copy.createdAt,
@@ -118,4 +124,9 @@ export class AdMapper
toResponse = (entity: AdEntity): undefined => {
return undefined;
};
toUnsupportedPersistence = (entity: AdEntity): AdUnsupportedWriteModel => ({
waypoints: this.directionEncoder.encode(entity.getProps().waypoints),
direction: this.directionEncoder.encode(entity.getProps().points),
});
}

View File

@@ -16,9 +16,12 @@ import { PostgresDirectionEncoder } from '@modules/geography/infrastructure/post
import { GetBasicRouteController } from '@modules/geography/interface/controllers/get-basic-route.controller';
import { RouteProvider } from './infrastructure/route-provider';
import { GeographyModule } from '@modules/geography/geography.module';
import { CreateAdService } from './core/application/commands/create-ad/create-ad.service';
const messageHandlers = [AdCreatedMessageHandler];
const commandHandlers: Provider[] = [CreateAdService];
const mappers: Provider[] = [AdMapper];
const repositories: Provider[] = [
@@ -56,6 +59,7 @@ const adapters: Provider[] = [
imports: [CqrsModule, GeographyModule],
providers: [
...messageHandlers,
...commandHandlers,
...mappers,
...repositories,
...messagePublishers,

View File

@@ -49,7 +49,7 @@ export class CreateAdService implements ICommandHandler {
});
try {
await this.repository.insert(ad);
await this.repository.insertWithUnsupportedFields(ad, 'ad');
return ad.id;
} catch (error: any) {
if (error instanceof ConflictException) {

View File

@@ -1,4 +1,4 @@
import { RepositoryPort } from '@mobicoop/ddd-library';
import { ExtendedRepositoryPort } from '@mobicoop/ddd-library';
import { AdEntity } from '../../domain/ad.entity';
export type AdRepositoryPort = RepositoryPort<AdEntity>;
export type AdRepositoryPort = ExtendedRepositoryPort<AdEntity>;

View File

@@ -1,15 +1,12 @@
import { Inject, Injectable, Logger } from '@nestjs/common';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { AdRepositoryPort } from '../core/application/ports/ad.repository.port';
import {
LoggerBase,
MessagePublisherPort,
PrismaRepositoryBase,
} from '@mobicoop/ddd-library';
import { LoggerBase, MessagePublisherPort } from '@mobicoop/ddd-library';
import { PrismaService } from './prisma.service';
import { AD_MESSAGE_PUBLISHER } from '../ad.di-tokens';
import { AdEntity } from '../core/domain/ad.entity';
import { AdMapper } from '../ad.mapper';
import { ExtendedPrismaRepositoryBase } from '@mobicoop/ddd-library/dist/db/prisma-repository.base';
export type AdBaseModel = {
uuid: string;
@@ -25,8 +22,6 @@ export type AdBaseModel = {
driverDistance: number;
passengerDuration: number;
passengerDistance: number;
waypoints: string;
direction: string;
fwdAzimuth: number;
backAzimuth: number;
createdAt: Date;
@@ -34,6 +29,8 @@ export type AdBaseModel = {
};
export type AdReadModel = AdBaseModel & {
waypoints: string;
direction: string;
schedule: ScheduleItemModel[];
};
@@ -43,6 +40,11 @@ export type AdWriteModel = AdBaseModel & {
};
};
export type AdUnsupportedWriteModel = {
waypoints: string;
direction: string;
};
export type ScheduleItemModel = {
uuid: string;
day: number;
@@ -57,7 +59,12 @@ export type ScheduleItemModel = {
* */
@Injectable()
export class AdRepository
extends PrismaRepositoryBase<AdEntity, AdReadModel, AdWriteModel>
extends ExtendedPrismaRepositoryBase<
AdEntity,
AdReadModel,
AdWriteModel,
AdUnsupportedWriteModel
>
implements AdRepositoryPort
{
constructor(

View File

@@ -12,8 +12,8 @@ export class AdCreatedMessageHandler {
name: 'adCreated',
})
public async adCreated(message: string) {
const createdAd: Ad = JSON.parse(message);
try {
const createdAd: Ad = JSON.parse(message);
await this.commandBus.execute(
new CreateAdCommand({
id: createdAd.id,

View File

@@ -4,6 +4,7 @@ import { AdEntity } from '@modules/ad/core/domain/ad.entity';
import { Frequency } from '@modules/ad/core/domain/ad.types';
import {
AdReadModel,
AdUnsupportedWriteModel,
AdWriteModel,
} from '@modules/ad/infrastructure/ad.repository';
import { DirectionEncoderPort } from '@modules/geography/core/application/ports/direction-encoder.port';
@@ -143,14 +144,19 @@ describe('Ad Mapper', () => {
it('should map domain entity to persistence data', async () => {
const mapped: AdWriteModel = adMapper.toPersistence(adEntity);
expect(mapped.schedule.create.length).toBe(1);
expect(mapped.driverDuration).toBe(14422);
expect(mapped.fwdAzimuth).toBe(273);
});
it('should map domain entity to unsupported db persistence data', async () => {
const mapped: AdUnsupportedWriteModel =
adMapper.toUnsupportedPersistence(adEntity);
expect(mapped.waypoints).toBe(
"'LINESTRING(6.1765102 48.689445,2.3522 48.8566)'",
);
expect(mapped.direction).toBe(
"'LINESTRING(6.1765102 48.689445,4.984578 48.725687,2.3522 48.8566)'",
);
expect(mapped.driverDuration).toBe(14422);
expect(mapped.fwdAzimuth).toBe(273);
});
it('should map persisted data to domain entity', async () => {

View File

@@ -4,13 +4,13 @@ import { WaypointProps } from '@modules/ad/core/domain/value-objects/waypoint.va
const originWaypointProps: WaypointProps = {
position: 0,
lon: 48.689445,
lat: 6.17651,
lat: 48.689445,
lon: 6.17651,
};
const destinationWaypointProps: WaypointProps = {
position: 1,
lon: 48.8566,
lat: 2.3522,
lat: 48.8566,
lon: 2.3522,
};
const createAdProps: CreateAdProps = {

View File

@@ -12,13 +12,13 @@ import { RouteProviderPort } from '@modules/ad/core/application/ports/route-prov
const originWaypoint: WaypointProps = {
position: 0,
lon: 48.689445,
lat: 6.17651,
lat: 48.689445,
lon: 6.17651,
};
const destinationWaypoint: WaypointProps = {
position: 1,
lon: 48.8566,
lat: 2.3522,
lat: 48.8566,
lon: 2.3522,
};
const createAdProps: CreateAdProps = {
id: '4eb6a6af-ecfd-41c3-9118-473a507014d4',
@@ -48,7 +48,7 @@ const createAdProps: CreateAdProps = {
};
const mockAdRepository = {
insert: jest
insertWithUnsupportedFields: jest
.fn()
.mockImplementationOnce(() => ({}))
.mockImplementationOnce(() => {

View File

@@ -4,25 +4,25 @@ import { Point } from '@modules/ad/core/domain/value-objects/point.value-object'
describe('Point value object', () => {
it('should create a point value object', () => {
const pointVO = new Point({
lon: 48.689445,
lat: 6.17651,
lat: 48.689445,
lon: 6.17651,
});
expect(pointVO.lon).toBe(48.689445);
expect(pointVO.lat).toBe(6.17651);
expect(pointVO.lat).toBe(48.689445);
expect(pointVO.lon).toBe(6.17651);
});
it('should throw an exception if longitude is invalid', () => {
try {
new Point({
lon: 348.689445,
lat: 6.17651,
lat: 48.689445,
lon: 186.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
try {
new Point({
lon: -348.689445,
lat: 6.17651,
lat: 48.689445,
lon: -186.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
@@ -31,16 +31,16 @@ describe('Point value object', () => {
it('should throw an exception if latitude is invalid', () => {
try {
new Point({
lon: 48.689445,
lat: 96.17651,
lat: 148.689445,
lon: 6.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
}
try {
new Point({
lon: 48.689445,
lat: -96.17651,
lat: -148.689445,
lon: 6.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);

View File

@@ -8,19 +8,19 @@ describe('Waypoint value object', () => {
it('should create a waypoint value object', () => {
const waypointVO = new Waypoint({
position: 0,
lon: 48.689445,
lat: 6.17651,
lat: 48.689445,
lon: 6.17651,
});
expect(waypointVO.position).toBe(0);
expect(waypointVO.lon).toBe(48.689445);
expect(waypointVO.lat).toBe(6.17651);
expect(waypointVO.lat).toBe(48.689445);
expect(waypointVO.lon).toBe(6.17651);
});
it('should throw an exception if position is invalid', () => {
try {
new Waypoint({
position: -1,
lon: 48.689445,
lat: 6.17651,
lat: 48.689445,
lon: 6.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentInvalidException);
@@ -30,8 +30,8 @@ describe('Waypoint value object', () => {
try {
new Waypoint({
position: 0,
lon: 348.689445,
lat: 6.17651,
lat: 48.689445,
lon: 186.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
@@ -39,8 +39,8 @@ describe('Waypoint value object', () => {
try {
new Waypoint({
position: 0,
lon: -348.689445,
lat: 6.17651,
lat: 48.689445,
lon: -186.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
@@ -50,8 +50,8 @@ describe('Waypoint value object', () => {
try {
new Waypoint({
position: 0,
lon: 48.689445,
lat: 96.17651,
lat: 148.689445,
lon: 6.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);
@@ -59,8 +59,8 @@ describe('Waypoint value object', () => {
try {
new Waypoint({
position: 0,
lon: 48.689445,
lat: -96.17651,
lat: -148.689445,
lon: 6.17651,
});
} catch (e: any) {
expect(e).toBeInstanceOf(ArgumentOutOfRangeException);