OrderBehaviorLogsService.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. <?php
  2. namespace common\services\mall\order;
  3. use common\enums\OrderBehaviorLogsEnum;
  4. use common\enums\RabbitMqEnum;
  5. use common\enums\ShippingTypeEnum;
  6. use common\enums\StatusEnum;
  7. use common\events\order\OrderBehaviorLogsEvent;
  8. use common\helpers\ArrayHelper;
  9. use common\helpers\FormatHelper;
  10. use common\models\order\Order;
  11. use common\models\order\OrderBehaviorLogs;
  12. use common\models\order\OrderComments;
  13. use common\models\order\OrderDetail;
  14. use common\models\order\OrderExpress;
  15. use common\models\order\OrderRefund;
  16. use Exception;
  17. use InvalidArgumentException;
  18. use Yii;
  19. class OrderBehaviorLogsService
  20. {
  21. /**
  22. * 处理用户行为事件
  23. *
  24. * @param array $data
  25. *
  26. * @return void
  27. */
  28. public static function handleSync(array $data)
  29. {
  30. self::getInsertDataByParams($data);
  31. OrderBehaviorLogs::setData($data);
  32. }
  33. /**
  34. * 触发行为记录事件
  35. *
  36. * @param int $mallId
  37. * @param array $data
  38. *
  39. * @return void
  40. */
  41. public static function dispatchUserBehaviorLogsEvent(int $mallId, array $data)
  42. {
  43. if (empty($mallId) && empty($data['mall_id'])) {
  44. $data['method'] = __METHOD__;
  45. Yii::$app->custom->logs('mall_id不存在', compact('data'));
  46. return;
  47. }
  48. if (empty($data['behavior']) || !isset(OrderBehaviorLogsEnum::getMap()[$data['behavior']])) {
  49. $data['method'] = __METHOD__;
  50. Yii::$app->custom->logs('行为类型不存在', $data);
  51. return;
  52. }
  53. try {
  54. $data['ip'] = ArrayHelper::get_client_ip();
  55. $data['operation_time'] = time();
  56. $data['mall_id'] = !empty($data['mall_id']) ? $data['mall_id'] : $mallId;
  57. $event = new OrderBehaviorLogsEvent($data['mall_id']);
  58. Yii::$app->services->events->dispatch($event, $data, $event->listeners);
  59. } catch (Exception $e) {
  60. $data['method'] = __METHOD__;
  61. Yii::$app->custom->logs(FormatHelper::exception($e, '触发用户行为事件失败'), compact('data'));
  62. }
  63. }
  64. /**
  65. * 根据传入的数据,完善模型写入时所需的数据
  66. *
  67. * @param array $params
  68. *
  69. * @return void
  70. */
  71. protected static function getInsertDataByParams(array &$params)
  72. {
  73. empty($params['order_id']) && $params['order_id'] = $params['id'] ?? 0;
  74. switch ($params['behavior']) {
  75. case OrderBehaviorLogsEnum::OPERATOR_ORDER_PAID: // 订单支付
  76. // 如果空就是用户支付,不为空就是后台支付
  77. if (empty($params['operator_id'])) {
  78. $params['operator_id'] = Order::find()
  79. ->select('user_id')
  80. ->where(['id' => $params['order_id']])
  81. ->scalar();
  82. }
  83. break;
  84. case OrderBehaviorLogsEnum::OPERATOR_APPRAISE: // 评价
  85. $orderCommentsListParams = [
  86. 'where' => [['=', 'status', StatusEnum::ENABLED], ['=', 'order_id', $params['order_id']]],
  87. 'select' => 'content, order_detail_id'
  88. ];
  89. $orderCommentsLists = OrderComments::lists($orderCommentsListParams);
  90. $orderDetailsParams = [
  91. 'where' => [['=', 'status', StatusEnum::ENABLED], ['in', 'id', array_column($orderCommentsLists, 'order_detail_id')]],
  92. 'select' => 'id, goods_name',
  93. 'index' => 'id'
  94. ];
  95. $orderDetailsLists = OrderDetail::lists($orderDetailsParams);
  96. $params['desc'] = '';
  97. foreach ($orderCommentsLists as $commentItem) {
  98. $params['desc'] .= sprintf('商品:%s 评价:%s', $orderDetailsLists[$commentItem['order_detail_id']]['goods_name'] ?? '', $commentItem['content']);
  99. }
  100. break;
  101. case OrderBehaviorLogsEnum::OPERATOR_CANCEL_SHIPMENT: // 取消发货
  102. case OrderBehaviorLogsEnum::OPERATOR_SHIPMENTS: // 发货
  103. case OrderBehaviorLogsEnum::OPERATOR_MODIFY_LOGISTICS: // 修改物流
  104. $params['desc'] = '';
  105. // 查询发货信息
  106. $orderExpress = OrderExpress::find()
  107. ->where(['id' => $params['id']])
  108. ->select('order_id, order_detail_ids, buyer_id, operator_id, shipping_type')
  109. ->asArray()
  110. ->one();
  111. if (empty($orderExpress)) {
  112. break;
  113. }
  114. $orderDetailsIds = json_decode($orderExpress['order_detail_ids'], true);
  115. $orderDetailsList = OrderDetail::getOrderDetails([['id' => $orderDetailsIds]], [], true, 'goods_name, num');
  116. foreach ($orderDetailsList as $item) {
  117. $params['desc'] .= sprintf('商品:%s %d件;', $item['goods_name'], $item['num']);
  118. }
  119. $params['desc'] = trim($params['desc'], ';');
  120. $sendType = [0 => '无需物流', 1 => '快递'];
  121. if (isset($sendType[$orderExpress['shipping_type']])) {
  122. $params['desc'] .= '-' . $sendType[$orderExpress['shipping_type']];
  123. }
  124. $params['order_id'] = $orderExpress['order_id'];
  125. $params['extra_info']['order_detail_ids'] = $orderDetailsIds;
  126. $params['extra_info']['shipping_type'] = $orderExpress['shipping_type'];
  127. $params['extra_info']['order_express_id'] = $params['order_express_id'];
  128. if (!empty($params['shipping_change'])) {
  129. $params['extra_info']['shipping_change'] = $params['shipping_change'];
  130. }
  131. break;
  132. case OrderBehaviorLogsEnum::OPERATOR_REFUND: // 售后
  133. case OrderBehaviorLogsEnum::OPERATOR_CANCEL_REFUND: // 撤销售后
  134. $params['extra_info']['order_detail_id'] = self::getValueOrReturnDefault($params, 'order_detail_id', 0);
  135. $params['extra_info']['refund_id'] = self::getValueOrReturnDefault($params, 'id', 0);
  136. $params['extra_info']['step_status'] = self::getValueOrReturnDefault($params, 'step_status', 0);
  137. // 如果是取消售后的情况,是否是超过期限之后撤销的售后
  138. if (!empty($params['is_expired'])) {
  139. $params['extra_info']['is_expired'] = $params['is_expired'];
  140. }
  141. // 是否是后台手动退款
  142. if (!empty($params['is_manual'])) {
  143. $params['extra_info']['is_manual'] = $params['is_manual'];
  144. }
  145. // 拒绝原因
  146. if (isset($params['refund_reason'])) {
  147. $params['extra_info']['refund_reason'] = $params['refund_reason'];
  148. }
  149. // 后台主动退款
  150. if (isset($params['admin_handler_refund'])) {
  151. $params['extra_info']['admin_handler_refund'] = $params['admin_handler_refund'];
  152. }
  153. $params['desc'] = '';
  154. // 得到order_id
  155. if (!empty($params['extra_info']['refund_id'])) {
  156. $orderRefundOne = OrderRefund::find()
  157. ->where(['id' => $params['extra_info']['refund_id']])
  158. ->select('order_id, order_detail_id, order_no')
  159. ->asArray()
  160. ->one();
  161. if ($orderRefundOne) {
  162. $params['order_id'] = $orderRefundOne['order_id'] ?? 0;
  163. if (empty($params['extra_info']['order_detail_id'])) {
  164. $params['extra_info']['order_detail_id'] = $orderRefundOne['order_detail_id'] ?? 0;
  165. }
  166. $params['desc'] .= sprintf('售后单号:%s,', $orderRefundOne['order_no']);
  167. }
  168. }
  169. // 设置退款的商品名称
  170. if (!empty($params['extra_info']['order_detail_id'])) {
  171. $orderDetail = OrderDetail::find()
  172. ->where(['id' => $params['extra_info']['order_detail_id'], 'status' => StatusEnum::ENABLED])
  173. ->select('goods_name, num')
  174. ->asArray()
  175. ->one();
  176. if ($orderDetail) {
  177. $params['desc'] .= sprintf('商品:%s %d件', $orderDetail['goods_name'], $orderDetail['num']);
  178. }
  179. }
  180. break;
  181. case OrderBehaviorLogsEnum::OPERATOR_REMARK: // 新增备注
  182. $params['desc'] = $params['seller_remark'] ?? '';
  183. $params['extra_info']['is_batch'] = $params['is_batch'] ?? 0; // 是否是批量
  184. break;
  185. case OrderBehaviorLogsEnum::OPERATOR_MESSAGE: // 留言
  186. $params['desc'] = $params['message'] ?? '';
  187. $params['extra_info']['is_batch'] = $params['is_batch'] ?? 0; // 是否是批量
  188. break;
  189. case OrderBehaviorLogsEnum::OPERATOR_MODIFY_ADDRESS: // 修改收货地址
  190. $params['desc'] = sprintf(
  191. '原地址:收货人:%s,收货人手机号:%s,收货地址:%s %s。新地址:收货人:%s,收货人手机号:%s,收货地址:%s %s',
  192. $params['old_receiver_name'] ?? '',
  193. $params['old_mobile'] ?? '',
  194. $params['old_region_name'] ?? '',
  195. $params['old_address'] ?? '',
  196. $params['receiver_name'] ?? '',
  197. $params['mobile'] ?? '',
  198. $params['region_name'] ?? '',
  199. $params['address'] ?? ''
  200. );
  201. break;
  202. }
  203. // 不是系统操作的则判断是管理员还是用户
  204. if (!self::setSystemType($params)) {
  205. if (!isset($params['operator_user_id'])) {
  206. if (isset($params['operator_id'])) {
  207. $params['operator_user_id'] = $params['operator_id'];
  208. } elseif (!empty($params['user_id'])) {
  209. $params['operator_user_id'] = $params['user_id'];
  210. }
  211. }
  212. if (!isset($params['operator_user_type'])) {
  213. $params['operator_user_type'] = OrderBehaviorLogsEnum::OPERATOR_USER_TYPE_USER;
  214. $fieldValue = [
  215. 'is_mch' => OrderBehaviorLogsEnum::OPERATOR_USER_TYPE_MCH,
  216. 'is_aiyunuo' => OrderBehaviorLogsEnum::OPERATOR_USER_TYPE_AIYUNUO,
  217. 'is_store' => OrderBehaviorLogsEnum::OPERATOR_USER_TYPE_STORE,
  218. 'is_admin' => OrderBehaviorLogsEnum::OPERATOR_USER_TYPE_ADMIN,
  219. ];
  220. foreach ($fieldValue as $field => $value) {
  221. if (!empty($params[$field])) {
  222. $params['operator_user_type'] = $value;
  223. break;
  224. }
  225. }
  226. }
  227. // 只有系统操作operator_user_id才会=0,所以,不是系统的行为,并且operator_user_id=0,那就给订单号用户
  228. if (empty($params['operator_user_id']) && !empty($params['order_id'])) {
  229. $params['operator_user_type'] = OrderBehaviorLogsEnum::OPERATOR_USER_TYPE_USER;
  230. $params['operator_user_id'] = Order::find()
  231. ->where(['id' => $params['order_id']])
  232. ->select('user_id')
  233. ->scalar();
  234. }
  235. }
  236. }
  237. /**
  238. * 检查是不是系统自动操作的
  239. *
  240. * @param array $params
  241. *
  242. * @return bool
  243. */
  244. protected static function setSystemType(array &$params): bool
  245. {
  246. if ((isset($params['operator_id']) && $params['operator_id'] == 0) || !empty($params['is_system_auto'])) {
  247. $params['operator_user_type'] = OrderBehaviorLogsEnum::OPERATOR_USER_TYPE_SYSTEM;
  248. $params['operator_user_id'] = 0;
  249. return true;
  250. }
  251. return false;
  252. }
  253. /**
  254. * 将行为事件写入队列
  255. *
  256. * @param array $data
  257. *
  258. * @return void
  259. */
  260. public static function logsPushQueue(array $data)
  261. {
  262. try {
  263. Yii::$app->services->rabbitMq->push(
  264. RabbitMqEnum::EXCHANGE_TASK,
  265. RabbitMqEnum::TASK_QUEUE,
  266. $data,
  267. self::class,
  268. 'handleSync'
  269. );
  270. } catch (Exception $e) {
  271. $data['method'] = __METHOD__;
  272. Yii::$app->custom->logs(FormatHelper::exception($e, '行为日志发布队列失败'), $data);
  273. }
  274. }
  275. /**
  276. * @param array $data
  277. * @param string $key
  278. * @param string $defaultValue
  279. *
  280. * @return mixed
  281. */
  282. protected static function getValueOrReturnDefault(array $data, string $key, string $defaultValue = '')
  283. {
  284. return $data[$key] ?? $defaultValue;
  285. }
  286. }