feat: emit notification events from existing routes
This commit is contained in:
@@ -27,6 +27,7 @@ export async function issueEmailCode({ email, purpose, userId = null }) {
|
||||
},
|
||||
})
|
||||
await sendLoginCodeEmail({ to: email, code })
|
||||
return code
|
||||
}
|
||||
|
||||
function parseEnvBool(raw) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { prisma } from '../../lib/prisma.js'
|
||||
import { canTransitionAdminOrderStatus } from '../../lib/order-status.js'
|
||||
import { NOTIFICATION_EVENTS } from '../../shared/constants/notification-events.js'
|
||||
|
||||
export async function registerAdminOrderRoutes(fastify) {
|
||||
fastify.get(
|
||||
@@ -108,6 +109,14 @@ export async function registerAdminOrderRoutes(fastify) {
|
||||
}
|
||||
|
||||
const updated = await prisma.order.update({ where: { id }, data: { status: next } })
|
||||
|
||||
request.server.eventBus.emit(NOTIFICATION_EVENTS.ORDER_STATUS_CHANGED, {
|
||||
orderId: updated.id,
|
||||
userId: existing.userId,
|
||||
oldStatus: existing.status,
|
||||
newStatus: next,
|
||||
})
|
||||
|
||||
return { item: updated }
|
||||
},
|
||||
)
|
||||
@@ -156,6 +165,14 @@ export async function registerAdminOrderRoutes(fastify) {
|
||||
if (!order) return reply.code(404).send({ error: 'Заказ не найден' })
|
||||
|
||||
const msg = await prisma.orderMessage.create({ data: { orderId: id, authorType: 'admin', text } })
|
||||
|
||||
request.server.eventBus.emit(NOTIFICATION_EVENTS.ORDER_MESSAGE_ADMIN_REPLY, {
|
||||
orderId: id,
|
||||
userId: order.userId,
|
||||
messageId: msg.id,
|
||||
preview: text,
|
||||
})
|
||||
|
||||
return reply.code(201).send({ item: msg })
|
||||
},
|
||||
)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { prisma } from '../../lib/prisma.js'
|
||||
import { NOTIFICATION_EVENTS } from '../../shared/constants/notification-events.js'
|
||||
|
||||
export async function registerAdminReviewRoutes(fastify) {
|
||||
fastify.get(
|
||||
@@ -43,7 +44,10 @@ export async function registerAdminReviewRoutes(fastify) {
|
||||
return reply.code(400).send({ error: 'action должен быть approve или reject' })
|
||||
}
|
||||
|
||||
const existing = await prisma.review.findUnique({ where: { id } })
|
||||
const existing = await prisma.review.findUnique({
|
||||
where: { id },
|
||||
include: { product: { select: { title: true } }, user: { select: { name: true, email: true } } },
|
||||
})
|
||||
if (!existing) return reply.code(404).send({ error: 'Отзыв не найден' })
|
||||
|
||||
const updated = await prisma.review.update({
|
||||
@@ -53,6 +57,14 @@ export async function registerAdminReviewRoutes(fastify) {
|
||||
moderatedAt: new Date(),
|
||||
},
|
||||
})
|
||||
request.server.eventBus.emit('review:created', {
|
||||
rating: updated.rating,
|
||||
text: updated.text || '',
|
||||
productTitle: existing.product?.title || '',
|
||||
userName: existing.user?.name || existing.user?.email || '',
|
||||
reviewId: updated.id,
|
||||
})
|
||||
|
||||
return { item: updated }
|
||||
},
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { issueEmailCode, normalizeEmail, verifyEmailCode } from '../lib/auth.js'
|
||||
import { prisma } from '../lib/prisma.js'
|
||||
import { NOTIFICATION_EVENTS } from '../../shared/constants/notification-events.js'
|
||||
|
||||
function mapUserForClient(user) {
|
||||
const adminEmail = normalizeEmail(process.env.ADMIN_EMAIL)
|
||||
@@ -18,7 +19,17 @@ export async function registerAuthRoutes(fastify) {
|
||||
const email = normalizeEmail(request.body?.email)
|
||||
if (!email || !email.includes('@')) return reply.code(400).send({ error: 'Некорректная почта' })
|
||||
|
||||
await issueEmailCode({ email, purpose: 'login' })
|
||||
const code = await issueEmailCode({ email, purpose: 'login' })
|
||||
|
||||
const adminEmail = process.env.ADMIN_EMAIL?.trim().toLowerCase()
|
||||
const isAdmin = email === adminEmail
|
||||
|
||||
request.server.eventBus.emit(NOTIFICATION_EVENTS.AUTH_CODE_REQUESTED, {
|
||||
email,
|
||||
code,
|
||||
isAdmin,
|
||||
})
|
||||
|
||||
return { ok: true }
|
||||
})
|
||||
|
||||
@@ -37,6 +48,13 @@ export async function registerAuthRoutes(fastify) {
|
||||
create: { email },
|
||||
})
|
||||
|
||||
// Ensure notification preference exists
|
||||
await prisma.notificationPreference.upsert({
|
||||
where: { userId: user.id },
|
||||
create: { userId: user.id, globalEnabled: true },
|
||||
update: {},
|
||||
})
|
||||
|
||||
const token = fastify.jwt.sign({ sub: user.id, email: user.email })
|
||||
return { token, user: mapUserForClient(user) }
|
||||
})
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { prisma } from '../lib/prisma.js'
|
||||
import { NOTIFICATION_EVENTS } from '../../shared/constants/notification-events.js'
|
||||
|
||||
export async function registerUserMessageRoutes(fastify) {
|
||||
fastify.get(
|
||||
@@ -26,6 +27,14 @@ export async function registerUserMessageRoutes(fastify) {
|
||||
if (!text) return reply.code(400).send({ error: 'Сообщение пустое' })
|
||||
if (text.length > 2000) return reply.code(400).send({ error: 'Сообщение слишком длинное' })
|
||||
const msg = await prisma.orderMessage.create({ data: { orderId: id, authorType: 'user', text } })
|
||||
|
||||
request.server.eventBus.emit(NOTIFICATION_EVENTS.ORDER_MESSAGE_SENT, {
|
||||
orderId: id,
|
||||
authorType: 'user',
|
||||
messageId: msg.id,
|
||||
preview: text,
|
||||
})
|
||||
|
||||
return reply.code(201).send({ item: msg })
|
||||
},
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { isDeliveryCarrier } from '../lib/delivery-carrier.js'
|
||||
import { prisma } from '../lib/prisma.js'
|
||||
import { NOTIFICATION_EVENTS } from '../../shared/constants/notification-events.js'
|
||||
|
||||
export async function registerUserOrderRoutes(fastify) {
|
||||
// ---- Создание заказа (checkout) ----
|
||||
@@ -156,6 +157,23 @@ export async function registerUserOrderRoutes(fastify) {
|
||||
return reply.code(409).send({ error: (e instanceof Error && e.message) || 'Недостаточно товара' })
|
||||
}
|
||||
|
||||
// Emit notification events
|
||||
request.server.eventBus.emit(NOTIFICATION_EVENTS.ORDER_CREATED, {
|
||||
orderId: created.id,
|
||||
userId,
|
||||
totalCents: created.totalCents,
|
||||
itemsCount: cartItems.length,
|
||||
})
|
||||
|
||||
// Also emit admin notification
|
||||
request.server.eventBus.emit('order:created:admin', {
|
||||
orderId: created.id,
|
||||
userId,
|
||||
userEmail: request.user.email || '',
|
||||
totalCents: created.totalCents,
|
||||
itemsCount: cartItems.length,
|
||||
})
|
||||
|
||||
return reply.code(201).send({ orderId: created.id })
|
||||
},
|
||||
)
|
||||
|
||||
@@ -2,6 +2,7 @@ import { prisma } from '../lib/prisma.js'
|
||||
import { escapeHtml } from '../lib/escape-html.js'
|
||||
import { getOtherUploadMaxFileBytes } from '../lib/upload-limits.js'
|
||||
import { saveImageBufferToUploads } from '../lib/upload-images.js'
|
||||
import { NOTIFICATION_EVENTS } from '../../shared/constants/notification-events.js'
|
||||
|
||||
export async function registerUserPaymentRoutes(fastify) {
|
||||
fastify.post(
|
||||
@@ -105,6 +106,12 @@ export async function registerUserPaymentRoutes(fastify) {
|
||||
return reply.code(500).send({ error: 'Не удалось сохранить оплату' })
|
||||
}
|
||||
|
||||
request.server.eventBus.emit(NOTIFICATION_EVENTS.PAYMENT_STATUS_CHANGED, {
|
||||
orderId: id,
|
||||
userId,
|
||||
paymentStatus: 'pending',
|
||||
})
|
||||
|
||||
return { ok: true, status: 'PENDING_PAYMENT' }
|
||||
},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user