文件
hyb-oa/server/src/routes/feeControl.js
T
wangsli 6dee2daf3e P25L-1~P25L-5 实现预算控制与AP最小可用运营
合同 CSV 已回填 reviewer/QA 结果;运行时回归受当前环境缺少 node/npm 阻塞。
2026-03-29 09:21:17 +08:00

54 行
1.5 KiB
JavaScript

const { z } = require("zod");
const { AppError } = require("../utils/AppError");
const { sendData } = require("../utils/reply");
const {
getPrecheckPermissionCode,
resolveEntityPrecheck,
} = require("../services/feeControl");
const PRECHECK_BODY_SCHEMA = z.object({
entityType: z.enum(["reimbursement", "purchase_request", "travel_request"]),
entityId: z.string().uuid(),
}).strict();
function buildValidationError(details, statusCode = 400) {
return new AppError({
code: "VALID_001",
message: "参数校验失败",
statusCode,
details,
});
}
function parseBody(body) {
const parsed = PRECHECK_BODY_SCHEMA.safeParse(body ?? {});
if (!parsed.success) {
throw buildValidationError(parsed.error.flatten());
}
return parsed.data;
}
async function feeControlRoutes(fastify) {
fastify.post("/fee-control/precheck", { preHandler: fastify.authenticate }, async (request, reply) => {
const body = parseBody(request.body);
const permissionCode = getPrecheckPermissionCode(body.entityType);
if (!permissionCode || !fastify.hasPermission(request.employee, permissionCode)) {
throw new AppError({ code: "PERM_001", message: "无权限", statusCode: 403 });
}
const precheck = await resolveEntityPrecheck({
prisma: fastify.prisma,
config: fastify.config,
logger: fastify.log,
entityType: body.entityType,
entityId: body.entityId,
actorDepartmentId: request.employee.department_id ?? null,
});
return sendData(reply, request, precheck);
});
}
module.exports = feeControlRoutes;