import { Injectable } from '@nestjs/common' import { isNil, omitBy } from 'lodash' import { Competition, Patient } from '../../../models' import { RequiredArgumentError } from '../../../errors' import { Notification, NotificationType } from '../types' import { NotificationService } from '../notification.service' import { AwsService } from '../../aws/aws.service' import { CountryCode, LanguageCountryCode } from '../../../utils/countries' import { Push } from '../../../typings/global' import { TranslateNotificationServiceHelper } from '../i18n' export type RankingMsgType = | 'ranking_invite_accepted_push' | 'ranking_finished_won_push' | 'ranking_finished_lose_push' | 'ranking_friend_did_bio_push' export type GetRankingMessageArgs = { patient_id: string device_id: string document_number: string country_code: LanguageCountryCode cell_phone: string email: string type: NotificationType winner?: boolean competition_id: string competition_title: string patient_name: string rankingMsgType: RankingMsgType } @Injectable() export class RankingNotificationService { constructor( private readonly notificationService: NotificationService, private readonly awsService: AwsService, private readonly translator: TranslateNotificationServiceHelper, ) {} async send(patient: Patient, rankingMsgType: RankingMsgType, competition: Competition): Promise { this.validatePatient(patient) if ( ![ 'ranking_invite_accepted_push', 'ranking_finished_won_push', 'ranking_finished_lose_push', 'ranking_friend_did_bio_push', ].includes(rankingMsgType) ) throw new Error('Message type not supported') const message = this.getMessageToPrepare({ patient_id: patient.id, device_id: patient.device_id, document_number: patient.document_number, country_code: patient.country_code as LanguageCountryCode, cell_phone: patient.cell_phone, email: patient.email, type: 'push', winner: competition.winner_id == patient.id, competition_id: competition.id, competition_title: competition.title, patient_name: patient.name, rankingMsgType, }) await this.awsService.sendSQS(this.notificationService.prepareMessage(message)) } private validatePatient(patient: Patient): void { if (!patient.device_id) throw new Error('Patient must have device_id to receive push messages.') if (!patient.country_code) throw new RequiredArgumentError('country_code') if (!patient.document_number && !patient.email) throw new RequiredArgumentError(Patient.loginField(patient.country_code)) } private getMessageToPrepare({ patient_id, device_id, document_number, country_code, cell_phone, email, type, winner, competition_id, competition_title, patient_name, rankingMsgType, }: GetRankingMessageArgs): Notification { const dynamicEnv = { competition_title, patient_name, competition_id, } const pushMsg = this.getPushTitleAndBody(rankingMsgType.replace('_push', ''), country_code, dynamicEnv) const additional_data = omitBy( { document_number, email, patient_id, device_id, country_code, cell_phone, winner, competition_id, flutter_page: pushMsg.page, }, isNil, ) return { DelaySeconds: 0, title: pushMsg.title, type, msg: pushMsg.body, additional_data, } as Notification } private getPushTitleAndBody( pushNotificationTemplate: string, countryCode: CountryCode, dynamicEnv?: Record, ): Push { const message = this.translator.get(countryCode, `pushes.${pushNotificationTemplate}` as any, { params: dynamicEnv ? { ...dynamicEnv, } : {}, }) if (!message) throw new Error('Push notification template not found') return { title: message['title'], body: message['message'], page: message['page'] } } }