升鲜宝客户账期完善解决方案---升鲜宝生鲜配送供应链管理系统源代码服务(客户订货端、分拣端、仓库PDA、供应商协同端、采购端、配送端、溯源端)

客户账期完善解决方案

主数据、客户绑定、应收快照、客户账单与逾期控制一体化落地方案

|----------|---------------------------------------|
| 文档版本 | v1.0 |
| 适用范围 | 客户账期主数据、客户/客户等级绑定、订单应收、期初应收、客户账单、逾期控制 |
| 文档定位 | 产品口径确认 + 技术落地方案 + 测试验收依据 |

交付说明:本方案基于现有客户账期逻辑分析文档与本次补充分析整理,重点补齐业务口径、数据快照、历史回填、缓存一致性、权限与验收标准。

目录

  1. 方案摘要

  2. 背景、目标与适用范围

  3. 核心业务口径

  4. 总体业务架构与流程

  5. 数据模型与快照设计

  6. 到期日与逾期计算规则

  7. 后端服务与接口落地方案

  8. 前端交互与导入导出方案

  9. 历史数据巡检、回填与上线策略

  10. 权限、缓存、并发与审计要求

  11. 实施计划与优先级

  12. 测试用例与验收标准

  13. 风险清单与处理策略

  14. 附录:伪代码、SQL 检查清单与字段字典

1. 方案摘要

|-----------------------------------------------------------------------------------------------------------|
| 核心结论 客户账期不是一个单纯的客户主数据字段,而是贯穿客户/等级绑定、应收生成、客户账单、到期与逾期控制的业务链路。系统应坚持"新单据按当前有效账期生成快照,历史单据不因主数据变更而反向重算"的原则。 |

本方案将客户账期能力拆分为"主数据配置、绑定优先级、快照生成、到期日计算、逾期控制、历史巡检、导入导出、权限与缓存"八个子模块,并给出统一的后端校验、统一的快照解析服务以及完整的测试验收标准。

推荐目标是:用户新增或修改账期时规则清晰,客户和客户等级只能新绑定有效账期,应收和客户账单生成时写入可追溯的账期快照,收款、应收查询、授信和逾期逻辑全部基于快照字段判断,避免历史数据被主数据变更污染。

1.1 方案交付内容

|---------|-------------------------------------|--------------|
| 交付项 | 说明 | 结果 |
| 业务口径 | 明确账期优先级、禁用回退、0 天账期、固定日边界、历史快照原则。 | 可作为产品确认单 |
| 数据模型 | 补齐应收明细与客户账单快照字段,明确主表字段、索引和约束。 | 可作为数据库改造依据 |
| 服务设计 | 统一 resolveSnapshot 服务,禁止业务模块自行计算账期。 | 可作为研发接口规范 |
| 前端与导入 | 新增/编辑、客户绑定、客户等级绑定、Excel 导入都复用同一套规则。 | 可作为前端和导入改造依据 |
| 上线策略 | 包含巡检、回填、缓存刷新、回滚和灰度验证。 | 可作为上线实施手册 |
| 测试验收 | 覆盖主数据、绑定、到期日、快照、逾期、权限、导入和历史数据。 | 可作为 QA 用例基线 |

2. 背景、目标与适用范围

2.1 背景

现有系统已具备客户账期主数据、客户和客户等级绑定、订单应收与客户账单快照等能力,但存在规则未完全收口的问题。例如前端表单对固定天数与固定日字段的互斥表达不足,下拉接口未严格过滤禁用账期,导入逻辑校验不完整,权限 key 疑似错配,历史快照与主数据变更边界需要进一步产品化说明。

如果这些问题不处理,可能出现客户新绑定禁用账期、导入脏数据、启用/禁用权限被错误授予、历史应收被错误重算、不同业务入口到期日计算不一致等风险。

2.2 建设目标

|----------|-----------|----------------------------------------|
| 目标编号 | 目标 | 落地要求 |
| G1 | 主数据规则统一 | 新增、修改、导入使用同一套后端校验;非法类型、非法固定日、重复名称不得入库。 |
| G2 | 绑定只选择有效账期 | 客户、客户等级新增或变更时只允许选择启用且未删除的账期。 |
| G3 | 应收和账单快照一致 | 所有生成应收、期初应收、客户账单的入口都调用统一账期快照服务。 |
| G4 | 历史单据稳定 | 账期主数据修改、禁用、删除不反向改写历史应收和历史客户账单快照。 |
| G5 | 逾期判断可追溯 | 逾期状态、逾期天数、收款控制、应收查询统一基于单据快照 due_date。 |
| G6 | 上线可控 | 上线前巡检,上线后抽检;必要回填只处理缺失快照,不重算已有有效快照。 |

2.3 适用范围

|----------|----------------------------------------------------------------|
| 范围类型 | 包含内容 |
| 主数据 | 客户账期表 cus_customer_period,以及账期状态、类型、固定天数、固定日、排序、备注等字段。 |
| 绑定关系 | 客户资料 cus_customer.period_id,客户等级 cus_customer_grade.period_id。 |
| 业务单据 | 订单对账转应收、客户期初应收、客户对账单/客户账单。 |
| 控制逻辑 | 到期日、逾期状态、逾期天数、收款和授信相关判断。 |
| 运维数据 | 历史快照巡检、缺失快照回填、异常数据豁免清单。 |

2.4 不适用范围

  • 不重构客户信用额度、授信模型、额度冻结等非账期核心能力;本方案只规定其应如何读取账期快照字段。
  • 不强制改写已有且完整的历史快照;除非明确判定为缺失或错误数据,并经过业务确认。
  • 不改变订单、账单、收款的主流程状态机,仅补齐账期相关字段、计算和校验。

3. 核心业务口径

以下口径建议作为产品、研发、测试共同确认的最终规则。未显式说明的历史异常数据,按"保留历史、生成异常清单、人工确认后修复"的原则处理。

|--------|---------|------------------------------------------------|------------------------------|
| 编号 | 口径 | 推荐规则 | 说明 |
| B01 | 变更影响范围 | 账期主数据修改只影响后续新生成的应收和客户账单,不自动改写历史快照。 | 避免历史财务数据被主数据变更污染。 |
| B02 | 绑定优先级 | 客户自身有效账期 > 客户等级有效账期 > 无账期。 | 客户自身配置优先;无有效配置时回退等级。 |
| B03 | 禁用/删除回退 | 运行时发现客户账期禁用、删除或不存在时,视为无效配置,继续尝试客户等级账期。 | 即使正常操作不允许禁用被引用账期,也要兼容历史脏数据。 |
| B04 | 无账期处理 | 客户和等级都无有效账期时,应收/账单照常生成,账期快照字段为空,due_date 为空。 | 无账期不应阻断业务单据生成。 |
| B05 | 0 天账期 | 系统允许 0 天,含义为起算日当天到期;配置范围建议为 0-3650。 | 适用于现结客户;前端文案必须明确"当天到期"。 |
| B06 | 固定日规则 | 起算日的日 <= 固定日则取当月固定日;否则取下月固定日;目标月无该日则取目标月最后一天。 | 固定日 31 遇 2 月、4 月等短月时取当月最后一天。 |
| B07 | 引用保护 | 被客户或客户等级引用的账期不允许禁用、不允许删除。 | 保护当前绑定关系;历史快照不计入引用保护。 |
| B08 | 历史禁用展示 | 历史客户/等级已绑定禁用账期时,详情页显示名称并标记"已禁用",但新增选择列表不再展示。 | 避免编辑页面误清空或误保存。 |
| B09 | 逾期判断 | 逾期状态和逾期天数以单据快照 due_date 为准,不回查当前账期主数据。 | 保证财务口径稳定。 |
| B10 | 历史回填 | 只回填缺失或明显异常的快照字段;已有完整快照默认不重算。 | 回填前必须输出候选统计和样例确认。 |

|----------------------------------------------------------------------------------------------------|
| 推荐最终口径 采用"有效账期优先 + 历史快照稳定 + 禁用运行时兜底回退"的组合规则。这样既能防止新绑定脏数据,又能兼容历史异常绑定,不会因为某个账期被误禁用而导致客户等级账期无法生效。 |

4. 总体业务架构与流程

4.1 总体架构

|--------|---------|--------------------------------|------------------------|
| 层级 | 模块 | 职责 | 关键输出 |
| 1 | 账期主数据 | 维护账期名称、类型、固定天数、固定日、状态、排序和备注。 | 有效账期配置 |
| 2 | 绑定关系 | 客户资料绑定账期,客户等级绑定账期;客户账期优先。 | 客户可用账期来源 |
| 3 | 统一解析服务 | 根据客户、等级和起算日解析账期快照并计算 due_date。 | CustomerPeriodSnapshot |
| 4 | 业务单据写快照 | 订单应收、期初应收、客户账单生成时写入快照。 | 应收快照、账单快照 |
| 5 | 查询与控制 | 应收查询、收款、逾期、授信读取单据快照。 | 到期/逾期结果 |
| 6 | 巡检与运维 | 检测缺失快照、异常到期日、缓存一致性和权限配置。 | 异常清单、回填结果 |

4.2 标准业务流

|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 客户账期主数据维护 ↓ 客户/客户等级绑定启用账期 ↓ 订单对账转应收 / 期初应收 / 客户账单生成 ↓ 调用 customerReceivablePeriodService.resolveSnapshot(customerId, periodStartDate) ↓ 写入 period_id、period_name、period_type、period_days、period_day、period_start_date、due_date ↓ 应收查询 / 收款控制 / 客户账单 / 授信与逾期分析读取快照 due_date ↓ 账期主数据后续变更只影响新单据,不反向改写历史快照 |

4.3 账期解析优先级

|-------------|------------|--------------|------------------|
| 场景 | 客户账期状态 | 客户等级账期状态 | 解析结果 |
| 客户有启用账期 | 启用、未删除、存在 | 任意 | 使用客户账期。 |
| 客户未配置账期 | 空 | 启用、未删除、存在 | 使用客户等级账期。 |
| 客户账期无效,等级有效 | 禁用、已删除或不存在 | 启用、未删除、存在 | 跳过客户账期,回退客户等级账期。 |
| 客户与等级均无效 | 空或无效 | 空或无效 | 返回空快照,应收/账单继续生成。 |

5. 数据模型与快照设计

5.1 账期主表 cus_customer_period

|----------------------|---------|----------------------------------------------------|
| 字段 | 含义 | 推荐规则 |
| id | 账期主键 | 不可为空,作为客户/等级绑定和快照 period_id 来源。 |
| customer_period_name | 账期名称 | 必填、trim 后唯一;建议长度 1-50。 |
| period_type | 账期类型 | 0=固定天数,1=固定日;必填。 |
| customer_period_date | 固定天数 | period_type=0 时必填,范围 0-3650;period_type=1 时建议保存 0。 |
| period_day | 固定日 | period_type=1 时必填,范围 1-31;period_type=0 时不参与计算。 |
| enabled | 状态 | 1=启用,0=禁用;为空默认 1。 |
| del_flag | 逻辑删除 | 0=正常,1=删除;下拉和解析只使用 del_flag=0。 |
| sort_code | 排序 | 为空默认 1;下拉可按 sort_code 倒序或正序,需与现有页面一致。 |
| remark | 备注 | 可选,限制长度。 |
| use_count | 历史使用数字段 | 仅作为展示兼容,不作为禁用/删除保护依据;保护逻辑使用动态统计。 |

5.2 绑定关系

|--------------------|-----------|--------------------------|
| | 字段 | 规则 |
| cus_customer | period_id | 客户自身账期;客户自身有效账期优先级最高。 |
| cus_customer_grade | period_id | 客户等级账期;客户自身无有效账期时作为回退来源。 |

5.3 应收明细快照 oms_order_bill_debt

应收明细是后续收款、逾期、对账、财务分析的核心明细,必须保留完整账期快照。

|-------------------|----------|---------------------------|
| 字段 | 是否必须 | 说明 |
| period_id | 建议保留 | 生成应收时解析到的账期 ID;无账期时为空。 |
| period_name | 建议保留 | 生成时的账期名称快照;主数据改名不影响历史。 |
| period_type | 必须 | 0=固定天数,1=固定日;用于审计还原规则。 |
| period_days | 必须 | 固定天数模式的天数快照;固定日模式可为 0 或空。 |
| period_day | 必须 | 固定日模式的固定日快照;固定天数模式可为空。 |
| period_start_date | 必须 | 应收账期起算日。 |
| due_date | 必须 | 根据快照规则计算得到的到期日。 |
| overdue_state | 按现有逻辑 | 是否逾期,基于 due_date 和结算状态计算。 |
| settlement_state | 按现有逻辑 | 结算/收款状态,用于判断是否仍需逾期。 |

5.4 客户账单快照 fin_customer_bill

客户账单目前已有 period_id、period_name、period_start_date、due_date、overdue_days 等字段。为保证客户账单在账期主数据变更后仍可完整审计,建议补齐 period_type、period_days、period_day。

|-------------------|--------|------------------------|
| 字段 | 建议 | 说明 |
| period_id | 保留 | 账单生成时解析到的账期 ID。 |
| period_name | 保留 | 账期名称快照。 |
| period_type | 新增/补齐 | 账期类型快照,支撑规则追溯。 |
| period_days | 新增/补齐 | 固定天数快照。 |
| period_day | 新增/补齐 | 固定日快照。 |
| period_start_date | 保留 | 账单账期起算日。 |
| due_date | 保留 | 账单到期日。 |
| overdue_days | 保留 | 账单逾期天数,基于 due_date 计算。 |

5.5 推荐数据库变更

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| -- 客户账单补齐账期规则快照字段(字段类型以现有数据库规范为准) ALTER TABLE fin_customer_bill ADD COLUMN period_type TINYINT NULL COMMENT '账期类型:0固定天数,1固定日' AFTER period_name, ADD COLUMN period_days INT NULL COMMENT '固定天数快照' AFTER period_type, ADD COLUMN period_day INT NULL COMMENT '固定日快照' AFTER period_days; -- 建议索引:用于应收/账单到期与逾期查询 CREATE INDEX idx_oms_debt_due_date ON oms_order_bill_debt(due_date); CREATE INDEX idx_fin_bill_due_date ON fin_customer_bill(due_date); |

若生产库已有同名字段或索引,上线脚本应先做存在性判断;新增字段为可空,保证数据库变更具备向后兼容性。

6. 到期日与逾期计算规则

6.1 固定天数

固定天数模式下,账期类型 period_type=0,customer_period_date=N。到期日等于起算日加 N 个自然日。N=0 表示起算日当天到期。

|-----------------------------------------------------------------------------------------------------------------------------|
| dueDate = periodStartDate + customerPeriodDate 天 示例:起算日 2026-07-03,N=30,到期日 2026-08-02 示例:起算日 2026-07-03,N=0,到期日 2026-07-03 |

6.2 固定日

固定日模式下,账期类型 period_type=1,period_day=D,D 的合法范围为 1-31。

|--------------------------|---------|
| 判断条件 | 到期日 |
| 起算日的"日" <= D,且当月存在 D 日 | 当月 D 日 |
| 起算日的"日" <= D,但当月不存在 D 日 | 当月最后一天 |
| 起算日的"日" > D,且下月存在 D 日 | 下月 D 日 |
| 起算日的"日" > D,但下月不存在 D 日 | 下月最后一天 |

|------------|---------|------------|----------------------|
| 起算日 | 固定日 | 到期日 | 说明 |
| 2026-07-03 | 15 | 2026-07-15 | 起算日的日小于固定日,取当月 15 日。 |
| 2026-07-20 | 15 | 2026-08-15 | 起算日的日大于固定日,取下月 15 日。 |
| 2026-02-10 | 31 | 2026-02-28 | 目标月 2 月无 31 日,取最后一天。 |
| 2028-02-10 | 31 | 2028-02-29 | 闰年 2 月取 29 日。 |
| 2026-04-30 | 30 | 2026-04-30 | 起算日等于固定日,当天到期。 |

6.3 逾期状态与逾期天数

逾期判断只依赖业务单据快照 due_date 和结算状态,不重新读取当前账期主数据。

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| if dueDate is null: overdueState = 0 overdueDays = 0 else if settlementState indicates fully settled: overdueState = 0 overdueDays = 0 else if businessDate > dueDate: overdueState = 1 overdueDays = businessDate - dueDate else: overdueState = 0 overdueDays = 0 |

businessDate 建议统一使用系统业务日期或数据库当前日期,不应由各模块自行取本地时间。若系统支持门店时区或账务日期,应以财务确认的账务日期为准。

7. 后端服务与接口落地方案

7.1 统一快照服务

所有生成客户应收、客户期初应收和客户账单的入口必须调用统一服务 customerReceivablePeriodService.resolveSnapshot(customerId, periodStartDate)。该服务是系统内唯一允许计算客户账期快照和 due_date 的后端入口。

|-----------------|----------------------------------|
| 输入 | 说明 |
| customerId | 客户 ID,不能为空。 |
| periodStartDate | 账期起算日,通常为应收生成日期、订单对账日期或客户账单起算日期。 |

|-----------------|---------------------------------------|
| 输出字段 | 说明 |
| periodId | 解析到的账期 ID;无有效账期为空。 |
| periodName | 账期名称快照。 |
| periodType | 账期类型快照。 |
| periodDays | 固定天数快照。 |
| periodDay | 固定日快照。 |
| periodStartDate | 起算日。 |
| dueDate | 计算后的到期日;无账期为空。 |
| sourceType | 建议新增内部字段:CUSTOMER、GRADE、NONE,用于日志和排查。 |

7.2 解析逻辑伪代码

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| CustomerPeriodSnapshot resolveSnapshot(Long customerId, LocalDate periodStartDate) { require(customerId != null); require(periodStartDate != null); MallShop customer = mallShopDao.selectById(customerId); // 1. 优先尝试客户自身账期 CusCustomerPeriod customerPeriod = getValidPeriod(customer.getPeriodId()); if (customerPeriod != null) { return buildSnapshot(customerPeriod, periodStartDate, "CUSTOMER"); } // 2. 客户账期为空或无效时,尝试客户等级账期 CusCustomerGrade grade = gradeDao.selectById(customer.getGradeId()); CusCustomerPeriod gradePeriod = getValidPeriod(grade == null ? null : grade.getPeriodId()); if (gradePeriod != null) { return buildSnapshot(gradePeriod, periodStartDate, "GRADE"); } // 3. 无有效账期,不阻断应收/账单生成 return CustomerPeriodSnapshot.empty(periodStartDate); } CusCustomerPeriod getValidPeriod(Long periodId) { if (periodId == null) return null; CusCustomerPeriod period = periodCache.get(periodId); if (period == null) return null; if (period.getDelFlag() != 0) return null; if (period.getEnabled() != 1) return null; return period; } |

7.3 主数据后端校验

新增、修改、导入更新必须复用同一个 normalizeAndValidatePeriodForm 方法,避免页面、导入、批量更新各自维护规则。

|---------|---------------------------------------------------|
| 校验项 | 规则 |
| 名称 | 必填,trim,长度 1-50;trim 后名称唯一。 |
| 账期类型 | 必填,只允许 0 或 1。 |
| 固定天数 | period_type=0 时必填,范围 0-3650;period_type=1 时建议置 0。 |
| 固定日 | period_type=1 时必填,范围 1-31;period_type=0 时不参与计算。 |
| 状态 | 为空默认启用;只允许启用/禁用合法字典值。 |
| 排序 | 为空默认 1;必须为整数。 |
| 引用保护 | 账期被客户或客户等级引用时,不允许禁用或删除。 |

7.4 接口调整清单

|-------------------------------------------|--------------------------------------|--------------------|
| 接口/方法 | 调整点 | 验收要求 |
| POST /cus/cuscustomerperiod | 新增账期时调用统一校验,写入规范化字段。 | 非法数据无法保存。 |
| PUT /cus/cuscustomerperiod | 修改账期时调用统一校验;名称唯一排除自身。 | 类型切换后无关字段不参与计算。 |
| POST /cus/cuscustomerperiod/updateStatus | 修正权限 key;禁用前执行动态引用统计。 | 被引用账期禁用失败并返回原因。 |
| DELETE /cus/cuscustomerperiod | 删除前执行动态引用统计。 | 被引用账期删除失败。 |
| /cus/cuscustomerperiod/customerperiodList | 默认只返回 del_flag=0 且 enabled=1 的账期。 | 客户/等级新增绑定时看不到禁用账期。 |
| /import | 导入复用统一校验;同 Excel 名称重复失败;不能导入禁用已引用账期。 | 导入错误行可追踪。 |
| /export | 导出补齐账期类型、固定日、状态等字段。 | 导出模板与导入模板字段一致。 |

7.5 业务调用点改造

|-----------------------------------------------------------|-----------------------------------------------------------------|
| 调用点 | 改造要求 |
| CustomerReceivablePostingServiceImpl.saveOrderDebtDetails | 订单对账转应收时调用 resolveSnapshot,并写入 oms_order_bill_debt 快照字段。 |
| OmsOrderBillDebtServiceImpl.saveBeginsPerod | 新增期初应收时调用 resolveSnapshot,并写入快照字段。 |
| OmsOrderBillDebtServiceImpl.updateBeginsPerod | 修改期初应收时如允许重算,应明确仅对未结算且用户主动修改起算日的记录重算;否则保持原快照。 |
| CustomerReconciliationCommandServiceImpl | 生成客户账单时写入 fin_customer_bill 账期快照。 |
| OmsOrderReconciliationServiceImpl | 生成客户账单时统一使用快照服务,不自行计算 due_date。 |
| 应收查询/收款/授信控制 | 读取 oms_order_bill_debt 或 fin_customer_bill 的 due_date,不回查当前主数据。 |

8. 前端交互与导入导出方案

8.1 账期新增/编辑页面

|----------|--------------------------------------|
| 页面元素 | 规则 |
| 账期名称 | 必填,前端 trim;后端最终校验唯一。 |
| 账期类型 | 必选:固定天数 / 固定日。 |
| 固定天数输入框 | 仅在固定天数模式显示或启用;允许 0-3650;0 文案为"当天到期"。 |
| 固定日输入框 | 仅在固定日模式显示或启用;范围 1-31。 |
| 状态 | 默认启用;被引用账期禁用失败时展示后端 protectReason。 |
| 到期日示例 | 根据当前配置展示动态示例,帮助用户理解固定日短月规则。 |

8.2 客户/客户等级绑定页面

  • 新增或编辑时,账期下拉只展示启用且未删除账期。
  • 历史记录已绑定禁用账期时,详情页应显示"账期名称(已禁用)",但下拉新选择不包含该账期。
  • 用户未主动修改账期时,不得因为下拉列表没有禁用账期而自动清空原 period_id。
  • 用户主动变更账期时,只能保存启用账期。

8.3 导入方案

导入是产生脏数据的高风险入口,应与新增/编辑使用同一套后端规则,并在导入结果中输出行号、账期名称、失败原因。

|---------|----------|---------------------------------------------|
| 导入列 | 是否必填 | 说明 |
| 账期名称 | 是 | trim 后不能为空;同 Excel 内不得重复;与数据库重复时按更新或失败策略处理。 |
| 账期类型 | 是 | 固定天数/固定日,或 0/1;非法值失败。 |
| 账期天数 | 条件必填 | 固定天数模式必填,范围 0-3650。 |
| 固定日 | 条件必填 | 固定日模式必填,范围 1-31。 |
| 状态 | 否 | 为空默认启用;支持启用/禁用、1/0;禁用已引用账期失败。 |
| 排序 | 否 | 为空默认 1。 |
| 备注 | 否 | 限制长度。 |

|----------|-------------------------------------------------------|
| 导入策略 | 推荐规则 |
| 事务策略 | 推荐整批失败回滚;如采用部分成功,必须输出成功和失败清单。 |
| 重复策略 | 同 Excel 内账期名称 trim 后重复直接失败;数据库重复可按"更新已有"处理,但必须复用修改校验。 |
| 缓存策略 | 新增、修改、状态变更、导入更新后统一清理或刷新账期 Redis 缓存。 |
| 引用保护 | 导入不能绕过禁用/删除引用保护。 |

8.4 导出方案

导出字段应与页面和导入模板保持一致,至少包含账期名称、账期类型、账期天数、固定日、状态、排序、备注、使用数、是否可禁用/删除、保护原因、到期日示例。

9. 历史数据巡检、回填与上线策略

9.1 巡检原则

  • 上线前先执行只读巡检,输出缺失快照、异常 due_date、引用禁用账期、权限配置异常等清单。
  • 巡检结果由产品、财务或业务负责人确认后再决定是否回填。
  • 回填只处理缺失或明显异常字段,不覆盖已有完整快照。
  • 无法可靠推定历史账期的记录保留为空,并进入异常豁免清单。

9.2 回填范围

|---------------------------------|--------------------------------------------------------------------------|
| 数据类型 | 处理策略 |
| 已有完整快照的历史应收/账单 | 不处理,不重算。 |
| 缺失 period_id 但可由客户/等级和单据起算日可靠推定 | 可回填快照字段和 due_date,但必须先抽样确认。 |
| 缺失 due_date 但已有完整账期快照 | 按快照中的 period_type、period_days、period_day 和 period_start_date 补 due_date。 |
| 已结清且年代久远的历史单据 | 默认只巡检不回填;如财务审计需要,单独制定回填方案。 |
| 无法推定账期的历史单据 | 不强行填充;输出异常清单并标记豁免。 |

9.3 上线步骤

  1. 发布前备份涉及表:cus_customer_period、cus_customer、cus_customer_grade、oms_order_bill_debt、fin_customer_bill。
  2. 执行数据库增量脚本,优先新增可空字段和索引。
  3. 发布后端服务:主数据校验、下拉过滤、权限 key、统一快照服务、导入校验。
  4. 发布前端页面:账期表单互斥、客户/等级绑定下拉、历史禁用账期展示。
  5. 清理账期 Redis 缓存,确保新规则读取最新账期配置。
  6. 执行只读巡检 SQL,确认"正常应无记录"的检查项无异常或有明确豁免。
  7. 抽样创建固定天数、固定日、客户优先、等级回退、无账期等场景的测试应收和客户账单。
  8. 若存在需要回填的历史缺失数据,按候选统计、样例确认、事务回填、后置检查顺序执行。

9.4 回滚策略

|----------|-------------------------------|
| 回滚对象 | 策略 |
| 应用代码 | 可回滚到上一版本;数据库新增字段为可空,不影响旧版本读取。 |
| 前端页面 | 可回滚到上一版本;后端校验仍应保留,防止脏数据进入。 |
| 数据库字段 | 新增字段不建议物理删除;如需回滚,仅停止写入并保留字段。 |
| 缓存 | 回滚后清理账期缓存,避免旧新结构混读。 |
| 历史回填 | 回填前必须备份候选记录;如需回滚,按备份记录恢复。 |

10. 权限、缓存、并发与审计要求

10.1 权限

启用/禁用客户账期属于主数据控制动作,应使用客户账期自己的权限 key,不应复用客户分组权限。

|--------|-------------------------------------|
| 动作 | 推荐权限 key |
| 列表/查询 | cus:cuscustomerperiod:list 或按现有菜单配置 |
| 新增 | cus:cuscustomerperiod:save |
| 修改 | cus:cuscustomerperiod:update |
| 启用/禁用 | cus:cuscustomerperiod:updateStatus |
| 删除 | cus:cuscustomerperiod:delete |
| 导入 | cus:cuscustomerperiod:import |
| 导出 | cus:cuscustomerperiod:export |

如果历史菜单系统尚未配置 updateStatus,可短期复用 cus:cuscustomerperiod:update,但推荐补齐独立权限,以便区分字段修改和状态开关。

10.2 缓存一致性

|----------|-----------------------------------|
| 触发动作 | 缓存处理 |
| 新增账期 | 新增后写入缓存或清理账期列表缓存。 |
| 修改账期 | 清理该账期 ID 缓存和账期列表缓存。 |
| 启用/禁用 | 清理该账期 ID 缓存和账期列表缓存。 |
| 删除账期 | 清理该账期 ID 缓存和账期列表缓存。 |
| 导入更新 | 批量清理受影响 ID 和列表缓存;必要时直接清空账期缓存命名空间。 |

10.3 并发与事务

  • 禁用/删除前的引用统计和状态更新建议在同一事务内完成,必要时对账期记录加行锁。
  • 客户或等级绑定账期时,保存前再次校验账期是否启用,避免用户打开页面后账期被禁用。
  • 导入更新已有账期时,逐行校验可能受到并发修改影响;提交前应再次执行唯一性和引用保护校验。
  • 应收/账单生成时写入快照应与业务单据保存处于同一事务,避免单据生成成功但快照缺失。

10.4 审计日志

|------------|---------------------------------------|
| 审计对象 | 建议记录内容 |
| 账期主数据新增/修改 | 操作人、时间、修改前后字段、原因。 |
| 启用/禁用/删除 | 操作人、时间、引用统计、失败原因或成功结果。 |
| 导入 | 文件名、操作人、总行数、成功数、失败数、失败明细。 |
| 历史回填 | 回填批次号、候选数量、实际更新数量、执行人、执行 SQL 版本、备份位置。 |
| 快照解析异常 | 客户 ID、等级 ID、账期 ID、失败原因、降级结果。 |

11. 实施计划与优先级

|---------|-----------|---------------------------------------------------------|-----------------|
| 优先级 | 任务 | 说明 | 产出 |
| P0 | 业务口径确认 | 确认 0 天账期、禁用回退、客户账单快照补齐、历史回填范围。 | 产品确认单 |
| P0 | 后端统一校验 | save/update/import 共用 normalizeAndValidatePeriodForm。 | 校验方法与单元测试 |
| P0 | 下拉过滤与绑定校验 | 新增选择只展示启用账期,保存前后端再次校验。 | 接口与前端改造 |
| P0 | 权限 key 修正 | updateStatus 使用客户账期权限。 | 菜单权限与接口注解 |
| P0 | 统一快照服务 | 修正禁用客户账期回退等级账期逻辑。 | resolveSnapshot |
| P1 | 客户账单快照补齐 | fin_customer_bill 补 period_type、period_days、period_day。 | 数据库脚本与写入逻辑 |
| P1 | 前端表单优化 | 固定天数/固定日互斥和到期日示例。 | 页面改造 |
| P1 | 导入导出补齐 | 模板字段、导入校验、错误明细、缓存刷新。 | 导入导出功能 |
| P1 | 回归测试 | 主数据、绑定、快照、到期日、逾期、权限、导入。 | 测试报告 |
| P2 | 历史巡检与回填 | 执行只读巡检,必要时回填缺失快照。 | 巡检和回填报告 |
| P2 | 编码与注释治理 | 修复中文编码污染和误导注释。 | 代码清理 PR |

11.1 建议研发拆分

|-----------|-------------------------------------------|
| 研发任务包 | 包含内容 |
| 后端主数据包 | 账期新增/修改校验、状态变更、删除保护、缓存刷新、权限 key。 |
| 快照服务包 | resolveSnapshot 优先级、due_date 计算、应收和账单调用点。 |
| 前端页面包 | 账期表单、客户/等级下拉、历史禁用账期展示、权限按钮。 |
| 导入导出包 | 导入模板、校验复用、错误报告、导出字段。 |
| 数据治理包 | 数据库字段、索引、巡检 SQL、回填脚本和上线验证。 |

12. 测试用例与验收标准

12.1 核心测试用例

|--------|---------------------------------|---------------------------------------|
| 类别 | 用例 | 预期结果 |
| 主数据 | 新增固定天数 30 天启用账期。 | 保存成功,到期日示例正确。 |
| 主数据 | 新增固定天数 0 天账期。 | 保存成功,示例为当天到期。 |
| 主数据 | 固定天数输入 -1 或 3651。 | 保存失败。 |
| 主数据 | 新增固定日 15 日启用账期。 | 保存成功,到期日示例正确。 |
| 主数据 | 固定日输入 0、32 或空。 | 保存失败。 |
| 主数据 | 名称"月结30天"和" 月结30天 "重复。 | trim 后视为重复,保存失败。 |
| 绑定 | 客户配置账期 A,等级配置账期 B。 | 新应收使用账期 A。 |
| 绑定 | 客户无账期,等级配置账期 B。 | 新应收使用账期 B。 |
| 绑定 | 客户账期无效,等级账期有效。 | 新应收回退等级账期。 |
| 绑定 | 客户和等级都无有效账期。 | 应收照常生成,账期快照为空。 |
| 到期日 | 起算日 2026-07-03,固定天数 30。 | 到期日 2026-08-02。 |
| 到期日 | 起算日 2026-07-03,固定日 15。 | 到期日 2026-07-15。 |
| 到期日 | 起算日 2026-07-20,固定日 15。 | 到期日 2026-08-15。 |
| 到期日 | 起算日 2026-02-10,固定日 31。 | 到期日 2026-02-28。 |
| 到期日 | 起算日 2028-02-10,固定日 31。 | 到期日 2028-02-29。 |
| 快照 | 订单对账转应收。 | oms_order_bill_debt 写入完整快照和 due_date。 |
| 快照 | 期初应收保存。 | 写入完整快照和 due_date。 |
| 快照 | 生成客户账单。 | fin_customer_bill 写入完整快照和 due_date。 |
| 历史稳定 | 修改账期名称或天数后查看历史应收。 | 历史快照不变。 |
| 引用保护 | 禁用被客户引用的账期。 | 禁用失败,返回保护原因。 |
| 引用保护 | 删除被客户等级引用的账期。 | 删除失败,返回保护原因。 |
| 下拉 | 客户/等级新增绑定账期。 | 下拉只显示启用账期。 |
| 历史展示 | 客户已绑定禁用账期并进入编辑页。 | 显示"已禁用",不误清空。 |
| 导入 | Excel 内重复名称。 | 导入失败,提示重复行。 |
| 导入 | 导入非法账期类型或非法固定日。 | 导入失败,显示行号和原因。 |
| 权限 | 无 updateStatus 权限用户禁用账期。 | 接口拒绝,按钮不可见或不可操作。 |
| 缓存 | 修改账期后立刻生成新应收。 | 新应收使用修改后的配置,历史不变。 |
| 逾期 | 未结清单据 businessDate > due_date。 | 逾期状态为是,逾期天数正确。 |

12.2 验收标准

|----------|-------------------------------------------------------------------|
| 验收维度 | 标准 |
| 主数据 | 不能出现重复名称、非法类型、非法固定日、非法固定天数。 |
| 绑定 | 客户/客户等级新绑定只能选择启用账期;保存时后端再次校验。 |
| 引用保护 | 被客户或客户等级引用的账期不能禁用、不能删除。 |
| 快照 | 新生成应收和客户账单均有正确账期快照和到期日;无账期时字段为空但业务不阻断。 |
| 历史稳定 | 修改账期主数据不影响历史 oms_order_bill_debt 和 fin_customer_bill 快照。 |
| 逾期控制 | 收款、应收查询、客户账单和授信控制统一基于快照 due_date。 |
| 导入导出 | 导入不能绕过后端校验;导出字段完整且可复导。 |
| 权限 | 启用/禁用使用 cus:cuscustomerperiod:updateStatus 或明确的客户账期权限。 |
| 数据巡检 | customer_period_receivable_check.sql 中标注"正常应无记录"的检查项无异常,或异常已明确豁免。 |
| 性能 | 账期解析使用缓存或批量预取,不因逐单生成造成明显慢查询。 |

13. 风险清单与处理策略

|--------------|----------------|----------------------------------------|
| 风险 | 影响 | 处理策略 |
| 禁用账期回退规则未统一 | 研发和测试口径不一致。 | 采用本方案 B03:无效客户账期继续回退等级账期。 |
| 客户账单快照字段不完整 | 后续无法审计账单到期日来源。 | 补齐 period_type、period_days、period_day。 |
| 导入绕过页面校验 | 产生非法账期或禁用引用账期。 | 导入复用后端统一校验,整批失败回滚。 |
| 缓存未刷新 | 新单据使用旧账期配置。 | 所有新增、修改、状态、删除、导入后清理缓存。 |
| 历史数据被误重算 | 财务历史口径变化。 | 回填只处理缺失/异常快照,已有完整快照不覆盖。 |
| 权限 key 复用错误 | 越权或无法操作。 | 使用客户账期独立权限 key,并同步菜单配置。 |
| 长表格或中文字体渲染异常 | 交付文档或导出文件显示问题。 | 使用稳定中文字体和导出前渲染检查。 |

14. 附录:伪代码、SQL 检查清单与字段字典

14.1 主数据规范化校验伪代码

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| void normalizeAndValidatePeriodForm(CusCustomerPeriodForm dto) { dto.customerPeriodName = trim(dto.customerPeriodName); requireNotBlank(dto.customerPeriodName, "账期名称不能为空"); requireLength(dto.customerPeriodName, 1, 50, "账期名称长度不合法"); requireIn(dto.periodType, 0, 1, "账期类型不合法"); if (dto.periodType == 0) { require(dto.customerPeriodDate != null, "固定天数不能为空"); require(dto.customerPeriodDate >= 0 && dto.customerPeriodDate <= 3650, "固定天数范围为 0-3650"); dto.periodDay = null; // 或保留但不参与计算,推荐置空 } if (dto.periodType == 1) { require(dto.periodDay != null, "固定日不能为空"); require(dto.periodDay >= 1 && dto.periodDay <= 31, "固定日范围为 1-31"); dto.customerPeriodDate = 0; } if (dto.enabled == null) dto.enabled = 1; if (dto.sortCode == null) dto.sortCode = 1; assertUniqueNameAfterTrim(dto.id, dto.customerPeriodName); } |

14.2 SQL 检查清单

|---------------------------------------|-----------------------------------------------------------------------|
| 检查项 | 说明 |
| customer_period_receivable_check.sql | 上线前后执行只读巡检;正常应无记录的检查项必须无异常或有明确豁免。 |
| customer_period_snapshot_due_date.sql | 用于补充字段、索引或根据快照补 due_date。 |
| customer_period_snapshot_backfill.sql | 用于候选统计、样例确认、事务回填和后置检查。 |
| 引用统计 SQL | 统计 cus_customer.period_id 和 cus_customer_grade.period_id;后续新增绑定点必须扩展。 |
| 缓存检查 | 修改账期后清缓存,抽样确认新生成应收使用新配置。 |

14.3 状态与类型字典

|-------------|----------|--------------|
| 字段 | | 含义 |
| period_type | 0 | 固定天数。 |
| period_type | 1 | 固定日。 |
| enabled | 1 | 启用。 |
| enabled | 0 | 禁用。 |
| del_flag | 0 | 正常。 |
| del_flag | 1 | 已删除。 |
| sourceType | CUSTOMER | 快照来源于客户自身账期。 |
| sourceType | GRADE | 快照来源于客户等级账期。 |
| sourceType | NONE | 无有效账期。 |

14.4 文档依据

本方案依据用户提供的《客户账期逻辑分析与实现方案》及本次补充分析整理。原始文档已明确客户账期贯穿主数据、客户/等级绑定、应收生成、客户账单和到期/逾期控制,并提出"账期配置变更只影响后续新生成的应收和账单,不应改写历史单据快照字段"的核心原则。

相关推荐
升鲜宝供应链及收银系统源代码服务24 天前
升鲜宝业务功能导入模块PRD 开发文档(一)---升鲜宝生鲜配送供应链管理系统源代码服务
生鲜配送系统·升鲜宝生鲜配送源代码·后端app与手机端·b2b订货商城·客户订货系统源代码·升鲜宝·生鲜配送系统架构设计
升鲜宝供应链及收银系统源代码服务1 个月前
升鲜宝AI助手开发功能详尽说明书(五)---升鲜宝生鲜配送供应链管理系统源代码服务
人工智能·生鲜配送源代码·升鲜宝生鲜配送源代码·后端app与手机端·b2b订货商城·客户订货系统源代码·升鲜宝生鲜配送源代码服务
升鲜宝供应链及收银系统源代码服务1 个月前
升鲜宝商品模块功能分析、操作流程示意图与数据库表结构数据字典 E-R 图(一)---升鲜宝生鲜配送供应链管理系统源代码服务
人工智能·生鲜配送源代码·升鲜宝生鲜配送源代码·后端app与手机端·b2b订货商城·客户订货系统源代码·生鲜配送系统源代码商品功能
升鲜宝供应链及收银系统源代码服务1 个月前
【竞品与研究】悦厚 SCP 仓配版详细开发说明文档及数据库表结构数据字典(一)---升鲜宝生鲜配送供应链管理系统源代码服务
生鲜配送源代码·升鲜宝生鲜配送源代码·后端app与手机端·b2b订货商城·客户订货系统源代码·生鲜配送系统源代码·生鲜配送供应链源码
升鲜宝供应链及收银系统源代码服务2 个月前
升鲜宝供应链管理系统box_周转物功能设计模块详细开发文档(一)---升鲜宝生鲜配送供应链管理系统源代码服务
java·intellij-idea·生鲜配送源代码·升鲜宝生鲜配送源代码·后端app与手机端·b2b订货商城·客户订货系统源代码
升鲜宝供应链及收银系统源代码服务2 个月前
升鲜宝 B2B 订货商城线性 --- |----- 原型图(一)---升鲜宝生鲜配送供应链管理系统源代码服务
生鲜配送源代码·升鲜宝生鲜配送源代码·后端app与手机端·b2b订货商城·客户订货系统源代码
升鲜宝供应链及收银系统源代码服务2 个月前
升鲜宝B2B订货商城后端开发文档(一)---升鲜宝生鲜配送供应链管理系统(源代码开发支持服务)
生鲜配送源代码·升鲜宝生鲜配送源代码·后端app与手机端·b2b订货商城·客户订货系统源代码
升鲜宝供应链及收银系统源代码服务2 个月前
升鲜宝后端 API 与手机端 API 开发说明(一)---升鲜宝生鲜配送供应链管理系统重构版
生鲜配送源代码·生鲜供应链管理系统·升鲜宝生鲜配送源代码·后端app与手机端