mirror of
https://gitlab.com/mobicoop/v3/service/matcher.git
synced 2026-01-01 00:32:41 +00:00
196 lines
5.3 KiB
TypeScript
196 lines
5.3 KiB
TypeScript
import { LoggerBase, MessagePublisherPort } from '@mobicoop/ddd-library';
|
|
import { ExtendedPrismaRepositoryBase } from '@mobicoop/ddd-library/dist/db/prisma-repository.base';
|
|
import { Inject, Injectable, Logger } from '@nestjs/common';
|
|
import { EventEmitter2 } from '@nestjs/event-emitter';
|
|
import { SERVICE_NAME } from '@src/app.constants';
|
|
import { AD_MESSAGE_PUBLISHER } from '../ad.di-tokens';
|
|
import { AdMapper } from '../ad.mapper';
|
|
import { AdRepositoryPort } from '../core/application/ports/ad.repository.port';
|
|
import { AdEntity } from '../core/domain/ad.entity';
|
|
import { Frequency } from '../core/domain/ad.types';
|
|
import { PrismaService } from './prisma.service';
|
|
|
|
export type AdModel = {
|
|
uuid: string;
|
|
driver: boolean;
|
|
passenger: boolean;
|
|
frequency: Frequency;
|
|
fromDate: Date;
|
|
toDate: Date;
|
|
seatsProposed: number;
|
|
seatsRequested: number;
|
|
strict: boolean;
|
|
pause: boolean;
|
|
driverDuration?: number;
|
|
driverDistance?: number;
|
|
passengerDuration?: number;
|
|
passengerDistance?: number;
|
|
fwdAzimuth: number;
|
|
backAzimuth: number;
|
|
};
|
|
|
|
/**
|
|
* The record as returned by the persistence system
|
|
*/
|
|
export type AdReadModel = AdModel & {
|
|
waypoints: string;
|
|
schedule: ScheduleItemModel[];
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
};
|
|
|
|
/**
|
|
* The record ready to be sent to the persistence system
|
|
*/
|
|
export type AdWriteModel = AdModel & {
|
|
schedule: ScheduleWriteModel;
|
|
};
|
|
|
|
export type ScheduleWriteModel = {
|
|
deleteMany?: PastCreatedFilter;
|
|
create: ScheduleItemModel[];
|
|
};
|
|
|
|
// used to delete records created in the past,
|
|
// because the order of `create` and `deleteMany` is not guaranteed
|
|
export type PastCreatedFilter = {
|
|
createdAt: { lt: Date };
|
|
};
|
|
|
|
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;
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
};
|
|
|
|
export type GroupedAdModel = AdModel & {
|
|
schedule: ScheduleItemModel[];
|
|
waypoints: string;
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
};
|
|
|
|
/**
|
|
* 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,
|
|
pause: ungroupedAd.pause,
|
|
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;
|
|
};
|
|
|
|
async update(
|
|
id: string,
|
|
entity: AdEntity,
|
|
identifier?: string,
|
|
): Promise<void> {
|
|
this.updateExtra(id, entity, 'ad', identifier);
|
|
}
|
|
}
|