feat(P20T2-1,P20T2-2,P20T2-3): 卡授权/交易/支付标记/发票绑定/ERP出站后端

这个提交包含在:
2026-03-11 06:41:11 +08:00
父节点 539c2cc4dd
当前提交 dc74d9e53f
共修改 23 个文件,包含 4265 行新增和 218 行删除
+29
查看文件
@@ -11,6 +11,7 @@ const { parseWorkflowSteps, resolveActionableStep } = require("../utils/workflow
const { sendNotificationEmailSafe } = require("../services/email");
const { createNotifications, resolveRecipientsForAssignee } = require("../services/notifications");
const { enqueueImNotifications } = require("../services/notifications/imEnqueue");
const { buildTravelPaymentTrack } = require("../services/travelPayments");
const { NOTIFICATION_TYPES } = require("../constants/notificationTypes");
const UUID_SCHEMA = z.string().uuid();
@@ -145,10 +146,16 @@ const TRAVEL_DETAIL_SELECT = {
external_order_no: true,
employee_id: true,
linked_reimbursement_id: true,
travel_request_id: true,
occurred_at: true,
amount: true,
currency: true,
status: true,
payment_voucher_no: true,
payment_date: true,
payment_channel: true,
paid_at: true,
paid_by: true,
created_at: true,
updated_at: true,
},
@@ -356,10 +363,16 @@ function mapTravelOrder(item) {
externalOrderNo: item.external_order_no,
employeeId: item.employee_id,
linkedReimbursementId: item.linked_reimbursement_id ?? null,
travelRequestId: item.travel_request_id ?? null,
occurredAt: toIsoDate(item.occurred_at),
amount: moneyToFixed(item.amount),
currency: item.currency,
status: item.status,
paymentVoucherNo: item.payment_voucher_no ?? null,
paymentDate: toIsoDate(item.payment_date),
paymentChannel: item.payment_channel ?? null,
paidAt: toIsoDateTime(item.paid_at),
paidBy: item.paid_by ?? null,
createdAt: toIsoDateTime(item.created_at),
updatedAt: toIsoDateTime(item.updated_at),
};
@@ -1054,6 +1067,22 @@ async function createTravelRequestsRoutes(fastify) {
},
);
fastify.get(
"/travel-requests/:id/payment-track",
{
preHandler: fastify.authenticate,
},
async (request, reply) => {
ensureTravelReadPermission(fastify, request);
const travelRequestId = parseTravelRequestId(request.params?.id);
await loadReadableTravelRequest(fastify.prisma, travelRequestId, request);
const track = await buildTravelPaymentTrack(fastify.prisma, travelRequestId, {
canManagePayments: fastify.hasPermission(request.employee, "travel.payment.manage"),
});
return sendData(reply, request, track);
},
);
fastify.post(
"/travel-requests/:id/withdraw",
{