R19/R20: 项目主域进 OA 并打通报销差旅周报待办
这个提交包含在:
@@ -268,6 +268,13 @@ function mapReimbursementSummary(item) {
|
||||
: null,
|
||||
createdAt: item.created_at?.toISOString?.() ?? null,
|
||||
updatedAt: item.updated_at?.toISOString?.() ?? null,
|
||||
project: item.project
|
||||
? {
|
||||
id: item.project.id,
|
||||
projectNo: item.project.project_no,
|
||||
name: item.project.name,
|
||||
}
|
||||
: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -549,6 +556,8 @@ async function reimbursementRoutes(fastify) {
|
||||
reimbursementDate,
|
||||
status: reimbursement.status,
|
||||
description: reimbursement.description,
|
||||
projectId: reimbursement.project_id ?? null,
|
||||
project: reimbursement.project ? { id: reimbursement.project.id, projectNo: reimbursement.project.project_no, name: reimbursement.project.name } : null,
|
||||
totalAmount: toMoneyString(reimbursement.total_amount),
|
||||
});
|
||||
},
|
||||
@@ -610,6 +619,7 @@ async function reimbursementRoutes(fastify) {
|
||||
paid_by: true,
|
||||
created_at: true,
|
||||
updated_at: true,
|
||||
project: { select: { id: true, project_no: true, name: true } },
|
||||
owner: {
|
||||
select: { id: true, employee_no: true, name: true },
|
||||
},
|
||||
@@ -652,6 +662,8 @@ async function reimbursementRoutes(fastify) {
|
||||
total_amount: true,
|
||||
status: true,
|
||||
description: true,
|
||||
project_id: true,
|
||||
project: { select: { id: true, project_no: true, name: true } },
|
||||
owner: {
|
||||
select: { id: true, employee_no: true, name: true },
|
||||
},
|
||||
@@ -745,6 +757,8 @@ async function reimbursementRoutes(fastify) {
|
||||
totalAmount: toMoneyString(reimbursement.total_amount),
|
||||
status: reimbursement.status,
|
||||
description: reimbursement.description,
|
||||
projectId: reimbursement.project_id ?? null,
|
||||
project: reimbursement.project ? { id: reimbursement.project.id, projectNo: reimbursement.project.project_no, name: reimbursement.project.name } : null,
|
||||
owner: reimbursement.owner,
|
||||
submitter: reimbursement.submitter,
|
||||
items: reimbursement.items.map((item) => ({
|
||||
@@ -1787,6 +1801,47 @@ async function reimbursementRoutes(fastify) {
|
||||
},
|
||||
);
|
||||
|
||||
fastify.post(
|
||||
"/reimbursements/:id/link-project",
|
||||
{
|
||||
preHandler: fastify.authenticate,
|
||||
},
|
||||
async (request, reply) => {
|
||||
const gate = await evaluateFeatureFlag({
|
||||
prisma: fastify.prisma,
|
||||
config: fastify.config,
|
||||
flagKey: FEATURE_FLAG_KEYS.projectLinking,
|
||||
departmentId: request.employee.department_id ?? null,
|
||||
strictDepartment: false,
|
||||
});
|
||||
if (!gate.enabled) {
|
||||
throw new AppError({ code: "VALID_001", message: "参数校验失败", statusCode: 409, details: { featureFlag: "project_linking_v1_disabled", reason: gate.reason } });
|
||||
}
|
||||
const reimbursementId = parseReimbursementId(request.params?.id);
|
||||
const body = parseBody(z.object({ projectId: z.string().uuid().nullable() }).strict(), request.body);
|
||||
const current = await fastify.prisma.reimbursementForm.findUnique({
|
||||
where: { id: reimbursementId },
|
||||
select: { id: true, owner_id: true, submitter_id: true, project_id: true, status: true },
|
||||
});
|
||||
if (!current) {
|
||||
throw new AppError({ code: "SYS_404", message: "Not Found", statusCode: 404 });
|
||||
}
|
||||
ensureOwnOrCanViewAll(fastify, request, current);
|
||||
const updated = await fastify.prisma.reimbursementForm.update({
|
||||
where: { id: reimbursementId },
|
||||
data: { project_id: body.projectId ?? null, updated_by: request.employee.id },
|
||||
select: { id: true, project_id: true, project: { select: { id: true, project_no: true, name: true } } },
|
||||
});
|
||||
return sendData(reply, request, {
|
||||
item: {
|
||||
reimbursementId: updated.id,
|
||||
projectId: updated.project_id ?? null,
|
||||
project: updated.project ? { id: updated.project.id, projectNo: updated.project.project_no, name: updated.project.name } : null,
|
||||
},
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
fastify.post(
|
||||
"/reimbursements/:id/pay",
|
||||
{
|
||||
|
||||
在新工单中引用
屏蔽一个用户