feat(server): 完成 P2 后端能力(支付幂等、委派回收、OCR异步、审计)

这个提交包含在:
2026-02-07 21:54:29 +08:00
父节点 7ea25e9d72
当前提交 c4df9a419a
共修改 23 个文件,包含 2102 行新增和 70 行删除
+66
查看文件
@@ -0,0 +1,66 @@
function buildActiveDelegationWhere(now, delegateEmployeeId, allowedScopes) {
return {
delegate_employee_id: delegateEmployeeId,
scope: { in: allowedScopes },
revoked_at: null,
valid_from: { lte: now },
OR: [{ valid_to: null }, { valid_to: { gt: now } }],
};
}
async function findActiveDelegationForDelegate(
tx,
{ principalEmployeeId, delegateEmployeeId, allowedScopes = ["all"], now = new Date() },
) {
return tx.delegationGrant.findFirst({
where: {
principal_employee_id: principalEmployeeId,
...buildActiveDelegationWhere(now, delegateEmployeeId, allowedScopes),
},
orderBy: { valid_from: "desc" },
select: {
id: true,
principal_employee_id: true,
delegate_employee_id: true,
scope: true,
valid_from: true,
valid_to: true,
},
});
}
async function listActiveDelegationPrincipals(
tx,
{ delegateEmployeeId, allowedScopes = ["all"], now = new Date() },
) {
const delegations = await tx.delegationGrant.findMany({
where: buildActiveDelegationWhere(now, delegateEmployeeId, allowedScopes),
select: {
principal_employee_id: true,
},
});
return Array.from(new Set(delegations.map((item) => item.principal_employee_id)));
}
function computeDelegationStatus(delegation, now = new Date()) {
if (delegation.revoked_at) {
return "revoked";
}
if (delegation.valid_to && delegation.valid_to <= now) {
return "expired";
}
if (delegation.valid_from > now) {
return "scheduled";
}
return "active";
}
module.exports = {
findActiveDelegationForDelegate,
listActiveDelegationPrincipals,
computeDelegationStatus,
};