matcher/old/modules/matcher/domain/entities/ecosystem/time.ts

207 lines
5.9 KiB
TypeScript

import {
MatcherException,
MatcherExceptionCode,
} from '../../../exceptions/matcher.exception';
import { MarginDurations } from '../../types/margin-durations.type';
import { IRequestTime } from '../../interfaces/time-request.interface';
import { DAYS } from '../../types/days.const';
import { TimeSchedule } from '../../types/time-schedule.type';
import { Frequency } from '../../../../ad/domain/types/frequency.enum';
import { Day } from '../../types/day.type';
import { IConvertTime } from '../../interfaces/time-converter.interface';
export class Time {
private timeRequest: IRequestTime;
private defaultValidityDuration: number;
private timeConverter: IConvertTime;
frequency: Frequency;
fromDate: Date;
toDate: Date;
schedule: TimeSchedule;
marginDurations: MarginDurations;
constructor(
timeRequest: IRequestTime,
defaultMarginDuration: number,
defaultValidityDuration: number,
timeConverter: IConvertTime,
) {
this.timeRequest = timeRequest;
this.defaultValidityDuration = defaultValidityDuration;
this.timeConverter = timeConverter;
this.schedule = {};
this.marginDurations = {
mon: defaultMarginDuration,
tue: defaultMarginDuration,
wed: defaultMarginDuration,
thu: defaultMarginDuration,
fri: defaultMarginDuration,
sat: defaultMarginDuration,
sun: defaultMarginDuration,
};
}
init = (): void => {
this.validateBaseDate();
this.validatePunctualRequest();
this.validateRecurrentRequest();
this.setPunctualRequest();
this.setRecurrentRequest();
this.setMargindurations();
};
private validateBaseDate = (): void => {
if (!this.timeRequest.departure && !this.timeRequest.fromDate) {
throw new MatcherException(
MatcherExceptionCode.INVALID_ARGUMENT,
'departure or fromDate is required',
);
}
};
private validatePunctualRequest = (): void => {
if (this.timeRequest.departure) {
this.fromDate = this.toDate = new Date(this.timeRequest.departure);
if (!this.isDate(this.fromDate)) {
throw new MatcherException(
MatcherExceptionCode.INVALID_ARGUMENT,
'Wrong departure date',
);
}
}
};
private validateRecurrentRequest = (): void => {
if (this.timeRequest.fromDate) {
this.fromDate = new Date(this.timeRequest.fromDate);
if (!this.isDate(this.fromDate)) {
throw new MatcherException(
MatcherExceptionCode.INVALID_ARGUMENT,
'Wrong fromDate',
);
}
}
if (this.timeRequest.toDate) {
this.toDate = new Date(this.timeRequest.toDate);
if (!this.isDate(this.toDate)) {
throw new MatcherException(
MatcherExceptionCode.INVALID_ARGUMENT,
'Wrong toDate',
);
}
if (this.toDate < this.fromDate) {
throw new MatcherException(
MatcherExceptionCode.INVALID_ARGUMENT,
'toDate must be after fromDate',
);
}
}
if (this.timeRequest.fromDate) {
this.validateSchedule();
}
};
private validateSchedule = (): void => {
if (!this.timeRequest.schedule) {
throw new MatcherException(
MatcherExceptionCode.INVALID_ARGUMENT,
'Schedule is required',
);
}
if (
!Object.keys(this.timeRequest.schedule).some((elem) =>
DAYS.includes(elem),
)
) {
throw new MatcherException(
MatcherExceptionCode.INVALID_ARGUMENT,
'No valid day in the given schedule',
);
}
Object.keys(this.timeRequest.schedule).map((day) => {
const time = new Date('1970-01-01 ' + this.timeRequest.schedule[day]);
if (!this.isDate(time)) {
throw new MatcherException(
MatcherExceptionCode.INVALID_ARGUMENT,
`Wrong time for ${day} in schedule`,
);
}
});
};
private setPunctualRequest = (): void => {
if (this.timeRequest.departure) {
this.frequency = Frequency.PUNCTUAL;
this.schedule[Day[this.fromDate.getDay()]] = this.timeConverter.toUtcDate(
this.fromDate,
this.timeRequest.timezone,
);
}
};
private setRecurrentRequest = (): void => {
if (this.timeRequest.fromDate) {
this.frequency = Frequency.RECURRENT;
if (!this.toDate) {
this.toDate = this.addDays(this.fromDate, this.defaultValidityDuration);
}
this.setSchedule();
}
};
private setSchedule = (): void => {
Object.keys(this.timeRequest.schedule).map((day) => {
this.schedule[day] = this.timeConverter.toUtcDate(
new Date(
`${this.fromDate.getFullYear()}-${this.fromDate.getMonth()}-${this.fromDate.getDate()} ${
this.timeRequest.schedule[day]
}`,
),
this.timeRequest.timezone,
);
});
};
private setMargindurations = (): void => {
if (this.timeRequest.marginDuration) {
const duration = Math.abs(this.timeRequest.marginDuration);
this.marginDurations = {
mon: duration,
tue: duration,
wed: duration,
thu: duration,
fri: duration,
sat: duration,
sun: duration,
};
}
if (this.timeRequest.marginDurations) {
if (
!Object.keys(this.timeRequest.marginDurations).some((elem) =>
DAYS.includes(elem),
)
) {
throw new MatcherException(
MatcherExceptionCode.INVALID_ARGUMENT,
'No valid day in the given margin durations',
);
}
Object.keys(this.timeRequest.marginDurations).map((day) => {
this.marginDurations[day] = Math.abs(
this.timeRequest.marginDurations[day],
);
});
}
};
private isDate = (date: Date): boolean => {
return date instanceof Date && isFinite(+date);
};
private addDays = (date: Date, days: number): Date => {
const result = new Date(date);
result.setDate(result.getDate() + days);
return result;
};
}