AgentPlanApplicationService.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. <?php
  2. namespace App\Services\Agent;
  3. use App\Models\Agent\Agent;
  4. use App\Models\Agent\AgentPlanApplication;
  5. use App\Models\Agent\AgentProfitCommissionProfile;
  6. use App\Models\Agent\AgentSetting;
  7. use Illuminate\Support\Facades\DB;
  8. /** 合营代理申请分成方案(方案由总后台配置),总后台审核通过后立即生效。 */
  9. class AgentPlanApplicationService
  10. {
  11. public function __construct(
  12. private AgentProfitCommissionAssignmentService $assignments,
  13. private AgentWalletService $wallets
  14. ) {
  15. }
  16. public function plans(Agent $agent): array
  17. {
  18. $agent->loadMissing('profitCommissionProfile');
  19. return [
  20. 'current_profile' => $agent->profitCommissionProfile,
  21. 'profit_active' => (int) $agent->profit_active,
  22. 'margin_stop_percent' => (string) AgentSetting::current()->margin_stop_percent,
  23. 'pending_application' => AgentPlanApplication::query()->where('agent_id', $agent->id)
  24. ->where('status', AgentPlanApplication::STATUS_PENDING)->latest('id')->first(),
  25. 'list' => AgentProfitCommissionProfile::query()->whereNull('owner_agent_id')
  26. ->orderBy('margin_amount')->orderBy('id')->get(),
  27. ];
  28. }
  29. public function apply(Agent $agent, int $profileId, string $remark = ''): AgentPlanApplication
  30. {
  31. return DB::transaction(function () use ($agent, $profileId, $remark) {
  32. $agent = Agent::query()->lockForUpdate()->findOrFail($agent->id);
  33. if (!$agent->isJoint()) throw new \RuntimeException('只有合营代理可以申请分成方案');
  34. $profile = AgentProfitCommissionProfile::query()->whereNull('owner_agent_id')->findOrFail($profileId);
  35. if ((int) $agent->profit_commission_profile_id === (int) $profile->id) throw new \RuntimeException('已在使用该方案');
  36. if (AgentPlanApplication::query()->where('agent_id', $agent->id)->where('status', AgentPlanApplication::STATUS_PENDING)->exists()) {
  37. throw new \RuntimeException('已有待审核的方案申请');
  38. }
  39. return AgentPlanApplication::query()->create([
  40. 'agent_id' => $agent->id, 'profile_id' => $profile->id, 'profile_name' => $profile->name,
  41. 'status' => AgentPlanApplication::STATUS_PENDING, 'remark' => trim($remark),
  42. ]);
  43. });
  44. }
  45. public function paginate(array $params, ?Agent $agent = null): array
  46. {
  47. $page = max(1, (int) ($params['page'] ?? 1));
  48. $limit = min(100, max(1, (int) ($params['limit'] ?? 20)));
  49. $query = AgentPlanApplication::query()->with(['agent:id,username,real_name,balance,margin_amount', 'profile']);
  50. if ($agent) $query->where('agent_id', $agent->id);
  51. if (!empty($params['agent_id'])) $query->where('agent_id', (int) $params['agent_id']);
  52. if (!empty($params['status'])) $query->where('status', $params['status']);
  53. if (!empty($params['username'])) {
  54. $query->whereHas('agent', fn ($q) => $q->where('username', 'like', '%' . $params['username'] . '%'));
  55. }
  56. $total = (clone $query)->count();
  57. $list = $query->orderByDesc('id')->forPage($page, $limit)->get();
  58. return compact('total', 'page', 'limit', 'list');
  59. }
  60. public function audit(int $id, string $status, int $adminId, string $reason = ''): AgentPlanApplication
  61. {
  62. return DB::transaction(function () use ($id, $status, $adminId, $reason) {
  63. $application = AgentPlanApplication::query()->lockForUpdate()->findOrFail($id);
  64. if ($application->status !== AgentPlanApplication::STATUS_PENDING) throw new \RuntimeException('申请已审核');
  65. $agent = Agent::query()->lockForUpdate()->findOrFail($application->agent_id);
  66. if ($status === AgentPlanApplication::STATUS_APPROVED) {
  67. $profile = AgentProfitCommissionProfile::query()->whereNull('owner_agent_id')->find($application->profile_id);
  68. if (!$profile) throw new \RuntimeException('方案已删除,请驳回');
  69. if (!$agent->isJoint()) throw new \RuntimeException('只有合营代理可以使用分成方案');
  70. $agent->profit_commission_profile_id = $profile->id;
  71. $agent->save();
  72. $this->assignments->assign($agent, $profile, $adminId);
  73. $this->wallets->evaluateActivation($agent, true);
  74. } else {
  75. $reason = trim($reason);
  76. if ($reason === '') throw new \InvalidArgumentException('请填写驳回原因');
  77. $application->reject_reason = $reason;
  78. }
  79. $application->status = $status;
  80. $application->reviewed_by = $adminId;
  81. $application->reviewed_at = now();
  82. $application->save();
  83. return $application->fresh(['agent:id,username,profit_active', 'profile']);
  84. });
  85. }
  86. }