竞价系统不是公开拍卖,核心流程是发布竞价项目、供应商下载文件、加密提交报价、截止后统一解密、自动排序和顺位中标。这个流程里最容易出错的是多次报价的覆盖关系、截止边界和加密解密时点。
业务状态机
项目状态需要明确,不能只靠“开始时间和结束时间”推断。建议用显式状态记录项目从发布到定标的完整生命周期。
常见状态包括草稿、已发布、报价中、已截止、解密中、已排序、已定标和流标。每个状态流转都需要记录操作人和时间,方便追查问题。
多次报价
供应商在截止前可以反复上传报价,系统要保证“最后一次提交有效”。这里有两个容易出错的地方:
- 旧请求不能覆盖新请求,需要给每次提交生成版本号。
- 同一个供应商不能同时出现多个有效报价,切换有效报价必须保证原子性。
BEGIN;
UPDATE quote
SET is_current = 0
WHERE project_id = ?
AND supplier_id = ?
AND is_current = 1;
INSERT INTO quote (project_id, supplier_id, version_no, content, is_current)
VALUES (?, ?, ?, ?, 1);
COMMIT;
加密提交
报价提交后应立即加密保存,业务展示和后续处理都基于密文。明文不应该长期停留在数据库或文件系统中,避免截止前通过内部查询或日志泄露。
加密需要在提交入口完成,而不是等后台任务再处理。这样即使文件上传和报价保存分属不同模块,也不会出现明文落库的窗口。
截止一致性
截止时间必须以服务端时间为准。用户请求可能因为网络延迟晚到,但系统不能因此把报价写入已截止的项目。
提交报价时需要在同一个事务里检查项目状态和截止时间。状态不是“报价中”或时间已过,直接拒绝,不能只依赖前端按钮禁用。
截止后解密
截止后由后台任务统一解密报价和文件。解密过程要保证幂等,同一批项目重复触发不会重复解密或产生重复记录。
解密失败不能直接跳过,需要重试、告警并进入人工处理队列。只有解密完成的报价才允许参与排序,未解密完成的项目不能提前生成结果。
自动排序与顺位中标
解密完成后,系统按业务规则自动排序,生成顺位中标结果。排序规则要配置化,结果要留痕。
中标结果不能通过直接改数据库实现,必须通过明确的定标操作触发,避免业务人员绕过流程修改最终结果。
这个系统的难点不是流量,而是报价覆盖、截止边界、加密解密时点和结果可追溯。先把这四条链路做严,业务才不会在关键时刻出问题。