R50 通知推送:dispatcher 投递服务、业务事件接入与员工推送开关
这个提交包含在:
@@ -3,10 +3,10 @@ const { z } = require("zod");
|
||||
const { AppError } = require("../utils/AppError");
|
||||
const { buildAuditLogData } = require("../utils/audit");
|
||||
const { sendData } = require("../utils/reply");
|
||||
const { createNotifications } = require("../services/notifications");
|
||||
const { enqueueImNotifications } = require("../services/notifications/imEnqueue");
|
||||
const { createNotificationsWithRecords } = require("../services/notifications");
|
||||
const { sendNotificationEmailSafe } = require("../services/email");
|
||||
const { NOTIFICATION_TYPES } = require("../constants/notificationTypes");
|
||||
const { flushNotificationDispatchTasks } = require("../services/notificationDispatcher");
|
||||
|
||||
const UUID_SCHEMA = z.string().uuid();
|
||||
const NOTE_SCHEMA = z.string().trim().max(500).nullable().optional();
|
||||
@@ -204,6 +204,7 @@ async function assetMovementsRoutes(fastify) {
|
||||
const body = parseBody(ASSIGN_BODY_SCHEMA, request.body);
|
||||
const note = normalizeNote(body.note);
|
||||
const emailTasks = [];
|
||||
const dispatchTasks = [];
|
||||
|
||||
const result = await fastify.prisma.$transaction(async (tx) => {
|
||||
const asset = await ensureAssetExists(tx, assetId);
|
||||
@@ -261,7 +262,7 @@ async function assetMovementsRoutes(fastify) {
|
||||
const recipients = uniq([employee.id]);
|
||||
const title = `【资产领用】资产卡片 ${asset.asset_no}`;
|
||||
const bodyText = `资产卡片 ${asset.asset_no} 已分配给你,请在资产台账中查看。`;
|
||||
await createNotifications(tx, {
|
||||
const notifications = await createNotificationsWithRecords(tx, {
|
||||
recipientEmployeeIds: recipients,
|
||||
type: NOTIFICATION_TYPES.assetAssigned,
|
||||
title,
|
||||
@@ -269,18 +270,14 @@ async function assetMovementsRoutes(fastify) {
|
||||
targetType: "asset_card",
|
||||
targetId: asset.id,
|
||||
});
|
||||
await enqueueImNotifications(tx, {
|
||||
config: fastify.config,
|
||||
logger: fastify.log,
|
||||
recipientEmployeeIds: recipients,
|
||||
dispatchTasks.push({
|
||||
notifications,
|
||||
type: NOTIFICATION_TYPES.assetAssigned,
|
||||
title,
|
||||
body: bodyText,
|
||||
targetType: "asset_card",
|
||||
targetId: asset.id,
|
||||
targetPath: "/assets",
|
||||
entityType: "asset_card",
|
||||
entityId: asset.id,
|
||||
actorId: request.employee.id,
|
||||
});
|
||||
emailTasks.push({
|
||||
@@ -303,6 +300,13 @@ async function assetMovementsRoutes(fastify) {
|
||||
...task,
|
||||
});
|
||||
}
|
||||
await flushNotificationDispatchTasks({
|
||||
prisma: fastify.prisma,
|
||||
config: fastify.config,
|
||||
logger: fastify.log,
|
||||
requestId: request.id,
|
||||
tasks: dispatchTasks,
|
||||
});
|
||||
|
||||
return sendData(reply, request, {
|
||||
assetId: result.updatedAsset.id,
|
||||
@@ -326,6 +330,7 @@ async function assetMovementsRoutes(fastify) {
|
||||
const body = parseBody(RETURN_BODY_SCHEMA, request.body);
|
||||
const note = normalizeNote(body.note);
|
||||
const emailTasks = [];
|
||||
const dispatchTasks = [];
|
||||
|
||||
const result = await fastify.prisma.$transaction(async (tx) => {
|
||||
const asset = await ensureAssetExists(tx, assetId);
|
||||
@@ -368,7 +373,7 @@ async function assetMovementsRoutes(fastify) {
|
||||
const recipients = uniq([asset.assignee_employee_id]);
|
||||
const title = `【资产归还】资产卡片 ${asset.asset_no}`;
|
||||
const bodyText = `资产卡片 ${asset.asset_no} 已完成归还。`;
|
||||
await createNotifications(tx, {
|
||||
const notifications = await createNotificationsWithRecords(tx, {
|
||||
recipientEmployeeIds: recipients,
|
||||
type: NOTIFICATION_TYPES.assetReturned,
|
||||
title,
|
||||
@@ -376,18 +381,14 @@ async function assetMovementsRoutes(fastify) {
|
||||
targetType: "asset_card",
|
||||
targetId: asset.id,
|
||||
});
|
||||
await enqueueImNotifications(tx, {
|
||||
config: fastify.config,
|
||||
logger: fastify.log,
|
||||
recipientEmployeeIds: recipients,
|
||||
dispatchTasks.push({
|
||||
notifications,
|
||||
type: NOTIFICATION_TYPES.assetReturned,
|
||||
title,
|
||||
body: bodyText,
|
||||
targetType: "asset_card",
|
||||
targetId: asset.id,
|
||||
targetPath: "/assets",
|
||||
entityType: "asset_card",
|
||||
entityId: asset.id,
|
||||
actorId: request.employee.id,
|
||||
});
|
||||
emailTasks.push({
|
||||
@@ -410,6 +411,13 @@ async function assetMovementsRoutes(fastify) {
|
||||
...task,
|
||||
});
|
||||
}
|
||||
await flushNotificationDispatchTasks({
|
||||
prisma: fastify.prisma,
|
||||
config: fastify.config,
|
||||
logger: fastify.log,
|
||||
requestId: request.id,
|
||||
tasks: dispatchTasks,
|
||||
});
|
||||
|
||||
return sendData(reply, request, {
|
||||
assetId: result.updatedAsset.id,
|
||||
@@ -436,6 +444,7 @@ async function assetMovementsRoutes(fastify) {
|
||||
const hasLocationField = Object.prototype.hasOwnProperty.call(body, "toLocation");
|
||||
const nextLocation = hasLocationField ? normalizeLocation(body.toLocation) : undefined;
|
||||
const emailTasks = [];
|
||||
const dispatchTasks = [];
|
||||
|
||||
const result = await fastify.prisma.$transaction(async (tx) => {
|
||||
const asset = await ensureAssetExists(tx, assetId);
|
||||
@@ -531,7 +540,7 @@ async function assetMovementsRoutes(fastify) {
|
||||
]);
|
||||
const title = `【资产调拨】资产卡片 ${asset.asset_no}`;
|
||||
const bodyText = `资产卡片 ${asset.asset_no} 已完成调拨,请在资产台账中查看最新归属与位置。`;
|
||||
await createNotifications(tx, {
|
||||
const notifications = await createNotificationsWithRecords(tx, {
|
||||
recipientEmployeeIds: recipients,
|
||||
type: NOTIFICATION_TYPES.assetTransferred,
|
||||
title,
|
||||
@@ -539,18 +548,14 @@ async function assetMovementsRoutes(fastify) {
|
||||
targetType: "asset_card",
|
||||
targetId: asset.id,
|
||||
});
|
||||
await enqueueImNotifications(tx, {
|
||||
config: fastify.config,
|
||||
logger: fastify.log,
|
||||
recipientEmployeeIds: recipients,
|
||||
dispatchTasks.push({
|
||||
notifications,
|
||||
type: NOTIFICATION_TYPES.assetTransferred,
|
||||
title,
|
||||
body: bodyText,
|
||||
targetType: "asset_card",
|
||||
targetId: asset.id,
|
||||
targetPath: "/assets",
|
||||
entityType: "asset_card",
|
||||
entityId: asset.id,
|
||||
actorId: request.employee.id,
|
||||
});
|
||||
emailTasks.push({
|
||||
@@ -573,6 +578,13 @@ async function assetMovementsRoutes(fastify) {
|
||||
...task,
|
||||
});
|
||||
}
|
||||
await flushNotificationDispatchTasks({
|
||||
prisma: fastify.prisma,
|
||||
config: fastify.config,
|
||||
logger: fastify.log,
|
||||
requestId: request.id,
|
||||
tasks: dispatchTasks,
|
||||
});
|
||||
|
||||
return sendData(reply, request, {
|
||||
assetId: result.updatedAsset.id,
|
||||
|
||||
在新工单中引用
屏蔽一个用户