Laravel中如何验证文档编号范围并避免重复旧范围?
实现发票编号范围校验与用尽提示的方案
1. 先搞定数据表结构
需要两张核心表支撑逻辑:
- invoices(发票表):存储已生成的发票记录,核心字段:
invoice_id(主键)、invoice_num(加唯一索引,保证发票编号不重复)、create_time - doc_number_ranges(编号范围记录表):存储所有用过的编号范围,核心字段:
range_id(主键)doc_type(比如填"发票",区分不同业务类型)start_num(范围起始编号)end_num(范围结束编号)is_exhausted(布尔值,标记该范围是否已用尽)
2. 范围用尽的判断与提示逻辑
每次生成发票后执行以下步骤:
- 生成下一个发票编号:基于当前在用的未用尽范围,取已生成发票中的最大
invoice_num加1 - 将新发票插入
invoices表后,检查当前生成的invoice_num是否等于该范围的end_num - 如果相等,更新
doc_number_ranges表中对应范围的is_exhausted为true,同时前端弹出提示:"当前发票编号范围已用尽,请重新设置新范围"
3. 新范围的重复校验(核心逻辑)
用户提交新范围时,必须确保新范围与所有旧范围完全无重叠(不管旧范围是否用尽):
后端校验(必须做,防止前端绕过)
用SQL查询判断新范围是否与已有范围重叠:
SELECT COUNT(*) FROM doc_number_ranges WHERE doc_type = '发票' -- 核心判断逻辑:新范围的起始 ≤ 旧范围的结束,且新范围的结束 ≥ 旧范围的起始,说明存在重叠 AND start_num <= :new_end AND end_num >= :new_start;
- 若查询结果>0,返回错误提示:"该编号范围已被使用,请选择全新的范围"
- 若结果=0,将新范围插入
doc_number_ranges表,标记is_exhausted为false
前端辅助校验(提升用户体验)
在用户输入新范围时,提前做基础校验:
- 检查起始编号是否大于结束编号(比如输入106-105直接提示非法)
- 拉取所有已存范围数据,在前端实时判断新范围与旧范围是否重叠,提前给用户提示
4. 避坑要点
- 给
invoice_num加唯一约束:避免并发场景下生成重复编号 - 生成编号时用事务:比如锁定当前范围记录或使用乐观锁,防止多用户同时操作导致的编号冲突
- 不要只校验完全相同的范围:比如旧范围是101-105,新范围填103-107属于部分重叠,必须拦截
内容的提问来源于stack exchange,提问作者Neha
相关产品推荐
相关产品推荐

