/** * Domain Entity: SponsorAccount * * Represents a sponsor's login account in the identity bounded context. * Separate from the racing domain's Sponsor entity which holds business data. */ import type { EmailValidationResult } from '../types/EmailAddress'; import { validateEmail } from '../types/EmailAddress'; import { UserId } from '../value-objects/UserId'; export interface SponsorAccountProps { id: UserId; sponsorId: string; // Reference to racing domain's Sponsor entity email: string; passwordHash: string; companyName: string; isActive: boolean; createdAt: Date; lastLoginAt?: Date; } export class SponsorAccount { private readonly id: UserId; private readonly sponsorId: string; private email: string; private passwordHash: string; private companyName: string; private isActive: boolean; private readonly createdAt: Date; private lastLoginAt: Date | undefined; private constructor(props: SponsorAccountProps) { this.id = props.id; this.sponsorId = props.sponsorId; this.email = props.email; this.passwordHash = props.passwordHash; this.companyName = props.companyName; this.isActive = props.isActive; this.createdAt = props.createdAt ?? new Date(); this.lastLoginAt = props.lastLoginAt; } public static create(props: Omit & { createdAt?: Date; isActive?: boolean; }): SponsorAccount { if (!props.sponsorId || !props.sponsorId.trim()) { throw new Error('SponsorAccount sponsorId is required'); } if (!props.companyName || !props.companyName.trim()) { throw new Error('SponsorAccount companyName is required'); } if (!props.passwordHash || !props.passwordHash.trim()) { throw new Error('SponsorAccount passwordHash is required'); } const emailResult: EmailValidationResult = validateEmail(props.email); if (!emailResult.success) { throw new Error(emailResult.error); } return new SponsorAccount({ ...props, email: emailResult.email, createdAt: props.createdAt ?? new Date(), isActive: props.isActive ?? true, }); } public getId(): UserId { return this.id; } public getSponsorId(): string { return this.sponsorId; } public getEmail(): string { return this.email; } public getPasswordHash(): string { return this.passwordHash; } public getCompanyName(): string { return this.companyName; } public getIsActive(): boolean { return this.isActive; } public getCreatedAt(): Date { return this.createdAt; } public getLastLoginAt(): Date | undefined { return this.lastLoginAt; } public canLogin(): boolean { return this.isActive; } public recordLogin(): SponsorAccount { return new SponsorAccount({ id: this.id, sponsorId: this.sponsorId, email: this.email, passwordHash: this.passwordHash, companyName: this.companyName, isActive: this.isActive, createdAt: this.createdAt, lastLoginAt: new Date(), }); } public deactivate(): SponsorAccount { return new SponsorAccount({ id: this.id, sponsorId: this.sponsorId, email: this.email, passwordHash: this.passwordHash, companyName: this.companyName, isActive: false, createdAt: this.createdAt, ...(this.lastLoginAt ? { lastLoginAt: this.lastLoginAt } : {}), }); } public updatePassword(newPasswordHash: string): SponsorAccount { if (!newPasswordHash || !newPasswordHash.trim()) { throw new Error('Password hash cannot be empty'); } return new SponsorAccount({ id: this.id, sponsorId: this.sponsorId, email: this.email, passwordHash: newPasswordHash, companyName: this.companyName, isActive: this.isActive, createdAt: this.createdAt, ...(this.lastLoginAt ? { lastLoginAt: this.lastLoginAt } : {}), }); } }