matcher/src/modules/ad/ad.mapper.ts

131 lines
4.1 KiB
TypeScript

import { Inject, Injectable } from '@nestjs/common';
import { AdEntity } from './core/domain/ad.entity';
import {
AdWriteModel,
AdReadModel,
ScheduleItemModel,
AdWriteExtraModel,
} from './infrastructure/ad.repository';
import { v4 } from 'uuid';
import {
ScheduleItem,
ScheduleItemProps,
} from './core/domain/value-objects/schedule-item.value-object';
import { DirectionEncoderPort } from '@modules/geography/core/application/ports/direction-encoder.port';
import { AD_DIRECTION_ENCODER } from './ad.di-tokens';
import { ExtendedMapper } from '@mobicoop/ddd-library';
/**
* Mapper constructs objects that are used in different layers:
* Record is an object that is stored in a database,
* Entity is an object that is used in application domain layer,
* and a ResponseDTO is an object returned to a user (usually as json).
*/
@Injectable()
export class AdMapper
implements
ExtendedMapper<
AdEntity,
AdReadModel,
AdWriteModel,
AdWriteExtraModel,
undefined
>
{
constructor(
@Inject(AD_DIRECTION_ENCODER)
private readonly directionEncoder: DirectionEncoderPort,
) {}
toPersistence = (entity: AdEntity): AdWriteModel => {
const copy = entity.getProps();
const now = new Date();
const record: AdWriteModel = {
uuid: copy.id,
driver: copy.driver,
passenger: copy.passenger,
frequency: copy.frequency,
fromDate: new Date(copy.fromDate),
toDate: new Date(copy.toDate),
schedule: {
create: copy.schedule.map((scheduleItem: ScheduleItemProps) => ({
uuid: v4(),
day: scheduleItem.day,
time: new Date(
1970,
0,
1,
parseInt(scheduleItem.time.split(':')[0]),
parseInt(scheduleItem.time.split(':')[1]),
),
margin: scheduleItem.margin,
createdAt: now,
updatedAt: now,
})),
},
seatsProposed: copy.seatsProposed,
seatsRequested: copy.seatsRequested,
strict: copy.strict,
driverDuration: copy.driverDuration,
driverDistance: copy.driverDistance,
passengerDuration: copy.passengerDuration,
passengerDistance: copy.passengerDistance,
fwdAzimuth: copy.fwdAzimuth,
backAzimuth: copy.backAzimuth,
createdAt: copy.createdAt,
updatedAt: copy.updatedAt,
};
return record;
};
toDomain = (record: AdReadModel): AdEntity =>
new AdEntity({
id: record.uuid,
createdAt: new Date(record.createdAt),
updatedAt: new Date(record.updatedAt),
props: {
seatsProposed: record.seatsProposed,
seatsRequested: record.seatsRequested,
strict: record.strict,
driverDuration: record.driverDuration,
driverDistance: record.driverDistance,
passengerDuration: record.passengerDuration,
passengerDistance: record.passengerDistance,
driver: record.driver,
passenger: record.passenger,
frequency: record.frequency,
fromDate: record.fromDate.toISOString().split('T')[0],
toDate: record.toDate.toISOString().split('T')[0],
schedule: record.schedule.map(
(scheduleItem: ScheduleItemModel) =>
new ScheduleItem({
day: scheduleItem.day,
time: `${scheduleItem.time
.getUTCHours()
.toString()
.padStart(2, '0')}:${scheduleItem.time
.getUTCMinutes()
.toString()
.padStart(2, '0')}`,
margin: scheduleItem.margin,
}),
),
waypoints: this.directionEncoder
.decode(record.waypoints)
.map((coordinates, index) => ({
position: index,
...coordinates,
})),
fwdAzimuth: record.fwdAzimuth,
backAzimuth: record.backAzimuth,
points: [],
},
});
toPersistenceExtra = (entity: AdEntity): AdWriteExtraModel => ({
waypoints: this.directionEncoder.encode(entity.getProps().waypoints),
direction: this.directionEncoder.encode(entity.getProps().points),
});
}