SpringBoot3Vue3 人力假期余额设计预占、扣减、回滚与重复回调怎么保证一致文档地址https://ruoyioffice.com 文章底部获取源码和演示地址 17156169080获取产品咨询员工看到“年假还剩 6 天”背后其实不是一道减法。审批中的 3 天算不算可用流程拒绝要不要自动退请了 5 天只休 3 天怎么返还同一条 Flowable 回调执行两次会不会再扣一次真正可靠的假期余额需要按账户系统来设计。▲ 规则负责算额度账户保存当前值流水解释每次变化请假单只通过余额服务改变账户引言一个 remainingDays 字段为什么撑不住真实请假最初版假勤系统往往只有员工、假种和剩余天数employee_id | leave_type | remaining_days它能支持“提交后减 1 天”却回答不了下面的问题两张审批中的请假单能否同时占用同一份余额审批拒绝、员工撤回、管理员取消是不是同一种退回流程通过后预占怎样变成正式使用销假实际天数变少差额回到哪一个年度账户工龄调整导致年假额度变化为什么从 10 天变成 12 天消息重试让回调重复执行时怎样避免重复扣减。所以假期余额的正确抽象是一套带业务来源、状态迁移和审计流水的额度账户。一、员工余额由三套配置合成余额不从账户表凭空产生。系统先合成假种、部门方案和员工参数再计算某员工某年度应得额度。1. 假种决定是否管理余额年假、调休假、福利假通常需要余额事假、婚假等可能只校验条件不做账户扣减。假种层应明确是否启用余额、默认额度、最小请假单位、是否允许透支和有效期。2. 部门方案承载企业差异总部、制造基地和项目团队可能适用不同方案。系统按员工部门查找生效方案必要时向上继承而不是在请假表单里写死规则。3. 员工参数处理个体差异员工入职日期、工龄起算日和奖励年假会改变最终额度。规则更新后不应直接覆盖旧数字而应生成一条调整流水。▲ HR 配的是规则员工拿到的是规则在某个年度计算后的账户结果核心边界是规则是计算依据账户是计算结果。历史账户不能随着规则页面每次打开而漂移否则系统无法解释余额变化。二、账户看当前流水看原因年度账户建议至少保留五个口径口径含义什么时候变化发放额度本年度累计获得年度发放、人工调整、工龄重算可用余额还能发起多少预占时减少释放或退回时增加预占余额已提交、尚未最终通过提交增加通过或拒绝减少已用额度已确认消耗审批通过时增加销假时减少结转额度来自上一周期年度初始化或结转任务TableName(hrm_leave_account)publicclassLeaveAccountDOextendsTenantBaseDO{TableIdprivateLongid;privateLongemployeeId;privateIntegerleaveType;privateIntegergrantYear;privateBigDecimalgrantedDays;privateBigDecimalusedDays;privateBigDecimalreservedDays;privateBigDecimalavailableDays;privateBigDecimalcarryForwardDays;privateLocalDateexpireDate;}账户只回答“现在是多少”。每一次变化还要写入hrm_leave_ledger记录变动类型、前后余额、业务类型、业务 ID 和备注。这样 HR 可以从“剩 6 天”继续追到“年度发放 10 天、请假确认 3 天、审批中预占 1 天”。三、提交时先预占不要等通过后才扣员工有 5 天年假同时提交两张各 4 天的申请。如果系统等审批通过才扣余额两张单都能通过提交校验最后必然透支。更稳妥的状态迁移是提交available - daysreserved days 通过reserved - daysused days 拒绝/撤回reserved - daysavailable days 销假used - returnedDaysavailable returnedDays▲ 预占解决并发申请透支确认、释放和销假退回分别对应不同业务结果预占动作必须和请假单进入审批状态处于同一事务边界。后端不能只相信前端展示的余额而要重新读取账户并完成原子扣减Transactional(rollbackForException.class)publicvoidreserveForBill(LongbillId,LongemployeeId,IntegerleaveType,BigDecimaldays){LeaveAccountDOaccountgetOrCreateAccount(employeeId,leaveType);if(account.getAvailableDays().compareTo(days)0){throwexception(LEAVE_BALANCE_NOT_ENOUGH);}BigDecimalbeforeaccount.getAvailableDays();account.setAvailableDays(before.subtract(days));account.setReservedDays(account.getReservedDays().add(days));leaveAccountMapper.updateById(account);createLedger(account,RESERVE,days.negate(),before,account.getAvailableDays(),billId,HRM_LEAVE_CANCEL_BILL);}高并发场景还应增加乐观锁版本号或带余额条件的原子更新让“余额足够”和“完成扣减”成为不可分割的数据库动作。四、审批回调只做状态迁移而且必须幂等Flowable 审批通过后不应再次从可用余额扣减而是把预占转成已用Transactional(rollbackForException.class)publicvoidconfirmForBill(LongbillId){if(leaveLedgerMapper.existsByBizAndType(HRM_LEAVE_CANCEL_BILL,billId,CONFIRM_USE)){return;}LeaveBillDObillvalidateBillExists(billId);LeaveAccountDOaccountgetAccount(bill);BigDecimaldaysbill.getExpectedDays();account.setReservedDays(account.getReservedDays().subtract(days));account.setUsedDays(account.getUsedDays().add(days));leaveAccountMapper.updateById(account);createLedger(account,CONFIRM_USE,BigDecimal.ZERO,account.getAvailableDays(),account.getAvailableDays(),billId,HRM_LEAVE_CANCEL_BILL);}确认使用时可用余额变化为 0因为额度在提交时已经预占。确认动作改变的是reservedDays和usedDays的归属。幂等不能只靠“当前流程状态已经通过”。更可靠的做法是用business_type business_id change_type定义业务幂等键数据库增加唯一约束或在落流水前检查账户更新与流水写入同事务重复调用直接返回已有结果异常补偿只追加新流水不修改历史流水。五、拒绝、撤回与取消都释放预占但保留不同原因从余额数学上看审批拒绝和员工撤回都执行reserved - days available days但审计含义不同。流水变动类型可以统一为RELEASE_RESERVE备注和业务状态要保留“审批拒绝”“发起人撤回”“管理员取消”的真实原因。释放时还要防止reservedDays变成负数。如果旧数据没有成功预占系统应先核对流水再决定拒绝补偿还是记录告警不能盲目加回余额。六、销假不是撤销原单而是按实际使用退差额员工原申请 5 天实际休 3 天销假通过后应退回 2 天原请假单仍保留“批准 5 天”的审批事实销假单记录实际使用 3 天年度账户usedDays减 2availableDays加 2新增CANCEL_RETURN流水并关联销假业务。▲ 表单在提交前展示余额审批后的实际天数由销假动作修正不回头篡改历史审批事实BigDecimalreturnedDaysbill.getExpectedDays().subtract(bill.getActualDays());if(returnedDays.signum()0){return;}account.setUsedDays(account.getUsedDays().subtract(returnedDays));account.setAvailableDays(account.getAvailableDays().add(returnedDays));如果实际天数大于预计天数不能静默把余额扣成负数应走补充申请、变更流程或明确的透支规则。七、前端负责解释余额不负责决定余额Vue3 表单在员工选择假种和预计天数后调用摘要接口展示本年度发放、已使用、审批中预占、当前可用、本次申请和提交后预计剩余。这能把“余额不足”从提交后的报错提前变成员工填表过程中的反馈。但前端数值只用于体验最终校验仍由后端事务完成。▲ PC 与移动端共享同一余额摘要接口避免两端各算一套口径▲ 移动端负责快速发起与查看状态余额变动仍统一由后端服务和流程回调驱动八、年度发放、工龄重算和到期清零都要走流水自动任务最容易被写成直接update available_days 0这会让系统失去解释能力。正确做法是把定时任务也当作业务来源年度发放GRANT工龄或奖励变化ADJUST_ADD/ADJUST_SUB上年度结转CARRY_FORWARD到期清零EXPIRE_CLEAR。任务应按员工、假种、年度建立幂等键。重复跑一次年度发放任务不能再发一份年假清零任务失败重试也不能生成多条相同清零流水。九、这套模型的边界在哪里假期余额账户解决的是额度一致性不会自动解决所有假勤问题工作日和请假时长仍要读取班次、节假日方案跨年度请假需要按日期拆分到不同年度账户调休额度可能来自加班审批不一定由年度任务发放小时假与天数假要统一换算精度多租户环境下账户、流水和规则都必须保留租户边界。余额服务应保持单一职责接收已经算好的变动额度执行可靠的账户迁移与流水留痕日历、班次和劳动政策由上游规则服务负责。十、上线前建议验证的 10 个场景余额 5 天同时提交两张 4 天申请第二张必须失败提交 3 天后可用减少 3 天、预占增加 3 天审批通过后可用不再减少预占转为已用同一通过回调执行两次账户只变化一次审批拒绝后预占释放且生成原因清晰的流水发起人撤回后与拒绝使用相同数学动作但不同备注请 5 天、销假实际 3 天退回 2 天工龄重算额度增加 2 天保留调整前后余额到期清零任务重复运行不重复清零或重复写流水PC 与 App 查询到的可用、预占、已用口径一致。结语企业假期余额的难点不在字段多而在业务动作多、审批时间长、回调可能重复、员工权益必须能解释。一套可靠设计可以归纳为四句话规则算额度账户存当前流水讲原因流程做迁移。再补上事务、并发控制和业务幂等假期余额才不会在流程重试、销假和年度任务中越算越乱。这套账户模型也可以复用到调休、福利额度、培训学时、补贴余额和会员积分等场景。区别只在发放规则可靠性骨架是相通的。如果这篇对你有用点个「在看」或收藏。演示地址https://ruoyioffice.com/webGitHub 源码https://github.com/yuqing2026/ruoyi-officeGitee 源码https://gitee.com/yqzy1688/ruoyi-office微信17156169080获取产品咨询打开演示地址直接查看系统。
企业数字化 ERP 产品动态
相关推荐
PHPWind 7.3.2 GBK老论坛源码:安装配置、二次开发与字符集迁移实战 简介:这是一套基于PHP语言和MySQL数据库架构的开源论坛程序,版本为7.3.2简体中文GBK,主要面向需要快速搭建网络社区的站长,以及想要通过阅读完整产品源码来提升开发能力的PHP学习者。它最大的特点是引入了‘圈子模式’,… · 2026/9/26 12:12:54
Unity期末作业实战:第三人称漫游完整工程与避坑指南 简介:一份基于Unity 2021的第三人称漫游场景期末大作业,面向正在学习Unity游戏开发的学生或需要完成结课设计的开发者,覆盖角色控制、场景建模、UI交互等关键环节,可帮助理解第三人称视角、碰撞检测和输入映射。资源为zip压缩包&a… · 2026/9/26 12:12:54
Pi Agent 10个核心插件:Node.js开发者效率跃迁实操地图 1. 项目概述:为什么“Pi Agent”插件清单不是又一份工具推荐列表,而是开发者效率跃迁的实操地图最近在几个技术社区里,总能看到有人问:“Pi Agent到底值不值得装?它和Copilot、Cursor、CodeWhisperer比起来差在哪&… · 2026/9/26 12:12:54
从Excel到CRM:中小团队客户管理落地实战指南 先说个我自己的感受:以前我们团队管客户,是Excel表格加微信聊天记录混合双打,客户问过什么、报价报了多少、上次跟进是什么时候,全靠人的记忆。换过两个销售之后,客户情况就变成一团迷雾,新接手的人只能挨个… · 2026/9/26 12:49:02
安琪酵母的底层原理的庖丁解牛 根因
安琪酵母的核心主体是酿酒酵母(Saccharomyces cerevisiae),属于单细胞真菌。安琪不是化学膨松剂,本质是把活酵母菌经过工业培养、脱水休眠,做成干粉产品。整个底层逻辑分为两段:工厂端的菌种培育休眠脱… · 2026/9/26 12:49:02
知识付费SaaS选型实测:小鹅通、知识星球、千聊谁更适合私域运营 2026年开年,我把团队的知识付费项目从"内容驱动"硬转成"运营驱动",第一个动作就是重新选型私域工具。市面上的知识付费SaaS平台看着功能大同小异,但真把同一套课程、同一个训练营、同一套促销策略放上去跑一轮࿰… · 2026/9/26 12:48:55
SpringBoot+Vue民宿管理系统:订单防重与房态计算实战 简介:这份资源是一篇基于SpringBoot与Vue的民宿管理系统毕业论文文档,面向计算机相关专业的本科或高职毕业生,以及需要完成课程设计、毕业设计的学生。论文围绕传统民宿管理效率低、数据出错率高、检索困难等问题,提出用信息化系统… · 2026/9/26 12:48:55
表格数据备份实操指南:从桌面文件到数据库的避坑手册 备份表格数据这种事,听起来好像没啥技术含量,感觉就是“把文件另存一份”而已。但真做起来就会发现,坑多到你怀疑人生:数据库表结构变了怎么办、备份文件恢复时报错怎么办、Excel里辛辛苦苦调的格式一备份就乱了怎么办。我这些年经… · 2026/9/26 12:48:55
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46