Laravel 5.5人力资源应用:请假天数计算与更新问题求助
解决Laravel HR应用中请假天数扣除与更新的问题
嘿,我来帮你捋捋这个请假天数计算的核心问题!咱们从数据库结构、后端逻辑到前端交互一步步拆解,确保你能顺利打通这个环节:
一、先理清楚数据库表的核心结构
假设你的两张表可以这样设计(可根据公司规则调整字段):
1. 员工请假额度分配表 (employee_leave_allocations)
这张表存每个员工每年的各类假期分配额度:
Schema::create('employee_leave_allocations', function (Blueprint $table) { $table->id(); $table->foreignId('employee_id')->constrained()->onDelete('cascade'); $table->foreignId('leave_type_id')->constrained(); -- 关联年假、病假等类型表 $table->decimal('allocated_days', 5, 2); -- 总分配天数 $table->decimal('used_days', 5, 2)->default(0); -- 已用天数 $table->decimal('remaining_days', 5, 2); -- 剩余天数 $table->year('allocation_year'); -- 按年度区分,避免跨年度混乱 $table->timestamps(); });
2. 请假申请表 (leave_applications)
这张表存员工提交的请假申请记录:
Schema::create('leave_applications', function (Blueprint $table) { $table->id(); $table->foreignId('employee_id')->constrained()->onDelete('cascade'); $table->foreignId('leave_type_id')->constrained(); $table->date('start_date'); $table->date('end_date'); $table->decimal('total_days', 5, 2); -- 申请的实际天数(已计算好工作日/自然日) $table->enum('status', ['pending', 'approved', 'rejected'])->default('pending'); $table->text('reason')->nullable(); $table->timestamps(); });
二、后端Laravel的核心逻辑实现
当请假申请被批准时,要自动扣除对应额度,这里的关键是确保数据一致性,建议用事务包裹操作:
1. 先写个工具方法计算请假天数
根据公司规则区分工作日/自然日,用Carbon处理更方便:
use Carbon\Carbon; function calculateLeaveDays($startDate, $endDate, $countWorkingDays = true) { $start = Carbon::parse($startDate); $end = Carbon::parse($endDate); if ($countWorkingDays) { // 计算工作日(排除周六周日,可额外加节假日排除逻辑) return $start->diffInWeekdays($end) + 1; // +1是包含开始当天 } else { // 计算自然日 return $start->diffInDays($end) + 1; } }
2. 批准申请时更新额度的逻辑
在控制器的批准方法里加这段逻辑:
public function approve(Request $request, $id) { DB::beginTransaction(); try { $application = LeaveApplication::findOrFail($id); $application->status = 'approved'; $application->save(); // 获取该员工当前年度对应假期类型的额度记录 $allocation = EmployeeLeaveAllocation::where('employee_id', $application->employee_id) ->where('leave_type_id', $application->leave_type_id) ->where('allocation_year', date('Y')) ->firstOrFail(); // 更新已用和剩余天数 $allocation->used_days += $application->total_days; $allocation->remaining_days = $allocation->allocated_days - $allocation->used_days; $allocation->save(); DB::commit(); return redirect()->back()->with('success', '申请已批准,假期额度已更新'); } catch (\Exception $e) { DB::rollBack(); return redirect()->back()->with('error', '批准失败:'.$e->getMessage()); } }
三、前端JS交互优化(结合你给出的代码片段)
你的JS开头应该是要实现「选择员工/假期类型后加载当前额度,实时校验申请天数」的功能,完善后的代码示例:
var baseUrl = $("#base_url").val(); var currentRemaining = 0; var currentUsed = 0; $(document).ready(function() { // 选择员工后加载其可用假期类型 $('#employee_id').on('change', function() { const empId = $(this).val(); if (!empId) return; $.ajax({ url: `${baseUrl}/employee-leaves/${empId}`, type: 'GET', success: function(res) { $('#leave_type_id').empty(); res.forEach(leave => { $('#leave_type_id').append(` <option value="${leave.id}" data-remaining="${leave.remaining_days}" data-used="${leave.used_days}"> ${leave.type_name}(剩余${leave.remaining_days}天) </option> `); }); // 默认加载第一个选项的额度信息 updateLeaveInfo(); } }); }); // 切换假期类型时更新额度显示 $('#leave_type_id').on('change', updateLeaveInfo); // 选择起止日期后计算申请天数并校验额度 $('#start_date, #end_date').on('change', function() { const start = $('#start_date').val(); const end = $('#end_date').val(); if (!start || !end) return; $.ajax({ url: `${baseUrl}/calculate-leave-days`, type: 'POST', data: { start_date: start, end_date: end, _token: $('meta[name="csrf-token"]').attr('content') }, success: function(res) { const requestedDays = res.total_days; $('#total_days').val(requestedDays); // 校验是否超过剩余额度 if (requestedDays > currentRemaining) { $('#error-tip').text(`申请天数超过剩余额度,最多可申请${currentRemaining}天`).show(); } else { $('#error-tip').hide(); } } }); }); // 更新当前选中假期的额度信息 function updateLeaveInfo() { const selected = $('#leave_type_id option:selected'); currentRemaining = parseFloat(selected.data('remaining')); currentUsed = parseFloat(selected.data('used')); $('#leave-info').text(`已使用${currentUsed}天,剩余${currentRemaining}天`); } });
对应的Laravel路由和控制器方法:
// 路由 Route::get('/employee-leaves/{empId}', [LeaveController::class, 'getEmployeeLeaves']); Route::post('/calculate-leave-days', [LeaveController::class, 'calculateLeaveDays']); // 控制器方法 public function getEmployeeLeaves($empId) { $leaves = EmployeeLeaveAllocation::where('employee_id', $empId) ->where('allocation_year', date('Y')) ->with('leaveType') ->get() ->map(function($item) { return [ 'id' => $item->leave_type_id, 'type_name' => $item->leaveType->name, 'remaining_days' => $item->remaining_days, 'used_days' => $item->used_days ]; }); return response()->json($leaves); } public function calculateLeaveDays(Request $request) { $days = calculateLeaveDays($request->start_date, $request->end_date); return response()->json(['total_days' => $days]); }
几个关键注意点
- 数据安全:后端一定要再做一次额度校验,不能只依赖前端,防止恶意提交
- 假期规则:可以根据需求调整天数计算逻辑(比如半天假、节假日排除)
- 权限控制:给批准申请的接口加权限验证,确保只有管理员能操作
内容的提问来源于stack exchange,提问作者Devzoo
相关产品推荐
相关产品推荐

