Files
calendar/packages/features/ee/workflows/lib/detectMatchedTemplate.ts
T
Udit TakkarGitHubMorganDevin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>morgan@cal.com <morgan@cal.com>
3860717ae3 fix: workflow locale (#26509)
* fix: workflow locale

* fix: workflow locale

* fix: check if tmeplate is changed

* fix: regression

* fix: also check subject when determining if template is customized

Co-Authored-By: morgan@cal.com <morgan@cal.com>

* refactor: extract template matching logic into testable function

- Create detectMatchedTemplate function in separate file
- Add comprehensive unit tests (20 test cases)
- Refactor EmailWorkflowService to use the new function

Addresses review comment from hariombalhara requesting
abstraction and tests for the template matching logic.

Co-Authored-By: udit@cal.com <udit222001@gmail.com>

---------

Co-authored-by: Morgan <33722304+ThyMinimalDev@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: morgan@cal.com <morgan@cal.com>
2026-01-14 13:01:40 +05:30

65 lines
2.2 KiB
TypeScript

import { WorkflowTemplates } from "@calcom/prisma/enums";
import compareReminderBodyToTemplate from "./compareReminderBodyToTemplate";
export type DefaultTemplates = {
reminder: { body: string | null; subject: string | null };
rating: { body: string | null; subject: string | null };
};
export type DetectMatchedTemplateParams = {
emailBody: string;
emailSubject: string;
template?: WorkflowTemplates;
defaultTemplates: DefaultTemplates;
};
/**
* Detects if the email body and subject match a default template (REMINDER or RATING).
*
* Logic:
* 1. If emailBody is empty but template is specified as REMINDER or RATING, return that template
* 2. If emailBody exists, check if both body AND subject match the REMINDER default template
* 3. If not matched, check if both body AND subject match the RATING default template
* 4. Return null if no match (indicating custom content that should be preserved)
*
* This is used to determine whether to regenerate the template with the recipient's locale
* for proper translation, or to preserve user customizations.
*/
export function detectMatchedTemplate({
emailBody,
emailSubject,
template,
defaultTemplates,
}: DetectMatchedTemplateParams): WorkflowTemplates | null {
if (!emailBody && template === WorkflowTemplates.REMINDER) {
return WorkflowTemplates.REMINDER;
}
if (!emailBody && template === WorkflowTemplates.RATING) {
return WorkflowTemplates.RATING;
}
if (emailBody) {
const { reminder, rating } = defaultTemplates;
const bodyMatchesReminder =
reminder.body && compareReminderBodyToTemplate({ reminderBody: emailBody, template: reminder.body });
const subjectMatchesReminder = reminder.subject && emailSubject === reminder.subject;
if (bodyMatchesReminder && subjectMatchesReminder) {
return WorkflowTemplates.REMINDER;
}
const bodyMatchesRating =
rating.body && compareReminderBodyToTemplate({ reminderBody: emailBody, template: rating.body });
const subjectMatchesRating = rating.subject && emailSubject === rating.subject;
if (bodyMatchesRating && subjectMatchesRating) {
return WorkflowTemplates.RATING;
}
}
return null;
}