You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel考勤系统:如何保留旧timeout值并添加新签退时间

问题描述

希望在考勤系统中添加新的签退(timeout)值时保留旧的timeout值——例如初始记录的timein为01:00:11、timeout为01:00:13,当员工再次签退时,旧的timeout会被更新为01:18:18,需要修改逻辑避免覆盖旧值,保留所有签退记录。尝试将代码中的update替换为insert、使用CreateorUpdate均无效。

当前问题代码片段

原签退逻辑中更新记录的代码:

if($attendance)
 {
                    
     DB::table('attendances')
                    ->where(['created_by' => $id, 'logdate' => $date] )
                    ->update([
                        'timeout' => $time,
                        'status'=>'1',
                        
                    ]);
                  
  }
相关代码与表结构

users表结构

Schema::create('users', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('created_by')->nullable();
        $table->string('employee_id')->nullable();
        $table->string('name');
        $table->string('email', 100)->unique()->nullable();
        $table->string('password');
        $table->string('P')->default('0');
        $table->rememberToken();
        $table->timestamps();
    });

attendances表结构

Schema::create('attendances', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('created_by');
        $table->integer('user_id')->unsigned();
        $table->time('timein')->nullable();
        $table->time('timeout')->nullable();
        $table->date('logdate');
        $table->string('status');   
        $table->timestamps();
    });

timeclock方法代码

public function timeclock(Request $request){

            $id = $request->input('id');
            // dd($id);
            $date = carbon::today() ; 
            $time = Carbon::now(); 
        
            $user = DB::table("users")
                    ->where("id", "=", $id)
                    ->first();
        
            
            if($user == NULL) {
                $msg = "<div class='alert alert-danger'><button class='close' data-dismiss='alert'>&times;</button> Please enter your first name to continue!</div>";
              }
              elseif ($user != NULL){
                
                $attendance =   DB::table("users")
                ->leftJoin("attendances", function($join){
                    $join->on("users.id", "=", "attendances.user_id");
                })
                ->select("attendances.*", "logdate", "timein", "timeout", "status")
                ->where("attendances.user_id", "=", $id)
                ->where("attendances.logdate", "=", $date)
                ->where("attendances.status", "=", 0)
                ->get()->toArray();
                // dd($attendance);
                if($user->P == '1') {
        
                    DB::table('users')
                    ->where(['id' => $id] )
                    ->update([
                    'p'=>'0',
                        
                    ]);
        
        
                }
                
                // dd($attendance);
        
                if($attendance){
                    
     
                    DB::table('attendances')
                    ->where(['created_by' => $id, 'logdate' => $date] )
                    ->update([
                        'timeout' => $time,
                        'status'=>'1',
                        
                    ]);
                  
                }
              
            
              else {
        
                $result = new Attendance;
                        $result->user_id = $id;
                        $result->created_by = $id;
                        $result->timein = $time;
                        $result->logdate =  $date;
                        $result->status = 0;
                        $result->save();
                
                          }
        
                          if($user->P == '0') {
        
                            DB::table('users')
                            ->where(['id' => $id] )
                            ->update([
                            'p'=>'1',
                                
                            ]);     
                        }
            }
            
                return redirect()->route('attendance.timeclockcreate')->with('id', $id)->with('message', 'Inserted successfully.');
        }

表单代码

<table class="table table-bordered table-striped">
                    <thead>
                        <tr>
                           <th> {{ __(' SL') }}</th>
                           {{--<th> {{ __(' EMP CD') }}</th>--}}
                           <th> {{ __(' EMPLOYEE NAME') }}</th>
                            <th> {{ __('TIMEMING') }}</th>
                            
                          
                            <!-- <th> {{ __(' Created At') }} </th> -->
                       
                           
                            
                        </tr>
                    </thead>
                    <tbody>

                        
                    @foreach($attendances as $key => $attd)
                        <tr>
                            <td>{{$key+1}}</td>
                            <td>{{ $attd['name'] }}</td>     
                            <td>
                            <form action="{{ route('attendance.timeclock') }}" method="post" name="department_add_form">
                            {{ csrf_field() }}
                            <input type="hidden" name="id" id="id" value="{{ $attd['id'] }}">
                        
                                @if($attd['P']=='1')
                                 <button type="submit" class="button-88, btn btn-warning" role="button">{{ __('SIGN OUT') }}</button>
                                @elseif($attd['P']=='0')
                                 <button type="submit" class="button-88, btn btn-primary" role="button">{{ __('SIGN  IN') }}</button>              
                                @endif
                       
                       
                            </form>
                            </td>   

                            
                        </tr>

                    @endforeach
                       
                    </tbody>
                </table>
解决方案

核心思路:不再覆盖旧的签退记录,针对不同场景处理:

  1. 若当天存在未完成(status=0)的考勤记录,正常更新该记录的签退时间和状态;
  2. 若当天无未完成记录(已签退过),则新增一条新的考勤记录,复用最后一次的签到时间作为当前记录的timein,同时记录新的签退时间。

修改后的timeclock方法关键代码如下:

public function timeclock(Request $request){

    $id = $request->input('id');
    $date = Carbon::today(); 
    $time = Carbon::now(); 

    $user = DB::table("users")
            ->where("id", "=", $id)
            ->first();

    if($user == NULL) {
        $msg = "<div class='alert alert-danger'><button class='close' data-dismiss='alert'>&times;</button> Please enter your first name to continue!</div>";
    } elseif ($user != NULL){
        // 1. 查询当天所有考勤记录
        $allAttendances = DB::table("attendances")
            ->where("user_id", "=", $id)
            ->where("logdate", "=", $date)
            ->get()->toArray();
        
        // 2. 查询当天未签退的记录
        $unfinishedAttendance = DB::table("attendances")
            ->where("user_id", "=", $id)
            ->where("logdate", "=", $date)
            ->where("status", "=", 0)
            ->first();

        if($user->P == '1') {
            DB::table('users')
                ->where(['id' => $id])
                ->update(['p'=>'0']);
        }

        // 3. 处理考勤记录
        if($unfinishedAttendance){
            // 存在未签退记录,精准更新该记录
            DB::table('attendances')
                ->where('id', $unfinishedAttendance->id)
                ->update([
                    'timeout' => $time,
                    'status'=>'1',
                ]);
        } else {
            // 无未签退记录,新增签退记录
            $lastTimein = null;
            if(!empty($allAttendances)){
                // 取最后一次签到的时间
                $lastAttendance = end($allAttendances);
                $lastTimein = $lastAttendance->timein;
            }
            // 新建记录,若没有历史签到时间则用当前时间作为timein
            $result = new Attendance;
            $result->user_id = $id;
            $result->created_by = $id;
            $result->timein = $lastTimein ?? $time;
            $result->timeout = $time;
            $result->logdate = $date;
            $result->status = 1;
            $result->save();
        }

        if($user->P == '0') {
            DB::table('users')
                ->where(['id' => $id])
                ->update(['p'=>'1']);
        }
    }

    return redirect()->route('attendance.timeclockcreate')->with('id', $id)->with('message', '操作成功.');
}

修改说明

  • 拆分原有的关联查询,分别获取“当天所有记录”和“当天未完成记录”,避免冗余;
  • 更新记录时使用id精准定位,防止因created_by和logdate重复导致批量更新错误;
  • 新增签退记录时复用历史签到时间,保证考勤记录的关联性;
  • 调整提示信息适配签到、签退两种场景。

内容的提问来源于stack exchange,提问作者Kairaoi Ientumoa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 07:25:18