rwadurian/backend/services/identity-service/src/domain/value-objects/account-sequence.vo.ts

61 lines
1.7 KiB
TypeScript

import { DomainError } from '@/shared/exceptions/domain.exception';
/**
* 账户序列号值对象
* 格式: D + 年(2位) + 月(2位) + 日(2位) + 5位序号
* 示例: D2512110008 -> 2025年12月11日的第8个注册用户
*/
export class AccountSequence {
private static readonly PATTERN = /^D\d{11}$/;
constructor(public readonly value: string) {
if (!AccountSequence.PATTERN.test(value)) {
throw new DomainError(
`账户序列号格式无效: ${value},应为 D + 年月日(6位) + 序号(5位)`,
);
}
}
static create(value: string): AccountSequence {
return new AccountSequence(value);
}
/**
* 根据日期和当日序号生成新的账户序列号
* @param date 日期
* @param dailySequence 当日序号 (0-99999)
*/
static generate(date: Date, dailySequence: number): AccountSequence {
if (dailySequence < 0 || dailySequence > 99999) {
throw new DomainError(`当日序号超出范围: ${dailySequence},应为 0-99999`);
}
const year = String(date.getFullYear()).slice(-2);
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const seq = String(dailySequence).padStart(5, '0');
return new AccountSequence(`D${year}${month}${day}${seq}`);
}
/**
* 从序列号中提取日期字符串 (YYMMDD)
*/
get dateString(): string {
return this.value.slice(1, 7);
}
/**
* 从序列号中提取当日序号
*/
get dailySequence(): number {
return parseInt(this.value.slice(7), 10);
}
equals(other: AccountSequence): boolean {
return this.value === other.value;
}
toString(): string {
return this.value;
}
}