SubAgentController.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. <?php
  2. namespace App\Http\Controllers\agent;
  3. use App\Http\Controllers\AgentApiController;
  4. use App\Models\Agent\Agent;
  5. use App\Services\Agent\AgentDomainService;
  6. use App\Services\Agent\AgentReportService;
  7. use App\Services\Agent\AgentService;
  8. use App\Services\Agent\AgentWalletService;
  9. use Illuminate\Http\Request;
  10. use App\Rules\DecimalNumber;
  11. class SubAgentController extends AgentApiController
  12. {
  13. public function index(Request $request, AgentReportService $reports, AgentDomainService $domains)
  14. {
  15. return $this->execute(function () use ($request, $reports, $domains) {
  16. $data = $request->validate([
  17. 'page' => ['nullable', 'integer', 'min:1'], 'limit' => ['nullable', 'integer', 'min:1', 'max:100'],
  18. 'username' => ['nullable', 'string', 'max:64'], 'status' => ['nullable', 'integer', 'in:0,1'],
  19. 'direct_only' => ['nullable', 'boolean'],
  20. ]);
  21. $root = $this->currentAgent();
  22. $page = max(1, (int) ($data['page'] ?? 1));
  23. $limit = min(100, max(1, (int) ($data['limit'] ?? 20)));
  24. $query = Agent::query()->with(['parent:id,username', 'flowCommissionProfile', 'profitCommissionProfile']);
  25. if ($request->boolean('direct_only')) {
  26. $query->where('parent_id', $root->id);
  27. } else {
  28. $query->whereIn('id', $reports->visibleAgentIds($root, false));
  29. }
  30. if (!empty($data['username'])) $query->where('username', 'like', '%' . $data['username'] . '%');
  31. if (isset($data['status'])) $query->where('status', $data['status']);
  32. $total = (clone $query)->count();
  33. $list = $query->orderByDesc('id')->forPage($page, $limit)->get()->map(function (Agent $agent) use ($domains) {
  34. return array_merge($agent->toArray(), $domains->format($agent));
  35. });
  36. return compact('total', 'page', 'limit', 'list');
  37. });
  38. }
  39. public function store(Request $request, AgentService $service)
  40. {
  41. return $this->execute(function () use ($request, $service) {
  42. $root = $this->currentAgent();
  43. $data = $request->validate([
  44. 'username' => ['required', 'string', 'min:4', 'max:64', 'alpha_dash', 'unique:agents,username'],
  45. 'password' => ['required', 'string', 'min:6', 'max:100'],
  46. 'withdraw_password' => ['nullable', 'string', 'min:6', 'max:100'],
  47. 'real_name' => ['nullable', 'string', 'max:128'],
  48. 'parent_id' => ['prohibited'],
  49. 'deposit_fee_rate' => ['nullable', 'numeric', 'between:0,100', new DecimalNumber(3, 4)],
  50. 'withdraw_fee_rate' => ['nullable', 'numeric', 'between:0,100', new DecimalNumber(3, 4)],
  51. 'flow_commission_rate' => ['prohibited'],
  52. 'profit_commission_rate' => ['prohibited'],
  53. 'flow_commission_profile_id' => ['required', 'integer', 'exists:agent_flow_commission_profiles,id'],
  54. 'profit_commission_profile_id' => ['nullable', 'integer', 'exists:agent_profit_commission_profiles,id'],
  55. 'status' => ['nullable', 'integer', 'in:0,1'],
  56. ]);
  57. return $service->create($data, null, $root);
  58. });
  59. }
  60. public function update(Request $request, AgentService $service)
  61. {
  62. return $this->execute(function () use ($request, $service) {
  63. $root = $this->currentAgent();
  64. $data = $request->validate([
  65. 'id' => ['required', 'integer', 'exists:agents,id'],
  66. 'password' => ['nullable', 'string', 'min:6', 'max:100'],
  67. 'withdraw_password' => ['nullable', 'string', 'min:6', 'max:100'],
  68. 'real_name' => ['nullable', 'string', 'max:128'],
  69. 'deposit_fee_rate' => ['nullable', 'numeric', 'between:0,100', new DecimalNumber(3, 4)],
  70. 'withdraw_fee_rate' => ['nullable', 'numeric', 'between:0,100', new DecimalNumber(3, 4)],
  71. 'flow_commission_rate' => ['prohibited'],
  72. 'profit_commission_rate' => ['prohibited'],
  73. 'flow_commission_profile_id' => ['nullable', 'integer', 'exists:agent_flow_commission_profiles,id'],
  74. 'profit_commission_profile_id' => ['nullable', 'integer', 'exists:agent_profit_commission_profiles,id'],
  75. 'status' => ['nullable', 'integer', 'in:0,1'],
  76. ]);
  77. if ((int) $data['id'] === (int) $root->id) throw new \RuntimeException('不能在下级代理接口修改自己');
  78. return $service->update(Agent::query()->findOrFail($data['id']), $data, $root);
  79. });
  80. }
  81. public function transfer(Request $request, AgentService $agents, AgentWalletService $wallets)
  82. {
  83. return $this->execute(function () use ($request, $agents, $wallets) {
  84. $data = $request->validate([
  85. 'agent_id' => ['required', 'integer', 'exists:agents,id'],
  86. 'direction' => ['required', 'in:credit,debit'],
  87. 'amount' => ['required', 'numeric', 'min:0.0001', new DecimalNumber()],
  88. 'remark' => ['required', 'string', 'max:500'],
  89. 'request_id' => ['required', 'string', 'max:64'],
  90. ]);
  91. $root = $this->currentAgent();
  92. if ((int) $data['agent_id'] === (int) $root->id) throw new \RuntimeException('不能给自己转账');
  93. $agents->assertVisible($root, (int) $data['agent_id']);
  94. $target = Agent::query()->findOrFail($data['agent_id']);
  95. if ($data['direction'] === 'credit' && (int) $target->status !== Agent::STATUS_ENABLED) {
  96. throw new \RuntimeException('不能给已禁用代理下发额度');
  97. }
  98. $from = $data['direction'] === 'credit' ? (int) $root->id : (int) $data['agent_id'];
  99. $to = $data['direction'] === 'credit' ? (int) $data['agent_id'] : (int) $root->id;
  100. return $wallets->transfer($from, $to, (string) $data['amount'], $data['remark'], 'agent:' . $root->id . ':' . $data['request_id'], (int) $root->id);
  101. });
  102. }
  103. }