FL6 完善财务台账与导出审计
这个提交包含在:
@@ -43,6 +43,7 @@ const PAY_BODY_SCHEMA = z.object({
|
||||
paymentVoucherNo: z.string().trim().min(1).max(50).optional(),
|
||||
paymentDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
|
||||
paymentChannel: z.enum(["bank", "alipay", "wechat", "cash", "other"]).optional(),
|
||||
paymentNote: z.string().trim().max(200).optional(),
|
||||
});
|
||||
|
||||
const REIMBURSEMENT_LIST_QUERY_SCHEMA = z.object({
|
||||
@@ -1556,6 +1557,19 @@ async function reimbursementRoutes(fastify) {
|
||||
reimbursementDate,
|
||||
status: reimbursement.status,
|
||||
description: reimbursement.description,
|
||||
payment: {
|
||||
paymentVoucherNo: reimbursement.payment_voucher_no ?? null,
|
||||
paymentDate: toDateOnlyString(reimbursement.payment_date),
|
||||
paymentChannel: reimbursement.payment_channel ?? null,
|
||||
paidAt: reimbursement.paid_at?.toISOString?.() ?? null,
|
||||
paidBy: reimbursement.paid_by_employee
|
||||
? {
|
||||
id: reimbursement.paid_by_employee.id,
|
||||
employeeNo: reimbursement.paid_by_employee.employee_no,
|
||||
name: reimbursement.paid_by_employee.name,
|
||||
}
|
||||
: null,
|
||||
},
|
||||
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),
|
||||
@@ -1958,8 +1972,19 @@ async function reimbursementRoutes(fastify) {
|
||||
total_amount: true,
|
||||
status: true,
|
||||
description: true,
|
||||
payment_voucher_no: true,
|
||||
payment_date: true,
|
||||
payment_channel: true,
|
||||
paid_at: true,
|
||||
project_id: true,
|
||||
linked_travel_request_id: true,
|
||||
paid_by_employee: {
|
||||
select: {
|
||||
id: true,
|
||||
employee_no: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
department: {
|
||||
select: {
|
||||
id: true,
|
||||
@@ -2158,6 +2183,19 @@ async function reimbursementRoutes(fastify) {
|
||||
totalAmount: toMoneyString(reimbursement.total_amount),
|
||||
status: reimbursement.status,
|
||||
description: reimbursement.description,
|
||||
payment: {
|
||||
paymentVoucherNo: reimbursement.payment_voucher_no ?? null,
|
||||
paymentDate: toDateOnlyString(reimbursement.payment_date),
|
||||
paymentChannel: reimbursement.payment_channel ?? null,
|
||||
paidAt: reimbursement.paid_at?.toISOString?.() ?? null,
|
||||
paidBy: reimbursement.paid_by_employee
|
||||
? {
|
||||
id: reimbursement.paid_by_employee.id,
|
||||
employeeNo: reimbursement.paid_by_employee.employee_no,
|
||||
name: reimbursement.paid_by_employee.name,
|
||||
}
|
||||
: null,
|
||||
},
|
||||
projectId: reimbursement.project_id ?? null,
|
||||
project: reimbursement.project ? { id: reimbursement.project.id, projectNo: reimbursement.project.project_no, name: reimbursement.project.name } : null,
|
||||
linkedTravelRequestId: reimbursement.linked_travel_request_id ?? null,
|
||||
@@ -3737,6 +3775,33 @@ async function reimbursementRoutes(fastify) {
|
||||
}
|
||||
}
|
||||
|
||||
await tx.auditLog.create({
|
||||
data: buildAuditLogData(request, {
|
||||
actorId: request.employee.id,
|
||||
action: "REIMBURSEMENT_PAYMENT_MARKED",
|
||||
targetType: "reimbursement_form",
|
||||
targetId: reimbursementId,
|
||||
extra: {
|
||||
formNumber: reimbursement.form_number ?? null,
|
||||
paymentVoucherNo:
|
||||
reimbursement.status === "paid"
|
||||
? reimbursement.payment_voucher_no ?? null
|
||||
: payInput.paymentVoucherNo ?? null,
|
||||
paymentDate:
|
||||
reimbursement.status === "paid"
|
||||
? existingPaymentDate
|
||||
: payInput.paymentDate ?? null,
|
||||
paymentChannel:
|
||||
reimbursement.status === "paid"
|
||||
? reimbursement.payment_channel ?? null
|
||||
: payInput.paymentChannel ?? null,
|
||||
paymentNote: payInput.paymentNote ?? null,
|
||||
idempotent: reimbursement.status === "paid",
|
||||
archivedInvoiceCount: archivedResult.count,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
response = {
|
||||
reimbursementId,
|
||||
outcome: "paid",
|
||||
@@ -3764,6 +3829,7 @@ async function reimbursementRoutes(fastify) {
|
||||
reimbursement.status === "paid"
|
||||
? reimbursement.paid_by ?? null
|
||||
: request.employee.id,
|
||||
paymentNote: payInput.paymentNote ?? null,
|
||||
idempotent: reimbursement.status === "paid",
|
||||
},
|
||||
};
|
||||
|
||||
在新工单中引用
屏蔽一个用户