feat(G2-1,G2-2,G2-3): 扩展预算编号与工作流跨域桥接
这个提交包含在:
@@ -2,7 +2,7 @@ const { z } = require("zod");
|
||||
const { AppError } = require("../utils/AppError");
|
||||
const { sendData } = require("../utils/reply");
|
||||
const { buildAuditLogData } = require("../utils/audit");
|
||||
const { compactDateString, currentDateString, parseDateOnlyString } = require("../utils/date");
|
||||
const { currentDateString, parseDateOnlyString } = require("../utils/date");
|
||||
const { findActiveDelegationForDelegate } = require("../utils/delegation");
|
||||
const {
|
||||
createNotifications,
|
||||
@@ -12,6 +12,8 @@ const { sendNotificationEmailSafe } = require("../services/email");
|
||||
const { enqueueIntegrationEvent } = require("../services/integrations/outbox");
|
||||
const { buildErpPayload } = require("../services/integrations/erp");
|
||||
const { FEATURE_FLAG_KEYS, evaluateFeatureFlag } = require("../services/featureFlags");
|
||||
const { resolveApplicableBudgetPoolByContext } = require("../services/budgetPool");
|
||||
const { issueDocumentNumber } = require("../services/documentSequence");
|
||||
const {
|
||||
buildWorkflowStepsFromApprovalRule,
|
||||
resolveActionableStep,
|
||||
@@ -90,12 +92,6 @@ function ensureApplicantOrAdmin(request, reimbursement) {
|
||||
}
|
||||
}
|
||||
|
||||
function formatFormNumber(sequence, timezone) {
|
||||
const datePart = compactDateString(timezone);
|
||||
const serial = String(sequence.current_number).padStart(sequence.number_length, "0");
|
||||
return `${sequence.prefix}${sequence.separator}${datePart}${sequence.separator}${serial}`;
|
||||
}
|
||||
|
||||
function parseWithdrawBody(body) {
|
||||
const bodySchema = z.object({
|
||||
comment: z.string().trim().min(1).max(500).optional(),
|
||||
@@ -350,14 +346,9 @@ async function loadApprovalRuleForAmount(tx, totalAmount) {
|
||||
}
|
||||
|
||||
async function resolveApplicableBudgetPool(tx, reimbursement) {
|
||||
return tx.budgetPool.findFirst({
|
||||
where: {
|
||||
status: "active",
|
||||
OR: [{ department_id: reimbursement.department_id }, { department_id: null }],
|
||||
period_start: { lte: reimbursement.reimbursement_date },
|
||||
period_end: { gte: reimbursement.reimbursement_date },
|
||||
},
|
||||
orderBy: [{ department_id: "desc" }, { created_at: "asc" }],
|
||||
return resolveApplicableBudgetPoolByContext(tx, {
|
||||
departmentId: reimbursement.department_id,
|
||||
effectiveDate: reimbursement.reimbursement_date,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1204,7 +1195,7 @@ async function reimbursementRoutes(fastify) {
|
||||
|
||||
await fastify.prisma.$transaction(async (tx) => {
|
||||
const reimbursementRows = await tx.$queryRaw`
|
||||
SELECT id, owner_id, submitter_id, department_id, status, form_number, total_amount
|
||||
SELECT id, owner_id, submitter_id, department_id, reimbursement_date, status, form_number, total_amount
|
||||
FROM "reimbursement_forms"
|
||||
WHERE id = ${reimbursementId}::uuid
|
||||
FOR UPDATE
|
||||
@@ -1371,31 +1362,13 @@ async function reimbursementRoutes(fastify) {
|
||||
|
||||
let formNumber = reimbursement.form_number;
|
||||
if (!formNumber) {
|
||||
const sequence = await tx.documentSequence.upsert({
|
||||
where: { document_type: "reimbursement" },
|
||||
update: {
|
||||
current_number: { increment: 1 },
|
||||
updated_by: request.employee.id,
|
||||
},
|
||||
create: {
|
||||
document_type: "reimbursement",
|
||||
prefix: "BX",
|
||||
date_format: "YYYYMMDD",
|
||||
separator: "-",
|
||||
number_length: 4,
|
||||
reset_period: "none",
|
||||
current_number: 1,
|
||||
updated_by: request.employee.id,
|
||||
},
|
||||
select: {
|
||||
prefix: true,
|
||||
separator: true,
|
||||
number_length: true,
|
||||
current_number: true,
|
||||
},
|
||||
const issued = await issueDocumentNumber(tx, {
|
||||
documentType: "reimbursement",
|
||||
actorId: request.employee.id,
|
||||
timeZone: fastify.config.appTimezone,
|
||||
});
|
||||
|
||||
formNumber = formatFormNumber(sequence, fastify.config.appTimezone);
|
||||
formNumber = issued.documentNumber;
|
||||
}
|
||||
|
||||
await tx.reimbursementForm.update({
|
||||
|
||||
在新工单中引用
屏蔽一个用户