Files
matcher/src/modules/ad/infrastructure/ad.repository.ts
2023-10-18 10:21:43 +02:00

173 lines
4.7 KiB
TypeScript

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 } 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';
import { Frequency } from '../core/domain/ad.types';
import { SERVICE_NAME } from '@src/app.constants';
export type AdModel = {
uuid: string;
driver: boolean;
passenger: boolean;
frequency: Frequency;
fromDate: Date;
toDate: Date;
seatsProposed: number;
seatsRequested: number;
strict: boolean;
driverDuration?: number;
driverDistance?: number;
passengerDuration?: number;
passengerDistance?: number;
fwdAzimuth: number;
backAzimuth: number;
createdAt: Date;
updatedAt: Date;
};
/**
* The record as returned by the persistence system
*/
export type AdReadModel = AdModel & {
waypoints: string;
schedule: ScheduleItemModel[];
};
/**
* The record ready to be sent to the persistence system
*/
export type AdWriteModel = AdModel & {
schedule: {
create: ScheduleItemModel[];
};
};
export type AdWriteExtraModel = {
waypoints: string;
direction: string;
};
export type ScheduleItem = {
day: number;
time: Date;
margin: number;
};
export type ScheduleItemModel = ScheduleItem & {
uuid: string;
createdAt: Date;
updatedAt: Date;
};
export type UngroupedAdModel = AdModel &
ScheduleItem & {
scheduleItemUuid: string;
scheduleItemCreatedAt: Date;
scheduleItemUpdatedAt: Date;
waypoints: string;
};
export type GroupedAdModel = AdModel & {
schedule: ScheduleItemModel[];
waypoints: string;
};
/**
* Repository is used for retrieving/saving domain entities
* */
@Injectable()
export class AdRepository
extends ExtendedPrismaRepositoryBase<
AdEntity,
AdReadModel,
AdWriteModel,
AdWriteExtraModel
>
implements AdRepositoryPort
{
constructor(
prisma: PrismaService,
mapper: AdMapper,
eventEmitter: EventEmitter2,
@Inject(AD_MESSAGE_PUBLISHER)
protected readonly messagePublisher: MessagePublisherPort,
) {
super(
prisma.ad,
prisma,
mapper,
eventEmitter,
new LoggerBase({
logger: new Logger(AdRepository.name),
domain: SERVICE_NAME,
messagePublisher,
}),
);
}
getCandidateAds = async (queryString: string): Promise<AdEntity[]> =>
this._toAdReadModels(
(await this.prismaRaw.$queryRawUnsafe(queryString)) as UngroupedAdModel[],
)
.map((adReadModel: AdReadModel) => {
if (this.mapper.toDomain) return this.mapper.toDomain(adReadModel);
})
.filter(
(adEntity: AdEntity | undefined) => adEntity !== undefined,
) as AdEntity[];
private _toAdReadModels = (
ungroupedAds: UngroupedAdModel[],
): AdReadModel[] => {
const groupedAdModels: GroupedAdModel[] = ungroupedAds.map(
(ungroupedAd: UngroupedAdModel) => ({
uuid: ungroupedAd.uuid,
driver: ungroupedAd.driver,
passenger: ungroupedAd.passenger,
frequency: ungroupedAd.frequency,
fromDate: ungroupedAd.fromDate,
toDate: ungroupedAd.toDate,
schedule: [
{
uuid: ungroupedAd.scheduleItemUuid,
day: ungroupedAd.day,
time: ungroupedAd.time,
margin: ungroupedAd.margin,
createdAt: ungroupedAd.scheduleItemCreatedAt,
updatedAt: ungroupedAd.scheduleItemUpdatedAt,
},
],
seatsProposed: ungroupedAd.seatsProposed,
seatsRequested: ungroupedAd.seatsRequested,
strict: ungroupedAd.strict,
driverDuration: ungroupedAd.driverDuration,
driverDistance: ungroupedAd.driverDistance,
passengerDuration: ungroupedAd.passengerDuration,
passengerDistance: ungroupedAd.passengerDistance,
fwdAzimuth: ungroupedAd.fwdAzimuth,
backAzimuth: ungroupedAd.backAzimuth,
waypoints: ungroupedAd.waypoints,
createdAt: ungroupedAd.createdAt,
updatedAt: ungroupedAd.updatedAt,
}),
);
const adReadModels: AdReadModel[] = [];
groupedAdModels.forEach((groupdeAdModel: GroupedAdModel) => {
const adReadModel: AdReadModel | undefined = adReadModels.find(
(arm: AdReadModel) => arm.uuid == groupdeAdModel.uuid,
);
if (adReadModel) {
adReadModel.schedule.push(...groupdeAdModel.schedule);
} else {
adReadModels.push(groupdeAdModel);
}
});
return adReadModels;
};
}