实现企业银行账户与建行制单(corporate-bank-account-payment-order)

这个提交包含在:
2026-08-02 23:36:40 +08:00
父节点 f946d64539
当前提交 5261d2849b
共修改 46 个文件,包含 2751 行新增和 73 行删除
+20 -1
查看文件
@@ -3,6 +3,7 @@ const { z } = require("zod");
const { AppError } = require("../utils/AppError");
const { buildAuditLogData } = require("../utils/audit");
const { sendData } = require("../utils/reply");
const { decryptStringOrThrow, maskBankAccount } = require("../services/crypto");
const NOTIFICATION_PREFERENCES_SCHEMA = z
.object({
@@ -30,7 +31,9 @@ function parseNotificationPreferences(body) {
function buildProfileCompleteness(employee) {
const hasEmergencyContact = Boolean(employee?.emergency_contact_name && employee?.emergency_contact_phone);
const hasBankAccount = Boolean(employee?.bank_account_encrypted && employee?.bank_name);
const hasBankAccount = Boolean(
employee?.bank_account_encrypted && (employee?.bank_institution || employee?.bank_name),
);
const hasAvatar = Boolean(employee?.avatar_path);
const hasIdNumber = Boolean(employee?.id_number_encrypted);
const completedCount = [hasEmergencyContact, hasBankAccount, hasAvatar, hasIdNumber].filter(Boolean).length;
@@ -66,6 +69,7 @@ async function meRoutes(fastify) {
emergency_contact_phone: true,
bank_account_encrypted: true,
bank_name: true,
bank_institution: { select: { id: true, code: true, name: true } },
avatar_path: true,
id_number_encrypted: true,
notification_push_enabled: true,
@@ -76,6 +80,16 @@ async function meRoutes(fastify) {
const roleCodes = (employee?.roles ?? []).map((r) => r.role_code);
const profileCompleteness = buildProfileCompleteness(employee);
let bankAccountMasked = null;
try {
const bankAccount = employee?.bank_account_encrypted
? decryptStringOrThrow(fastify.config, employee.bank_account_encrypted)
: null;
bankAccountMasked = bankAccount ? maskBankAccount(bankAccount) : null;
} catch (error) {
fastify.log.error({ err: error, requestId: request.id }, "FIELD_ENCRYPTION_KEY misconfigured");
throw new AppError({ code: "SYS_001", message: "服务器内部错误", statusCode: 500 });
}
return sendData(reply, request, {
id: employee?.id ?? request.employee.id,
employeeNo: employee?.employee_no ?? "",
@@ -87,6 +101,11 @@ async function meRoutes(fastify) {
status: employee?.status ?? "active",
notificationPushEnabled: employee?.notification_push_enabled ?? true,
roleCodes,
bankAccount: {
bankName: employee?.bank_institution?.name ?? employee?.bank_name ?? null,
bankInstitutionCode: employee?.bank_institution?.code ?? null,
accountNumberMasked: bankAccountMasked,
},
profileCompleteness,
wecomBinding: employee?.wecom_identity_binding ? { externalUserId: employee.wecom_identity_binding.external_user_id, createdAt: employee.wecom_identity_binding.created_at?.toISOString?.() ?? null } : null,
});