rwadurian/backend/services/wallet-service/src/domain/aggregates/ledger-entry.aggregate.ts

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,
);
}
}