112 lines
3.6 KiB
TypeScript
112 lines
3.6 KiB
TypeScript
import Decimal from 'decimal.js';
|
|
import { UserId, AssetType, LedgerEntryType, Money } from '@/domain/value-objects';
|
|
|
|
export class LedgerEntry {
|
|
private readonly _id: bigint;
|
|
private readonly _accountSequence: bigint; // 跨服务关联标识 (全局唯一业务ID)
|
|
private readonly _userId: UserId; // 保留兼容
|
|
private readonly _entryType: LedgerEntryType;
|
|
private readonly _amount: Money;
|
|
private readonly _balanceAfter: Money | null;
|
|
private readonly _refOrderId: string | null;
|
|
private readonly _refTxHash: string | null;
|
|
private readonly _memo: string | null;
|
|
private readonly _payloadJson: Record<string, unknown> | null;
|
|
private readonly _createdAt: Date;
|
|
|
|
private constructor(
|
|
id: bigint,
|
|
accountSequence: bigint,
|
|
userId: UserId,
|
|
entryType: LedgerEntryType,
|
|
amount: Money,
|
|
balanceAfter: Money | null,
|
|
refOrderId: string | null,
|
|
refTxHash: string | null,
|
|
memo: string | null,
|
|
payloadJson: Record<string, unknown> | null,
|
|
createdAt: Date,
|
|
) {
|
|
this._id = id;
|
|
this._accountSequence = accountSequence;
|
|
this._userId = userId;
|
|
this._entryType = entryType;
|
|
this._amount = amount;
|
|
this._balanceAfter = balanceAfter;
|
|
this._refOrderId = refOrderId;
|
|
this._refTxHash = refTxHash;
|
|
this._memo = memo;
|
|
this._payloadJson = payloadJson;
|
|
this._createdAt = createdAt;
|
|
}
|
|
|
|
// Getters
|
|
get id(): bigint { return this._id; }
|
|
get accountSequence(): bigint { return this._accountSequence; }
|
|
get userId(): UserId { return this._userId; }
|
|
get entryType(): LedgerEntryType { return this._entryType; }
|
|
get amount(): Money { return this._amount; }
|
|
get assetType(): string { return this._amount.currency; }
|
|
get balanceAfter(): Money | null { return this._balanceAfter; }
|
|
get refOrderId(): string | null { return this._refOrderId; }
|
|
get refTxHash(): string | null { return this._refTxHash; }
|
|
get memo(): string | null { return this._memo; }
|
|
get payloadJson(): Record<string, unknown> | null { return this._payloadJson; }
|
|
get createdAt(): Date { return this._createdAt; }
|
|
|
|
static create(params: {
|
|
accountSequence: bigint;
|
|
userId: UserId;
|
|
entryType: LedgerEntryType;
|
|
amount: Money;
|
|
balanceAfter?: Money;
|
|
refOrderId?: string;
|
|
refTxHash?: string;
|
|
memo?: string;
|
|
payloadJson?: Record<string, unknown>;
|
|
}): LedgerEntry {
|
|
return new LedgerEntry(
|
|
BigInt(0), // Will be set by database
|
|
params.accountSequence,
|
|
params.userId,
|
|
params.entryType,
|
|
params.amount,
|
|
params.balanceAfter ?? null,
|
|
params.refOrderId ?? null,
|
|
params.refTxHash ?? null,
|
|
params.memo ?? null,
|
|
params.payloadJson ?? null,
|
|
new Date(),
|
|
);
|
|
}
|
|
|
|
static reconstruct(params: {
|
|
id: bigint;
|
|
accountSequence: bigint;
|
|
userId: bigint;
|
|
entryType: string;
|
|
amount: Decimal;
|
|
assetType: string;
|
|
balanceAfter: Decimal | null;
|
|
refOrderId: string | null;
|
|
refTxHash: string | null;
|
|
memo: string | null;
|
|
payloadJson: Record<string, unknown> | null;
|
|
createdAt: Date;
|
|
}): LedgerEntry {
|
|
return new LedgerEntry(
|
|
params.id,
|
|
params.accountSequence,
|
|
UserId.create(params.userId),
|
|
params.entryType as LedgerEntryType,
|
|
Money.signed(params.amount, params.assetType), // Use signed() to allow negative amounts for deductions
|
|
params.balanceAfter ? Money.create(params.balanceAfter, params.assetType) : null,
|
|
params.refOrderId,
|
|
params.refTxHash,
|
|
params.memo,
|
|
params.payloadJson,
|
|
params.createdAt,
|
|
);
|
|
}
|
|
}
|