import { Event } from '@sanar/payments-sdk'; import * as EmailValidator from 'email-validator'; import { HttpRequestService } from './http.request.service'; import { SubscriptionsService } from './subscriptions.service'; import { WalletsService } from './wallets.service'; import { ms } from '../server'; require('dotenv/config'); export class EcommerceService { private static instance: EcommerceService; private subscriptionsService = SubscriptionsService.getInstance(); private walletsService = WalletsService.getInstance(); private httpService: HttpRequestService; constructor() { this.httpService = new HttpRequestService( process.env.SANAR_ECOMMERCE_API_URL, { 'Content-Type': 'application/json', 'X-Auth-Key': process.env.SANAR_ECOMMERCE_API_KEY, }, ); } static getInstance() : EcommerceService { if (!this.instance) { this.instance = new EcommerceService(); } return this.instance; } private async getCurrentSubscription(email: string) : Promise { const customer = await this.walletsService.findCustomer(email); if (!customer) { throw new Error('Customer not found'); } const subscriptions = await this.subscriptionsService.listCustomerSubscriptions(customer.id); if (subscriptions.length === 0) { throw new Error('Subscription not found'); } return subscriptions[0]; } async insertAffiliate(aff: Event.AffiliateUser) : Promise { const affiliate: Event.AffiliateUser = aff; if (!affiliate || !EmailValidator.validate(affiliate.email)) { throw new Error('Invalid e-mail'); } try { const subscription = await this.getCurrentSubscription(affiliate.email); if (subscription.current_history.object.customer.name) { affiliate.name = subscription.current_history.object.customer.name; } } catch (error) { ms.logger.error('insertAffiliate getCurrentSubscription', error); } const body = { affNome: affiliate.name, affEmail: affiliate.email, affTipo: 'Afiliado', }; const result = await this.httpService.post('/affiliates', body); if (!result.sucesso) { throw new Error(result.erro); } return { id: result.afiliado.affId, name: result.afiliado.affNome, email: result.afiliado.affEmail, } as Event.AffiliateUser; } async insertAffiliateCoupon(affiliate: Event.AffiliateUser, discount: number = 10) : Promise { const expiresAt = discount !== 10 ? new Date(2020, 11, 11) : new Date(2022, 11, 30); const body = { cupCodigo: `${affiliate.email.substring(0, 2)}${affiliate.id}${discount !== 10 ? discount : ''}MGM`.toUpperCase(), cupDescricao: 'Cupom de MGM', cupDesconto: discount, cupTipoDesconto: 'P', affId: affiliate.id, cupUnico: false, maxUsage: 9999, cupDtInicial: new Date().toISOString(), cupDtFinal: expiresAt.toISOString(), token: process.env.SANAR_ECOMMERCE_API_KEY, }; const result = await this.httpService.post('/coupon', body); if (!result.sucesso) { throw new Error(result.erro); } return { name: affiliate.name, discount: `${body.cupDesconto}%`, coupon: result.cupom.cupCodigo, expiresAt: expiresAt.toISOString(), }; } async listCouponUsage(coupon: string) : Promise { if (!coupon || coupon.trim().length === 0) { throw new Error('You must inform a coupon'); } const result = await this.httpService.get(`/coupon/${coupon}/usage-resmed`); if (!result.sucesso) { throw new Error(result.erro); } const parse = (p) => ({ date: p.pedData, status: p.pedStatus, clientName: p.cliNome, }); const compare = (a, b) => { if (a.pedData > b.pedData) return -1; if (a.pedData < b.pedData) return 1; return 0; }; return result.pedidos.map((p) => parse(p)).sort(compare); } async findCoupon(coupon: string) : Promise { if (!coupon || coupon.trim().length === 0) { throw new Error('You must inform a coupon'); } const result = await this.httpService.get(`/coupon/${coupon}`); if (!result.sucesso) { throw new Error(result.erro); } return result.cupom; } async listAffiliateCoupons(affiliateId: number) : Promise { if (!affiliateId) { throw new Error('You must inform a coupon'); } const result = await this.httpService.get(`/coupon/affiliate/${affiliateId}`); if (!result.sucesso) { throw new Error(result.erro); } return result.cupons.filter((c) => c.cupCodigo.endsWith('MGM')); } }