import { Injectable } from '@nestjs/common'; import { Mapper } from '@mobicoop/ddd-library'; import { MatchingEntity } from './core/domain/matching.entity'; import { Frequency, Role } from './core/domain/ad.types'; import { MatchEntity } from './core/domain/match.entity'; import { Target } from './core/domain/candidate.types'; import { Waypoint } from './core/application/types/waypoint.type'; import { ScheduleItem } from './core/application/types/schedule-item.type'; import { Journey } from './core/domain/value-objects/journey.value-object'; import { JourneyItem } from './core/domain/value-objects/journey-item.value-object'; import { ActorTime } from './core/domain/value-objects/actor-time.value-object'; @Injectable() export class MatchingMapper implements Mapper { toPersistence = (entity: MatchingEntity): string => JSON.stringify({ id: entity.id, createdAt: entity.createdAt.toISOString(), updatedAt: entity.updatedAt.toISOString(), matches: entity.getProps().matches.map((match: MatchEntity) => ({ adId: match.getProps().adId, role: match.getProps().role, frequency: match.getProps().frequency, distance: match.getProps().distance, duration: match.getProps().duration, initialDistance: match.getProps().initialDistance, initialDuration: match.getProps().initialDuration, distanceDetour: match.getProps().distanceDetour, durationDetour: match.getProps().durationDetour, distanceDetourPercentage: match.getProps().distanceDetourPercentage, durationDetourPercentage: match.getProps().durationDetourPercentage, journeys: match.getProps().journeys.map((journey: Journey) => ({ firstDate: journey.firstDate.toISOString(), lastDate: journey.lastDate.toISOString(), journeyItems: journey.journeyItems.map( (journeyItem: JourneyItem) => ({ lon: journeyItem.lon, lat: journeyItem.lat, duration: journeyItem.duration, distance: journeyItem.distance, actorTimes: journeyItem.actorTimes.map( (actorTime: ActorTime) => ({ role: actorTime.role, target: actorTime.target, firstDatetime: actorTime.firstDatetime.toISOString(), firstMinDatetime: actorTime.firstMinDatetime.toISOString(), firstMaxDatetime: actorTime.firstMaxDatetime.toISOString(), lastDatetime: actorTime.lastDatetime.toISOString(), lastMinDatetime: actorTime.lastMinDatetime.toISOString(), lastMaxDatetime: actorTime.lastMaxDatetime.toISOString(), }), ), }), ), })), })), query: { driver: entity.getProps().query.driver, passenger: entity.getProps().query.passenger, frequency: entity.getProps().query.frequency, fromDate: entity.getProps().query.fromDate, toDate: entity.getProps().query.toDate, schedule: entity .getProps() .query.schedule?.map((scheduleItem: ScheduleItem) => ({ day: scheduleItem.day, time: scheduleItem.time, margin: scheduleItem.margin, })), seatsProposed: entity.getProps().query.seatsProposed, seatsRequested: entity.getProps().query.seatsRequested, strict: entity.getProps().query.strict, waypoints: entity .getProps() .query.waypoints.map((waypoint: Waypoint) => ({ lon: waypoint.lon, lat: waypoint.lat, position: waypoint.position, houseNumber: waypoint.houseNumber, street: waypoint.street, postalCode: waypoint.postalCode, locality: waypoint.locality, country: waypoint.country, })), algorithmType: entity.getProps().query.algorithmType, remoteness: entity.getProps().query.remoteness, useProportion: entity.getProps().query.useProportion, proportion: entity.getProps().query.proportion, useAzimuth: entity.getProps().query.useAzimuth, azimuthMargin: entity.getProps().query.azimuthMargin, maxDetourDistanceRatio: entity.getProps().query.maxDetourDistanceRatio, maxDetourDurationRatio: entity.getProps().query.maxDetourDurationRatio, }, }); toDomain = (record: string): MatchingEntity => { const parsedRecord: PersistedMatching = JSON.parse(record); const matchingEntity: MatchingEntity = new MatchingEntity({ id: parsedRecord.id, createdAt: new Date(parsedRecord.createdAt), updatedAt: new Date(parsedRecord.updatedAt), props: { query: parsedRecord.query, matches: parsedRecord.matches.map((match: PersistedMatch) => MatchEntity.create({ adId: match.adId, role: match.role, frequency: match.frequency, distance: match.distance, duration: match.duration, initialDistance: match.initialDistance, initialDuration: match.initialDuration, journeys: match.journeys.map( (journey: PersistedJourney) => new Journey({ firstDate: new Date(journey.firstDate), lastDate: new Date(journey.lastDate), journeyItems: journey.journeyItems.map( (journeyItem: PersistedJourneyItem) => new JourneyItem({ lon: journeyItem.lon, lat: journeyItem.lat, duration: journeyItem.duration, distance: journeyItem.distance, actorTimes: journeyItem.actorTimes.map( (actorTime: PersistedActorTime) => new ActorTime({ role: actorTime.role, target: actorTime.target, firstDatetime: new Date(actorTime.firstDatetime), firstMinDatetime: new Date( actorTime.firstMinDatetime, ), firstMaxDatetime: new Date( actorTime.firstMaxDatetime, ), lastDatetime: new Date(actorTime.lastDatetime), lastMinDatetime: new Date( actorTime.lastMinDatetime, ), lastMaxDatetime: new Date( actorTime.lastMaxDatetime, ), }), ), }), ), }), ), }), ), }, }); return matchingEntity; }; } type PersistedMatching = { id: string; createdAt: string; updatedAt: string; matches: PersistedMatch[]; query: { driver: boolean; passenger: boolean; frequency: Frequency; fromDate: string; toDate: string; schedule: { day: number; time: string; margin: number; }[]; seatsProposed: number; seatsRequested: number; strict: boolean; waypoints: { houseNumber: string; street: string; postalCode: string; locality: string; lon: number; lat: number; country: string; position: number; }[]; algorithmType: string; remoteness: number; useProportion: boolean; proportion: number; useAzimuth: boolean; azimuthMargin: number; maxDetourDistanceRatio: number; maxDetourDurationRatio: number; }; }; type PersistedMatch = { adId: string; role: Role; frequency: Frequency; distance: number; duration: number; initialDistance: number; initialDuration: number; journeys: PersistedJourney[]; }; type PersistedJourney = { firstDate: string; lastDate: string; journeyItems: PersistedJourneyItem[]; }; type PersistedJourneyItem = { lon: number; lat: number; duration: number; distance: number; actorTimes: PersistedActorTime[]; }; type PersistedActorTime = { role: Role; target: Target; firstDatetime: string; firstMinDatetime: string; firstMaxDatetime: string; lastDatetime: string; lastMinDatetime: string; lastMaxDatetime: string; };