import { Injectable } from '@nestjs/common' import { isNil } from 'lodash' import { BioimpedanceCreditService, CreditService, TeleconsultationsCreditService } from '../../../services/credits' import { BusinessExceptionError } from '../../../errors/business_exception.error' import { CampaignRepository, CreditPendingRepository } from '../../../repositories/credits' import { CreditPending, Patient, Products } from '../../../models' type finishPendingCreditsParams = { documentNumber?: string email?: string } @Injectable() export class Credits { constructor( private readonly bioimpedanceCreditService: BioimpedanceCreditService, private readonly teleconsultationsCreditService: TeleconsultationsCreditService, private readonly creditPendingRepository: CreditPendingRepository, private readonly campaignRepository: CampaignRepository, ) {} async finishPendingCredits(patient: Patient): Promise { const pendings = await this.findPendingCredits({ documentNumber: patient.document_number, email: patient.email }) await Promise.all( pendings.map(creditPending => this.getCreditServiceByProduct(creditPending.product).freePendingCredit(creditPending, patient.id), ), ) } async earnBioimpedanceCredit(patient: Patient): Promise { const credits = await this.bioimpedanceCreditService.getBalance(patient.id) if (credits > 0) return await this.bioimpedanceCreditService.createTransaction({ patientId: patient.id, reason: 'signup', value: 1, author: patient, }) } async addByCampaign(patientId: string, campaignValue: string): Promise { const campaign = await this.campaignRepository.get(campaignValue) if (!campaign.isValid) return false const hasUsedCampaign = await this.campaignRepository.checkIfPatientsAlreadyUsedCampaign(patientId, campaign) if (hasUsedCampaign) return false await this.getCreditServiceByProduct(campaign.product).createTransaction({ patientId, reason: 'campaign', value: campaign.credit_quantity, author: Patient.toInstance({ id: patientId }), campaignValue, }) return true } private async findPendingCredits(identifier: finishPendingCreditsParams): Promise { if (!isNil(identifier.documentNumber)) return this.creditPendingRepository.findByDocumentNumber(identifier.documentNumber) if (!isNil(identifier.email)) return this.creditPendingRepository.findByEmail(identifier.email) return [] } private getCreditServiceByProduct(productCode: Products): CreditService { if (productCode === Products.BIOIMPEDANCE) return this.bioimpedanceCreditService if (productCode === Products.TELECONSULTATIONS) return this.teleconsultationsCreditService throw new BusinessExceptionError('Invalid product') } }