add from to notification model (#14102)

This commit is contained in:
Pedro Guzman
2025-11-24 09:24:38 +01:00
committed by GitHub
parent 0cb12021ef
commit f67bfb9f92
9 changed files with 83 additions and 15 deletions
+7
View File
@@ -0,0 +1,7 @@
---
"@medusajs/notification": patch
"@medusajs/core-flows": patch
"@medusajs/types": patch
---
add from to notification model
@@ -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 { Modules } from "@medusajs/framework/utils"
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk" 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. * the channel. For example, the email address for the email channel.
*/ */
to: string 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`. * The channel to send the notification through. For example, `email`.
*/ */
@@ -147,6 +147,10 @@ export interface FilterableNotificationProps
* Filter based on the recipient of the notification. * Filter based on the recipient of the notification.
*/ */
to?: string | string[] | OperatorMap<string | string[]> to?: string | string[] | OperatorMap<string | string[]>
/**
* Filter based on the recipient of the notification.
*/
from?: string | string[] | OperatorMap<string | string[]>
/** /**
* Filter based on the channel through which the notification is sent, such as 'email' or 'sms' * Filter based on the channel through which the notification is sent, such as 'email' or 'sms'
*/ */
@@ -11,6 +11,10 @@ export interface CreateNotificationDTO {
* The recipient of the notification. It can be email, phone number, or username, depending on the channel. * The recipient of the notification. It can be email, phone number, or username, depending on the channel.
*/ */
to: string 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`. * The channel through which the notification is sent, such as `email` or `sms`.
*/ */
@@ -1,4 +1,7 @@
import { INotificationModuleService } from "@medusajs/framework/types" import {
CreateNotificationDTO,
INotificationModuleService,
} from "@medusajs/framework/types"
import { import {
CommonEvents, CommonEvents,
composeMessage, composeMessage,
@@ -74,19 +77,27 @@ moduleIntegrationTestRunner<INotificationModuleService>({
it("should send a notification and stores it in the database", async () => { it("should send a notification and stores it in the database", async () => {
const notification = { const notification = {
to: "admin@medusa.com", to: "admin@medusa.com",
from: "sender@verified.com",
template: "some-template", template: "some-template",
channel: "email", channel: "email",
data: {}, data: {},
} } as CreateNotificationDTO
const result = await service.createNotifications(notification) const result = await service.createNotifications(notification)
expect(result).toEqual( const retrieved = await service.retrieveNotification(result.id)
expect.objectContaining({
provider_id: "test-provider", const expected = {
external_id: "external_id", to: "admin@medusa.com",
status: NotificationStatus.SUCCESS, 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 () => { it("should send a notification and don't store the content in the database", async () => {
@@ -14,6 +14,7 @@ const successMedusaCloudEmailResponse = {
const testNotification = { const testNotification = {
to: "customer@test.com", to: "customer@test.com",
from: "sender@verified.com",
template: "some-template", template: "some-template",
channel: "email", channel: "email",
data: { data: {
@@ -50,6 +51,13 @@ moduleIntegrationTestRunner<INotificationModuleService>({
const result = await service.createNotifications(testNotification) const result = await service.createNotifications(testNotification)
expect(result).toEqual( expect(result).toEqual(
expect.objectContaining({ expect.objectContaining({
to: "customer@test.com",
from: "sender@verified.com",
template: "some-template",
channel: "email",
data: {
link: "https://test.com",
},
provider_id: "cloud", provider_id: "cloud",
external_id: "external_id_1", external_id: "external_id_1",
status: NotificationStatus.SUCCESS, status: NotificationStatus.SUCCESS,
@@ -66,6 +74,7 @@ moduleIntegrationTestRunner<INotificationModuleService>({
) )
expect(JSON.parse(request.body)).toEqual({ expect(JSON.parse(request.body)).toEqual({
to: "customer@test.com", to: "customer@test.com",
from: "sender@verified.com",
template: "some-template", template: "some-template",
data: { data: {
link: "https://test.com", link: "https://test.com",
@@ -96,7 +96,7 @@
"constraint": false, "constraint": false,
"primary": false, "primary": false,
"unique": 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", "keyName": "notification_provider_pkey",
@@ -133,6 +133,15 @@
"nullable": false, "nullable": false,
"mappedType": "text" "mappedType": "text"
}, },
"from": {
"name": "from",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": true,
"mappedType": "text"
},
"channel": { "channel": {
"name": "channel", "name": "channel",
"type": "text", "type": "text",
@@ -290,7 +299,7 @@
"constraint": false, "constraint": false,
"primary": false, "primary": false,
"unique": 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", "keyName": "IDX_notification_idempotency_key_unique",
@@ -299,7 +308,7 @@
"constraint": false, "constraint": false,
"primary": false, "primary": false,
"unique": 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", "keyName": "IDX_notification_provider_id",
@@ -308,7 +317,7 @@
"constraint": false, "constraint": false,
"primary": false, "primary": false,
"unique": 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", "keyName": "IDX_notification_deleted_at",
@@ -317,7 +326,7 @@
"constraint": false, "constraint": false,
"primary": false, "primary": false,
"unique": 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", "keyName": "notification_pkey",
@@ -0,0 +1,13 @@
import { Migration } from '@mikro-orm/migrations';
export class Migration20251121123942 extends Migration {
override async up(): Promise<void> {
this.addSql(`alter table if exists "notification" add column if not exists "from" text null;`);
}
override async down(): Promise<void> {
this.addSql(`alter table if exists "notification" drop column if exists "from";`);
}
}
@@ -6,6 +6,8 @@ export const Notification = model.define("notification", {
id: model.id({ prefix: "noti" }).primaryKey(), id: model.id({ prefix: "noti" }).primaryKey(),
// This can be an email, phone number, or username, depending on the channel. // This can be an email, phone number, or username, depending on the channel.
to: model.text().searchable(), 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(), channel: model.text(),
// The template name in the provider's system. // The template name in the provider's system.
template: model.text().nullable(), template: model.text().nullable(),