@voyant-travel/notifications 0.111.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +179 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +196 -0
- package/dist/liquid.d.ts +5 -0
- package/dist/liquid.d.ts.map +1 -0
- package/dist/liquid.js +156 -0
- package/dist/providers/local.d.ts +22 -0
- package/dist/providers/local.d.ts.map +1 -0
- package/dist/providers/local.js +23 -0
- package/dist/providers/voyant-cloud-email.d.ts +27 -0
- package/dist/providers/voyant-cloud-email.d.ts.map +1 -0
- package/dist/providers/voyant-cloud-email.js +73 -0
- package/dist/providers/voyant-cloud-sms.d.ts +26 -0
- package/dist/providers/voyant-cloud-sms.d.ts.map +1 -0
- package/dist/providers/voyant-cloud-sms.js +24 -0
- package/dist/routes.d.ts +1546 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +337 -0
- package/dist/schema.d.ts +2119 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +356 -0
- package/dist/service-booking-document-lifecycle.d.ts +99 -0
- package/dist/service-booking-document-lifecycle.d.ts.map +1 -0
- package/dist/service-booking-document-lifecycle.js +259 -0
- package/dist/service-booking-documents.d.ts +256 -0
- package/dist/service-booking-documents.d.ts.map +1 -0
- package/dist/service-booking-documents.js +323 -0
- package/dist/service-deliveries.d.ts +183 -0
- package/dist/service-deliveries.d.ts.map +1 -0
- package/dist/service-deliveries.js +413 -0
- package/dist/service-delivery-metadata.d.ts +42 -0
- package/dist/service-delivery-metadata.d.ts.map +1 -0
- package/dist/service-delivery-metadata.js +114 -0
- package/dist/service-reminder-authoring.d.ts +33 -0
- package/dist/service-reminder-authoring.d.ts.map +1 -0
- package/dist/service-reminder-authoring.js +247 -0
- package/dist/service-reminder-booking-context.d.ts +94 -0
- package/dist/service-reminder-booking-context.d.ts.map +1 -0
- package/dist/service-reminder-booking-context.js +164 -0
- package/dist/service-reminder-events.d.ts +33 -0
- package/dist/service-reminder-events.d.ts.map +1 -0
- package/dist/service-reminder-events.js +178 -0
- package/dist/service-reminder-run-state.d.ts +114 -0
- package/dist/service-reminder-run-state.d.ts.map +1 -0
- package/dist/service-reminder-run-state.js +100 -0
- package/dist/service-reminder-stage-runs.d.ts +6 -0
- package/dist/service-reminder-stage-runs.d.ts.map +1 -0
- package/dist/service-reminder-stage-runs.js +310 -0
- package/dist/service-reminders.d.ts +30 -0
- package/dist/service-reminders.d.ts.map +1 -0
- package/dist/service-reminders.js +189 -0
- package/dist/service-sequence-targets.d.ts +50 -0
- package/dist/service-sequence-targets.d.ts.map +1 -0
- package/dist/service-sequence-targets.js +136 -0
- package/dist/service-sequence.d.ts +68 -0
- package/dist/service-sequence.d.ts.map +1 -0
- package/dist/service-sequence.js +316 -0
- package/dist/service-shared.d.ts +107 -0
- package/dist/service-shared.d.ts.map +1 -0
- package/dist/service-shared.js +159 -0
- package/dist/service-stages.d.ts +23 -0
- package/dist/service-stages.d.ts.map +1 -0
- package/dist/service-stages.js +203 -0
- package/dist/service-template-data.d.ts +19 -0
- package/dist/service-template-data.d.ts.map +1 -0
- package/dist/service-template-data.js +278 -0
- package/dist/service-templates.d.ts +260 -0
- package/dist/service-templates.d.ts.map +1 -0
- package/dist/service-templates.js +293 -0
- package/dist/service.d.ts +273 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +51 -0
- package/dist/task-runtime.d.ts +19 -0
- package/dist/task-runtime.d.ts.map +1 -0
- package/dist/task-runtime.js +11 -0
- package/dist/tasks/deliver-reminder.d.ts +9 -0
- package/dist/tasks/deliver-reminder.d.ts.map +1 -0
- package/dist/tasks/deliver-reminder.js +12 -0
- package/dist/tasks/index.d.ts +3 -0
- package/dist/tasks/index.d.ts.map +1 -0
- package/dist/tasks/index.js +2 -0
- package/dist/tasks/send-due-reminders.d.ts +7 -0
- package/dist/tasks/send-due-reminders.d.ts.map +1 -0
- package/dist/tasks/send-due-reminders.js +31 -0
- package/dist/template-authoring.d.ts +23 -0
- package/dist/template-authoring.d.ts.map +1 -0
- package/dist/template-authoring.js +386 -0
- package/dist/types.d.ts +82 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/validation.d.ts +1093 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +451 -0
- package/package.json +102 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { bookingItems, bookingTravelers } from "@voyant-travel/bookings/schema";
|
|
2
|
+
import { and, desc, eq } from "drizzle-orm";
|
|
3
|
+
import { renderLiquidTemplate } from "./liquid.js";
|
|
4
|
+
import { enrichBookingItem, normalizeNotificationTemplateData } from "./service-template-data.js";
|
|
5
|
+
export { normalizeNotificationTemplateData } from "./service-template-data.js";
|
|
6
|
+
export class NotificationError extends Error {
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "NotificationError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export function createNotificationService(providers) {
|
|
13
|
+
const byChannel = new Map();
|
|
14
|
+
const byName = new Map();
|
|
15
|
+
for (const provider of providers) {
|
|
16
|
+
byName.set(provider.name, provider);
|
|
17
|
+
for (const channel of provider.channels) {
|
|
18
|
+
byChannel.set(channel, provider);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
async send(payload) {
|
|
23
|
+
const hintedProvider = payload.provider ? byName.get(payload.provider) : null;
|
|
24
|
+
const provider = hintedProvider ?? byChannel.get(payload.channel);
|
|
25
|
+
if (!provider) {
|
|
26
|
+
throw new NotificationError(`No notification provider registered for channel "${payload.channel}"`);
|
|
27
|
+
}
|
|
28
|
+
return provider.send(payload);
|
|
29
|
+
},
|
|
30
|
+
async sendWith(providerName, payload) {
|
|
31
|
+
const provider = byName.get(providerName);
|
|
32
|
+
if (!provider) {
|
|
33
|
+
throw new NotificationError(`No notification provider registered with name "${providerName}"`);
|
|
34
|
+
}
|
|
35
|
+
return provider.send(payload);
|
|
36
|
+
},
|
|
37
|
+
getProvider(channel) {
|
|
38
|
+
return byChannel.get(channel);
|
|
39
|
+
},
|
|
40
|
+
getProviderByName(providerName) {
|
|
41
|
+
return byName.get(providerName);
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export function summarizeNotificationAttachments(attachments) {
|
|
46
|
+
if (!attachments || attachments.length === 0) {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
return attachments.map((attachment) => ({
|
|
50
|
+
filename: attachment.filename,
|
|
51
|
+
path: attachment.path ?? null,
|
|
52
|
+
contentType: attachment.contentType ?? null,
|
|
53
|
+
disposition: attachment.disposition ?? null,
|
|
54
|
+
contentId: attachment.contentId ?? null,
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
export function renderNotificationTemplate(template, data) {
|
|
58
|
+
return renderLiquidTemplate(template, normalizeNotificationTemplateData(data));
|
|
59
|
+
}
|
|
60
|
+
export function previewNotificationTemplate(input) {
|
|
61
|
+
const data = normalizeNotificationTemplateData(input.data ?? {});
|
|
62
|
+
return {
|
|
63
|
+
channel: input.channel,
|
|
64
|
+
provider: input.provider ?? null,
|
|
65
|
+
fromAddress: input.fromAddress ?? null,
|
|
66
|
+
subject: renderNotificationTemplate(input.subjectTemplate, data),
|
|
67
|
+
html: renderNotificationTemplate(input.htmlTemplate, data),
|
|
68
|
+
text: renderNotificationTemplate(input.textTemplate, data),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
export function toTimestamp(value) {
|
|
72
|
+
return value ? new Date(value) : null;
|
|
73
|
+
}
|
|
74
|
+
export function startOfUtcDay(value) {
|
|
75
|
+
return new Date(Date.UTC(value.getUTCFullYear(), value.getUTCMonth(), value.getUTCDate()));
|
|
76
|
+
}
|
|
77
|
+
export function addUtcDays(value, days) {
|
|
78
|
+
return new Date(value.getTime() + days * 24 * 60 * 60 * 1000);
|
|
79
|
+
}
|
|
80
|
+
export function toDateString(value) {
|
|
81
|
+
return value.toISOString().slice(0, 10);
|
|
82
|
+
}
|
|
83
|
+
export function buildReminderDedupeKey(ruleId, targetId, runDate) {
|
|
84
|
+
return `${ruleId}:${targetId}:${runDate}`;
|
|
85
|
+
}
|
|
86
|
+
export function resolveReminderRecipient(booking, participants) {
|
|
87
|
+
if (booking?.contactEmail) {
|
|
88
|
+
return {
|
|
89
|
+
email: booking.contactEmail,
|
|
90
|
+
firstName: booking.contactFirstName ?? "",
|
|
91
|
+
lastName: booking.contactLastName ?? "",
|
|
92
|
+
participantType: "booking_contact",
|
|
93
|
+
isPrimary: true,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const withEmail = participants.filter((traveler) => traveler.email);
|
|
97
|
+
if (withEmail.length === 0) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
const nonStaffWithEmail = withEmail.filter((traveler) => traveler.participantType !== "staff");
|
|
101
|
+
const primary = nonStaffWithEmail.find((traveler) => traveler.isPrimary) ??
|
|
102
|
+
withEmail.find((traveler) => traveler.isPrimary);
|
|
103
|
+
if (primary) {
|
|
104
|
+
return primary;
|
|
105
|
+
}
|
|
106
|
+
const preferredTypes = ["traveler", "occupant", "other"];
|
|
107
|
+
for (const type of preferredTypes) {
|
|
108
|
+
const match = nonStaffWithEmail.find((traveler) => traveler.participantType === type);
|
|
109
|
+
if (match) {
|
|
110
|
+
return match;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return nonStaffWithEmail[0] ?? withEmail[0] ?? null;
|
|
114
|
+
}
|
|
115
|
+
export async function listBookingNotificationParticipants(db, bookingId) {
|
|
116
|
+
return db
|
|
117
|
+
.select({
|
|
118
|
+
id: bookingTravelers.id,
|
|
119
|
+
firstName: bookingTravelers.firstName,
|
|
120
|
+
lastName: bookingTravelers.lastName,
|
|
121
|
+
email: bookingTravelers.email,
|
|
122
|
+
participantType: bookingTravelers.participantType,
|
|
123
|
+
isPrimary: bookingTravelers.isPrimary,
|
|
124
|
+
})
|
|
125
|
+
.from(bookingTravelers)
|
|
126
|
+
.where(eq(bookingTravelers.bookingId, bookingId))
|
|
127
|
+
.orderBy(desc(bookingTravelers.isPrimary), bookingTravelers.createdAt);
|
|
128
|
+
}
|
|
129
|
+
export async function listBookingNotificationItems(db, bookingId) {
|
|
130
|
+
const rows = await db
|
|
131
|
+
.select({
|
|
132
|
+
id: bookingItems.id,
|
|
133
|
+
title: bookingItems.title,
|
|
134
|
+
description: bookingItems.description,
|
|
135
|
+
quantity: bookingItems.quantity,
|
|
136
|
+
itemType: bookingItems.itemType,
|
|
137
|
+
serviceDate: bookingItems.serviceDate,
|
|
138
|
+
sellCurrency: bookingItems.sellCurrency,
|
|
139
|
+
unitSellAmountCents: bookingItems.unitSellAmountCents,
|
|
140
|
+
totalSellAmountCents: bookingItems.totalSellAmountCents,
|
|
141
|
+
})
|
|
142
|
+
.from(bookingItems)
|
|
143
|
+
.where(eq(bookingItems.bookingId, bookingId))
|
|
144
|
+
.orderBy(bookingItems.createdAt);
|
|
145
|
+
return rows.map((row) => enrichBookingItem(row));
|
|
146
|
+
}
|
|
147
|
+
export async function paginate(rowsPromise, totalPromise, limit, offset) {
|
|
148
|
+
const [data, totalRows] = await Promise.all([rowsPromise, totalPromise]);
|
|
149
|
+
return {
|
|
150
|
+
data,
|
|
151
|
+
total: totalRows[0]?.total ?? 0,
|
|
152
|
+
limit,
|
|
153
|
+
offset,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
export function buildWhereClause(conditions) {
|
|
157
|
+
const filtered = conditions.filter((condition) => Boolean(condition));
|
|
158
|
+
return filtered.length > 0 ? and(...filtered) : undefined;
|
|
159
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
|
2
|
+
import type { z } from "zod";
|
|
3
|
+
import { type NotificationReminderRuleStage, type NotificationReminderStageChannel, type NotificationSettings } from "./schema.js";
|
|
4
|
+
import type { insertNotificationReminderRuleStageSchema, insertNotificationReminderStageChannelSchema, reorderReminderRuleStagesSchema, updateNotificationReminderRuleStageSchema, updateNotificationReminderStageChannelSchema, updateNotificationSettingsSchema } from "./validation.js";
|
|
5
|
+
export type CreateReminderRuleStageInput = z.infer<typeof insertNotificationReminderRuleStageSchema>;
|
|
6
|
+
export type UpdateReminderRuleStageInput = z.infer<typeof updateNotificationReminderRuleStageSchema>;
|
|
7
|
+
export type CreateReminderStageChannelInput = z.infer<typeof insertNotificationReminderStageChannelSchema>;
|
|
8
|
+
export type UpdateReminderStageChannelInput = z.infer<typeof updateNotificationReminderStageChannelSchema>;
|
|
9
|
+
export type ReorderReminderRuleStagesInput = z.infer<typeof reorderReminderRuleStagesSchema>;
|
|
10
|
+
export type UpdateNotificationSettingsInput = z.infer<typeof updateNotificationSettingsSchema>;
|
|
11
|
+
export declare function listReminderRuleStages(db: PostgresJsDatabase, reminderRuleId: string): Promise<NotificationReminderRuleStage[]>;
|
|
12
|
+
export declare function getReminderRuleStageById(db: PostgresJsDatabase, stageId: string): Promise<NotificationReminderRuleStage | null>;
|
|
13
|
+
export declare function createReminderRuleStage(db: PostgresJsDatabase, reminderRuleId: string, input: CreateReminderRuleStageInput): Promise<NotificationReminderRuleStage>;
|
|
14
|
+
export declare function updateReminderRuleStage(db: PostgresJsDatabase, stageId: string, input: UpdateReminderRuleStageInput): Promise<NotificationReminderRuleStage | null>;
|
|
15
|
+
export declare function deleteReminderRuleStage(db: PostgresJsDatabase, stageId: string): Promise<boolean>;
|
|
16
|
+
export declare function reorderReminderRuleStages(db: PostgresJsDatabase, reminderRuleId: string, input: ReorderReminderRuleStagesInput): Promise<NotificationReminderRuleStage[]>;
|
|
17
|
+
export declare function listStageChannels(db: PostgresJsDatabase, stageId: string): Promise<NotificationReminderStageChannel[]>;
|
|
18
|
+
export declare function createStageChannel(db: PostgresJsDatabase, stageId: string, input: CreateReminderStageChannelInput): Promise<NotificationReminderStageChannel>;
|
|
19
|
+
export declare function updateStageChannel(db: PostgresJsDatabase, channelId: string, input: UpdateReminderStageChannelInput): Promise<NotificationReminderStageChannel | null>;
|
|
20
|
+
export declare function deleteStageChannel(db: PostgresJsDatabase, channelId: string): Promise<boolean>;
|
|
21
|
+
export declare function getNotificationSettingsRecord(db: PostgresJsDatabase, scope?: string): Promise<NotificationSettings>;
|
|
22
|
+
export declare function upsertNotificationSettings(db: PostgresJsDatabase, input: UpdateNotificationSettingsInput): Promise<NotificationSettings>;
|
|
23
|
+
//# sourceMappingURL=service-stages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-stages.d.ts","sourceRoot":"","sources":["../src/service-stages.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { and, asc, eq } from "drizzle-orm";
|
|
2
|
+
import { notificationReminderRuleStages, notificationReminderStageChannels, notificationSettings, } from "./schema.js";
|
|
3
|
+
import { DEFAULT_NOTIFICATION_SETTINGS } from "./service-sequence.js";
|
|
4
|
+
export async function listReminderRuleStages(db, reminderRuleId) {
|
|
5
|
+
return db
|
|
6
|
+
.select()
|
|
7
|
+
.from(notificationReminderRuleStages)
|
|
8
|
+
.where(eq(notificationReminderRuleStages.reminderRuleId, reminderRuleId))
|
|
9
|
+
.orderBy(asc(notificationReminderRuleStages.orderIndex));
|
|
10
|
+
}
|
|
11
|
+
export async function getReminderRuleStageById(db, stageId) {
|
|
12
|
+
const [row] = await db
|
|
13
|
+
.select()
|
|
14
|
+
.from(notificationReminderRuleStages)
|
|
15
|
+
.where(eq(notificationReminderRuleStages.id, stageId))
|
|
16
|
+
.limit(1);
|
|
17
|
+
return row ?? null;
|
|
18
|
+
}
|
|
19
|
+
export async function createReminderRuleStage(db, reminderRuleId, input) {
|
|
20
|
+
const [row] = await db
|
|
21
|
+
.insert(notificationReminderRuleStages)
|
|
22
|
+
.values({
|
|
23
|
+
reminderRuleId,
|
|
24
|
+
orderIndex: input.orderIndex,
|
|
25
|
+
name: input.name ?? null,
|
|
26
|
+
anchor: input.anchor,
|
|
27
|
+
windowStartDays: input.windowStartDays,
|
|
28
|
+
windowEndDays: input.windowEndDays,
|
|
29
|
+
cadenceKind: input.cadenceKind,
|
|
30
|
+
cadenceEveryDays: input.cadenceEveryDays ?? null,
|
|
31
|
+
cadenceIntervals: input.cadenceIntervals ?? null,
|
|
32
|
+
maxSendsInStage: input.maxSendsInStage ?? null,
|
|
33
|
+
respectQuietHours: input.respectQuietHours,
|
|
34
|
+
metadata: input.metadata ?? null,
|
|
35
|
+
})
|
|
36
|
+
.returning();
|
|
37
|
+
if (!row)
|
|
38
|
+
throw new Error("Failed to create reminder stage");
|
|
39
|
+
return row;
|
|
40
|
+
}
|
|
41
|
+
export async function updateReminderRuleStage(db, stageId, input) {
|
|
42
|
+
const updates = { updatedAt: new Date() };
|
|
43
|
+
if (input.name !== undefined)
|
|
44
|
+
updates.name = input.name ?? null;
|
|
45
|
+
if (input.orderIndex !== undefined)
|
|
46
|
+
updates.orderIndex = input.orderIndex;
|
|
47
|
+
if (input.anchor !== undefined)
|
|
48
|
+
updates.anchor = input.anchor;
|
|
49
|
+
if (input.windowStartDays !== undefined)
|
|
50
|
+
updates.windowStartDays = input.windowStartDays;
|
|
51
|
+
if (input.windowEndDays !== undefined)
|
|
52
|
+
updates.windowEndDays = input.windowEndDays;
|
|
53
|
+
if (input.cadenceKind !== undefined)
|
|
54
|
+
updates.cadenceKind = input.cadenceKind;
|
|
55
|
+
if (input.cadenceEveryDays !== undefined)
|
|
56
|
+
updates.cadenceEveryDays = input.cadenceEveryDays ?? null;
|
|
57
|
+
if (input.cadenceIntervals !== undefined)
|
|
58
|
+
updates.cadenceIntervals = input.cadenceIntervals ?? null;
|
|
59
|
+
if (input.maxSendsInStage !== undefined)
|
|
60
|
+
updates.maxSendsInStage = input.maxSendsInStage ?? null;
|
|
61
|
+
if (input.respectQuietHours !== undefined)
|
|
62
|
+
updates.respectQuietHours = input.respectQuietHours;
|
|
63
|
+
if (input.metadata !== undefined)
|
|
64
|
+
updates.metadata = input.metadata ?? null;
|
|
65
|
+
const [row] = await db
|
|
66
|
+
.update(notificationReminderRuleStages)
|
|
67
|
+
.set(updates)
|
|
68
|
+
.where(eq(notificationReminderRuleStages.id, stageId))
|
|
69
|
+
.returning();
|
|
70
|
+
return row ?? null;
|
|
71
|
+
}
|
|
72
|
+
export async function deleteReminderRuleStage(db, stageId) {
|
|
73
|
+
const rows = await db
|
|
74
|
+
.delete(notificationReminderRuleStages)
|
|
75
|
+
.where(eq(notificationReminderRuleStages.id, stageId))
|
|
76
|
+
.returning({ id: notificationReminderRuleStages.id });
|
|
77
|
+
return rows.length > 0;
|
|
78
|
+
}
|
|
79
|
+
export async function reorderReminderRuleStages(db, reminderRuleId, input) {
|
|
80
|
+
const now = new Date();
|
|
81
|
+
await db.transaction(async (tx) => {
|
|
82
|
+
for (let i = 0; i < input.stageIds.length; i += 1) {
|
|
83
|
+
const stageId = input.stageIds[i];
|
|
84
|
+
await tx
|
|
85
|
+
.update(notificationReminderRuleStages)
|
|
86
|
+
.set({ orderIndex: i, updatedAt: now })
|
|
87
|
+
.where(and(eq(notificationReminderRuleStages.id, stageId), eq(notificationReminderRuleStages.reminderRuleId, reminderRuleId)));
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
return listReminderRuleStages(db, reminderRuleId);
|
|
91
|
+
}
|
|
92
|
+
export async function listStageChannels(db, stageId) {
|
|
93
|
+
return db
|
|
94
|
+
.select()
|
|
95
|
+
.from(notificationReminderStageChannels)
|
|
96
|
+
.where(eq(notificationReminderStageChannels.stageId, stageId))
|
|
97
|
+
.orderBy(asc(notificationReminderStageChannels.orderIndex), asc(notificationReminderStageChannels.createdAt));
|
|
98
|
+
}
|
|
99
|
+
export async function createStageChannel(db, stageId, input) {
|
|
100
|
+
const [row] = await db
|
|
101
|
+
.insert(notificationReminderStageChannels)
|
|
102
|
+
.values({
|
|
103
|
+
stageId,
|
|
104
|
+
orderIndex: input.orderIndex,
|
|
105
|
+
channel: input.channel,
|
|
106
|
+
provider: input.provider ?? null,
|
|
107
|
+
templateId: input.templateId ?? null,
|
|
108
|
+
templateSlug: input.templateSlug ?? null,
|
|
109
|
+
recipientKind: input.recipientKind,
|
|
110
|
+
recipientRole: input.recipientRole ?? null,
|
|
111
|
+
metadata: input.metadata ?? null,
|
|
112
|
+
})
|
|
113
|
+
.returning();
|
|
114
|
+
if (!row)
|
|
115
|
+
throw new Error("Failed to create stage channel");
|
|
116
|
+
return row;
|
|
117
|
+
}
|
|
118
|
+
export async function updateStageChannel(db, channelId, input) {
|
|
119
|
+
const updates = { updatedAt: new Date() };
|
|
120
|
+
if (input.orderIndex !== undefined)
|
|
121
|
+
updates.orderIndex = input.orderIndex;
|
|
122
|
+
if (input.channel !== undefined)
|
|
123
|
+
updates.channel = input.channel;
|
|
124
|
+
if (input.provider !== undefined)
|
|
125
|
+
updates.provider = input.provider ?? null;
|
|
126
|
+
if (input.templateId !== undefined)
|
|
127
|
+
updates.templateId = input.templateId ?? null;
|
|
128
|
+
if (input.templateSlug !== undefined)
|
|
129
|
+
updates.templateSlug = input.templateSlug ?? null;
|
|
130
|
+
if (input.recipientKind !== undefined)
|
|
131
|
+
updates.recipientKind = input.recipientKind;
|
|
132
|
+
if (input.recipientRole !== undefined)
|
|
133
|
+
updates.recipientRole = input.recipientRole ?? null;
|
|
134
|
+
if (input.metadata !== undefined)
|
|
135
|
+
updates.metadata = input.metadata ?? null;
|
|
136
|
+
const [row] = await db
|
|
137
|
+
.update(notificationReminderStageChannels)
|
|
138
|
+
.set(updates)
|
|
139
|
+
.where(eq(notificationReminderStageChannels.id, channelId))
|
|
140
|
+
.returning();
|
|
141
|
+
return row ?? null;
|
|
142
|
+
}
|
|
143
|
+
export async function deleteStageChannel(db, channelId) {
|
|
144
|
+
const rows = await db
|
|
145
|
+
.delete(notificationReminderStageChannels)
|
|
146
|
+
.where(eq(notificationReminderStageChannels.id, channelId))
|
|
147
|
+
.returning({ id: notificationReminderStageChannels.id });
|
|
148
|
+
return rows.length > 0;
|
|
149
|
+
}
|
|
150
|
+
export async function getNotificationSettingsRecord(db, scope = "default") {
|
|
151
|
+
const [row] = await db
|
|
152
|
+
.select()
|
|
153
|
+
.from(notificationSettings)
|
|
154
|
+
.where(eq(notificationSettings.scope, scope))
|
|
155
|
+
.limit(1);
|
|
156
|
+
return row ?? { ...DEFAULT_NOTIFICATION_SETTINGS, scope };
|
|
157
|
+
}
|
|
158
|
+
export async function upsertNotificationSettings(db, input) {
|
|
159
|
+
const scope = input.scope ?? "default";
|
|
160
|
+
const existing = await db
|
|
161
|
+
.select()
|
|
162
|
+
.from(notificationSettings)
|
|
163
|
+
.where(eq(notificationSettings.scope, scope))
|
|
164
|
+
.limit(1);
|
|
165
|
+
const updates = { updatedAt: new Date() };
|
|
166
|
+
if (input.quietHoursLocal !== undefined)
|
|
167
|
+
updates.quietHoursLocal = input.quietHoursLocal ?? null;
|
|
168
|
+
if (input.blackoutDates !== undefined)
|
|
169
|
+
updates.blackoutDates = input.blackoutDates ?? null;
|
|
170
|
+
if (input.skipWeekends !== undefined)
|
|
171
|
+
updates.skipWeekends = input.skipWeekends;
|
|
172
|
+
if (input.recipientRateLimitPerDay !== undefined)
|
|
173
|
+
updates.recipientRateLimitPerDay = input.recipientRateLimitPerDay ?? null;
|
|
174
|
+
if (input.suppressionWindowHours !== undefined)
|
|
175
|
+
updates.suppressionWindowHours = input.suppressionWindowHours;
|
|
176
|
+
if (input.metadata !== undefined)
|
|
177
|
+
updates.metadata = input.metadata ?? null;
|
|
178
|
+
if (existing[0]) {
|
|
179
|
+
const [row] = await db
|
|
180
|
+
.update(notificationSettings)
|
|
181
|
+
.set(updates)
|
|
182
|
+
.where(eq(notificationSettings.scope, scope))
|
|
183
|
+
.returning();
|
|
184
|
+
if (!row)
|
|
185
|
+
throw new Error("Failed to update notification settings");
|
|
186
|
+
return row;
|
|
187
|
+
}
|
|
188
|
+
const [row] = await db
|
|
189
|
+
.insert(notificationSettings)
|
|
190
|
+
.values({
|
|
191
|
+
scope,
|
|
192
|
+
quietHoursLocal: input.quietHoursLocal ?? null,
|
|
193
|
+
blackoutDates: input.blackoutDates ?? null,
|
|
194
|
+
skipWeekends: input.skipWeekends ?? false,
|
|
195
|
+
recipientRateLimitPerDay: input.recipientRateLimitPerDay ?? null,
|
|
196
|
+
suppressionWindowHours: input.suppressionWindowHours ?? 24,
|
|
197
|
+
metadata: input.metadata ?? null,
|
|
198
|
+
})
|
|
199
|
+
.returning();
|
|
200
|
+
if (!row)
|
|
201
|
+
throw new Error("Failed to create notification settings");
|
|
202
|
+
return row;
|
|
203
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare function enrichBookingItem(value: unknown): unknown;
|
|
2
|
+
export declare function normalizeNotificationTemplateData(data: Record<string, unknown>): {
|
|
3
|
+
traveler: unknown;
|
|
4
|
+
travelers: unknown[];
|
|
5
|
+
billingPerson: unknown;
|
|
6
|
+
billing: unknown;
|
|
7
|
+
booking: unknown;
|
|
8
|
+
invoice: unknown;
|
|
9
|
+
paymentSession: unknown;
|
|
10
|
+
paymentSchedule: unknown;
|
|
11
|
+
payment: Record<string, unknown> | null;
|
|
12
|
+
documents: unknown[];
|
|
13
|
+
documentsCount: number;
|
|
14
|
+
items: unknown[];
|
|
15
|
+
product: {
|
|
16
|
+
title: {} | null;
|
|
17
|
+
} | null;
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=service-template-data.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-template-data.d.ts","sourceRoot":"","sources":["../src/service-template-data.ts"],"names":[],"mappings":"AAiLA,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,WAwB/C;AAED,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;;;;;;;;;;EA2G9E"}
|