chore(P14-8): 完成运营化与验收收口

这个提交包含在:
2026-03-06 23:24:16 +08:00
父节点 b50b084100
当前提交 d8fff0ba21
共修改 28 个文件,包含 2820 行新增和 123 行删除
+14 -12
查看文件
@@ -103,6 +103,7 @@ function registerInvoicePoolReadRoutes(fastify) {
fastify.get(
"/invoice-pool",
{
schema: { tags: ["Invoice Pool"], summary: "List Invoices" },
preHandler: fastify.authenticate,
},
async (request, reply) => {
@@ -134,19 +135,19 @@ function registerInvoicePoolReadRoutes(fastify) {
...(ownerScope === "all"
? {}
: {
OR: [
{ owner_employee_id: request.employee.id },
{ uploaded_by_employee_id: request.employee.id },
{
linked_reimbursement: {
OR: [
{ owner_id: request.employee.id },
{ submitter_id: request.employee.id },
],
},
OR: [
{ owner_employee_id: request.employee.id },
{ uploaded_by_employee_id: request.employee.id },
{
linked_reimbursement: {
OR: [
{ owner_id: request.employee.id },
{ submitter_id: request.employee.id },
],
},
],
}),
},
],
}),
};
const [items, total] = await Promise.all([
@@ -173,6 +174,7 @@ function registerInvoicePoolReadRoutes(fastify) {
fastify.get(
"/invoice-pool/:id",
{
schema: { tags: ["Invoice Pool"], summary: "Get Invoice Detail" },
preHandler: fastify.authenticate,
},
async (request, reply) => {
+21 -18
查看文件
@@ -251,17 +251,17 @@ function mapReimbursementSummary(item) {
},
owner: item.owner
? {
id: item.owner.id,
employeeNo: item.owner.employee_no,
name: item.owner.name,
}
id: item.owner.id,
employeeNo: item.owner.employee_no,
name: item.owner.name,
}
: null,
submitter: item.submitter
? {
id: item.submitter.id,
employeeNo: item.submitter.employee_no,
name: item.submitter.name,
}
id: item.submitter.id,
employeeNo: item.submitter.employee_no,
name: item.submitter.name,
}
: null,
createdAt: item.created_at?.toISOString?.() ?? null,
updatedAt: item.updated_at?.toISOString?.() ?? null,
@@ -403,6 +403,7 @@ async function reimbursementRoutes(fastify) {
fastify.post(
"/reimbursements",
{
schema: { tags: ["Reimbursements"], summary: "Create Reimbursement" },
preHandler: fastify.requirePermission("expense.create"),
},
async (request, reply) => {
@@ -526,6 +527,7 @@ async function reimbursementRoutes(fastify) {
fastify.get(
"/reimbursements",
{
schema: { tags: ["Reimbursements"], summary: "List Reimbursements" },
preHandler: fastify.authenticate,
},
async (request, reply) => {
@@ -602,6 +604,7 @@ async function reimbursementRoutes(fastify) {
fastify.get(
"/reimbursements/:id",
{
schema: { tags: ["Reimbursements"], summary: "Get Reimbursement Detail" },
preHandler: fastify.authenticate,
},
async (request, reply) => {
@@ -714,12 +717,12 @@ async function reimbursementRoutes(fastify) {
description: item.description,
expenseType: item.expense_type
? {
id: item.expense_type.id,
code: item.expense_type.code,
name: item.expense_type.name,
category: item.expense_type.category,
enabled: item.expense_type.enabled,
}
id: item.expense_type.id,
code: item.expense_type.code,
name: item.expense_type.name,
category: item.expense_type.category,
enabled: item.expense_type.enabled,
}
: null,
})),
budgetHint,
@@ -732,10 +735,10 @@ async function reimbursementRoutes(fastify) {
})),
pendingWorkflow: pendingInstance
? {
instanceId: pendingInstance.id,
stepId: pendingInstance.current_step_id,
task: pendingTask,
}
instanceId: pendingInstance.id,
stepId: pendingInstance.current_step_id,
task: pendingTask,
}
: null,
});
},
+46 -44
查看文件
@@ -140,10 +140,10 @@ function isoOrNull(value) {
function mapTaskSummary(task) {
const workflowInstance = task.workflow_instance
? {
entity_type: task.workflow_instance.entity_type,
entity_id: task.workflow_instance.entity_id,
current_status: task.workflow_instance.current_status,
}
entity_type: task.workflow_instance.entity_type,
entity_id: task.workflow_instance.entity_id,
current_status: task.workflow_instance.current_status,
}
: null;
return {
@@ -168,10 +168,10 @@ function mapTaskSummary(task) {
completedAt: isoOrNull(task.completed_at),
workflowInstance: workflowInstance
? {
entityType: workflowInstance.entity_type,
entityId: workflowInstance.entity_id,
currentStatus: workflowInstance.current_status,
}
entityType: workflowInstance.entity_type,
entityId: workflowInstance.entity_id,
currentStatus: workflowInstance.current_status,
}
: null,
};
}
@@ -425,6 +425,7 @@ async function workflowRoutes(fastify) {
fastify.get(
"/workflow/tasks",
{
schema: { tags: ["Workflow"], summary: "List Workflow Tasks" },
preHandler: fastify.authenticate,
},
async (request, reply) => {
@@ -479,6 +480,7 @@ async function workflowRoutes(fastify) {
fastify.get(
"/workflow/tasks/:taskId",
{
schema: { tags: ["Workflow"], summary: "Get Workflow Task Detail" },
preHandler: fastify.authenticate,
},
async (request, reply) => {
@@ -612,39 +614,39 @@ async function workflowRoutes(fastify) {
},
workflowInstance: task.workflow_instance
? {
id: task.workflow_instance.id,
currentStatus: task.workflow_instance.current_status,
currentStepId: task.workflow_instance.current_step_id,
startedAt: isoOrNull(task.workflow_instance.started_at),
completedAt: isoOrNull(task.workflow_instance.completed_at),
}
id: task.workflow_instance.id,
currentStatus: task.workflow_instance.current_status,
currentStepId: task.workflow_instance.current_step_id,
startedAt: isoOrNull(task.workflow_instance.started_at),
completedAt: isoOrNull(task.workflow_instance.completed_at),
}
: null,
reimbursement: task.workflow_instance?.reimbursement_form
? {
id: task.workflow_instance.reimbursement_form.id,
formNumber: task.workflow_instance.reimbursement_form.form_number,
status: task.workflow_instance.reimbursement_form.status,
reimbursementDate:
task.workflow_instance.reimbursement_form.reimbursement_date
?.toISOString?.()
?.slice(0, 10) ?? null,
totalAmount: toMoneyString(task.workflow_instance.reimbursement_form.total_amount),
description: task.workflow_instance.reimbursement_form.description,
owner: task.workflow_instance.reimbursement_form.owner
? {
id: task.workflow_instance.reimbursement_form.owner.id,
employeeNo: task.workflow_instance.reimbursement_form.owner.employee_no,
name: task.workflow_instance.reimbursement_form.owner.name,
}
: null,
submitter: task.workflow_instance.reimbursement_form.submitter
? {
id: task.workflow_instance.reimbursement_form.submitter.id,
employeeNo: task.workflow_instance.reimbursement_form.submitter.employee_no,
name: task.workflow_instance.reimbursement_form.submitter.name,
}
: null,
}
id: task.workflow_instance.reimbursement_form.id,
formNumber: task.workflow_instance.reimbursement_form.form_number,
status: task.workflow_instance.reimbursement_form.status,
reimbursementDate:
task.workflow_instance.reimbursement_form.reimbursement_date
?.toISOString?.()
?.slice(0, 10) ?? null,
totalAmount: toMoneyString(task.workflow_instance.reimbursement_form.total_amount),
description: task.workflow_instance.reimbursement_form.description,
owner: task.workflow_instance.reimbursement_form.owner
? {
id: task.workflow_instance.reimbursement_form.owner.id,
employeeNo: task.workflow_instance.reimbursement_form.owner.employee_no,
name: task.workflow_instance.reimbursement_form.owner.name,
}
: null,
submitter: task.workflow_instance.reimbursement_form.submitter
? {
id: task.workflow_instance.reimbursement_form.submitter.id,
employeeNo: task.workflow_instance.reimbursement_form.submitter.employee_no,
name: task.workflow_instance.reimbursement_form.submitter.name,
}
: null,
}
: null,
allowedActions: listAllowedActionsForTask(request, task, actionable),
history: historyItems.map((item) => ({
@@ -681,12 +683,12 @@ async function workflowRoutes(fastify) {
},
...(query.keyword
? {
OR: [
{ name: { contains: query.keyword, mode: "insensitive" } },
{ email: { contains: query.keyword, mode: "insensitive" } },
{ employee_no: { contains: query.keyword, mode: "insensitive" } },
],
}
OR: [
{ name: { contains: query.keyword, mode: "insensitive" } },
{ email: { contains: query.keyword, mode: "insensitive" } },
{ employee_no: { contains: query.keyword, mode: "insensitive" } },
],
}
: {}),
};