diff --git a/src/Prisma/prisma.service.ts b/src/Prisma/prisma.service.ts index fbe9ab3..0aecccf 100644 --- a/src/Prisma/prisma.service.ts +++ b/src/Prisma/prisma.service.ts @@ -31,6 +31,10 @@ export class PrismaService extends PrismaClient implements OnModuleInit { }, ], errorFormat: 'pretty', + transactionOptions: { + maxWait: 30 * 1000, + timeout: 60 * 1000, + }, }); } diff --git a/src/Service/service.schema.ts b/src/Service/service.schema.ts index 4864c5c..923f530 100644 --- a/src/Service/service.schema.ts +++ b/src/Service/service.schema.ts @@ -9,12 +9,14 @@ import { Builder } from '../Graphql/graphql.builder'; import { PrismaService } from '../Prisma/prisma.service'; import { MinioService } from '../Minio/minio.service'; import { ServiceStatus } from '@prisma/client'; +import { MailService } from '../Mail/mail.service'; @Injectable() export class ServiceSchema extends PothosSchema { constructor( @Inject(SchemaBuilderToken) private readonly builder: Builder, private readonly prisma: PrismaService, private readonly minioService: MinioService, + private readonly mailService: MailService, ) { super(); } @@ -217,6 +219,75 @@ export class ServiceSchema extends PothosSchema { }); }, }), + approveOrRejectService: t.prismaField({ + description: 'Approve or reject a service. For moderator only.', + type: this.service(), + args: { + serviceId: t.arg({ + type: 'String', + required: true, + }), + approve: t.arg({ + type: 'Boolean', + required: true, + }), + }, + resolve: async (query, root, args, ctx, info) => { + return await this.prisma.$transaction(async (prisma) => { + // check if service is already approved or rejected + const service = await prisma.service.findUnique({ + where: { id: args.serviceId }, + }); + if (!service) { + throw new Error('Service not found'); + } + if ( + service.status === ServiceStatus.APPROVED || + service.status === ServiceStatus.REJECTED + ) { + throw new Error('Service is already approved or rejected'); + } + // update service status + const updatedService = await prisma.service.update({ + ...query, + where: { id: args.serviceId }, + data: { + status: args.approve + ? ServiceStatus.APPROVED + : ServiceStatus.REJECTED, + }, + }); + // mail to center owner and staff who requested the service + const center = await prisma.center.findUnique({ + where: { id: service.centerId }, + }); + if (!center?.centerOwnerId) { + throw new Error('Center owner not found'); + } + const centerOwner = await prisma.user.findUnique({ + where: { id: center.centerOwnerId }, + }); + if (!centerOwner) { + throw new Error('Center owner not found'); + } + const centerStaff = await prisma.centerStaff.findMany({ + where: { centerId: service.centerId }, + }); + const staffEmails = centerStaff.map((staff) => staff.staffId); + const emails = [centerOwner.email, ...staffEmails]; + for (const email of emails) { + await this.mailService.sendEmail( + email, + args.approve + ? 'Your service has been approved' + : 'Your service has been rejected', + args.approve ? 'service-approved' : 'service-rejected', + ); + } + return updatedService; + }); + }, + }), })); } }