import db from '../../database/models/index.js'; import { Op } from 'sequelize'; import { sendEmail } from './email.service.js'; import { NotificationService } from '../../services/NotificationService.js'; import { REQUEST_TYPES } from '../config/constants.js'; const { RequestParticipant, User, Outlet, District } = db; const frontendBase = () => process.env.FRONTEND_URL || 'http://localhost:5173'; /** Dealer acknowledgement + internal reviewers after resignation is created. */ export async function notifyResignationSubmittedEmails(resignation: any): Promise { const dealerUser = await User.findByPk(resignation.dealerId, { attributes: ['id', 'email', 'fullName'] }); if (!dealerUser?.email) return; const base = frontendBase(); const resignationCode = resignation.resignationId || resignation.id; const lwd = resignation.lastOperationalDateSales || resignation.lastOperationalDateServices || 'As per application'; const dealerName = dealerUser.fullName || 'Dealer'; await sendEmail( dealerUser.email, `We received your resignation request — ${resignationCode}`, 'RESIGNATION_RECEIVED', { dealerName, resignationId: resignationCode, lwd: String(lwd), link: `${base}/dealer-resignation/${resignation.id}`, ctaLabel: 'View request' } ).catch((err) => console.error('[notifyResignationSubmittedEmails] dealer ack:', err)); const participants = await RequestParticipant.findAll({ where: { requestId: resignation.id, requestType: REQUEST_TYPES.RESIGNATION, userId: { [Op.ne]: resignation.dealerId } }, include: [{ model: User, as: 'user', attributes: ['id', 'email', 'fullName'] }] }); const internalLink = `${base}/resignation/${resignation.id}`; for (const p of participants) { const u = (p as any).user; if (!u?.email) continue; await NotificationService.notify(u.id, u.email, { title: `New resignation request: ${resignationCode}`, message: `Submitted by ${dealerName}.`, channels: ['email', 'system'], templateCode: 'RESIGNATION_SUBMITTED', placeholders: { dealerName, resignationId: resignationCode, lwd: String(lwd), link: internalLink, ctaLabel: 'Review resignation' } }).catch((err) => console.error('[notifyResignationSubmittedEmails] internal:', err)); } } /** Internal reviewers after constitutional request is created. */ export async function notifyConstitutionalSubmittedEmails(request: any, dealerDisplayName: string): Promise { const participants = await RequestParticipant.findAll({ where: { requestId: request.id, requestType: REQUEST_TYPES.CONSTITUTIONAL, userId: { [Op.ne]: request.dealerId } }, include: [{ model: User, as: 'user', attributes: ['id', 'email', 'fullName'] }] }); const base = frontendBase(); const link = `${base}/constitutional-change/${request.id}`; for (const p of participants) { const u = (p as any).user; if (!u?.email) continue; await NotificationService.notify(u.id, u.email, { title: `New constitutional change request: ${request.requestId}`, message: `${dealerDisplayName} submitted a request.`, channels: ['email', 'system'], templateCode: 'CONSTITUTIONAL_CHANGE_SUBMITTED', placeholders: { dealerName: dealerDisplayName, changeType: request.changeType || '', requestId: request.requestId, link, ctaLabel: 'Review request' } }).catch((err) => console.error('[notifyConstitutionalSubmittedEmails]:', err)); } } /** Dealer + ASM when relocation request is submitted. */ export async function notifyRelocationSubmittedEmails( request: any, submitter: { email: string; fullName?: string | null } ): Promise { const base = frontendBase(); const code = request.requestId || request.id; const dealerName = submitter.fullName?.trim() || 'Dealer'; if (submitter.email) { await sendEmail( submitter.email, `Relocation request received — ${code}`, 'RELOCATION_RECEIVED', { dealerName, requestId: code, link: `${base}/relocation-requests/${request.id}`, ctaLabel: 'View request' } ).catch((err) => console.error('[notifyRelocationSubmittedEmails] dealer:', err)); } const outlet = await Outlet.findByPk(request.outletId, { include: [{ model: District, as: 'district', attributes: ['id', 'asmId'] }] }); const asmId = (outlet as any)?.district?.asmId; if (!asmId) return; const asm = await User.findByPk(asmId, { attributes: ['id', 'email', 'fullName'] }); if (!asm?.email) return; await NotificationService.notify(asm.id, asm.email, { title: `New relocation request: ${code}`, message: 'A dealer submitted an outlet relocation request.', channels: ['email', 'system'], templateCode: 'RELOCATION_SUBMITTED', placeholders: { dealerName, requestId: code, outletCode: outlet?.code || '', link: `${base}/relocation-requests/${request.id}`, ctaLabel: 'Review relocation' } }).catch((err) => console.error('[notifyRelocationSubmittedEmails] ASM:', err)); }