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'; export type AdBaseModel = { 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; }; export type AdReadModel = AdBaseModel & { waypoints: string; schedule: ScheduleItemModel[]; }; export type AdWriteModel = AdBaseModel & { schedule: { create: ScheduleItemModel[]; }; }; export type AdUnsupportedWriteModel = { waypoints: string; direction: string; }; export type ScheduleItemModel = { uuid: string; day: number; time: Date; margin: number; createdAt: Date; updatedAt: Date; }; export type RawAdBaseModel = { 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; waypoints: string; createdAt: Date; updatedAt: Date; }; export type RawScheduleItemModel = { day: number; time: Date; margin: number; }; export type RawAdModel = RawAdBaseModel & RawScheduleItemModel; export type RawAdReadModel = RawAdBaseModel & { schedule: RawScheduleItemModel[]; }; /** * Repository is used for retrieving/saving domain entities * */ @Injectable() export class AdRepository extends ExtendedPrismaRepositoryBase< AdEntity, AdReadModel, AdWriteModel, AdUnsupportedWriteModel > 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: 'matcher', messagePublisher, }), ); } getCandidates = async (queryString: string): Promise => this.toReadModels((await this.queryRawUnsafe(queryString)) as RawAdModel[]); private toReadModels = (rawAds: RawAdModel[]): AdReadModel[] => { const rawAdReadModels: RawAdReadModel[] = rawAds.map( (rawAd: RawAdModel) => ({ uuid: rawAd.uuid, driver: rawAd.driver, passenger: rawAd.passenger, frequency: rawAd.frequency, fromDate: rawAd.fromDate, toDate: rawAd.toDate, schedule: [ { day: rawAd.day, time: rawAd.time, margin: rawAd.margin, }, ], seatsProposed: rawAd.seatsProposed, seatsRequested: rawAd.seatsRequested, strict: rawAd.strict, driverDuration: rawAd.driverDuration, driverDistance: rawAd.driverDistance, passengerDuration: rawAd.passengerDuration, passengerDistance: rawAd.passengerDistance, fwdAzimuth: rawAd.fwdAzimuth, backAzimuth: rawAd.backAzimuth, waypoints: rawAd.waypoints, createdAt: rawAd.createdAt, updatedAt: rawAd.updatedAt, }), ); const adReadModels: AdReadModel[] = []; rawAdReadModels.forEach((adReadModel: AdReadModel) => { const ad: AdReadModel | undefined = adReadModels.find( (arm: AdReadModel) => arm.uuid == adReadModel.uuid, ); if (ad) { ad.schedule.push(...adReadModel.schedule); } else { adReadModels.push(adReadModel); } }); return adReadModels; }; }