From f67bfb9f92b9ea4c06910ea203c685e18fafe1d7 Mon Sep 17 00:00:00 2001 From: Pedro Guzman Date: Mon, 24 Nov 2025 09:24:38 +0100 Subject: [PATCH] add from to notification model (#14102) --- .changeset/yummy-squids-sniff.md | 7 +++++ .../notification/steps/send-notifications.ts | 11 ++++++- .../core/types/src/notification/common.ts | 4 +++ .../core/types/src/notification/mutations.ts | 4 +++ .../notification-module-service/index.spec.ts | 29 +++++++++++++------ .../medusa-cloud-email.spec.ts | 9 ++++++ .../.snapshot-medusa-notification.json | 19 ++++++++---- .../src/migrations/Migration20251121123942.ts | 13 +++++++++ .../notification/src/models/notification.ts | 2 ++ 9 files changed, 83 insertions(+), 15 deletions(-) create mode 100644 .changeset/yummy-squids-sniff.md create mode 100644 packages/modules/notification/src/migrations/Migration20251121123942.ts diff --git a/.changeset/yummy-squids-sniff.md b/.changeset/yummy-squids-sniff.md new file mode 100644 index 0000000000..4ba4902f71 --- /dev/null +++ b/.changeset/yummy-squids-sniff.md @@ -0,0 +1,7 @@ +--- +"@medusajs/notification": patch +"@medusajs/core-flows": patch +"@medusajs/types": patch +--- + +add from to notification model diff --git a/packages/core/core-flows/src/notification/steps/send-notifications.ts b/packages/core/core-flows/src/notification/steps/send-notifications.ts index e67de5a63f..d111bc029f 100644 --- a/packages/core/core-flows/src/notification/steps/send-notifications.ts +++ b/packages/core/core-flows/src/notification/steps/send-notifications.ts @@ -1,4 +1,8 @@ -import type { Attachment, INotificationModuleService, NotificationContent } from "@medusajs/framework/types" +import type { + Attachment, + INotificationModuleService, + NotificationContent, +} from "@medusajs/framework/types" import { Modules } from "@medusajs/framework/utils" import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk" @@ -11,6 +15,11 @@ export type SendNotificationsStepInput = { * the channel. For example, the email address for the email channel. */ to: string + /** + * The address to send the notification from, depending on + * the channel. For example, the email address for the email channel. + */ + from?: string | null /** * The channel to send the notification through. For example, `email`. */ diff --git a/packages/core/types/src/notification/common.ts b/packages/core/types/src/notification/common.ts index 8a2b07d0fd..447b2d0ac5 100644 --- a/packages/core/types/src/notification/common.ts +++ b/packages/core/types/src/notification/common.ts @@ -147,6 +147,10 @@ export interface FilterableNotificationProps * Filter based on the recipient of the notification. */ to?: string | string[] | OperatorMap + /** + * Filter based on the recipient of the notification. + */ + from?: string | string[] | OperatorMap /** * Filter based on the channel through which the notification is sent, such as 'email' or 'sms' */ diff --git a/packages/core/types/src/notification/mutations.ts b/packages/core/types/src/notification/mutations.ts index c27249a124..0ef088d022 100644 --- a/packages/core/types/src/notification/mutations.ts +++ b/packages/core/types/src/notification/mutations.ts @@ -11,6 +11,10 @@ export interface CreateNotificationDTO { * The recipient of the notification. It can be email, phone number, or username, depending on the channel. */ to: string + /** + * The sender of the notification. It can be email, phone number, or username, depending on the channel. + */ + from?: string | null /** * The channel through which the notification is sent, such as `email` or `sms`. */ diff --git a/packages/modules/notification/integration-tests/__tests__/notification-module-service/index.spec.ts b/packages/modules/notification/integration-tests/__tests__/notification-module-service/index.spec.ts index bd96ceb425..5f6df79a36 100644 --- a/packages/modules/notification/integration-tests/__tests__/notification-module-service/index.spec.ts +++ b/packages/modules/notification/integration-tests/__tests__/notification-module-service/index.spec.ts @@ -1,4 +1,7 @@ -import { INotificationModuleService } from "@medusajs/framework/types" +import { + CreateNotificationDTO, + INotificationModuleService, +} from "@medusajs/framework/types" import { CommonEvents, composeMessage, @@ -74,19 +77,27 @@ moduleIntegrationTestRunner({ it("should send a notification and stores it in the database", async () => { const notification = { to: "admin@medusa.com", + from: "sender@verified.com", template: "some-template", channel: "email", data: {}, - } + } as CreateNotificationDTO const result = await service.createNotifications(notification) - expect(result).toEqual( - expect.objectContaining({ - provider_id: "test-provider", - external_id: "external_id", - status: NotificationStatus.SUCCESS, - }) - ) + const retrieved = await service.retrieveNotification(result.id) + + const expected = { + to: "admin@medusa.com", + from: "sender@verified.com", + template: "some-template", + channel: "email", + data: {}, + provider_id: "test-provider", + external_id: "external_id", + status: NotificationStatus.SUCCESS, + } + expect(result).toEqual(expect.objectContaining(expected)) + expect(retrieved).toEqual(expect.objectContaining(expected)) }) it("should send a notification and don't store the content in the database", async () => { diff --git a/packages/modules/notification/integration-tests/__tests__/notification-module-service/medusa-cloud-email.spec.ts b/packages/modules/notification/integration-tests/__tests__/notification-module-service/medusa-cloud-email.spec.ts index 50f0034ba2..e71388660b 100644 --- a/packages/modules/notification/integration-tests/__tests__/notification-module-service/medusa-cloud-email.spec.ts +++ b/packages/modules/notification/integration-tests/__tests__/notification-module-service/medusa-cloud-email.spec.ts @@ -14,6 +14,7 @@ const successMedusaCloudEmailResponse = { const testNotification = { to: "customer@test.com", + from: "sender@verified.com", template: "some-template", channel: "email", data: { @@ -50,6 +51,13 @@ moduleIntegrationTestRunner({ const result = await service.createNotifications(testNotification) expect(result).toEqual( expect.objectContaining({ + to: "customer@test.com", + from: "sender@verified.com", + template: "some-template", + channel: "email", + data: { + link: "https://test.com", + }, provider_id: "cloud", external_id: "external_id_1", status: NotificationStatus.SUCCESS, @@ -66,6 +74,7 @@ moduleIntegrationTestRunner({ ) expect(JSON.parse(request.body)).toEqual({ to: "customer@test.com", + from: "sender@verified.com", template: "some-template", data: { link: "https://test.com", diff --git a/packages/modules/notification/src/migrations/.snapshot-medusa-notification.json b/packages/modules/notification/src/migrations/.snapshot-medusa-notification.json index 11a701ae74..b6a598f273 100644 --- a/packages/modules/notification/src/migrations/.snapshot-medusa-notification.json +++ b/packages/modules/notification/src/migrations/.snapshot-medusa-notification.json @@ -96,7 +96,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_notification_provider_deleted_at\" ON \"notification_provider\" (deleted_at) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_notification_provider_deleted_at\" ON \"notification_provider\" (\"deleted_at\") WHERE deleted_at IS NULL" }, { "keyName": "notification_provider_pkey", @@ -133,6 +133,15 @@ "nullable": false, "mappedType": "text" }, + "from": { + "name": "from", + "type": "text", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "mappedType": "text" + }, "channel": { "name": "channel", "type": "text", @@ -290,7 +299,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_notification_receiver_id\" ON \"notification\" (receiver_id) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_notification_receiver_id\" ON \"notification\" (\"receiver_id\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_notification_idempotency_key_unique", @@ -299,7 +308,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE UNIQUE INDEX IF NOT EXISTS \"IDX_notification_idempotency_key_unique\" ON \"notification\" (idempotency_key) WHERE deleted_at IS NULL" + "expression": "CREATE UNIQUE INDEX IF NOT EXISTS \"IDX_notification_idempotency_key_unique\" ON \"notification\" (\"idempotency_key\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_notification_provider_id", @@ -308,7 +317,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_notification_provider_id\" ON \"notification\" (provider_id) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_notification_provider_id\" ON \"notification\" (\"provider_id\") WHERE deleted_at IS NULL" }, { "keyName": "IDX_notification_deleted_at", @@ -317,7 +326,7 @@ "constraint": false, "primary": false, "unique": false, - "expression": "CREATE INDEX IF NOT EXISTS \"IDX_notification_deleted_at\" ON \"notification\" (deleted_at) WHERE deleted_at IS NULL" + "expression": "CREATE INDEX IF NOT EXISTS \"IDX_notification_deleted_at\" ON \"notification\" (\"deleted_at\") WHERE deleted_at IS NULL" }, { "keyName": "notification_pkey", diff --git a/packages/modules/notification/src/migrations/Migration20251121123942.ts b/packages/modules/notification/src/migrations/Migration20251121123942.ts new file mode 100644 index 0000000000..c8c1102850 --- /dev/null +++ b/packages/modules/notification/src/migrations/Migration20251121123942.ts @@ -0,0 +1,13 @@ +import { Migration } from '@mikro-orm/migrations'; + +export class Migration20251121123942 extends Migration { + + override async up(): Promise { + this.addSql(`alter table if exists "notification" add column if not exists "from" text null;`); + } + + override async down(): Promise { + this.addSql(`alter table if exists "notification" drop column if exists "from";`); + } + +} diff --git a/packages/modules/notification/src/models/notification.ts b/packages/modules/notification/src/models/notification.ts index dd22c75706..26b432c9f2 100644 --- a/packages/modules/notification/src/models/notification.ts +++ b/packages/modules/notification/src/models/notification.ts @@ -6,6 +6,8 @@ export const Notification = model.define("notification", { id: model.id({ prefix: "noti" }).primaryKey(), // This can be an email, phone number, or username, depending on the channel. to: model.text().searchable(), + // This can be an email, phone number, or username, depending on the channel. + from: model.text().searchable().nullable(), channel: model.text(), // The template name in the provider's system. template: model.text().nullable(),