61 lines
1.7 KiB
TypeScript
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;
|
|
}
|
|
}
|