=', $begin]; } if ($end) { $where[] = ['l.day', '<=', $end]; } // 打卡记录表 每300条处理一次 打卡记录表中同一个indexs只计算一次 ClockLog::alias('l') ->leftJoin('account a', 'a.id = l.account_id') ->leftJoin('pay_log pl', 'pl.indexs = l.indexs') ->where('l.is_statistic', ClockLog::COMMON_OFF) ->where('l.status', ClockLog::COMMON_ON) ->where('l.need_statistic', ClockLog::COMMON_ON) ->where('l.role', ClockLog::COMMON_ON)//工人 ->where('a.pay', '>', 0) ->where('l.handle_count', '<=', 10) //查询处理次数10次以下 ->where($where) ->group('l.indexs') ->fieldRaw('count(l.id),l.id,l.account_id,l.worksite_id,l.created_at,l.day,l.indexs,a.pay,pl.id as pay_log_id,pl.base_amount_count') ->chunk(300, function ($items) { $update = []; $indexsList = []; $ids = $items->column('id'); \think\facade\Log::write($ids); // 每查询一次就增加一次handle_count 避免未处理成功后 死循环一直查询 (new ClockLog)->whereIn('id', $ids)->save([ 'handle_count' => Db::raw('`handle_count` + 1') ]); foreach ($items as $item) { if ($item['pay_log_id'] && $item['base_amount_count'] == 0) { $update[] = [ 'id' => $item['pay_log_id'], 'amount' => Db::raw('`amount` + '.$item['pay']), 'base_amount' => Db::raw('`base_amount` + '.$item['pay']), 'remarks' => Db::raw('CONCAT_WS(char(10), `remarks`,"基本工资入账 '.$item['pay'].'元")'), 'base_amount_count' => 1, ]; $indexsList[] = $item['indexs']; } } if (!empty($update)) { // \think\facade\Log::write($update); // 启动事务 Db::startTrans(); try { (new PayLog())->saveAll($update); ClockLog::whereIn('indexs', $indexsList)->update(['is_statistic' => ClockLog::COMMON_ON]); Db::commit(); } catch (\Exception $e) { Db::rollback(); \think\facade\Log::error('批量统计基本工资失败'.$e->getMessage().' file:'.$e->getFile().' line:'.$e->getLine()); } } }, 'pl.id', 'desc'); // 加班记录表 每300条处理一次 OvertimeLog::alias('l') ->leftJoin('account a', 'a.id = l.account_id') ->leftJoin('pay_log pl', 'pl.indexs = l.indexs') ->where('l.is_statistic', ClockLog::COMMON_OFF) ->where('l.status', ClockLog::COMMON_ON) ->where('a.pay', '>', 0) ->where('l.handle_count', '<=', 10) //查询处理次数10次以下 ->where($where) ->fieldRaw('l.id,l.account_id,l.worksite_id,l.created_at,l.`day`,l.time,l.indexs,a.pay,pl.id as pay_log_id,pl.overtime_amount_count') ->chunk(300, function ($items) { $update = []; $ids = []; $handleIds = $items->column('id'); // 每查询一次就增加一次handle_count 避免未处理成功后 死循环一直查询 (new OvertimeLog)->whereIn('id', $handleIds)->save([ 'handle_count' => Db::raw('`handle_count` + 1') ]); foreach ($items as $item) { if ($item['pay_log_id']) { // 加班工资=基本工资/6小时 * 加班小时 $overtimeAmount = round(Math::mul(Math::div($item['pay'], 6), $item['time']), 2); $update[] = [ 'id' => $item['pay_log_id'], 'amount' => Db::raw('`amount` + '.$overtimeAmount), 'overtime_amount' => Db::raw('`overtime_amount` + '.$overtimeAmount), 'remarks' => Db::raw('CONCAT_WS(char(10), `remarks`,"加班工资入账 '.$overtimeAmount.'元")'), 'overtime_amount_count' => Db::raw('`overtime_amount_count` + 1'), ]; $ids[] = $item['id']; } } // \think\facade\Log::write($update); if (!empty($update)) { Db::startTrans(); try { (new PayLog())->saveAll($update); OvertimeLog::whereIn('id', $ids)->update(['is_statistic' => OvertimeLog::COMMON_ON]); Db::commit(); } catch (\Exception $e) { Db::rollback(); \think\facade\Log::error('批量统计加班工资失败'.$e->getMessage().' file:'.$e->getFile().' line:'.$e->getLine()); } } }, 'l.id', 'desc'); } /** * 生成月份工资记录 * * @param int $time 生成时间 按月份 格式为年月 如202209 date('Ym') * @return bool */ public static function generateMonthLog(int $time = 0): bool { if ($time == 0) { // 默认生成上个月 $time = date('Ym', strtotime('last month')); } $timestamp = strtotime($time.'01'); $year = date('Y', $timestamp); $month = date('m', $timestamp); $where = [ ['year', '=', $year], ['month', '=', $month], ['role', '=', Account::ROLE_WORKER], ]; // 每次统计 都讲之前的结果清理,插入新计算结果 $insert = []; // 每日工资记录(基本工资和加班工资) PayLog::where($where) ->chunk(300, function ($items) use (&$insert, $time, $year, $month) { foreach ($items as $item) { $indexs = $item['account_id'].'-'.$item['worksite_id'].'-'.$time; if (!isset($insert[$indexs])) { $insert[$indexs] = [ 'account_id' => $item['account_id'], 'worksite_id' => $item['worksite_id'], 'outsource_id' => $item['outsource_id'], 'indexs' => $indexs, 'time' => $time, 'year' => $year, 'month' => $month, 'created_at' => date('Y-m-d H:i:s'), 'amount' => $item['amount'], 'base_amount' => $item['base_amount'], 'overtime_amount' => $item['overtime_amount'], ]; } else { $insert[$indexs]['amount'] = $insert[$indexs]['amount'] + $item['amount']; $insert[$indexs]['base_amount'] = $insert[$indexs]['base_amount'] + $item['base_amount']; $insert[$indexs]['overtime_amount'] = $insert[$indexs]['overtime_amount'] + $item['overtime_amount']; } } }); if (!empty($insert)) { // \think\facade\Log::write($insert); // 启动事务 Db::startTrans(); try { PayMonthLog::where('time', $time)->delete(); (new PayMonthLog())->insertAll($insert); Db::commit(); } catch (\Exception $e) { Db::rollback(); \think\facade\Log::error('统计['.$time.']工资失败'.$e->getMessage().' file:'.$e->getFile().' line:'.$e->getLine()); } } return true; } }