From 153e487a94d9e191e2c994b307964ea44e721794 Mon Sep 17 00:00:00 2001 From: Peter Savchenko Date: Tue, 23 Dec 2025 22:19:50 +0300 Subject: [PATCH 1/2] Add repetitionId to event notification flow Introduces the repetitionId field to event notification data structures and templates, allowing emails and notifications to reference specific event repetitions. Updates TypeScript interfaces, worker logic, and email templates to support and display repetitionId where applicable. --- workers/email/src/templates/emails/event/html.twig | 7 ++++++- workers/email/src/templates/emails/event/text.twig | 7 ++++++- workers/grouper/src/index.ts | 1 + workers/notifier/src/index.ts | 1 + workers/notifier/types/channel.ts | 6 ++++++ workers/notifier/types/notifier-task.ts | 6 ++++++ workers/sender/src/index.ts | 3 ++- workers/sender/types/template-variables/event.ts | 5 +++++ 8 files changed, 33 insertions(+), 3 deletions(-) diff --git a/workers/email/src/templates/emails/event/html.twig b/workers/email/src/templates/emails/event/html.twig index 35be79c6c..535afe3a7 100644 --- a/workers/email/src/templates/emails/event/html.twig +++ b/workers/email/src/templates/emails/event/html.twig @@ -8,6 +8,7 @@ {% set utmParams = 'utm_source=email&utm_medium=transactional&utm_campaign=event' %} {% set event = events[0].event %} + {% set repetitionId = events[0].repetitionId %} {% set daysRepeated = events[0].daysRepeated %} {% set newCount = events[0].newCount %} {% set usersAffected = events[0].usersAffected %} @@ -56,7 +57,11 @@ - {% set eventURL = host ~ '/project/' ~ project._id ~ '/event/' ~ event._id ~ '?' ~ utmParams %} + {% if repetitionId %} + {% set eventURL = host ~ '/project/' ~ project._id ~ '/event/' ~ event._id ~ '/' ~ repetitionId ~ '/overview?' ~ utmParams %} + {% else %} + {% set eventURL = host ~ '/project/' ~ project._id ~ '/event/' ~ event._id ~ '?' ~ utmParams %} + {% endif %} {% include '../../components/button.twig' with {href: eventURL, label: 'Смотреть детали'} %} diff --git a/workers/email/src/templates/emails/event/text.twig b/workers/email/src/templates/emails/event/text.twig index d12c7f00d..f078d7d10 100644 --- a/workers/email/src/templates/emails/event/text.twig +++ b/workers/email/src/templates/emails/event/text.twig @@ -1,4 +1,5 @@ {% set event = events[0].event %} +{% set repetitionId = events[0].repetitionId %} {% set daysRepeated = events[0].daysRepeated %} {% set newCount = events[0].newCount %} {% set usersAffected = events[0].usersAffected %} @@ -25,7 +26,11 @@ Это событие произошло {{ event.totalCount }} {{ pluralize_ru(event.totalCount, ['раз', 'раза', 'раз']) }} за {{ daysRepeated }} {{ pluralize_ru(daysRepeated, ['день', 'дня', 'дней']) }}. -Смотреть детали: {{ host }}/project/{{ project._id }}/event/{{ event._id }}?{{ utmParams }} +{% if repetitionId %} +Смотреть детали: {{ host }}/project/{{ project._id }}/event/{{ event._id }}/{{ repetitionId }}/overview?{{ utmParams }} +{% else %} +Смотреть детали: {{ host }}/project/{{ project._id }}/event/{{ event._id }}/overview?{{ utmParams }} +{% endif %} *** diff --git a/workers/grouper/src/index.ts b/workers/grouper/src/index.ts index 8eef04fce..8d20daf56 100644 --- a/workers/grouper/src/index.ts +++ b/workers/grouper/src/index.ts @@ -265,6 +265,7 @@ export default class GrouperWorker extends Worker { title: task.payload.title, groupHash: uniqueEventHash, isNew: isFirstOccurrence, + repetitionId: repetitionId ? repetitionId.toString() : null, }, }); } diff --git a/workers/notifier/src/index.ts b/workers/notifier/src/index.ts index a05101c32..d2d17966e 100644 --- a/workers/notifier/src/index.ts +++ b/workers/notifier/src/index.ts @@ -160,6 +160,7 @@ export default class NotifierWorker extends Worker { await this.sendToSenderWorker(channelKey, [ { key: event.groupHash, count: 1, + repetitionId: event.repetitionId, } ]); } } diff --git a/workers/notifier/types/channel.ts b/workers/notifier/types/channel.ts index 3a195c3d7..001a1f273 100644 --- a/workers/notifier/types/channel.ts +++ b/workers/notifier/types/channel.ts @@ -35,6 +35,12 @@ export interface SenderData { * Number of events received */ count: number; + + /** + * ID of the repetition that triggered this notification + * null for first occurrence, ObjectId string for repetitions + */ + repetitionId: string | null; } /** diff --git a/workers/notifier/types/notifier-task.ts b/workers/notifier/types/notifier-task.ts index f773660c9..04bf3abb6 100644 --- a/workers/notifier/types/notifier-task.ts +++ b/workers/notifier/types/notifier-task.ts @@ -14,6 +14,12 @@ export type NotifierEvent = Pick, 'title'> & { * Flag to show if event is received first time */ isNew: boolean; + + /** + * ID of the repetition that triggered this notification + * null for first occurrence, string for repetitions + */ + repetitionId: string | null; }; /** diff --git a/workers/sender/src/index.ts b/workers/sender/src/index.ts index 7f24c1dc3..23fdeb63c 100644 --- a/workers/sender/src/index.ts +++ b/workers/sender/src/index.ts @@ -171,13 +171,14 @@ export default abstract class SenderWorker extends Worker { const eventsData = await Promise.all( events.map( - async ({ key: groupHash, count }: { key: string; count: number }): Promise => { + async ({ key: groupHash, count, repetitionId }: { key: string; count: number; repetitionId?: string | null }): Promise => { const [event, daysRepeated] = await this.getEventDataByGroupHash(projectId, groupHash); return { event, newCount: count, daysRepeated, + repetitionId: repetitionId ?? null, }; } ) diff --git a/workers/sender/types/template-variables/event.ts b/workers/sender/types/template-variables/event.ts index 701444ece..69e7fe3d3 100644 --- a/workers/sender/types/template-variables/event.ts +++ b/workers/sender/types/template-variables/event.ts @@ -25,6 +25,11 @@ export interface TemplateEventData { * Number of affected users for this event */ usersAffected?: number; + + /** + * ID of the particular repetition of occurred event + */ + repetitionId?: string | null; } /** From 1b82711b354530da8f6801dd10a02c3dd9b258ce Mon Sep 17 00:00:00 2001 From: Peter Savchenko Date: Tue, 23 Dec 2025 22:51:50 +0300 Subject: [PATCH 2/2] fix grouper test --- workers/grouper/tests/index.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/workers/grouper/tests/index.test.ts b/workers/grouper/tests/index.test.ts index 153a7952b..ee781e98a 100644 --- a/workers/grouper/tests/index.test.ts +++ b/workers/grouper/tests/index.test.ts @@ -734,6 +734,7 @@ describe('GrouperWorker', () => { title: task.payload.title, groupHash: expect.any(String), isNew: true, + repetitionId: null, }, });