267 lines
5.9 KiB
TypeScript
267 lines
5.9 KiB
TypeScript
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<ServiceWithPlans> {
|
|
// 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<ServiceWithPlans[]> {
|
|
// 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<ServiceWithPlans> {
|
|
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<ServiceWithPlans> {
|
|
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<void> {
|
|
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<PlanEntity> {
|
|
// 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<PlanEntity[]> {
|
|
// 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<PlanEntity> {
|
|
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<PlanEntity> {
|
|
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<void> {
|
|
await this.findOnePlan(id); // Check if exists
|
|
|
|
await this.prisma.plan.delete({
|
|
where: { id },
|
|
});
|
|
|
|
this.eventEmitter.emit('plan.deleted', {
|
|
planId: id,
|
|
timestamp: new Date(),
|
|
});
|
|
}
|
|
} |