Laravel Eloquent模型:按佣金总和范围筛选并导出CSV及标记已支付
解决Laravel中用户每月佣金筛选、导出及标记已支付的问题
我来帮你梳理这个需求的实现步骤,分三个核心部分处理:筛选符合金额范围的每月佣金、导出CSV、标记对应佣金为已支付。
1. 计算并筛选符合金额范围的用户每月佣金总和
首先需要通过关联查询,按用户+月份分组统计佣金总和,并用having子句筛选出总和在25到25000之间的记录:
use Carbon\Carbon; use Illuminate\Support\Facades\DB; // 统计未支付佣金中,每月总和符合条件的用户数据 $validMonthlyCommissions = User::query() ->select([ 'users.id', 'users.name', 'users.email', DB::raw('DATE_FORMAT(commissions.created_at, "%Y-%m") as month'), DB::raw('SUM(commissions.amount) as total_amount') ]) ->join('commissions', 'users.id', '=', 'commissions.user_id') ->where('commissions.paid', false) // 仅处理未支付的佣金 ->groupBy('users.id', 'month') ->havingRaw('SUM(commissions.amount) > ? AND SUM(commissions.amount) < ?', [25, 25000]) ->get();
这段代码会返回每个符合条件的用户、对应月份、以及该月的佣金总和,已经自动过滤掉了金额不在范围内的记录。
2. 将筛选结果导出为CSV
利用Laravel的响应流功能,直接生成并下载CSV文件:
use Illuminate\Http\Response; $headers = [ 'Content-Type' => 'text/csv', 'Content-Disposition' => 'attachment; filename="monthly-commissions-' . Carbon::now()->format('Y-m-d') . '.csv"', ]; $callback = function() use ($validMonthlyCommissions) { $file = fopen('php://output', 'w'); // 写入CSV表头 fputcsv($file, ['用户ID', '姓名', '邮箱', '月份', '佣金总额']); foreach ($validMonthlyCommissions as $item) { fputcsv($file, [ $item->id, $item->name, $item->email, $item->month, $item->total_amount ]); } fclose($file); }; return response()->stream($callback, 200, $headers);
访问对应路由后,浏览器会自动下载生成的CSV文件,方便后续批量付款操作。
3. 标记符合条件的佣金为已支付
为了避免重复处理,我们需要找到对应用户对应月份的未支付佣金,批量更新paid字段为true。推荐用事务包裹更新操作,保证数据一致性:
use Illuminate\Support\Facades\DB; DB::transaction(function () use ($validMonthlyCommissions) { foreach ($validMonthlyCommissions as $item) { // 解析月份为具体的起止日期 [$year, $month] = explode('-', $item->month); $startDate = Carbon::create($year, $month, 1)->startOfMonth(); $endDate = Carbon::create($year, $month, 1)->endOfMonth(); // 更新该用户该月的所有未支付佣金 Commission::where('user_id', $item->id) ->where('paid', false) ->whereBetween('created_at', [$startDate, $endDate]) ->update(['paid' => true]); } });
如果你的数据量很大,也可以用子查询优化批量更新,减少循环次数:
$validGroups = $validMonthlyCommissions->map(function ($item) { [$year, $month] = explode('-', $item->month); return [ 'user_id' => $item->id, 'year' => $year, 'month' => $month ]; }); DB::transaction(function () use ($validGroups) { Commission::where('paid', false) ->where(function ($query) use ($validGroups) { foreach ($validGroups as $group) { $query->orWhere(function ($q) use ($group) { $q->whereYear('created_at', $group['year']) ->whereMonth('created_at', $group['month']) ->where('user_id', $group['user_id']); }); } }) ->update(['paid' => true]); });
内容的提问来源于stack exchange,提问作者Zoli
相关产品推荐
相关产品推荐

