matcher/src/modules/ad/infrastructure/ad.repository.ts

170 lines
4.3 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';
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<AdReadModel[]> =>
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;
};
}