UserAchievementService.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. <?php
  2. namespace common\services\mall\user;
  3. use common\enums\OrderStatusEnum;
  4. use common\enums\RefundStatusEnum;
  5. use common\enums\RefundTypeEnum;
  6. use common\enums\StatusEnum;
  7. use common\helpers\DateHelper;
  8. use common\models\common\MallSetting;
  9. use common\models\order\Order;
  10. use common\models\order\OrderAchievementGoods;
  11. use common\models\order\OrderDetail;
  12. use common\models\order\OrderRefund;
  13. use common\models\statistics\UserAchievementStatistics;
  14. use common\models\statistics\UserAchievementStatisticsTotal;
  15. use common\models\statistics\UserTeamAchievementStatistics;
  16. use common\models\statistics\UserTeamDateAchievementStatistics;
  17. use common\models\user\User;
  18. use common\models\user\UserLevel;
  19. use common\models\user\UserPartitionRelationship;
  20. class UserAchievementService
  21. {
  22. public function getListByUserId(array $params)
  23. {
  24. if (!$params['user_id']) {
  25. return [];
  26. }
  27. $direct = UserPartitionRelationship::getChildIdArr($params['user_id'], 1);// 直推
  28. $indirect = UserPartitionRelationship::getChildIdArr($params['user_id'], 2);// 间推
  29. $groupUserIds = array_merge($direct, $indirect, [$params['user_id']]);// 包含自己
  30. $userBaseWhere = [
  31. ['=', 'status', StatusEnum::ENABLED],
  32. ['=', 'mall_id', $params['mall_id']],
  33. ['id' => $groupUserIds],
  34. ];
  35. $date = $params['date'] ?? [];
  36. empty($date) && $with = [
  37. 'userAchievementStatisticsTotal' => function ($query) {
  38. $query->select('user_id, user_order_num, pay_selling_price, user_goods_price_total');
  39. }
  40. ];
  41. $list = User::listPage([
  42. 'with' => $with ?? [],
  43. 'select' => 'id, nickname, avatar_url, mobile, level',
  44. 'where' => $userBaseWhere,
  45. 'limit' => $params['limit'] ?? 10
  46. ]);
  47. if ($list === false) {
  48. return false;
  49. }
  50. if (empty($list['list'])) {
  51. return $list;
  52. }
  53. $userStatistics = [];
  54. // 按日期查
  55. $where = [
  56. ['user_id' => $groupUserIds],
  57. ];
  58. if ($date) {
  59. $date = array_map(function ($val) {
  60. return is_numeric($val) ? $val : date('Ymd', strtotime($val));
  61. }, $date);
  62. $where[] = ['between', 'date', reset($date), end($date)];
  63. }
  64. $userStatisticsFind = UserAchievementStatistics::find();
  65. UserAchievementStatistics::paramPack([
  66. 'select' => 'user_id, SUM(user_order_num) total_order_num, SUM(user_goods_price_total) total_achievement, SUM(pay_selling_price) total_product_amount, mall_id',
  67. 'where' => $where,
  68. 'group' => 'user_id',
  69. 'index' => 'user_id'
  70. ], $userStatisticsFind);
  71. $userStatistics = $userStatisticsFind->asArray()->all();
  72. array_walk($list['list'], function (&$item) use ($userStatistics) {
  73. $item['total_order_num'] = $userStatistics[$item['id']]['total_order_num'] ?? ($item['userStatisticsTotal']['user_order_num'] ?? 0);
  74. $item['total_product_amount'] = $userStatistics[$item['id']]['total_product_amount'] ?? ($item['userStatisticsTotal']['pay_selling_price'] ?? 0);
  75. $item['total_achievement'] = $userStatistics[$item['id']]['total_achievement'] ?? ($item['userStatisticsTotal']['user_goods_price_total'] ?? 0);
  76. });
  77. // 不包含自己的(群组订单数、群组订单金额、群组订单业绩)
  78. $list['other_data'] = $this->getGroupLeaderStatisticsTotal($params['user_id'], $date);
  79. $thisMonth = DateHelper::thisMonth();
  80. $list['other_data']['default_date_filter'] = [
  81. date('Y-m-d', $thisMonth['start']),
  82. date('Y-m-d', $thisMonth['end'])
  83. ];
  84. return $list;
  85. }
  86. public function getGroupLeaderStatisticsTotal(int $userId, array $date): array
  87. {
  88. if ($date) {
  89. $date = array_map(function ($val) {
  90. return is_numeric($val) ? $val : date('Ymd', strtotime($val));
  91. }, $date);
  92. // 群组数据
  93. $userTeamDateStatisticsSelect = 'SUM(team_order_num) team_order_num, ' .
  94. 'SUM(team_pay_selling_price) team_pay_selling_price, ' .
  95. 'SUM(team_goods_price_total) team_goods_price_total';
  96. $groupDataStatisticsTotalFind = UserTeamDateAchievementStatistics::setTableNumAndReturnSelf($userId, false)->asArray();
  97. UserTeamDateAchievementStatistics::paramPack([
  98. 'select' => $userTeamDateStatisticsSelect,
  99. 'where' => [
  100. ['user_id' => $userId],
  101. ['between', 'date', reset($date), end($date)]
  102. ],
  103. 'group' => 'user_id',
  104. ], $groupDataStatisticsTotalFind);
  105. $userTeamStatisticsData = $groupDataStatisticsTotalFind->one();
  106. // 自己的数据
  107. $userStatisticsSelect = 'SUM(user_order_num) user_order_num, ' .
  108. 'SUM(pay_selling_price) pay_selling_price, ' .
  109. 'SUM(user_goods_price_total) user_goods_price_total';
  110. $userStatisticsDataFind = UserAchievementStatistics::find()->asArray();
  111. UserAchievementStatistics::paramPack([
  112. 'select' => $userStatisticsSelect,
  113. 'where' => [
  114. ['user_id' => $userId],
  115. ['between', 'date', reset($date), end($date)]
  116. ],
  117. 'group' => 'user_id',
  118. ], $userStatisticsDataFind);
  119. $userStatisticsData = $userStatisticsDataFind->one();
  120. } else {
  121. // 群组数据
  122. $userTeamStatisticsData = UserTeamAchievementStatistics::getOne(
  123. [['user_id' => $userId]],
  124. true,
  125. [],
  126. false,
  127. 'team_pay_selling_price, team_goods_price_total, team_order_num'
  128. );
  129. // 自己的数据
  130. $userStatisticsData = UserAchievementStatisticsTotal::getOne(
  131. [['user_id' => $userId]],
  132. true,
  133. [],
  134. false,
  135. 'user_order_num, pay_selling_price, user_goods_price_total'
  136. );
  137. }
  138. return [
  139. 'child_total_order_num' => bcadd(
  140. ($userTeamStatisticsData['team_order_num'] ?? 0),
  141. ($userStatisticsData['user_order_num'] ?? 0),
  142. 2
  143. ),
  144. 'child_total_product_amount' => bcadd(
  145. ($userTeamStatisticsData['team_pay_selling_price'] ?? 0),
  146. ($userStatisticsData['pay_selling_price'] ?? 0),
  147. 2
  148. ),
  149. 'child_total_achievement' => bcadd(
  150. ($userTeamStatisticsData['team_goods_price_total'] ?? 0),
  151. ($userStatisticsData['user_goods_price_total'] ?? 0),
  152. 2
  153. ),
  154. ];
  155. }
  156. public function getGroupDetail(array $params = []): array
  157. {
  158. $date = $params['date'] ?? [];
  159. $limit = $params['limit'] ?? 10;
  160. $direct = UserPartitionRelationship::getChildIdArr($params['user_id'], 1);// 直推
  161. $indirect = UserPartitionRelationship::getChildIdArr($params['user_id'], 2);// 间推
  162. $getChildIdArr = array_merge($direct, $indirect, [$params['user_id']]);// 包含自己
  163. // 只查询业绩订单
  164. $achievementOrderIdsColumn = OrderAchievementGoods::find()
  165. ->where(['user_id' => $getChildIdArr])
  166. ->select('order_id')
  167. ->column();
  168. $where = [
  169. [
  170. 'id' => $achievementOrderIdsColumn,
  171. 'pay_status' => OrderStatusEnum::PAY,
  172. 'status' => StatusEnum::ENABLED,
  173. ],
  174. ];
  175. if ($date) {
  176. $date[1] .= ' 23:59:59';
  177. $date2Timestamp = array_map(function ($val) {
  178. return strtotime($val);
  179. }, $date);
  180. $where[] = ['between', 'created_at', reset($date2Timestamp), end($date2Timestamp)];
  181. }
  182. // 查询出因换货导致总订单表的order_status = OrderStatusEnum::REPEAL 的订单
  183. $repealOrderFind = Order::find();
  184. Order::paramPack(['where' => $where, 'select' => 'id'], $repealOrderFind);
  185. $repealOrderIds = $repealOrderFind->column();
  186. $exchangeOrderIds = OrderRefund::find()
  187. ->where(['order_id' => $repealOrderIds, 'refund_status' => RefundStatusEnum::FINISH, 'type' => RefundTypeEnum::EXCHANGE_GOODS])
  188. ->select('order_id')
  189. ->column();
  190. // 不显示已经关闭的订单 或者 已经关闭的订单但是售后是换货导致的订单关闭
  191. if ($exchangeOrderIds) {
  192. $where[] = ['or', ['!=', 'order_status', OrderStatusEnum::REPEAL], ['in', 'id', $exchangeOrderIds]];
  193. }else { // 正常订单的条件
  194. $where[] = ['!=', 'order_status', OrderStatusEnum::REPEAL];
  195. }
  196. $orderList = Order::listPage([
  197. 'where' => $where,
  198. 'select' => 'id, user_id, goods_price, order_no, shipping_money, created_at, pay_time, original_goods_price',
  199. 'with' => [
  200. 'user' => function ($query) {
  201. $query->select('id, mobile, level, nickname, avatar_url');
  202. }
  203. ],
  204. 'limit' => $limit,
  205. 'order' => 'id desc'
  206. ]);
  207. // 查出订单的业绩商品
  208. $achievementOrderIds = array_column($orderList['list'], 'id');
  209. $achievementOrderDetailsIds = OrderAchievementGoods::find()
  210. ->where(['order_id' => $achievementOrderIds])
  211. ->select('order_details_ids')
  212. ->column();
  213. array_walk($achievementOrderDetailsIds, function (&$item) {
  214. $item = json_decode($item, true);
  215. $item = is_array($item) ? $item : [];
  216. });
  217. $mergedDetailsIds = [];
  218. if (!empty($achievementOrderDetailsIds)) {
  219. $mergedDetailsIds = array_merge(...array_filter($achievementOrderDetailsIds));
  220. }
  221. $achievementOrderDetail = OrderDetail::find()
  222. ->where(['id' => $mergedDetailsIds]) // 使用处理后的数组
  223. ->select('id, order_id, is_feedback, goods_price, original_goods_price')
  224. ->asArray()
  225. ->all();
  226. $orderList['list'] = array_column($orderList['list'], null, 'id');
  227. foreach ($achievementOrderDetail as $orderDetail) {
  228. if (isset($orderList['list'][$orderDetail['order_id']])) {
  229. $orderList['list'][$orderDetail['order_id']]['detail'][] = $orderDetail;
  230. }
  231. }
  232. $orderList['list'] = array_values($orderList['list']);
  233. // 售后成功的商品
  234. $refundSuccessOrderDetailIds = [];
  235. foreach ($orderList['list'] as &$item) {
  236. if (empty($item['detail'])) {
  237. continue;
  238. }
  239. $item['goods_price'] = number_format(array_sum(array_column($item['detail'], 'goods_price')), 2);
  240. $item['original_goods_price'] = number_format(array_sum(array_column($item['detail'], 'original_goods_price')), 2);
  241. foreach ($item['detail'] as $detail) {
  242. // 售后成功的子订单
  243. if ($detail['is_feedback'] == OrderStatusEnum::FEEDBACKED) {
  244. $refundSuccessOrderDetailIds[] = $detail['id'];
  245. }
  246. }
  247. }
  248. // 如果存在售后成功的商品,需要将主订单的金额减少(换货不需要减)
  249. if ($refundSuccessOrderDetailIds) {
  250. $refundSuccessOrderDetailIds = OrderRefund::find()
  251. ->where(['order_detail_id' => $refundSuccessOrderDetailIds, 'refund_status' => RefundStatusEnum::FINISH])
  252. ->andWhere(['!=', 'type', RefundTypeEnum::EXCHANGE_GOODS])
  253. ->select('order_detail_id')
  254. ->column();
  255. if ($refundSuccessOrderDetailIds) {
  256. foreach ($orderList['list'] as &$item) {
  257. foreach ($item['detail'] as $detail) {
  258. // 在售后成功数组里,则减少
  259. if (in_array($detail['id'], $refundSuccessOrderDetailIds)) {
  260. $item['goods_price'] = bcsub($item['goods_price'], $detail['goods_price'], 2);
  261. $item['original_goods_price'] = bcsub($item['original_goods_price'], $detail['original_goods_price'], 2);
  262. }
  263. }
  264. }
  265. }
  266. }
  267. return [
  268. 'statistics_data' => $this->getGroupLeaderStatisticsTotal($params['user_id'], $date),
  269. 'order_list' => $orderList
  270. ];
  271. }
  272. }