import { Transform, Type } from 'class-transformer' import { add } from 'date-fns' import { isNil } from 'lodash' import { CountryCode, parseDate } from '../utils' import { BaseModel } from './base.model' import { IntervalInMonths, Intervals, PaymentProviders } from './enums' import { PlanFeature } from './plan_feature.model' import { PlanPaymentProvider } from './plan_payment_provider.model' import { FeatureValue } from './vo' export const DEFAULT_INSTALLMENTS_AMOUNT = 1 export class Plan extends BaseModel { id: string name: string order: number interval: Intervals enabled: boolean visible: boolean omie_service_id?: number trial_value: number trial_interval: Intervals version_gte?: string grace_period_days?: number complete?: boolean @Transform(value => parseDate(value), { toClassOnly: true }) created_at: Date @Transform(value => parseDate(value), { toClassOnly: true }) updated_at: Date @Transform(value => parseDate(value), { toClassOnly: true }) active_since: Date @Transform(value => parseDate(value), { toClassOnly: true }) active_until: Date @Type(() => PlanPaymentProvider) payment_providers?: PlanPaymentProvider[] @Type(() => PlanFeature) features?: PlanFeature[] get intervalInMonths(): number { if (!IntervalInMonths[this.interval]) throw new Error('Actual interval not processable') return IntervalInMonths[this.interval] } get trialInDays(): number { switch (this.trial_interval) { case Intervals.DAILY: return this.trial_value case Intervals.MONTHLY: return this.trial_value * 30 case Intervals.YEARLY: return this.trial_value * 365 default: return null } } get trialExpiresAtFromNow(): Date { if (isNil(this.trial_value)) throw new Error(`Plan ${this.id} doesn't has a valid trial`) const periodUnit = this.trial_interval === Intervals.YEARLY ? 'years' : this.trial_interval === Intervals.MONTHLY ? 'months' : 'days' return add(new Date(), { [periodUnit]: this.trial_value }) } get kind(): 'bio' | 'complete' | 'teleconsultation' { if (this.complete) return 'complete' return !this.getFeature('teleconsultation')?.quantity ? 'bio' : 'teleconsultation' } getPaymentProvider(provider: PaymentProviders, countryCode?: CountryCode): PlanPaymentProvider { return this.payment_providers.find( paymentProvider => paymentProvider.provider === provider && (!countryCode || paymentProvider.country_code === countryCode), ) } addInstallmentsToPaymentProviders(installmentsMap: Record): void { this.payment_providers = this.payment_providers.map( paymentProvider => new PlanPaymentProvider({ ...paymentProvider, installments: installmentsMap?.[paymentProvider.code] || DEFAULT_INSTALLMENTS_AMOUNT, }), ) } getFeature(feature: FeatureValue): PlanFeature { return this.features?.find(planFeature => planFeature.feature === feature) } }