R50 通知推送:dispatcher 投递服务、业务事件接入与员工推送开关
这个提交包含在:
+67
-1
@@ -1,5 +1,33 @@
|
||||
const { z } = require("zod");
|
||||
|
||||
const { AppError } = require("../utils/AppError");
|
||||
const { buildAuditLogData } = require("../utils/audit");
|
||||
const { sendData } = require("../utils/reply");
|
||||
|
||||
const NOTIFICATION_PREFERENCES_SCHEMA = z
|
||||
.object({
|
||||
notificationPushEnabled: z.boolean(),
|
||||
})
|
||||
.strict();
|
||||
|
||||
function buildValidationError(details) {
|
||||
return new AppError({
|
||||
code: "VALID_001",
|
||||
message: "参数校验失败",
|
||||
statusCode: 400,
|
||||
details,
|
||||
});
|
||||
}
|
||||
|
||||
function parseNotificationPreferences(body) {
|
||||
const parsed = NOTIFICATION_PREFERENCES_SCHEMA.safeParse(body ?? {});
|
||||
if (!parsed.success) {
|
||||
throw buildValidationError(parsed.error.flatten());
|
||||
}
|
||||
|
||||
return parsed.data;
|
||||
}
|
||||
|
||||
async function meRoutes(fastify) {
|
||||
fastify.get(
|
||||
"/me",
|
||||
@@ -18,6 +46,7 @@ async function meRoutes(fastify) {
|
||||
department_id: true,
|
||||
direct_manager_id: true,
|
||||
status: true,
|
||||
notification_push_enabled: true,
|
||||
roles: { select: { role_code: true } },
|
||||
wecom_identity_binding: { select: { external_user_id: true, created_at: true } },
|
||||
},
|
||||
@@ -33,12 +62,49 @@ async function meRoutes(fastify) {
|
||||
departmentId: employee?.department_id ?? "",
|
||||
directManagerId: employee?.direct_manager_id ?? null,
|
||||
status: employee?.status ?? "active",
|
||||
notificationPushEnabled: employee?.notification_push_enabled ?? true,
|
||||
roleCodes,
|
||||
wecomBinding: employee?.wecom_identity_binding ? { externalUserId: employee.wecom_identity_binding.external_user_id, createdAt: employee.wecom_identity_binding.created_at?.toISOString?.() ?? null } : null,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
fastify.patch(
|
||||
"/me/notification-preferences",
|
||||
{
|
||||
preHandler: fastify.authenticate,
|
||||
},
|
||||
async (request, reply) => {
|
||||
const body = parseNotificationPreferences(request.body);
|
||||
const employee = await fastify.prisma.employee.update({
|
||||
where: { id: request.employee.id },
|
||||
data: {
|
||||
notification_push_enabled: body.notificationPushEnabled,
|
||||
updated_by: request.employee.id,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
notification_push_enabled: true,
|
||||
},
|
||||
});
|
||||
|
||||
await fastify.prisma.auditLog.create({
|
||||
data: buildAuditLogData(request, {
|
||||
actorId: request.employee.id,
|
||||
action: "EMPLOYEE_NOTIFICATION_PREFERENCE_UPDATED",
|
||||
targetType: "employee",
|
||||
targetId: employee.id,
|
||||
extra: {
|
||||
notificationPushEnabled: employee.notification_push_enabled,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
return sendData(reply, request, {
|
||||
notificationPushEnabled: employee.notification_push_enabled,
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = meRoutes;
|
||||
|
||||
|
||||
在新工单中引用
屏蔽一个用户