159 行
4.3 KiB
JavaScript
159 行
4.3 KiB
JavaScript
const { z } = require("zod");
|
|
|
|
const { AppError } = require("../utils/AppError");
|
|
const { sendData } = require("../utils/reply");
|
|
const {
|
|
normalizeDocumentType,
|
|
resolveDocumentSequenceConfig,
|
|
} = require("../services/documentSequence");
|
|
|
|
const ENABLED_QUERY_SCHEMA = z.object({
|
|
enabled: z.enum(["true", "false", "1", "0"]).optional(),
|
|
});
|
|
|
|
const DOCUMENT_TYPE_PARAM_SCHEMA = z.object({
|
|
documentType: z.string().trim().min(1).max(64).regex(/^[a-z_]+$/),
|
|
});
|
|
|
|
function parseEnabledQuery(query) {
|
|
const parsed = ENABLED_QUERY_SCHEMA.safeParse(query ?? {});
|
|
if (!parsed.success) {
|
|
throw new AppError({
|
|
code: "VALID_001",
|
|
message: "参数校验失败",
|
|
statusCode: 400,
|
|
details: parsed.error.flatten(),
|
|
});
|
|
}
|
|
|
|
const enabledRaw = parsed.data.enabled;
|
|
const enabled =
|
|
enabledRaw == null
|
|
? null
|
|
: ["true", "1"].includes(enabledRaw)
|
|
? true
|
|
: ["false", "0"].includes(enabledRaw)
|
|
? false
|
|
: null;
|
|
|
|
return { enabled };
|
|
}
|
|
|
|
function parseDocumentTypeParams(params) {
|
|
const parsed = DOCUMENT_TYPE_PARAM_SCHEMA.safeParse(params ?? {});
|
|
if (!parsed.success) {
|
|
throw new AppError({
|
|
code: "VALID_001",
|
|
message: "参数校验失败",
|
|
statusCode: 400,
|
|
details: parsed.error.flatten(),
|
|
});
|
|
}
|
|
|
|
return normalizeDocumentType(parsed.data.documentType);
|
|
}
|
|
|
|
function mapApprovalRule(item) {
|
|
return {
|
|
id: item.id,
|
|
name: item.name,
|
|
minAmount: item.min_amount?.toString?.() ?? String(item.min_amount ?? "0"),
|
|
maxAmount: item.max_amount == null ? null : item.max_amount?.toString?.() ?? String(item.max_amount),
|
|
level1Role: item.level1_role,
|
|
level2Role: item.level2_role ?? null,
|
|
level3Role: item.level3_role ?? null,
|
|
ownerSelfFallbackRole: item.owner_self_fallback_role ?? null,
|
|
enabled: item.enabled,
|
|
priority: item.priority,
|
|
createdAt: item.created_at?.toISOString?.() ?? null,
|
|
updatedAt: item.updated_at?.toISOString?.() ?? null,
|
|
};
|
|
}
|
|
|
|
function mapDocumentSequence(config) {
|
|
return {
|
|
exists: Boolean(config.exists),
|
|
source: config.source,
|
|
documentType: config.documentType,
|
|
documentCategoryCode: config.documentCategoryCode ?? null,
|
|
prefix: config.prefix,
|
|
dateFormat: config.dateFormat,
|
|
separator: config.separator,
|
|
numberLength: config.numberLength,
|
|
resetPeriod: config.resetPeriod,
|
|
currentNumber: config.currentNumber,
|
|
lastResetDate: config.lastResetDate ?? null,
|
|
updatedAt: config.updatedAt ?? null,
|
|
updatedBy: config.updatedBy ?? null,
|
|
};
|
|
}
|
|
|
|
async function loadDocumentSequenceConfig(fastify, documentType) {
|
|
return resolveDocumentSequenceConfig(fastify.prisma, {
|
|
documentType,
|
|
});
|
|
}
|
|
|
|
async function configReadRoutes(fastify) {
|
|
fastify.get(
|
|
"/approval-rules",
|
|
{
|
|
preHandler: fastify.authenticate,
|
|
},
|
|
async (request, reply) => {
|
|
const query = parseEnabledQuery(request.query);
|
|
|
|
const items = await fastify.prisma.approvalRule.findMany({
|
|
where: {
|
|
...(query.enabled == null ? {} : { enabled: query.enabled }),
|
|
},
|
|
orderBy: [{ priority: "asc" }, { min_amount: "asc" }],
|
|
select: {
|
|
id: true,
|
|
name: true,
|
|
min_amount: true,
|
|
max_amount: true,
|
|
level1_role: true,
|
|
level2_role: true,
|
|
level3_role: true,
|
|
owner_self_fallback_role: true,
|
|
enabled: true,
|
|
priority: true,
|
|
created_at: true,
|
|
updated_at: true,
|
|
},
|
|
});
|
|
|
|
return sendData(reply, request, {
|
|
enabled: query.enabled,
|
|
items: items.map(mapApprovalRule),
|
|
});
|
|
},
|
|
);
|
|
|
|
fastify.get(
|
|
"/document-sequences/reimbursement",
|
|
{
|
|
preHandler: fastify.requirePermission("system.settings"),
|
|
},
|
|
async (request, reply) => {
|
|
const config = await loadDocumentSequenceConfig(fastify, "reimbursement");
|
|
return sendData(reply, request, mapDocumentSequence(config));
|
|
},
|
|
);
|
|
|
|
fastify.get(
|
|
"/document-sequences/:documentType",
|
|
{
|
|
preHandler: fastify.requirePermission("system.settings"),
|
|
},
|
|
async (request, reply) => {
|
|
const documentType = parseDocumentTypeParams(request.params);
|
|
const config = await loadDocumentSequenceConfig(fastify, documentType);
|
|
return sendData(reply, request, mapDocumentSequence(config));
|
|
},
|
|
);
|
|
}
|
|
|
|
module.exports = configReadRoutes;
|