import { Injectable, NotFoundException } from '@nestjs/common'; import { PrismaService } from 'src/shared/services/prisma.service'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { CreateServiceDto } from '../dto/create.service.dto'; import { UpdateServiceDto } from '../dto/update.service.dto'; import { CreatePlanDto } from '../dto/create.plan.dto'; import { UpdatePlanDto } from '../dto/update.plan.dto'; import { ServiceWithPlans, PlanEntity } from '../entities/service.entity'; @Injectable() export class ServiceManagementService { constructor( private readonly prisma: PrismaService, private readonly eventEmitter: EventEmitter2, ) {} // ==================== SERVICE METHODS ==================== /** * Create a new service for a merchant */ async createService(dto: CreateServiceDto): Promise { // Check if merchant exists const merchant = await this.prisma.merchantPartner.findUnique({ where: { id: dto.merchantPartnerId }, }); if (!merchant) { throw new NotFoundException( `Merchant with ID ${dto.merchantPartnerId} not found`, ); } const service = await this.prisma.service.create({ data: { name: dto.name, description: dto.description, merchantPartnerId: dto.merchantPartnerId, }, include: { plans: true, merchantPartner: true, }, }); this.eventEmitter.emit('service.created', { serviceId: service.id, serviceName: service.name, merchantId: dto.merchantPartnerId, timestamp: new Date(), }); return service; } /** * Find all services for a merchant */ async findAllByMerchant(merchantId: number): Promise { // Check if merchant exists const merchant = await this.prisma.merchantPartner.findUnique({ where: { id: merchantId }, }); if (!merchant) { throw new NotFoundException(`Merchant with ID ${merchantId} not found`); } return this.prisma.service.findMany({ where: { merchantPartnerId: merchantId }, include: { plans: true, merchantPartner: true, }, orderBy: { createdAt: 'desc', }, }); } /** * Find service by ID */ async findOneService(id: number): Promise { const service = await this.prisma.service.findUnique({ where: { id }, include: { plans: true, merchantPartner: true, }, }); if (!service) { throw new NotFoundException(`Service with ID ${id} not found`); } return service; } /** * Update service */ async updateService( id: number, dto: UpdateServiceDto, ): Promise { await this.findOneService(id); // Check if exists const service = await this.prisma.service.update({ where: { id }, data: { name: dto.name, description: dto.description, }, include: { plans: true, merchantPartner: true, }, }); this.eventEmitter.emit('service.updated', { serviceId: id, serviceName: service.name, timestamp: new Date(), }); return service; } /** * Delete service */ async removeService(id: number): Promise { await this.findOneService(id); // Check if exists await this.prisma.service.delete({ where: { id }, }); this.eventEmitter.emit('service.deleted', { serviceId: id, timestamp: new Date(), }); } // ==================== PLAN METHODS ==================== /** * Create a new plan for a service */ async createPlan( serviceId: number, dto: CreatePlanDto, ): Promise { // Check if service exists await this.findOneService(serviceId); const plan = await this.prisma.plan.create({ data: { name: dto.name, type: dto.type, amount: dto.amount, tax: dto.tax, currency: dto.currency, periodicity: dto.periodicity, serviceId, }, include: { service: true, }, }); this.eventEmitter.emit('plan.created', { planId: plan.id, planName: plan.name, serviceId, amount: plan.amount, currency: plan.currency, timestamp: new Date(), }); return plan; } /** * Find all plans for a service */ async findAllPlansByService(serviceId: number): Promise { // Check if service exists await this.findOneService(serviceId); return this.prisma.plan.findMany({ where: { serviceId }, include: { service: true, }, orderBy: { amount: 'asc', }, }); } /** * Find plan by ID */ async findOnePlan(id: number): Promise { const plan = await this.prisma.plan.findUnique({ where: { id }, include: { service: true, }, }); if (!plan) { throw new NotFoundException(`Plan with ID ${id} not found`); } return plan; } /** * Update plan */ async updatePlan(id: number, dto: UpdatePlanDto): Promise { await this.findOnePlan(id); // Check if exists const plan = await this.prisma.plan.update({ where: { id }, data: { name: dto.name, type: dto.type, amount: dto.amount, tax: dto.tax, currency: dto.currency, periodicity: dto.periodicity, }, include: { service: true, }, }); this.eventEmitter.emit('plan.updated', { planId: id, planName: plan.name, amount: plan.amount, timestamp: new Date(), }); return plan; } /** * Delete plan */ async removePlan(id: number): Promise { await this.findOnePlan(id); // Check if exists await this.prisma.plan.delete({ where: { id }, }); this.eventEmitter.emit('plan.deleted', { planId: id, timestamp: new Date(), }); } }