rwadurian/backend/services/leaderboard-service/src/infrastructure/repositories/virtual-account.repository....

156 lines
4.7 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import { PrismaService } from '../database/prisma.service';
import { IVirtualAccountRepository } from '../../domain/repositories/virtual-account.repository.interface';
import { VirtualAccount } from '../../domain/entities/virtual-account.entity';
import { VirtualAccountType } from '../../domain/value-objects/virtual-account-type.enum';
import { Decimal } from '@prisma/client/runtime/library';
@Injectable()
export class VirtualAccountRepositoryImpl implements IVirtualAccountRepository {
constructor(private readonly prisma: PrismaService) {}
async save(account: VirtualAccount): Promise<void> {
const data = {
accountType: account.accountType,
displayName: account.displayName,
avatar: account.avatar,
provinceCode: account.provinceCode,
cityCode: account.cityCode,
minScore: account.minScore,
maxScore: account.maxScore,
currentScore: account.currentScore,
usdtBalance: new Decimal(account.usdtBalance),
hashpowerBalance: new Decimal(account.hashpowerBalance),
isActive: account.isActive,
};
if (account.id) {
await this.prisma.virtualAccount.update({
where: { id: account.id },
data,
});
} else {
const result = await this.prisma.virtualAccount.create({
data,
});
account.setId(result.id);
}
}
async saveAll(accounts: VirtualAccount[]): Promise<void> {
await this.prisma.$transaction(
accounts.map((account) =>
this.prisma.virtualAccount.create({
data: {
accountType: account.accountType,
displayName: account.displayName,
avatar: account.avatar,
provinceCode: account.provinceCode,
cityCode: account.cityCode,
minScore: account.minScore,
maxScore: account.maxScore,
currentScore: account.currentScore,
usdtBalance: new Decimal(account.usdtBalance),
hashpowerBalance: new Decimal(account.hashpowerBalance),
isActive: account.isActive,
},
})
)
);
}
async findById(id: bigint): Promise<VirtualAccount | null> {
const record = await this.prisma.virtualAccount.findUnique({
where: { id },
});
if (!record) return null;
return this.toDomain(record);
}
async findByType(type: VirtualAccountType): Promise<VirtualAccount[]> {
const records = await this.prisma.virtualAccount.findMany({
where: { accountType: type },
orderBy: { createdAt: 'asc' },
});
return records.map((r) => this.toDomain(r));
}
async findActiveRankingVirtuals(limit: number): Promise<VirtualAccount[]> {
const records = await this.prisma.virtualAccount.findMany({
where: {
accountType: VirtualAccountType.RANKING_VIRTUAL,
isActive: true,
},
take: limit,
orderBy: { createdAt: 'asc' },
});
return records.map((r) => this.toDomain(r));
}
async findByProvinceCode(provinceCode: string): Promise<VirtualAccount | null> {
const record = await this.prisma.virtualAccount.findFirst({
where: {
accountType: VirtualAccountType.SYSTEM_PROVINCE,
provinceCode,
},
});
if (!record) return null;
return this.toDomain(record);
}
async findByCityCode(cityCode: string): Promise<VirtualAccount | null> {
const record = await this.prisma.virtualAccount.findFirst({
where: {
accountType: VirtualAccountType.SYSTEM_CITY,
cityCode,
},
});
if (!record) return null;
return this.toDomain(record);
}
async findHeadquarters(): Promise<VirtualAccount | null> {
const record = await this.prisma.virtualAccount.findFirst({
where: { accountType: VirtualAccountType.HEADQUARTERS },
});
if (!record) return null;
return this.toDomain(record);
}
async countByType(type: VirtualAccountType): Promise<number> {
return this.prisma.virtualAccount.count({
where: { accountType: type },
});
}
async deleteById(id: bigint): Promise<void> {
await this.prisma.virtualAccount.delete({
where: { id },
});
}
private toDomain(record: any): VirtualAccount {
return VirtualAccount.reconstitute({
id: record.id,
accountType: record.accountType as VirtualAccountType,
displayName: record.displayName,
avatar: record.avatar,
provinceCode: record.provinceCode,
cityCode: record.cityCode,
minScore: record.minScore,
maxScore: record.maxScore,
currentScore: record.currentScore,
usdtBalance: Number(record.usdtBalance),
hashpowerBalance: Number(record.hashpowerBalance),
isActive: record.isActive,
createdAt: record.createdAt,
});
}
}