实现企业银行账户与建行制单(corporate-bank-account-payment-order)
这个提交包含在:
+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,
|
||||
});
|
||||
|
||||
在新工单中引用
屏蔽一个用户