wip
This commit is contained in:
@@ -11,40 +11,53 @@ import type { IEntity } from '@gridpilot/shared/domain';
|
||||
import type { Money } from '../value-objects/Money';
|
||||
|
||||
export type SponsorshipTier = 'main' | 'secondary';
|
||||
export type SponsorshipStatus = 'pending' | 'active' | 'cancelled';
|
||||
export type SponsorshipStatus = 'pending' | 'active' | 'ended' | 'cancelled';
|
||||
|
||||
export interface SeasonSponsorshipProps {
|
||||
id: string;
|
||||
seasonId: string;
|
||||
/**
|
||||
* Optional denormalized leagueId for fast league-level aggregations.
|
||||
* Must always match the owning Season's leagueId when present.
|
||||
*/
|
||||
leagueId?: string;
|
||||
sponsorId: string;
|
||||
tier: SponsorshipTier;
|
||||
pricing: Money;
|
||||
status: SponsorshipStatus;
|
||||
createdAt: Date;
|
||||
activatedAt?: Date;
|
||||
endedAt?: Date;
|
||||
cancelledAt?: Date;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
export class SeasonSponsorship implements IEntity<string> {
|
||||
readonly id: string;
|
||||
readonly seasonId: string;
|
||||
readonly leagueId: string | undefined;
|
||||
readonly sponsorId: string;
|
||||
readonly tier: SponsorshipTier;
|
||||
readonly pricing: Money;
|
||||
readonly status: SponsorshipStatus;
|
||||
readonly createdAt: Date;
|
||||
readonly activatedAt: Date | undefined;
|
||||
readonly endedAt: Date | undefined;
|
||||
readonly cancelledAt: Date | undefined;
|
||||
readonly description: string | undefined;
|
||||
|
||||
private constructor(props: SeasonSponsorshipProps) {
|
||||
this.id = props.id;
|
||||
this.seasonId = props.seasonId;
|
||||
this.leagueId = props.leagueId;
|
||||
this.sponsorId = props.sponsorId;
|
||||
this.tier = props.tier;
|
||||
this.pricing = props.pricing;
|
||||
this.status = props.status;
|
||||
this.createdAt = props.createdAt;
|
||||
this.activatedAt = props.activatedAt;
|
||||
this.endedAt = props.endedAt;
|
||||
this.cancelledAt = props.cancelledAt;
|
||||
this.description = props.description;
|
||||
}
|
||||
|
||||
@@ -57,12 +70,15 @@ export class SeasonSponsorship implements IEntity<string> {
|
||||
return new SeasonSponsorship({
|
||||
id: props.id,
|
||||
seasonId: props.seasonId,
|
||||
...(props.leagueId !== undefined ? { leagueId: props.leagueId } : {}),
|
||||
sponsorId: props.sponsorId,
|
||||
tier: props.tier,
|
||||
pricing: props.pricing,
|
||||
status: props.status ?? 'pending',
|
||||
createdAt: props.createdAt ?? new Date(),
|
||||
...(props.activatedAt !== undefined ? { activatedAt: props.activatedAt } : {}),
|
||||
...(props.endedAt !== undefined ? { endedAt: props.endedAt } : {}),
|
||||
...(props.cancelledAt !== undefined ? { cancelledAt: props.cancelledAt } : {}),
|
||||
...(props.description !== undefined ? { description: props.description } : {}),
|
||||
});
|
||||
}
|
||||
@@ -105,15 +121,56 @@ export class SeasonSponsorship implements IEntity<string> {
|
||||
throw new RacingDomainInvariantError('Cannot activate a cancelled SeasonSponsorship');
|
||||
}
|
||||
|
||||
if (this.status === 'ended') {
|
||||
throw new RacingDomainInvariantError('Cannot activate an ended SeasonSponsorship');
|
||||
}
|
||||
|
||||
const base: SeasonSponsorshipProps = {
|
||||
id: this.id,
|
||||
seasonId: this.seasonId,
|
||||
...(this.leagueId !== undefined ? { leagueId: this.leagueId } : {}),
|
||||
sponsorId: this.sponsorId,
|
||||
tier: this.tier,
|
||||
pricing: this.pricing,
|
||||
status: 'active',
|
||||
createdAt: this.createdAt,
|
||||
activatedAt: new Date(),
|
||||
...(this.endedAt !== undefined ? { endedAt: this.endedAt } : {}),
|
||||
...(this.cancelledAt !== undefined ? { cancelledAt: this.cancelledAt } : {}),
|
||||
};
|
||||
|
||||
const next: SeasonSponsorshipProps =
|
||||
this.description !== undefined
|
||||
? { ...base, description: this.description }
|
||||
: base;
|
||||
|
||||
return new SeasonSponsorship(next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the sponsorship as ended (completed term)
|
||||
*/
|
||||
end(): SeasonSponsorship {
|
||||
if (this.status === 'cancelled') {
|
||||
throw new RacingDomainInvariantError('Cannot end a cancelled SeasonSponsorship');
|
||||
}
|
||||
|
||||
if (this.status === 'ended') {
|
||||
throw new RacingDomainInvariantError('SeasonSponsorship is already ended');
|
||||
}
|
||||
|
||||
const base: SeasonSponsorshipProps = {
|
||||
id: this.id,
|
||||
seasonId: this.seasonId,
|
||||
...(this.leagueId !== undefined ? { leagueId: this.leagueId } : {}),
|
||||
sponsorId: this.sponsorId,
|
||||
tier: this.tier,
|
||||
pricing: this.pricing,
|
||||
status: 'ended',
|
||||
createdAt: this.createdAt,
|
||||
...(this.activatedAt !== undefined ? { activatedAt: this.activatedAt } : {}),
|
||||
endedAt: new Date(),
|
||||
...(this.cancelledAt !== undefined ? { cancelledAt: this.cancelledAt } : {}),
|
||||
};
|
||||
|
||||
const next: SeasonSponsorshipProps =
|
||||
@@ -135,22 +192,55 @@ export class SeasonSponsorship implements IEntity<string> {
|
||||
const base: SeasonSponsorshipProps = {
|
||||
id: this.id,
|
||||
seasonId: this.seasonId,
|
||||
...(this.leagueId !== undefined ? { leagueId: this.leagueId } : {}),
|
||||
sponsorId: this.sponsorId,
|
||||
tier: this.tier,
|
||||
pricing: this.pricing,
|
||||
status: 'cancelled',
|
||||
createdAt: this.createdAt,
|
||||
...(this.activatedAt !== undefined ? { activatedAt: this.activatedAt } : {}),
|
||||
...(this.endedAt !== undefined ? { endedAt: this.endedAt } : {}),
|
||||
cancelledAt: new Date(),
|
||||
};
|
||||
|
||||
const withActivated =
|
||||
this.activatedAt !== undefined
|
||||
? { ...base, activatedAt: this.activatedAt }
|
||||
: base;
|
||||
|
||||
const next: SeasonSponsorshipProps =
|
||||
this.description !== undefined
|
||||
? { ...withActivated, description: this.description }
|
||||
: withActivated;
|
||||
? { ...base, description: this.description }
|
||||
: base;
|
||||
|
||||
return new SeasonSponsorship(next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update pricing/terms when allowed
|
||||
*/
|
||||
withPricing(pricing: Money): SeasonSponsorship {
|
||||
if (pricing.amount <= 0) {
|
||||
throw new RacingDomainValidationError('SeasonSponsorship pricing must be greater than zero');
|
||||
}
|
||||
|
||||
if (this.status === 'cancelled' || this.status === 'ended') {
|
||||
throw new RacingDomainInvariantError('Cannot update pricing for ended or cancelled SeasonSponsorship');
|
||||
}
|
||||
|
||||
const base: SeasonSponsorshipProps = {
|
||||
id: this.id,
|
||||
seasonId: this.seasonId,
|
||||
...(this.leagueId !== undefined ? { leagueId: this.leagueId } : {}),
|
||||
sponsorId: this.sponsorId,
|
||||
tier: this.tier,
|
||||
pricing,
|
||||
status: this.status,
|
||||
createdAt: this.createdAt,
|
||||
...(this.activatedAt !== undefined ? { activatedAt: this.activatedAt } : {}),
|
||||
...(this.endedAt !== undefined ? { endedAt: this.endedAt } : {}),
|
||||
...(this.cancelledAt !== undefined ? { cancelledAt: this.cancelledAt } : {}),
|
||||
};
|
||||
|
||||
const next: SeasonSponsorshipProps =
|
||||
this.description !== undefined
|
||||
? { ...base, description: this.description }
|
||||
: base;
|
||||
|
||||
return new SeasonSponsorship(next);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user