feat(realtime): implement SSE realtime notifications; publish events from resolvers; remove polling in chat/sidebar/supplies/warehouse and wire realtime refetch
This commit is contained in:
@ -4,6 +4,7 @@ import { GraphQLError, GraphQLScalarType, Kind } from 'graphql'
|
||||
import jwt from 'jsonwebtoken'
|
||||
|
||||
import { prisma } from '@/lib/prisma'
|
||||
import { notifyMany, notifyOrganization } from '@/lib/realtime'
|
||||
import { DaDataService } from '@/services/dadata-service'
|
||||
import { MarketplaceService } from '@/services/marketplace-service'
|
||||
import { SmsService } from '@/services/sms-service'
|
||||
@ -3336,6 +3337,18 @@ export const resolvers = {
|
||||
},
|
||||
})
|
||||
|
||||
// Уведомляем получателя о новой заявке
|
||||
try {
|
||||
notifyOrganization(args.organizationId, {
|
||||
type: 'counterparty:request:new',
|
||||
payload: {
|
||||
requestId: request.id,
|
||||
senderId: request.senderId,
|
||||
receiverId: request.receiverId,
|
||||
},
|
||||
})
|
||||
} catch {}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Заявка отправлена',
|
||||
@ -3425,6 +3438,14 @@ export const resolvers = {
|
||||
])
|
||||
}
|
||||
|
||||
// Оповещаем обе стороны об обновлении заявки и возможном изменении списка контрагентов
|
||||
try {
|
||||
notifyMany([request.senderId, request.receiverId], {
|
||||
type: 'counterparty:request:updated',
|
||||
payload: { requestId: updatedRequest.id, status: updatedRequest.status },
|
||||
})
|
||||
} catch {}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: args.accept ? 'Заявка принята' : 'Заявка отклонена',
|
||||
@ -3597,6 +3618,19 @@ export const resolvers = {
|
||||
},
|
||||
})
|
||||
|
||||
// Реалтайм нотификация для обеих организаций (отправитель и получатель)
|
||||
try {
|
||||
notifyMany([currentUser.organization.id, args.receiverOrganizationId], {
|
||||
type: 'message:new',
|
||||
payload: {
|
||||
messageId: message.id,
|
||||
senderOrgId: message.senderOrganizationId,
|
||||
receiverOrgId: message.receiverOrganizationId,
|
||||
type: message.type,
|
||||
},
|
||||
})
|
||||
} catch {}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Сообщение отправлено',
|
||||
@ -3684,6 +3718,18 @@ export const resolvers = {
|
||||
},
|
||||
})
|
||||
|
||||
try {
|
||||
notifyMany([currentUser.organization.id, args.receiverOrganizationId], {
|
||||
type: 'message:new',
|
||||
payload: {
|
||||
messageId: message.id,
|
||||
senderOrgId: message.senderOrganizationId,
|
||||
receiverOrgId: message.receiverOrganizationId,
|
||||
type: message.type,
|
||||
},
|
||||
})
|
||||
} catch {}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Голосовое сообщение отправлено',
|
||||
@ -3765,6 +3811,18 @@ export const resolvers = {
|
||||
},
|
||||
})
|
||||
|
||||
try {
|
||||
notifyMany([currentUser.organization.id, args.receiverOrganizationId], {
|
||||
type: 'message:new',
|
||||
payload: {
|
||||
messageId: message.id,
|
||||
senderOrgId: message.senderOrganizationId,
|
||||
receiverOrgId: message.receiverOrganizationId,
|
||||
type: message.type,
|
||||
},
|
||||
})
|
||||
} catch {}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Изображение отправлено',
|
||||
@ -3846,6 +3904,18 @@ export const resolvers = {
|
||||
},
|
||||
})
|
||||
|
||||
try {
|
||||
notifyMany([currentUser.organization.id, args.receiverOrganizationId], {
|
||||
type: 'message:new',
|
||||
payload: {
|
||||
messageId: message.id,
|
||||
senderOrgId: message.senderOrganizationId,
|
||||
receiverOrgId: message.receiverOrganizationId,
|
||||
type: message.type,
|
||||
},
|
||||
})
|
||||
} catch {}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Файл отправлен',
|
||||
@ -4225,6 +4295,14 @@ export const resolvers = {
|
||||
description: args.input.description,
|
||||
})
|
||||
|
||||
// Реалтайм: уведомляем о смене складских остатков
|
||||
try {
|
||||
notifyOrganization(currentUser.organization.id, {
|
||||
type: 'warehouse:changed',
|
||||
payload: { supplyId: updatedSupply.id, change: -args.input.quantityUsed },
|
||||
})
|
||||
} catch {}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: `Использовано ${args.input.quantityUsed} ${updatedSupply.unit} расходника "${updatedSupply.name}"`,
|
||||
@ -4492,6 +4570,20 @@ export const resolvers = {
|
||||
},
|
||||
})
|
||||
|
||||
// Реалтайм: уведомляем поставщика и вовлеченные стороны о новом заказе
|
||||
try {
|
||||
const orgIds = [
|
||||
currentUser.organization.id,
|
||||
args.input.partnerId,
|
||||
fulfillmentCenterId || undefined,
|
||||
args.input.logisticsPartnerId || undefined,
|
||||
].filter(Boolean) as string[]
|
||||
notifyMany(orgIds, {
|
||||
type: 'supply-order:new',
|
||||
payload: { id: supplyOrder.id, organizationId: currentUser.organization.id },
|
||||
})
|
||||
} catch {}
|
||||
|
||||
// 📦 РЕЗЕРВИРУЕМ ТОВАРЫ У ПОСТАВЩИКА
|
||||
// Увеличиваем поле "ordered" для каждого заказанного товара
|
||||
for (const item of args.input.items) {
|
||||
@ -6361,6 +6453,19 @@ export const resolvers = {
|
||||
console.warn('🎉 Склад организации успешно обновлен!')
|
||||
}
|
||||
|
||||
// Уведомляем вовлеченные организации об изменении статуса заказа
|
||||
try {
|
||||
const orgIds = [
|
||||
existingOrder.organizationId,
|
||||
existingOrder.partnerId,
|
||||
existingOrder.fulfillmentCenterId || undefined,
|
||||
].filter(Boolean) as string[]
|
||||
notifyMany(orgIds, {
|
||||
type: 'supply-order:updated',
|
||||
payload: { id: updatedOrder.id, status: updatedOrder.status },
|
||||
})
|
||||
} catch {}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: `Статус заказа поставки обновлен на "${args.status}"`,
|
||||
@ -6467,6 +6572,19 @@ export const resolvers = {
|
||||
newStatus: 'CONFIRMED',
|
||||
})
|
||||
|
||||
try {
|
||||
const orgIds = [
|
||||
existingOrder.organizationId,
|
||||
existingOrder.partnerId,
|
||||
existingOrder.fulfillmentCenterId || undefined,
|
||||
args.logisticsPartnerId,
|
||||
].filter(Boolean) as string[]
|
||||
notifyMany(orgIds, {
|
||||
type: 'supply-order:updated',
|
||||
payload: { id: updatedOrder.id, status: updatedOrder.status },
|
||||
})
|
||||
} catch {}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Логистика успешно назначена',
|
||||
@ -6590,6 +6708,19 @@ export const resolvers = {
|
||||
})
|
||||
|
||||
console.warn(`[DEBUG] Заказ ${args.id} успешно обновлен до статуса: ${updatedOrder.status}`)
|
||||
try {
|
||||
const orgIds = [
|
||||
updatedOrder.organizationId,
|
||||
updatedOrder.partnerId,
|
||||
updatedOrder.fulfillmentCenterId || undefined,
|
||||
updatedOrder.logisticsPartnerId || undefined,
|
||||
].filter(Boolean) as string[]
|
||||
notifyMany(orgIds, {
|
||||
type: 'supply-order:updated',
|
||||
payload: { id: updatedOrder.id, status: updatedOrder.status },
|
||||
})
|
||||
} catch {}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Заказ поставки одобрен поставщиком. Товары зарезервированы, остатки обновлены.',
|
||||
@ -6693,6 +6824,19 @@ export const resolvers = {
|
||||
updatedOrder.items.map((item) => `${item.productId}: -${item.quantity} шт.`).join(', '),
|
||||
)
|
||||
|
||||
try {
|
||||
const orgIds = [
|
||||
updatedOrder.organizationId,
|
||||
updatedOrder.partnerId,
|
||||
updatedOrder.fulfillmentCenterId || undefined,
|
||||
updatedOrder.logisticsPartnerId || undefined,
|
||||
].filter(Boolean) as string[]
|
||||
notifyMany(orgIds, {
|
||||
type: 'supply-order:updated',
|
||||
payload: { id: updatedOrder.id, status: updatedOrder.status },
|
||||
})
|
||||
} catch {}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: args.reason ? `Заказ отклонен поставщиком. Причина: ${args.reason}` : 'Заказ отклонен поставщиком',
|
||||
@ -6792,6 +6936,19 @@ export const resolvers = {
|
||||
},
|
||||
})
|
||||
|
||||
try {
|
||||
const orgIds = [
|
||||
updatedOrder.organizationId,
|
||||
updatedOrder.partnerId,
|
||||
updatedOrder.fulfillmentCenterId || undefined,
|
||||
updatedOrder.logisticsPartnerId || undefined,
|
||||
].filter(Boolean) as string[]
|
||||
notifyMany(orgIds, {
|
||||
type: 'supply-order:updated',
|
||||
payload: { id: updatedOrder.id, status: updatedOrder.status },
|
||||
})
|
||||
} catch {}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: "Заказ отправлен поставщиком. Товары переведены в статус 'в пути'.",
|
||||
@ -6859,6 +7016,19 @@ export const resolvers = {
|
||||
},
|
||||
})
|
||||
|
||||
try {
|
||||
const orgIds = [
|
||||
updatedOrder.organizationId,
|
||||
updatedOrder.partnerId,
|
||||
updatedOrder.fulfillmentCenterId || undefined,
|
||||
updatedOrder.logisticsPartnerId || undefined,
|
||||
].filter(Boolean) as string[]
|
||||
notifyMany(orgIds, {
|
||||
type: 'supply-order:updated',
|
||||
payload: { id: updatedOrder.id, status: updatedOrder.status },
|
||||
})
|
||||
} catch {}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'Заказ подтвержден логистической компанией',
|
||||
@ -6926,6 +7096,19 @@ export const resolvers = {
|
||||
},
|
||||
})
|
||||
|
||||
try {
|
||||
const orgIds = [
|
||||
updatedOrder.organizationId,
|
||||
updatedOrder.partnerId,
|
||||
updatedOrder.fulfillmentCenterId || undefined,
|
||||
updatedOrder.logisticsPartnerId || undefined,
|
||||
].filter(Boolean) as string[]
|
||||
notifyMany(orgIds, {
|
||||
type: 'supply-order:updated',
|
||||
payload: { id: updatedOrder.id, status: updatedOrder.status },
|
||||
})
|
||||
} catch {}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: args.reason
|
||||
|
Reference in New Issue
Block a user