import { PasswordUtil } from '@/common/utils/password.util' import { LicenseChargeTransaction } from '@/generated/prisma/client' import { AccountStatus, AccountType, PartnerRole, PartnerStatus, } from '@/generated/prisma/enums' import { PartnerSelect } from '@/generated/prisma/models' import { PrismaService } from '@/prisma/prisma.service' import { Injectable } from '@nestjs/common' import { ResponseMapper } from 'common/response/response-mapper' import { CreatePartnerDto, UpdatePartnerDto } from './dto/partner.dto' @Injectable() export class PartnersService { constructor(private readonly prisma: PrismaService) {} private readonly defaultSelect: PartnerSelect = { id: true, name: true, code: true, status: true, created_at: true, } private readonly separateLicenseCount = ( transactions: LicenseChargeTransaction[] | null, ) => { function toDateOnlyString(date) { return date.toISOString().slice(0, 10) } const startOfTodayDate = toDateOnlyString(new Date()) const used = transactions?.reduce((sum, cur) => { const license = cur as any return sum + license.licenses.filter(license => license.activation).length || 0 }, 0) const total = transactions?.reduce((sum, cur) => { const license = cur as any return sum + license.licenses.length || 0 }, 0) const expired = transactions?.reduce((sum, cur) => { const license = cur as any const activationExpiresDate = toDateOnlyString(license.activation_expires_at) if (startOfTodayDate > activationExpiresDate) return sum + license.licenses.filter(license => !license.activation).length || 0 return sum }, 0) return { total, used, expired, } } async findAll() { const partners = await this.prisma.partner.findMany({ select: this.defaultSelect, }) // const mappedPartners = partners.map(partner => { // const { license_charge_transactions, account_quota_charge_transactions, ...rest } = partner // const a = { total: 0, used: 0, expired: 0 } // account_quota_charge_transactions.forEach(account_quota_charge_transaction => { // a.total += account_quota_charge_transaction. // }) // return { // ...rest, // licenses_status: this.separateLicenseCount(license_charge_transactions), // } // }) return ResponseMapper.list(partners) } async findOne(id: string) { const partner = await this.prisma.partner.findUniqueOrThrow({ where: { id }, select: { ...this.defaultSelect, license_charge_transactions: { select: { purchased_count: true, _count: { select: { licenses: { where: { activation: { isNot: null, }, }, }, }, }, }, }, account_quota_charge_transactions: { select: { purchased_count: true, _count: { select: { allocations: { where: { license_id: null, }, }, }, }, }, }, }, }) const { license_charge_transactions, account_quota_charge_transactions, ...rest } = partner const account_quota_status = { total: 0, used: 0, expired: 0 } account_quota_charge_transactions.forEach(account_quota_charge_transaction => { account_quota_status.total += account_quota_charge_transaction.purchased_count account_quota_status.used += account_quota_charge_transaction._count.allocations account_quota_status.expired += account_quota_charge_transaction.purchased_count - account_quota_charge_transaction._count.allocations }) const licenses_status = { total: 0, used: 0, expired: 0 } license_charge_transactions.forEach(license_charge_transaction => { licenses_status.total += license_charge_transaction.purchased_count licenses_status.used += license_charge_transaction._count.licenses licenses_status.expired += license_charge_transaction.purchased_count - license_charge_transaction._count.licenses }) const mappedPartner = { ...rest, licenses_status, account_quota_status, } return ResponseMapper.single(mappedPartner) } async create(data: CreatePartnerDto) { const { username, password, ...rest } = data const partner = await this.prisma.partner.create({ data: { ...rest, status: PartnerStatus.ACTIVE, partner_accounts: { create: { role: PartnerRole.OWNER, account: { create: { username, password: await PasswordUtil.hash(data.password), status: AccountStatus.ACTIVE, type: AccountType.PARTNER, }, }, }, }, }, select: this.defaultSelect, }) return ResponseMapper.create(partner) } async update(id: string, data: UpdatePartnerDto) { const partner = await this.prisma.partner.update({ where: { id }, data, select: this.defaultSelect, }) return ResponseMapper.update(partner) } async delete(id: string) { await this.prisma.partner.delete({ where: { id } }) return ResponseMapper.delete() } }