/** * Value Object: MembershipFee * Represents membership fee configuration for league drivers */ import { RacingDomainValidationError } from '../errors/RacingDomainError'; import type { Money } from './Money'; import type { IValueObject } from '@gridpilot/shared/domain'; export type MembershipFeeType = 'season' | 'monthly' | 'per_race'; export interface MembershipFeeProps { type: MembershipFeeType; amount: Money; } export class MembershipFee implements IValueObject { readonly type: MembershipFeeType; readonly amount: Money; private constructor(props: MembershipFeeProps) { this.type = props.type; this.amount = props.amount; } static create(type: MembershipFeeType, amount: Money): MembershipFee { if (!type) { throw new RacingDomainValidationError('MembershipFee type is required'); } if (!amount) { throw new RacingDomainValidationError('MembershipFee amount is required'); } if (amount.amount < 0) { throw new RacingDomainValidationError('MembershipFee amount cannot be negative'); } return new MembershipFee({ type, amount }); } /** * Get platform fee for this membership fee */ getPlatformFee(): Money { return this.amount.calculatePlatformFee(); } /** * Get net amount after platform fee */ getNetAmount(): Money { return this.amount.calculateNetAmount(); } get props(): MembershipFeeProps { return { type: this.type, amount: this.amount, }; } /** * Check if this is a recurring fee */ isRecurring(): boolean { return this.type === 'monthly'; } equals(other: IValueObject): boolean { const a = this.props; const b = other.props; return a.type === b.type && a.amount.equals(b.amount); } /** * Get display name for fee type */ getDisplayName(): string { switch (this.type) { case 'season': return 'Season Fee'; case 'monthly': return 'Monthly Subscription'; case 'per_race': return 'Per-Race Fee'; } } }