execute(function () use ($request, $reports) { $data = $request->validate([ 'page' => ['nullable', 'integer', 'min:1'], 'limit' => ['nullable', 'integer', 'min:1', 'max:100'], 'order_no' => ['nullable', 'string', 'max:48'], 'username' => ['nullable', 'string', 'max:64'], 'platform' => ['nullable', 'string', 'max:32'], 'flow_status' => ['nullable', 'in:pending,credited'], 'profit_status' => ['nullable', 'in:pending,credited'], 'settlement_date' => ['nullable', 'date_format:Y-m-d'], 'start_date' => ['nullable', 'date_format:Y-m-d'], 'end_date' => ['nullable', 'date_format:Y-m-d', 'after_or_equal:start_date'], 'include_children' => ['nullable', 'boolean'], ]); $page = max(1, (int) ($data['page'] ?? 1)); $limit = min(100, max(1, (int) ($data['limit'] ?? 20))); $agent = $this->currentAgent(); $ids = $request->boolean('include_children') ? $reports->visibleAgentIds($agent) : [(int) $agent->id]; $query = AgentRebateRecord::query()->with('agent:id,username')->whereIn('agent_id', $ids); foreach (['order_no', 'platform', 'flow_status', 'profit_status'] as $field) { if (!empty($data[$field])) $query->where($field, $data[$field]); } if (!empty($data['username'])) { $query->whereHas('agent', fn($query) => $query->where('username', 'like', '%' . $data['username'] . '%')); } if (!empty($data['settlement_date'])) $query->where('settlement_date', $data['settlement_date']); if (!empty($data['start_date'])) $query->where('created_at', '>=', $data['start_date'] . ' 00:00:00'); if (!empty($data['end_date'])) $query->where('created_at', '<=', $data['end_date'] . ' 23:59:59'); $total = (clone $query)->count(); $list = $query->orderByDesc('settlement_date')->orderByDesc('id')->forPage($page, $limit)->get(); return compact('total', 'page', 'limit', 'list'); }); } public function flowProfiles(Request $request, AgentFlowCommissionProfileService $service) { return $this->execute(function () use ($request, $service) { return $this->listProfiles($request, $service); }); } public function saveFlowCommissionProfile(Request $request, AgentFlowCommissionProfileService $service) { return $this->execute(function () use ($request, $service) { $owner = $this->requireLevelOne(); $data = $request->validate($this->profileRules('agent_flow_commission_profiles', (int) $owner->id)); return $service->save($data, null, $owner); }); } public function deleteFlowCommissionProfile(Request $request, AgentFlowCommissionProfileService $service) { return $this->execute(function () use ($request, $service) { $owner = $this->requireLevelOne(); $data = $request->validate(['id' => ['required', 'integer', 'exists:agent_flow_commission_profiles,id']]); $service->delete((int) $data['id'], null, $owner); return []; }); } public function profitProfiles(Request $request, AgentProfitCommissionProfileService $service) { return $this->execute(function () use ($request, $service) { return $this->listProfiles($request, $service); }); } public function saveProfitCommissionProfile(Request $request, AgentProfitCommissionProfileService $service) { return $this->execute(function () use ($request, $service) { $owner = $this->requireLevelOne(); $data = $request->validate($this->profileRules('agent_profit_commission_profiles', (int) $owner->id)); return $service->save($data, null, $owner); }); } public function deleteProfitCommissionProfile(Request $request, AgentProfitCommissionProfileService $service) { return $this->execute(function () use ($request, $service) { $owner = $this->requireLevelOne(); $data = $request->validate(['id' => ['required', 'integer', 'exists:agent_profit_commission_profiles,id']]); $service->delete((int) $data['id'], null, $owner); return []; }); } private function listProfiles( Request $request, AgentFlowCommissionProfileService|AgentProfitCommissionProfileService $service ): array { $data = $request->validate([ 'page' => ['nullable', 'integer', 'min:1'], 'limit' => ['nullable', 'integer', 'min:1', 'max:100'], 'name' => ['nullable', 'string', 'max:128'], 'selectable' => ['nullable', 'boolean'], ]); $agent = $this->currentAgent(); if ((int) $agent->level !== Agent::LEVEL_ONE) { $page = max(1, (int) ($data['page'] ?? 1)); $limit = min(100, max(1, (int) ($data['limit'] ?? 20))); return ['total' => 0, 'page' => $page, 'limit' => $limit, 'list' => []]; } if ($request->boolean('selectable')) { return $service->paginateSelectable($agent, $data); } return $service->paginate($data, $agent); } private function requireLevelOne(): Agent { $agent = $this->currentAgent(); if ((int) $agent->level !== Agent::LEVEL_ONE) { throw new \RuntimeException('只有一级代理可以配置下级佣金方案'); } return $agent; } private function profileRules(string $table, int $ownerId): array { $id = (int) request()->input('id', 0); return [ 'id' => ['nullable', 'integer', 'exists:' . $table . ',id'], 'name' => [ 'required', 'string', 'max:128', Rule::unique($table, 'name')->where('owner_agent_id', $ownerId)->ignore($id), ], 'live_rate' => ['required', 'numeric', 'between:0,100', new DecimalNumber(3, 4)], 'slot_rate' => ['required', 'numeric', 'between:0,100', new DecimalNumber(3, 4)], 'lottery_rate' => ['required', 'numeric', 'between:0,100', new DecimalNumber(3, 4)], 'sport_rate' => ['required', 'numeric', 'between:0,100', new DecimalNumber(3, 4)], 'esports_rate' => ['required', 'numeric', 'between:0,100', new DecimalNumber(3, 4)], 'fishing_rate' => ['required', 'numeric', 'between:0,100', new DecimalNumber(3, 4)], 'chess_rate' => ['required', 'numeric', 'between:0,100', new DecimalNumber(3, 4)], 'is_default' => ['required', 'boolean'], ]; } }