完善借款、编号、付款与预算并发及验收(09-06-release-gate-integrity)
汇总已落盘的借款本金与还款、兼容历史编号的周期化编号、付款责任与回单核验、报销进度和排序、PWA/采购事务、错误原因与日期校验及ERP退役。 统一共享预算池锁序和锁后判断,恢复差旅原预算选择,补原因码固定夹具及反向完整性检查。 纳入配套迁移、测试、受管QA、分层验收合同、规约及任务记录;原始证据留在ignored artifacts。 关联任务:09-17-company-loan-principal-repayment、09-17-erp-exclusive-retirement、09-18-reimbursement-periodic-numbering、09-08-reimbursement-payment-closeout、09-18-local-concurrency-product-fixes、09-19-budget-pool-concurrency、09-05-error-explainability-payment-readiness。 预算补审由Claude定向验证2文件928项通过,原4446/28及r6结果仍仅对应各自历史输入;本轮未重跑测试。 完整新候选门禁、R1真实入口接入与12项公网义务仍开放。生产编号未启用、差旅仍冻结;不推送、不部署,不宣称发布资格。
这个提交包含在:
@@ -39,8 +39,8 @@ describe("evaluateFeatureFlag", () => {
|
||||
it("returns env_hard_off when env gate is closed", async () => {
|
||||
const result = await evaluateFeatureFlag({
|
||||
prisma: buildPrisma(),
|
||||
config: { erpSyncEnabled: false, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: true },
|
||||
flagKey: FEATURE_FLAG_KEYS.erpSync,
|
||||
config: { paymentBatchEnabled: false, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: true },
|
||||
flagKey: FEATURE_FLAG_KEYS.paymentBatch,
|
||||
});
|
||||
|
||||
expect(result.enabled).toBe(false);
|
||||
@@ -50,8 +50,8 @@ describe("evaluateFeatureFlag", () => {
|
||||
it("returns missing_flag_record when record does not exist", async () => {
|
||||
const result = await evaluateFeatureFlag({
|
||||
prisma: buildPrisma(),
|
||||
config: { erpSyncEnabled: true, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: true },
|
||||
flagKey: FEATURE_FLAG_KEYS.erpSync,
|
||||
config: { paymentBatchEnabled: true, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: true },
|
||||
flagKey: FEATURE_FLAG_KEYS.paymentBatch,
|
||||
});
|
||||
|
||||
expect(result.enabled).toBe(false);
|
||||
@@ -60,16 +60,16 @@ describe("evaluateFeatureFlag", () => {
|
||||
|
||||
it("returns flag_force_off when override mode is force_off", async () => {
|
||||
const prisma = buildPrisma({
|
||||
[FEATURE_FLAG_KEYS.erpSync]: buildRecord({
|
||||
flagKey: FEATURE_FLAG_KEYS.erpSync,
|
||||
[FEATURE_FLAG_KEYS.paymentBatch]: buildRecord({
|
||||
flagKey: FEATURE_FLAG_KEYS.paymentBatch,
|
||||
overrideMode: "force_off",
|
||||
}),
|
||||
});
|
||||
|
||||
const result = await evaluateFeatureFlag({
|
||||
prisma,
|
||||
config: { erpSyncEnabled: true, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: true },
|
||||
flagKey: FEATURE_FLAG_KEYS.erpSync,
|
||||
config: { paymentBatchEnabled: true, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: true },
|
||||
flagKey: FEATURE_FLAG_KEYS.paymentBatch,
|
||||
});
|
||||
|
||||
expect(result.enabled).toBe(false);
|
||||
@@ -78,8 +78,8 @@ describe("evaluateFeatureFlag", () => {
|
||||
|
||||
it("returns global enabled when inherit + global", async () => {
|
||||
const prisma = buildPrisma({
|
||||
[FEATURE_FLAG_KEYS.erpSync]: buildRecord({
|
||||
flagKey: FEATURE_FLAG_KEYS.erpSync,
|
||||
[FEATURE_FLAG_KEYS.paymentBatch]: buildRecord({
|
||||
flagKey: FEATURE_FLAG_KEYS.paymentBatch,
|
||||
overrideMode: "inherit",
|
||||
rolloutType: "global",
|
||||
}),
|
||||
@@ -87,8 +87,8 @@ describe("evaluateFeatureFlag", () => {
|
||||
|
||||
const result = await evaluateFeatureFlag({
|
||||
prisma,
|
||||
config: { erpSyncEnabled: true, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: true },
|
||||
flagKey: FEATURE_FLAG_KEYS.erpSync,
|
||||
config: { paymentBatchEnabled: true, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: true },
|
||||
flagKey: FEATURE_FLAG_KEYS.paymentBatch,
|
||||
});
|
||||
|
||||
expect(result.enabled).toBe(true);
|
||||
@@ -97,8 +97,8 @@ describe("evaluateFeatureFlag", () => {
|
||||
|
||||
it("returns allowlist guards for department rollout", async () => {
|
||||
const prisma = buildPrisma({
|
||||
[FEATURE_FLAG_KEYS.erpSync]: buildRecord({
|
||||
flagKey: FEATURE_FLAG_KEYS.erpSync,
|
||||
[FEATURE_FLAG_KEYS.paymentBatch]: buildRecord({
|
||||
flagKey: FEATURE_FLAG_KEYS.paymentBatch,
|
||||
rolloutType: "department_allowlist",
|
||||
departmentIds: ["dept-a"],
|
||||
}),
|
||||
@@ -106,23 +106,23 @@ describe("evaluateFeatureFlag", () => {
|
||||
|
||||
const missingDepartment = await evaluateFeatureFlag({
|
||||
prisma,
|
||||
config: { erpSyncEnabled: true, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: true },
|
||||
flagKey: FEATURE_FLAG_KEYS.erpSync,
|
||||
config: { paymentBatchEnabled: true, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: true },
|
||||
flagKey: FEATURE_FLAG_KEYS.paymentBatch,
|
||||
strictDepartment: true,
|
||||
});
|
||||
|
||||
const blockedDepartment = await evaluateFeatureFlag({
|
||||
prisma,
|
||||
config: { erpSyncEnabled: true, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: true },
|
||||
flagKey: FEATURE_FLAG_KEYS.erpSync,
|
||||
config: { paymentBatchEnabled: true, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: true },
|
||||
flagKey: FEATURE_FLAG_KEYS.paymentBatch,
|
||||
departmentId: "dept-b",
|
||||
strictDepartment: true,
|
||||
});
|
||||
|
||||
const allowedDepartment = await evaluateFeatureFlag({
|
||||
prisma,
|
||||
config: { erpSyncEnabled: true, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: true },
|
||||
flagKey: FEATURE_FLAG_KEYS.erpSync,
|
||||
config: { paymentBatchEnabled: true, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: true },
|
||||
flagKey: FEATURE_FLAG_KEYS.paymentBatch,
|
||||
departmentId: "dept-a",
|
||||
strictDepartment: true,
|
||||
});
|
||||
@@ -144,7 +144,7 @@ describe("evaluateFeatureFlag", () => {
|
||||
|
||||
const result = await evaluateFeatureFlag({
|
||||
prisma,
|
||||
config: { erpSyncEnabled: true, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: true },
|
||||
config: { paymentBatchEnabled: true, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: true },
|
||||
flagKey: FEATURE_FLAG_KEYS.invoiceVerification,
|
||||
strictDepartment: false,
|
||||
});
|
||||
@@ -164,7 +164,7 @@ describe("evaluateFeatureFlag", () => {
|
||||
|
||||
const result = await evaluateFeatureFlag({
|
||||
prisma,
|
||||
config: { erpSyncEnabled: true, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: true },
|
||||
config: { paymentBatchEnabled: true, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: true },
|
||||
flagKey: FEATURE_FLAG_KEYS.invoiceVerification,
|
||||
strictDepartment: true,
|
||||
});
|
||||
@@ -178,7 +178,7 @@ describe("feature flag env gates", () => {
|
||||
it("uses the dedicated leave holiday calendar env gate", async () => {
|
||||
const result = await evaluateFeatureFlag({
|
||||
prisma: buildPrisma(),
|
||||
config: { aiAssistEnabled: true, erpSyncEnabled: true, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: false },
|
||||
config: { aiAssistEnabled: true, paymentBatchEnabled: true, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: false },
|
||||
flagKey: FEATURE_FLAG_KEYS.leaveHolidayCalendar,
|
||||
});
|
||||
|
||||
@@ -189,7 +189,7 @@ describe("feature flag env gates", () => {
|
||||
it("uses the dedicated ai assist env gate", async () => {
|
||||
const result = await evaluateFeatureFlag({
|
||||
prisma: buildPrisma(),
|
||||
config: { aiAssistEnabled: false, erpSyncEnabled: true, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: true },
|
||||
config: { aiAssistEnabled: false, paymentBatchEnabled: true, invoiceVerificationEnabled: true, leaveHolidayCalendarEnabled: true },
|
||||
flagKey: FEATURE_FLAG_KEYS.aiAssist,
|
||||
});
|
||||
|
||||
@@ -201,14 +201,14 @@ describe("feature flag env gates", () => {
|
||||
describe("listFeatureFlags", () => {
|
||||
it("returns all known keys even if part of records are missing", async () => {
|
||||
const prisma = buildPrisma({
|
||||
[FEATURE_FLAG_KEYS.erpSync]: buildRecord({
|
||||
flagKey: FEATURE_FLAG_KEYS.erpSync,
|
||||
[FEATURE_FLAG_KEYS.paymentBatch]: buildRecord({
|
||||
flagKey: FEATURE_FLAG_KEYS.paymentBatch,
|
||||
overrideMode: "inherit",
|
||||
}),
|
||||
});
|
||||
|
||||
const items = await listFeatureFlags(prisma, {
|
||||
erpSyncEnabled: true,
|
||||
paymentBatchEnabled: true,
|
||||
invoiceVerificationEnabled: true,
|
||||
});
|
||||
|
||||
|
||||
在新工单中引用
屏蔽一个用户