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 { 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 { 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 { const record = await this.prisma.virtualAccount.findUnique({ where: { id }, }); if (!record) return null; return this.toDomain(record); } async findByType(type: VirtualAccountType): Promise { 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 { 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 { 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 { const record = await this.prisma.virtualAccount.findFirst({ where: { accountType: VirtualAccountType.SYSTEM_CITY, cityCode, }, }); if (!record) return null; return this.toDomain(record); } async findHeadquarters(): Promise { const record = await this.prisma.virtualAccount.findFirst({ where: { accountType: VirtualAccountType.HEADQUARTERS }, }); if (!record) return null; return this.toDomain(record); } async countByType(type: VirtualAccountType): Promise { return this.prisma.virtualAccount.count({ where: { accountType: type }, }); } async deleteById(id: bigint): Promise { 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, }); } }