AgentProfitCommissionProfileService.php 5.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. <?php
  2. namespace App\Services\Agent;
  3. use App\Models\Agent\Agent;
  4. use App\Models\Agent\AgentProfitCommissionProfile;
  5. use Illuminate\Support\Facades\DB;
  6. class AgentProfitCommissionProfileService
  7. {
  8. public function __construct(private AgentProfitCommissionAssignmentService $assignments)
  9. {
  10. }
  11. public function paginate(array $params): array
  12. {
  13. $page = max(1, (int) ($params['page'] ?? 1));
  14. $limit = min(100, max(1, (int) ($params['limit'] ?? 20)));
  15. $query = AgentProfitCommissionProfile::query();
  16. if (!empty($params['name'])) $query->where('name', 'like', '%' . $params['name'] . '%');
  17. $total = (clone $query)->count();
  18. $list = $query->orderByDesc('is_default')->orderByDesc('id')->forPage($page, $limit)->get();
  19. return compact('total', 'page', 'limit', 'list');
  20. }
  21. public function save(array $data, ?int $adminId = null): AgentProfitCommissionProfile
  22. {
  23. return DB::transaction(function () use ($data, $adminId) {
  24. $profiles = AgentProfitCommissionProfile::query()->orderBy('id')->lockForUpdate()->get(['id', 'is_default']);
  25. $profile = empty($data['id'])
  26. ? new AgentProfitCommissionProfile()
  27. : AgentProfitCommissionProfile::query()->lockForUpdate()->findOrFail($data['id']);
  28. $oldDefaultId = $profiles->firstWhere('is_default', 1)?->id;
  29. $isDefault = !empty($data['is_default']);
  30. if ($profile->exists && (int) $oldDefaultId === (int) $profile->id && !$isDefault) {
  31. throw new \RuntimeException('默认比例必须始终保留一条,请先将其他比例设为默认');
  32. }
  33. $name = trim((string) $data['name']);
  34. if ($name === '') throw new \InvalidArgumentException('盈亏比例名称不能为空');
  35. $duplicate = AgentProfitCommissionProfile::query()->where('name', $name)
  36. ->when($profile->exists, fn($query) => $query->where('id', '<>', $profile->id))->exists();
  37. if ($duplicate) throw new \InvalidArgumentException('盈亏比例名称已存在');
  38. $profile->name = $name;
  39. foreach (AgentProfitCommissionProfile::RATE_FIELDS as $field) $profile->{$field} = (string) $data[$field];
  40. $willBeDefault = $isDefault || (!$profile->exists && !$oldDefaultId);
  41. $profile->is_default = $willBeDefault ? 1 : 0;
  42. $snapshotChanged = !$profile->exists
  43. || $profile->isDirty(AgentProfitCommissionProfile::RATE_FIELDS);
  44. $affectedAgentIds = [];
  45. if ($snapshotChanged && $profile->exists) {
  46. $affectedAgentIds = Agent::query()->where('profit_commission_profile_id', $profile->id)
  47. ->pluck('id')->map(fn($id) => (int) $id)->all();
  48. }
  49. if ($willBeDefault) {
  50. $defaultAgentIds = Agent::query()->where(function ($query) use ($oldDefaultId, $profile) {
  51. $query->whereNull('profit_commission_profile_id');
  52. if ($oldDefaultId && (int) $oldDefaultId !== (int) $profile->id) {
  53. $query->orWhere('profit_commission_profile_id', $oldDefaultId);
  54. }
  55. })->pluck('id')->map(fn($id) => (int) $id)->all();
  56. $affectedAgentIds = array_values(array_unique(array_merge($affectedAgentIds, $defaultAgentIds)));
  57. }
  58. $profile->save();
  59. if ($willBeDefault) {
  60. AgentProfitCommissionProfile::query()->where('id', '<>', $profile->id)->update(['is_default' => 0]);
  61. Agent::query()->where(function ($query) use ($oldDefaultId) {
  62. $query->whereNull('profit_commission_profile_id');
  63. if ($oldDefaultId) $query->orWhere('profit_commission_profile_id', $oldDefaultId);
  64. })->update(['profit_commission_profile_id' => $profile->id]);
  65. }
  66. $this->assignments->assignMany($affectedAgentIds, $profile, now()->toDateString(), $adminId);
  67. return $profile->fresh();
  68. });
  69. }
  70. public function delete(int $id, ?int $adminId = null): void
  71. {
  72. DB::transaction(function () use ($id, $adminId) {
  73. $profile = AgentProfitCommissionProfile::query()->lockForUpdate()->findOrFail($id);
  74. if ((int) $profile->is_default === 1) throw new \RuntimeException('默认比例不能删除');
  75. $default = AgentProfitCommissionProfile::query()->where('is_default', 1)->lockForUpdate()->first();
  76. if (!$default) throw new \RuntimeException('缺少默认比例,不能删除');
  77. $agentIds = Agent::query()->where('profit_commission_profile_id', $profile->id)
  78. ->pluck('id')->map(fn($agentId) => (int) $agentId)->all();
  79. $this->assignments->assignMany($agentIds, $default, now()->toDateString(), $adminId);
  80. Agent::query()->where('profit_commission_profile_id', $profile->id)
  81. ->update(['profit_commission_profile_id' => $default->id]);
  82. $profile->delete();
  83. });
  84. }
  85. }