176 lines
4.7 KiB
JavaScript
176 lines
4.7 KiB
JavaScript
export default defineEventHandler(async (event) => {
|
|
try {
|
|
const body = await readBody(event)
|
|
|
|
// Basic validation
|
|
if (!body.name) {
|
|
throw createError({
|
|
statusCode: 400,
|
|
statusMessage: 'Name is required'
|
|
})
|
|
}
|
|
|
|
if (!['email', 'push'].includes(body.type)) {
|
|
throw createError({
|
|
statusCode: 400,
|
|
statusMessage: 'Type must be either email or push'
|
|
})
|
|
}
|
|
|
|
if (body.priority && !['low', 'medium', 'high', 'critical'].includes(body.priority)) {
|
|
throw createError({
|
|
statusCode: 400,
|
|
statusMessage: 'Priority must be low, medium, high, or critical'
|
|
})
|
|
}
|
|
|
|
// Set default priority if not provided
|
|
const validatedData = {
|
|
...body,
|
|
priority: body.priority || 'medium'
|
|
}
|
|
|
|
// Get user from session
|
|
const user = event.context.user
|
|
if (!user) {
|
|
throw createError({
|
|
statusCode: 401,
|
|
statusMessage: 'Unauthorized'
|
|
})
|
|
}
|
|
|
|
// Start transaction
|
|
const result = await prisma.$transaction(async (tx) => {
|
|
// Get template if provided
|
|
let templateData = null
|
|
if (validatedData.template) {
|
|
templateData = await tx.notification_templates.findUnique({
|
|
where: { id: validatedData.template }
|
|
})
|
|
if (!templateData) {
|
|
throw createError({
|
|
statusCode: 400,
|
|
statusMessage: 'Template not found'
|
|
})
|
|
}
|
|
}
|
|
|
|
// Get segment if provided
|
|
let segmentData = null
|
|
let estimatedReach = 0
|
|
if (validatedData.segment) {
|
|
segmentData = await tx.user_segments.findFirst({
|
|
where: {
|
|
value: validatedData.segment,
|
|
is_active: true
|
|
}
|
|
})
|
|
if (!segmentData) {
|
|
throw createError({
|
|
statusCode: 400,
|
|
statusMessage: 'Segment not found'
|
|
})
|
|
}
|
|
// TODO: Calculate estimated reach based on segment
|
|
estimatedReach = 1000 // Placeholder
|
|
}
|
|
|
|
// Create notification
|
|
const notification = await tx.notifications.create({
|
|
data: {
|
|
title: validatedData.name,
|
|
type: 'bulk',
|
|
priority: validatedData.priority,
|
|
delivery_type: validatedData.scheduledAt ? 'scheduled' : 'immediate',
|
|
scheduled_at: validatedData.scheduledAt ? new Date(validatedData.scheduledAt) : null,
|
|
status: validatedData.scheduledAt ? 'scheduled' : 'sending',
|
|
audience_type: validatedData.segment ? 'segmented' : 'all',
|
|
content_type: validatedData.template ? 'template' : 'new',
|
|
template_id: templateData?.id,
|
|
estimated_reach: estimatedReach,
|
|
created_by: user.userID.toString(),
|
|
enable_tracking: true,
|
|
exclude_unsubscribed: true,
|
|
respect_do_not_disturb: true
|
|
}
|
|
})
|
|
|
|
// Create notification channel
|
|
await tx.notification_channels.create({
|
|
data: {
|
|
notification_id: notification.id,
|
|
channel_type: validatedData.type
|
|
}
|
|
})
|
|
|
|
// Add segment if provided
|
|
if (segmentData) {
|
|
await tx.notification_user_segments.create({
|
|
data: {
|
|
notification_id: notification.id,
|
|
segment_id: segmentData.id
|
|
}
|
|
})
|
|
}
|
|
|
|
// Queue for processing if immediate
|
|
if (!validatedData.scheduledAt) {
|
|
// Process recipients immediately
|
|
await processImmediateNotification(notification.id, {
|
|
type: validatedData.type,
|
|
segment: validatedData.segment
|
|
}, tx)
|
|
}
|
|
|
|
return {
|
|
id: notification.id,
|
|
estimatedReach
|
|
}
|
|
})
|
|
|
|
return result
|
|
} catch (error) {
|
|
console.error('Error creating batch:', error)
|
|
throw error
|
|
}
|
|
})
|
|
|
|
// Helper function to process immediate notifications
|
|
async function processImmediateNotification(notificationId, data, tx) {
|
|
// Get target users based on segment
|
|
const usersQuery = {
|
|
select: {
|
|
id: true,
|
|
email: true
|
|
},
|
|
where: {}
|
|
}
|
|
|
|
if (data.segment) {
|
|
// Add segment criteria
|
|
// TODO: Implement proper segment filtering
|
|
}
|
|
|
|
const users = await tx.users.findMany(usersQuery)
|
|
|
|
// Create recipient records and queue entries
|
|
for (const user of users) {
|
|
const notificationRecipient = await tx.notification_recipients.create({
|
|
data: {
|
|
notification_id: notificationId,
|
|
user_id: user.id,
|
|
email: user.email,
|
|
channel_type: data.type
|
|
}
|
|
})
|
|
|
|
await tx.notification_queue.create({
|
|
data: {
|
|
notification_id: notificationId,
|
|
recipient_id: notificationRecipient.id,
|
|
scheduled_for: new Date(),
|
|
priority: 5 // Default priority
|
|
}
|
|
})
|
|
}
|
|
}
|