const { getJobAssignmentType } = require("./stringHelpers"); /** * Populates the recipients for app, email, and FCM notifications based on scenario watchers. * * @param {Object} data - The data object containing scenarioWatchers and bodyShopId. * @param {Object} result - The result object to populate with recipients for app, email, and FCM notifications. */ const populateWatchers = (data, result) => { data.scenarioWatchers.forEach((recipients) => { const { user, app, fcm, email, firstName, lastName, employeeId, associationId } = recipients; if (app === true) result.app.recipients.push({ user, bodyShopId: data.bodyShopId, employeeId, associationId }); if (fcm === true) result.fcm.recipients.push(user); if (email === true) result.email.recipients.push({ user, firstName, lastName }); }); }; /** * Builds notification data for changes to alternate transport. */ // Verified const alternateTransportChangedBuilder = (data) => { const body = `The Alternate Transport status has been updated to ${data?.data?.alt_transport}.`; const result = { app: { jobId: data.jobId, bodyShopId: data.bodyShopId, jobRoNumber: data.jobRoNumber, key: "notifications.job.alternateTransportChanged", body, // Same as email body variables: { alternateTransport: data.changedFields.alt_transport?.new, oldAlternateTransport: data.changedFields.alt_transport?.old }, recipients: [] }, email: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopName: data.bodyShopName, body, recipients: [] }, fcm: { recipients: [] } }; populateWatchers(data, result); return result; }; /** * Builds notification data for bill posted events. */ //verified const billPostedHandler = (data) => { const facing = data?.data?.isinhouse ? "In-House" : "External"; const body = `An ${facing} Bill has been posted${data?.data?.is_credit_memo ? " (Credit Memo)" : ""}.`.trim(); const result = { app: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopId: data.bodyShopId, key: "notifications.job.billPosted", body, variables: { facing, is_credit_memo: data?.data?.is_credit_memo }, recipients: [] }, email: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopName: data.bodyShopName, body, recipients: [] }, fcm: { recipients: [] } }; populateWatchers(data, result); return result; }; /** * Builds notification data for changes to critical parts status. */ // TODO: Needs change const criticalPartsStatusChangedBuilder = (data) => { const body = `The critical parts status has changed to ${data.data.queued_for_parts ? "queued" : "not queued"}.`; const result = { app: { jobId: data.jobId, bodyShopId: data.bodyShopId, jobRoNumber: data.jobRoNumber, key: "notifications.job.criticalPartsStatusChanged", body, variables: { queuedForParts: data.data.queued_for_parts, oldQueuedForParts: data.changedFields.queued_for_parts?.old }, recipients: [] }, email: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopName: data.bodyShopName, body, recipients: [] }, fcm: { recipients: [] } }; populateWatchers(data, result); return result; }; /** * Builds notification data for completed intake or delivery checklists. */ // Verified const intakeDeliveryChecklistCompletedBuilder = (data) => { const checklistType = data?.changedFields?.intakechecklist ? "Intake" : "Delivery"; const body = `The ${checklistType.charAt(0).toUpperCase() + checklistType.slice(1)} checklist has been completed.`; const result = { app: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopId: data.bodyShopId, key: "notifications.job.checklistCompleted", body, variables: { checklistType, completed: true }, recipients: [] }, email: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopName: data.bodyShopName, body, recipients: [] }, fcm: { recipients: [] } }; populateWatchers(data, result); return result; }; /** * Builds notification data for job assignment events. */ // Verified const jobAssignedToMeBuilder = (data) => { const body = `You have been assigned to ${getJobAssignmentType(data.scenarioFields?.[0])}`; const result = { app: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopId: data.bodyShopId, key: "notifications.job.assigned", body, variables: { type: data.scenarioFields?.[0] }, recipients: [] }, email: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopName: data.bodyShopName, body, recipients: [] }, fcm: { recipients: [] } }; populateWatchers(data, result); return result; }; /** * Builds notification data for jobs added to production. */ // Verified const jobsAddedToProductionBuilder = (data) => { const body = `Has been added to Production.`; const result = { app: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopId: data.bodyShopId, key: "notifications.job.addedToProduction", body, variables: {}, recipients: [] }, email: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopName: data.bodyShopName, body, recipients: [] }, fcm: { recipients: [] } }; populateWatchers(data, result); return result; }; /** * Builds notification data for job status changes. */ // Verified const jobStatusChangeBuilder = (data) => { const body = `The status has changed from ${data.changedFields.status.old} to ${data.changedFields.status.new}`; const result = { app: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopId: data.bodyShopId, key: "notifications.job.statusChanged", body, variables: { status: data.changedFields.status.new, oldStatus: data.changedFields.status.old }, recipients: [] }, email: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopName: data.bodyShopName, body, recipients: [] }, fcm: { recipients: [] } }; populateWatchers(data, result); return result; }; /** * Builds notification data for new media added or reassigned events. */ // Verified const newMediaAddedReassignedBuilder = (data) => { // Determine if it's an image or document const mediaType = data?.data?.type?.startsWith("image") ? "Image" : "Document"; // Determine if it's added or updated const action = data.isNew ? "added" : "updated"; // Construct the body string const body = `An ${mediaType} has been ${action}.`; const result = { app: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopId: data.bodyShopId, key: "notifications.job.newMediaAdded", body, variables: { mediaType, action }, recipients: [] }, email: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopName: data.bodyShopName, body, recipients: [] }, fcm: { recipients: [] } }; populateWatchers(data, result); return result; }; /** * Builds notification data for new notes added to a job. */ const newNoteAddedBuilder = (data) => { const body = `An Note has been added: "${data.data.text}"`; const result = { app: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopId: data.bodyShopId, key: "notifications.job.newNoteAdded", body, variables: { text: data.data.text }, recipients: [] }, email: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopName: data.bodyShopName, body, recipients: [] }, fcm: { recipients: [] } }; populateWatchers(data, result); return result; }; /** * Builds notification data for new time tickets posted. */ const newTimeTicketPostedBuilder = (data) => { const type = data?.data?.cost_center; const body = `An ${type} time ticket has been posted${data?.data?.flat_rate ? " (Flat Rate)" : ""}.`.trim(); const result = { app: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopId: data.bodyShopId, key: "notifications.job.newTimeTicketPosted", body, variables: { type }, recipients: [] }, email: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopName: data.bodyShopName, body, recipients: [] }, fcm: { recipients: [] } }; populateWatchers(data, result); return result; }; /** * Builds notification data for parts marked as back-ordered. */ const partMarkedBackOrderedBuilder = (data) => { const body = `A part has been marked as back-ordered.`; const result = { app: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopId: data.bodyShopId, key: "notifications.job.partBackOrdered", body, variables: { queuedForParts: data.changedFields.queued_for_parts?.new, oldQueuedForParts: data.changedFields.queued_for_parts?.old }, recipients: [] }, email: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopName: data.bodyShopName, body, recipients: [] }, fcm: { recipients: [] } }; populateWatchers(data, result); return result; }; /** * Builds notification data for payment collection events. */ const paymentCollectedCompletedBuilder = (data) => { const body = `Payment of $${data.data.clm_total} has been collected.`; const result = { app: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopId: data.bodyShopId, key: "notifications.job.paymentCollected", body, variables: { clmTotal: data.data.clm_total }, recipients: [] }, email: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopName: data.bodyShopName, body, recipients: [] }, fcm: { recipients: [] } }; populateWatchers(data, result); return result; }; /** * Builds notification data for changes to scheduled dates. */ const scheduledDatesChangedBuilder = (data) => { const body = `Scheduled dates have been updated.`; const result = { app: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopId: data.bodyShopId, key: "notifications.job.scheduledDatesChanged", body, variables: { scheduledIn: data.changedFields.scheduled_in?.new, oldScheduledIn: data.changedFields.scheduled_in?.old, scheduledCompletion: data.changedFields.scheduled_completion?.new, oldScheduledCompletion: data.changedFields.scheduled_completion?.old, scheduledDelivery: data.changedFields.scheduled_delivery?.new, oldScheduledDelivery: data.changedFields.scheduled_delivery?.old }, recipients: [] }, email: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopName: data.bodyShopName, body, recipients: [] }, fcm: { recipients: [] } }; populateWatchers(data, result); return result; }; /** * Builds notification data for supplement imported events. */ const supplementImportedBuilder = (data) => { const body = `A supplement of $${data.data.cieca_ttl?.data?.supp_amt || 0} has been imported.`; const result = { app: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopId: data.bodyShopId, key: "notifications.job.supplementImported", body, variables: { suppAmt: data.data.cieca_ttl?.data?.supp_amt }, recipients: [] }, email: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopName: data.bodyShopName, body, recipients: [] }, fcm: { recipients: [] } }; populateWatchers(data, result); return result; }; /** * Builds notification data for tasks updated or created. */ const tasksUpdatedCreatedBuilder = (data) => { const body = `Tasks have been ${data.isNew ? "created" : "updated"}.`; const result = { app: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopId: data.bodyShopId, key: data.isNew ? "notifications.job.taskCreated" : "notifications.job.taskUpdated", body, variables: { isNew: data.isNew, roNumber: data.jobRoNumber }, recipients: [] }, email: { jobId: data.jobId, jobRoNumber: data.jobRoNumber, bodyShopName: data.bodyShopName, body, recipients: [] }, fcm: { recipients: [] } }; populateWatchers(data, result); return result; }; module.exports = { alternateTransportChangedBuilder, billPostedHandler, criticalPartsStatusChangedBuilder, intakeDeliveryChecklistCompletedBuilder, jobAssignedToMeBuilder, jobsAddedToProductionBuilder, jobStatusChangeBuilder, newMediaAddedReassignedBuilder, newNoteAddedBuilder, newTimeTicketPostedBuilder, partMarkedBackOrderedBuilder, paymentCollectedCompletedBuilder, scheduledDatesChangedBuilder, supplementImportedBuilder, tasksUpdatedCreatedBuilder };