RegionalCommission.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. <?php
  2. namespace app\common\Service\commission;
  3. use app\common\model\commission\Agent as AgentModel;
  4. use app\common\model\commission\Reward as RewardModel;
  5. use app\common\model\commission\Log as LogModel;
  6. use app\common\model\User as UserModel;
  7. use app\common\Enum\AgentType;
  8. use think\Db;
  9. /**
  10. * 区域代理商分佣服务
  11. */
  12. class RegionalCommission
  13. {
  14. protected $commissionOrder;
  15. protected $orderUser;
  16. protected $goods;
  17. protected $config;
  18. public function __construct($commissionOrder, $goods, $config)
  19. {
  20. $this->commissionOrder = $commissionOrder;
  21. $this->goods = $goods;
  22. $this->config = $config;
  23. // 获取下单用户信息
  24. $this->orderUser = UserModel::where('id', $commissionOrder->buyer_id)->find();
  25. }
  26. /**
  27. * 执行区域代理商分佣
  28. */
  29. public function executeRegionalCommission()
  30. {
  31. if (!$this->orderUser) {
  32. return false;
  33. }
  34. // 获取下单用户的地区信息
  35. $userArea = $this->getUserArea();
  36. if (!$userArea) {
  37. return false;
  38. }
  39. // 查找管辖该区域的区域代理商
  40. $regionalAgents = $this->getRegionalAgents($userArea);
  41. foreach ($regionalAgents as $agent) {
  42. $this->processRegionalAgent($agent, $userArea);
  43. }
  44. return true;
  45. }
  46. /**
  47. * 获取用户地区信息
  48. */
  49. protected function getUserArea()
  50. {
  51. // 假设用户表有地区字段,或者从用户地址中获取
  52. // 这里需要根据实际业务逻辑调整
  53. return [
  54. 'province_id' => $this->orderUser->province_id ?? 0,
  55. 'city_id' => $this->orderUser->city_id ?? 0,
  56. 'district_id' => $this->orderUser->district_id ?? 0
  57. ];
  58. }
  59. /**
  60. * 获取管辖该区域的区域代理商
  61. */
  62. protected function getRegionalAgents($userArea)
  63. {
  64. $agents = [];
  65. // 查找区域代理商:按管辖范围从小到大查找(区 -> 市 -> 省)
  66. // 1. 查找区域级代理商(district类型)
  67. if ($userArea['district_id'] > 0) {
  68. $districtAgents = AgentModel::where('agent_type', AgentType::DISTRICT)
  69. ->where('manage_district_id', $userArea['district_id'])
  70. ->where('status', AgentModel::AGENT_STATUS_NORMAL)
  71. ->with(['identity'])
  72. ->select();
  73. $agents = array_merge($agents, $districtAgents->toArray());
  74. }
  75. // 2. 查找市级代理商(city类型),如果还没有区级代理商
  76. if (empty($agents) && $userArea['city_id'] > 0) {
  77. $cityAgents = AgentModel::where('agent_type', AgentType::CITY)
  78. ->where('manage_city_id', $userArea['city_id'])
  79. ->where('status', AgentModel::AGENT_STATUS_NORMAL)
  80. ->with(['identity'])
  81. ->select();
  82. $agents = array_merge($agents, $cityAgents->toArray());
  83. }
  84. // 3. 查找省级代理商(province类型),如果还没有市级代理商
  85. if (empty($agents) && $userArea['province_id'] > 0) {
  86. $provinceAgents = AgentModel::where('agent_type', AgentType::PROVINCE)
  87. ->where('manage_province_id', $userArea['province_id'])
  88. ->where('status', AgentModel::AGENT_STATUS_NORMAL)
  89. ->with(['identity'])
  90. ->select();
  91. $agents = array_merge($agents, $provinceAgents->toArray());
  92. }
  93. return $agents;
  94. }
  95. /**
  96. * 处理单个区域代理商分佣
  97. */
  98. protected function processRegionalAgent($agent, $userArea)
  99. {
  100. // 防止重复分佣
  101. $existingReward = RewardModel::where([
  102. 'commission_order_id' => $this->commissionOrder->id,
  103. 'agent_id' => $agent['user_id'],
  104. 'reward_type' => 'regional'
  105. ])->find();
  106. if ($existingReward) {
  107. return false;
  108. }
  109. // 获取区域分佣比例
  110. $commissionRate = $agent['identity']['regional_commission_rate'] ?? 0;
  111. if ($commissionRate <= 0) {
  112. return false;
  113. }
  114. // 计算佣金
  115. $commission = round($this->commissionOrder->amount * $commissionRate / 100, 2);
  116. if ($commission <= 0) {
  117. return false;
  118. }
  119. // 创建区域分佣记录
  120. $rewardData = [
  121. 'order_id' => $this->commissionOrder->order_id,
  122. 'order_item_id' => $this->commissionOrder->order_item_id,
  123. 'buyer_id' => $this->commissionOrder->buyer_id,
  124. 'commission_order_id' => $this->commissionOrder->id,
  125. 'agent_id' => $agent['user_id'],
  126. 'type' => 'commission',
  127. 'reward_type' => 'regional', // 区域分佣标识
  128. 'commission' => $commission,
  129. 'original_commission' => $commission,
  130. 'commission_level' => 0, // 区域分佣不按层级
  131. 'agent_level' => $agent['level'],
  132. 'commission_rules' => json_encode([
  133. 'type' => 'regional',
  134. 'rate' => $commissionRate,
  135. 'area' => $userArea,
  136. 'agent_area' => [
  137. 'province' => $agent['manage_province_id'],
  138. 'city' => $agent['manage_city_id'],
  139. 'district' => $agent['manage_district_id']
  140. ]
  141. ]),
  142. 'status' => 0 // 待入账
  143. ];
  144. $reward = RewardModel::create($rewardData);
  145. // 记录日志
  146. LogModel::add($agent['user_id'], 'reward', [
  147. 'type' => 'regional_commission',
  148. 'reward' => $reward,
  149. 'area' => $userArea
  150. ], $this->orderUser);
  151. return $reward;
  152. }
  153. /**
  154. * 检查区域冲突 - 确保同一区域只有一个代理商获得分佣
  155. */
  156. protected function checkAreaConflict($agents, $userArea)
  157. {
  158. // 按管辖范围精确度排序:区 > 市 > 省
  159. usort($agents, function($a, $b) {
  160. $aScore = 0;
  161. $bScore = 0;
  162. if ($a['manage_district_id'] > 0) $aScore = 3;
  163. elseif ($a['manage_city_id'] > 0) $aScore = 2;
  164. elseif ($a['manage_province_id'] > 0) $aScore = 1;
  165. if ($b['manage_district_id'] > 0) $bScore = 3;
  166. elseif ($b['manage_city_id'] > 0) $bScore = 2;
  167. elseif ($b['manage_province_id'] > 0) $bScore = 1;
  168. return $bScore - $aScore; // 降序,精确度高的优先
  169. });
  170. // 只返回最精确的代理商
  171. return array_slice($agents, 0, 1);
  172. }
  173. }