fix: 加固日历日期与动态错误合同(09-05-error-explainability-payment-readiness,09-08-reimbursement-payment-closeout)
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s

这个提交包含在:
2026-09-16 20:20:11 +08:00
父节点 842c61e696
当前提交 b1d25d3c99
共修改 20 个文件,包含 253 行新增和 21 行删除
+2 -2
查看文件
@@ -2,7 +2,7 @@ const { z } = require("zod");
const { AppError } = require("../utils/AppError");
const { buildAuditLogData } = require("../utils/audit");
const { parseDateOnlyString } = require("../utils/date");
const { parseDateOnlyString, isValidDateOnlyString } = require("../utils/date");
const { issueDocumentNumber } = require("../services/documentSequence");
const { FEATURE_FLAG_KEYS, evaluateFeatureFlag } = require('../services/featureFlags');
const {
@@ -14,7 +14,7 @@ const { sendData } = require("../utils/reply");
const UUID_SCHEMA = z.string().uuid();
const BOOLEAN_QUERY_SCHEMA = z.enum(["0", "1", "true", "false"]).optional();
const DATE_ONLY_SCHEMA = z.string().regex(/^\d{4}-\d{2}-\d{2}$/);
const DATE_ONLY_SCHEMA = z.string().regex(/^\d{4}-\d{2}-\d{2}$/).refine(isValidDateOnlyString, { message: "invalid_calendar_date" });
const ASSET_STATUS_VALUES = ["in_stock", "in_use", "under_repair", "retired", "archived"];
const ASSET_TYPE_VALUES = ["fixed_asset", "electronic_document", "electronic_system", "code_repository", "backup_media"];
const ASSET_SENSITIVITY_VALUES = ["public_candidate", "internal", "confidential", "strictly_confidential"];
+3 -3
查看文件
@@ -12,7 +12,7 @@ const { z } = require("zod");
const { AppError } = require("../utils/AppError");
const { sendData } = require("../utils/reply");
const { buildAuditLogData } = require("../utils/audit");
const { currentDateString, parseDateOnlyString } = require("../utils/date");
const { currentDateString, parseDateOnlyString, isValidDateOnlyString } = require("../utils/date");
const { FEATURE_FLAG_KEYS, evaluateFeatureFlag } = require("../services/featureFlags");
const { createNotificationsWithRecords } = require("../services/notifications");
const { NOTIFICATION_TYPES } = require("../constants/notificationTypes");
@@ -70,14 +70,14 @@ const CREATE_SCHEMA = z.object({
entityType: ENTITY_TYPE_SCHEMA,
name: z.string().trim().min(1).max(120).optional(),
entityIds: z.array(UUID_SCHEMA).min(1).max(200),
defaultPaymentDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
defaultPaymentDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).refine(isValidDateOnlyString, { message: "invalid_calendar_date" }).optional(),
defaultPaymentChannel: PAYMENT_CHANNEL_SCHEMA.optional(),
voucherPrefix: z.string().trim().min(1).max(32).optional(),
}).strict();
const PATCH_ITEM_SCHEMA = z.object({
paymentVoucherNoOverride: z.string().trim().max(50).nullable().optional(),
paymentDateOverride: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).nullable().optional(),
paymentDateOverride: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).refine(isValidDateOnlyString, { message: "invalid_calendar_date" }).nullable().optional(),
}).strict().refine((value) => Object.keys(value).length > 0, { message: "empty_patch" });
const REVIEW_SCHEMA = z.object({
+10 -10
查看文件
@@ -10,7 +10,7 @@ const { buildAuditLogData } = require("../utils/audit");
const { sha256Hex } = require("../utils/crypto");
const { buildAttachmentContentDisposition } = require("../utils/contentDisposition");
const { signPayload, verifyToken } = require("../utils/signedUrl");
const { compactDateString, currentDateString, parseDateOnlyString } = require("../utils/date");
const { compactDateString, currentDateString, parseDateOnlyString, isValidDateOnlyString } = require("../utils/date");
const { findActiveDelegationForDelegate, listActiveDelegationPrincipals } = require("../utils/delegation");
const { hasPermission, resolveEntityPermission } = require("../constants/permissions");
const {
@@ -76,7 +76,7 @@ const {
const UUID_SCHEMA = z.string().uuid();
const PAY_BODY_SCHEMA = z.object({
paymentVoucherNo: z.string().trim().min(1).max(50).optional(),
paymentDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
paymentDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).refine(isValidDateOnlyString, { message: "invalid_calendar_date" }).optional(),
paymentChannel: z.enum(["bank", "alipay", "wechat", "cash", "other"]).optional(),
paymentNote: z.string().trim().max(200).optional(),
});
@@ -91,12 +91,12 @@ const REIMBURSEMENT_LIST_QUERY_SCHEMA = z.object({
});
const REIMBURSEMENT_UPDATE_BODY_SCHEMA = z.object({
reimbursementDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
reimbursementDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).refine(isValidDateOnlyString, { message: "invalid_calendar_date" }).optional(),
description: z.string().trim().max(500).nullable().optional(),
travelPurpose: z.string().trim().max(200).nullable().optional(),
travelLocation: z.string().trim().max(200).nullable().optional(),
travelStartDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).nullable().optional(),
travelEndDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).nullable().optional(),
travelStartDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).refine(isValidDateOnlyString, { message: "invalid_calendar_date" }).nullable().optional(),
travelEndDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).refine(isValidDateOnlyString, { message: "invalid_calendar_date" }).nullable().optional(),
}).superRefine((value, ctx) => {
if (value.travelStartDate && value.travelEndDate && value.travelStartDate > value.travelEndDate) {
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "invalid_date_range", path: ["travelEndDate"] });
@@ -151,14 +151,14 @@ function throwMaterialPreviewAppError(error) {
const REIMBURSEMENT_CREATE_BODY_SCHEMA = z
.object({
ownerEmployeeId: z.string().uuid().optional(),
reimbursementDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
reimbursementDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).refine(isValidDateOnlyString, { message: "invalid_calendar_date" }).optional(),
description: z.string().max(500).optional(),
templateId: z.string().uuid().optional(),
linkedTravelRequestId: z.string().uuid().optional(),
travelPurpose: z.string().trim().max(200).optional(),
travelLocation: z.string().trim().max(200).optional(),
travelStartDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
travelEndDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
travelStartDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).refine(isValidDateOnlyString, { message: "invalid_calendar_date" }).optional(),
travelEndDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).refine(isValidDateOnlyString, { message: "invalid_calendar_date" }).optional(),
})
.strict()
.superRefine((value, ctx) => {
@@ -181,13 +181,13 @@ const REIMBURSEMENT_CREATE_BODY_SCHEMA = z
const REIMBURSEMENT_ITEM_BODY_SCHEMA = z.object({
expenseTypeId: z.string().uuid().nullable(),
expenseDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/),
expenseDate: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).refine(isValidDateOnlyString, { message: "invalid_calendar_date" }),
amount: z.string().regex(/^\d+(\.\d{1,2})?$/),
description: z.string().trim().max(500),
assetPriorApprovalBasis: z.string().trim().max(500).nullable().optional(),
});
const DATE_ONLY_QUERY_SCHEMA = z.string().regex(/^\d{4}-\d{2}-\d{2}$/);
const DATE_ONLY_QUERY_SCHEMA = z.string().regex(/^\d{4}-\d{2}-\d{2}$/).refine(isValidDateOnlyString, { message: "invalid_calendar_date" });
const REIMBURSEMENT_STATS_QUERY_SCHEMA = z.object({
dateFrom: DATE_ONLY_QUERY_SCHEMA.optional(),
dateTo: DATE_ONLY_QUERY_SCHEMA.optional(),
+2 -2
查看文件
@@ -2,7 +2,7 @@ const { z } = require("zod");
const { AppError } = require("../utils/AppError");
const { buildAuditLogData } = require("../utils/audit");
const { parseDateOnlyString } = require("../utils/date");
const { parseDateOnlyString, isValidDateOnlyString } = require("../utils/date");
const { sendData } = require("../utils/reply");
const { issueDocumentNumber } = require("../services/documentSequence");
const { resolveApplicableBudgetPoolByContext } = require("../services/budgetPool");
@@ -28,7 +28,7 @@ const { flushNotificationDispatchTasks } = require("../services/notificationDisp
const UUID_SCHEMA = z.string().uuid();
const BOOLEAN_QUERY_SCHEMA = z.enum(["0", "1", "true", "false"]).optional();
const MONEY_STRING_SCHEMA = z.string().regex(/^\d+(?:\.\d{1,2})?$/);
const DATE_ONLY_SCHEMA = z.string().regex(/^\d{4}-\d{2}-\d{2}$/);
const DATE_ONLY_SCHEMA = z.string().regex(/^\d{4}-\d{2}-\d{2}$/).refine(isValidDateOnlyString, { message: "invalid_calendar_date" });
const DATE_TIME_SCHEMA = z.string().min(1).max(64);
const TRAVEL_STATUS_SCHEMA = z.enum(["draft", "reviewing", "approved", "rejected"]);
const TRIP_TYPE_SCHEMA = z.enum(["domestic", "international"]);
+7
查看文件
@@ -17,8 +17,15 @@ function parseDateOnlyString(value) {
return new Date(`${value}T00:00:00.000Z`);
}
function isValidDateOnlyString(value) {
if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}$/.test(value)) return false;
const date = parseDateOnlyString(value);
return Number.isFinite(date.getTime()) && date.toISOString().slice(0, 10) === value;
}
module.exports = {
compactDateString,
currentDateString,
parseDateOnlyString,
isValidDateOnlyString,
};