Add transactional emails: welcome, professional submission, status changes
- mail/mail.service.ts: MailService with HTML templates (welcome, submitted, approved, rejected, pending, deactivated). Silent if SMTP not configured. - mail/mail.module.ts: global module so all services can inject MailService - auth.service.ts: send welcome email on register() - professionals.service.ts: notify admin on new submission; notify professional on approve/deny/deactivate/setPending Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
0a67f5d80a
commit
27f4a2d7ec
@@ -1,9 +1,10 @@
|
||||
import { Injectable, NotFoundException, BadRequestException, ForbiddenException } from '@nestjs/common';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { MailService } from '../mail/mail.service';
|
||||
|
||||
@Injectable()
|
||||
export class ProfessionalsService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
constructor(private prisma: PrismaService, private mail: MailService) {}
|
||||
|
||||
async findAllActive(page = 1, limit = 20, city?: string) {
|
||||
const skip = (page - 1) * limit;
|
||||
@@ -72,16 +73,20 @@ export class ProfessionalsService {
|
||||
|
||||
if (!existing) {
|
||||
await this.prisma.users.update({ where: { id: userId }, data: { pro_state: 1 } });
|
||||
return this.prisma.professionals.create({ data: { user_id: userId, is_active: false, ...data } });
|
||||
const prof = await this.prisma.professionals.create({ data: { user_id: userId, is_active: false, ...data } });
|
||||
const u = await this.prisma.users.findUnique({ where: { id: userId }, select: { name: true, email: true } });
|
||||
if (u?.email) this.mail.sendProfessionalSubmitted(u.name || 'Usuario', u.email, data.profession || '').catch(() => {});
|
||||
return prof;
|
||||
}
|
||||
|
||||
// Re-submitting after rejection reset (pro_state=0): move back to pending
|
||||
const user = await this.prisma.users.findUnique({ where: { id: userId }, select: { pro_state: true } });
|
||||
const user = await this.prisma.users.findUnique({ where: { id: userId }, select: { pro_state: true, name: true, email: true } });
|
||||
if (user?.pro_state === 0) {
|
||||
await this.prisma.$transaction([
|
||||
this.prisma.professionals.update({ where: { user_id: userId }, data: { ...data, is_active: false } }),
|
||||
this.prisma.users.update({ where: { id: userId }, data: { pro_state: 1 } }),
|
||||
]);
|
||||
if (user.email) this.mail.sendProfessionalSubmitted(user.name || 'Usuario', user.email, data.profession || '').catch(() => {});
|
||||
return this.prisma.professionals.findUnique({ where: { user_id: userId } });
|
||||
}
|
||||
|
||||
@@ -155,15 +160,11 @@ export class ProfessionalsService {
|
||||
if (!prof) throw new NotFoundException('Profesional no encontrado');
|
||||
|
||||
await this.prisma.$transaction([
|
||||
this.prisma.professionals.update({
|
||||
where: { id: professionalId },
|
||||
data: { is_active: true },
|
||||
}),
|
||||
this.prisma.users.update({
|
||||
where: { id: prof.user_id },
|
||||
data: { pro_state: 2 },
|
||||
}),
|
||||
this.prisma.professionals.update({ where: { id: professionalId }, data: { is_active: true } }),
|
||||
this.prisma.users.update({ where: { id: prof.user_id }, data: { pro_state: 2 } }),
|
||||
]);
|
||||
const u = await this.prisma.users.findUnique({ where: { id: prof.user_id }, select: { name: true, email: true } });
|
||||
if (u?.email) this.mail.sendStatusChanged(u.name || 'Profesional', u.email, 'approved').catch(() => {});
|
||||
return { message: 'Profesional aprobado' };
|
||||
}
|
||||
|
||||
@@ -175,6 +176,8 @@ export class ProfessionalsService {
|
||||
this.prisma.professionals.update({ where: { id: professionalId }, data: { is_active: false, updated_at: new Date() } }),
|
||||
this.prisma.users.update({ where: { id: prof.user_id }, data: { pro_state: 3 } }),
|
||||
]);
|
||||
const u = await this.prisma.users.findUnique({ where: { id: prof.user_id }, select: { name: true, email: true } });
|
||||
if (u?.email) this.mail.sendStatusChanged(u.name || 'Profesional', u.email, 'rejected').catch(() => {});
|
||||
return { message: 'Solicitud rechazada' };
|
||||
}
|
||||
|
||||
@@ -191,6 +194,8 @@ export class ProfessionalsService {
|
||||
this.prisma.professionals.update({ where: { id }, data: { is_active: false } }),
|
||||
this.prisma.users.update({ where: { id: prof.user_id }, data: { pro_state: 3 } }),
|
||||
]);
|
||||
const u = await this.prisma.users.findUnique({ where: { id: prof.user_id }, select: { name: true, email: true } });
|
||||
if (u?.email) this.mail.sendStatusChanged(u.name || 'Profesional', u.email, 'deactivated').catch(() => {});
|
||||
return { message: 'Profesional desactivado' };
|
||||
}
|
||||
|
||||
@@ -201,6 +206,8 @@ export class ProfessionalsService {
|
||||
this.prisma.professionals.update({ where: { id }, data: { is_active: false } }),
|
||||
this.prisma.users.update({ where: { id: prof.user_id }, data: { pro_state: 1 } }),
|
||||
]);
|
||||
const u = await this.prisma.users.findUnique({ where: { id: prof.user_id }, select: { name: true, email: true } });
|
||||
if (u?.email) this.mail.sendStatusChanged(u.name || 'Profesional', u.email, 'pending').catch(() => {});
|
||||
return { message: 'Profesional puesto en revisión' };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user