Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | 8x 8x 8x 8x 8x 8x 8x 8x 8x 1x 7x 7x 9x 7x 8x 8x 8x 7x 7x 8x 1x 7x | import { getDb } from "../../../db";
import { createDal } from "../../../dal";
import { CommunicationGateway } from "../gateway";
import { NotificationService } from "../../../services/notification/notification.service";
export async function checkDueReminders(env: CloudflareBindings): Promise<void> {
const db = getDb(env.DB);
const dal = createDal(db);
const gateway = new CommunicationGateway(dal, env);
const notificationService = new NotificationService(dal, env);
const dueReminders = await dal.leadReminders.findDueReminders();
for (const { reminder, leadId, proId, customerName } of dueReminders) {
// Deduplicate: skip if already notified in the last hour
const oneHourAgo = new Date(Date.now() - 60 * 60 * 1000);
const recentNotifications = await dal.communicationLog.findRecentByEventAndMetadata(
"reminder_due",
oneHourAgo,
`"reminderId":${reminder.id}`,
);
if (recentNotifications.length > 0) {
continue;
}
// Find pro team owners/managers to notify
const teamMembers = await dal.userTenantRoles.getProUsersWithContact(proId);
const ownersAndManagers = teamMembers.filter(
(m) => m.role === "owner" || m.role === "manager",
);
const portalUrl = env.PORTAL_URL || "https://portal.interioring.com";
const leadUrl = `${portalUrl}/crm/leads/${leadId}`;
for (const member of ownersAndManagers) {
await gateway.send({
channel: "email",
recipient: member.email,
eventType: "reminder_due",
proId,
userId: member.userId,
content: {
template: "reminder-due",
subject: `Reminder due: ${reminder.title}`,
props: {
proName: member.name,
reminderTitle: reminder.title,
customerName,
dueAt: reminder.dueAt.toLocaleString("en-IN", {
timeZone: "Asia/Kolkata",
dateStyle: "medium",
timeStyle: "short",
}),
notes: reminder.notes ?? undefined,
leadUrl,
},
recipientName: member.name,
},
metadata: { reminderId: reminder.id, leadId },
});
}
// Send push notifications to owners/managers
try {
await notificationService.notify({
proId,
eventType: "reminder_due",
title: `Reminder: ${reminder.title || "Follow up"}`,
body: reminder.notes?.substring(0, 200) || "You have a reminder due",
data: { url: `/crm/leads/${leadId}`, leadId },
targetUserIds: ownersAndManagers.map((m) => m.userId),
});
} catch (err) {
console.error("[REMINDER] Failed to send push notification:", err);
}
// Update status from "upcoming" to "overdue"
await dal.leadReminders.update(reminder.id, { status: "overdue" });
}
}
|