CommissionController.php 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. <?php
  2. namespace App\Http\Controllers\agent;
  3. use App\Http\Controllers\AgentApiController;
  4. use App\Models\Agent\Agent;
  5. use App\Models\Agent\AgentRebateRecord;
  6. use App\Rules\DecimalNumber;
  7. use App\Services\Agent\AgentFlowCommissionProfileService;
  8. use App\Services\Agent\AgentProfitCommissionProfileService;
  9. use App\Services\Agent\AgentReportService;
  10. use Illuminate\Http\Request;
  11. use Illuminate\Validation\Rule;
  12. class CommissionController extends AgentApiController
  13. {
  14. public function records(Request $request, AgentReportService $reports)
  15. {
  16. return $this->execute(function () use ($request, $reports) {
  17. $data = $request->validate([
  18. 'page' => ['nullable', 'integer', 'min:1'], 'limit' => ['nullable', 'integer', 'min:1', 'max:100'],
  19. 'order_no' => ['nullable', 'string', 'max:48'], 'username' => ['nullable', 'string', 'max:64'],
  20. 'platform' => ['nullable', 'string', 'max:32'],
  21. 'flow_status' => ['nullable', 'in:pending,credited'],
  22. 'profit_status' => ['nullable', 'in:pending,credited'],
  23. 'settlement_date' => ['nullable', 'date_format:Y-m-d'],
  24. 'start_date' => ['nullable', 'date_format:Y-m-d'], 'end_date' => ['nullable', 'date_format:Y-m-d', 'after_or_equal:start_date'],
  25. 'include_children' => ['nullable', 'boolean'],
  26. ]);
  27. $page = max(1, (int) ($data['page'] ?? 1));
  28. $limit = min(100, max(1, (int) ($data['limit'] ?? 20)));
  29. $agent = $this->currentAgent();
  30. $ids = $request->boolean('include_children') ? $reports->visibleAgentIds($agent) : [(int) $agent->id];
  31. $query = AgentRebateRecord::query()->with('agent:id,username')->whereIn('agent_id', $ids);
  32. foreach (['order_no', 'platform', 'flow_status', 'profit_status'] as $field) {
  33. if (!empty($data[$field])) $query->where($field, $data[$field]);
  34. }
  35. if (!empty($data['username'])) {
  36. $query->whereHas('agent', fn($query) => $query->where('username', 'like', '%' . $data['username'] . '%'));
  37. }
  38. if (!empty($data['settlement_date'])) $query->where('settlement_date', $data['settlement_date']);
  39. if (!empty($data['start_date'])) $query->where('created_at', '>=', $data['start_date'] . ' 00:00:00');
  40. if (!empty($data['end_date'])) $query->where('created_at', '<=', $data['end_date'] . ' 23:59:59');
  41. $total = (clone $query)->count();
  42. $list = $query->orderByDesc('settlement_date')->orderByDesc('id')->forPage($page, $limit)->get();
  43. return compact('total', 'page', 'limit', 'list');
  44. });
  45. }
  46. public function flowProfiles(Request $request, AgentFlowCommissionProfileService $service)
  47. {
  48. return $this->execute(function () use ($request, $service) {
  49. return $this->listProfiles($request, $service);
  50. });
  51. }
  52. public function saveFlowCommissionProfile(Request $request, AgentFlowCommissionProfileService $service)
  53. {
  54. return $this->execute(function () use ($request, $service) {
  55. $owner = $this->requireLevelOne();
  56. $data = $request->validate($this->profileRules('agent_flow_commission_profiles', (int) $owner->id));
  57. return $service->save($data, null, $owner);
  58. });
  59. }
  60. public function deleteFlowCommissionProfile(Request $request, AgentFlowCommissionProfileService $service)
  61. {
  62. return $this->execute(function () use ($request, $service) {
  63. $owner = $this->requireLevelOne();
  64. $data = $request->validate(['id' => ['required', 'integer', 'exists:agent_flow_commission_profiles,id']]);
  65. $service->delete((int) $data['id'], null, $owner);
  66. return [];
  67. });
  68. }
  69. public function profitProfiles(Request $request, AgentProfitCommissionProfileService $service)
  70. {
  71. return $this->execute(function () use ($request, $service) {
  72. return $this->listProfiles($request, $service);
  73. });
  74. }
  75. public function saveProfitCommissionProfile(Request $request, AgentProfitCommissionProfileService $service)
  76. {
  77. return $this->execute(function () use ($request, $service) {
  78. $owner = $this->requireLevelOne();
  79. $data = $request->validate($this->profileRules('agent_profit_commission_profiles', (int) $owner->id));
  80. return $service->save($data, null, $owner);
  81. });
  82. }
  83. public function deleteProfitCommissionProfile(Request $request, AgentProfitCommissionProfileService $service)
  84. {
  85. return $this->execute(function () use ($request, $service) {
  86. $owner = $this->requireLevelOne();
  87. $data = $request->validate(['id' => ['required', 'integer', 'exists:agent_profit_commission_profiles,id']]);
  88. $service->delete((int) $data['id'], null, $owner);
  89. return [];
  90. });
  91. }
  92. private function listProfiles(
  93. Request $request,
  94. AgentFlowCommissionProfileService|AgentProfitCommissionProfileService $service
  95. ): array {
  96. $data = $request->validate([
  97. 'page' => ['nullable', 'integer', 'min:1'],
  98. 'limit' => ['nullable', 'integer', 'min:1', 'max:100'],
  99. 'name' => ['nullable', 'string', 'max:128'],
  100. 'selectable' => ['nullable', 'boolean'],
  101. ]);
  102. $agent = $this->currentAgent();
  103. if ((int) $agent->level !== Agent::LEVEL_ONE) {
  104. $page = max(1, (int) ($data['page'] ?? 1));
  105. $limit = min(100, max(1, (int) ($data['limit'] ?? 20)));
  106. return ['total' => 0, 'page' => $page, 'limit' => $limit, 'list' => []];
  107. }
  108. if ($request->boolean('selectable')) {
  109. return $service->paginateSelectable($agent, $data);
  110. }
  111. return $service->paginate($data, $agent);
  112. }
  113. private function requireLevelOne(): Agent
  114. {
  115. $agent = $this->currentAgent();
  116. if ((int) $agent->level !== Agent::LEVEL_ONE) {
  117. throw new \RuntimeException('只有一级代理可以配置下级佣金方案');
  118. }
  119. return $agent;
  120. }
  121. private function profileRules(string $table, int $ownerId): array
  122. {
  123. $id = (int) request()->input('id', 0);
  124. return [
  125. 'id' => ['nullable', 'integer', 'exists:' . $table . ',id'],
  126. 'name' => [
  127. 'required', 'string', 'max:128',
  128. Rule::unique($table, 'name')->where('owner_agent_id', $ownerId)->ignore($id),
  129. ],
  130. 'live_rate' => ['required', 'numeric', 'between:0,100', new DecimalNumber(3, 4)],
  131. 'slot_rate' => ['required', 'numeric', 'between:0,100', new DecimalNumber(3, 4)],
  132. 'lottery_rate' => ['required', 'numeric', 'between:0,100', new DecimalNumber(3, 4)],
  133. 'sport_rate' => ['required', 'numeric', 'between:0,100', new DecimalNumber(3, 4)],
  134. 'esports_rate' => ['required', 'numeric', 'between:0,100', new DecimalNumber(3, 4)],
  135. 'fishing_rate' => ['required', 'numeric', 'between:0,100', new DecimalNumber(3, 4)],
  136. 'chess_rate' => ['required', 'numeric', 'between:0,100', new DecimalNumber(3, 4)],
  137. 'is_default' => ['required', 'boolean'],
  138. ];
  139. }
  140. }