OrderActionService.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. <?php
  2. namespace app\common\Service;
  3. use app\common\repository\OrderActionRepository;
  4. use app\common\Enum\OrderActionEnum;
  5. use think\Exception;
  6. use think\Collection;
  7. /**
  8. * 订单操作记录服务类
  9. * 业务逻辑层,处理复杂的业务规则和流程
  10. */
  11. class OrderActionService
  12. {
  13. protected $repository;
  14. public function __construct()
  15. {
  16. $this->repository = new OrderActionRepository();
  17. }
  18. /**
  19. * 添加订单操作记录
  20. * @param string $order_sn 订单编号
  21. * @param string $operator 操作人
  22. * @param string $memo 备注
  23. * @return bool
  24. */
  25. public function push($order_sn, $operator, $memo)
  26. {
  27. return $this->addAction([
  28. 'order_sn' => $order_sn,
  29. 'operator' => $operator,
  30. 'memo' => $memo,
  31. 'action_type' => OrderActionEnum::ACTION_MODIFY,
  32. 'user_type' => OrderActionEnum::USER_TYPE_ADMIN,
  33. 'operator_type' => OrderActionEnum::OPERATOR_TYPE_ADMIN,
  34. ]);
  35. }
  36. /**
  37. * 静态方法兼容(向后兼容)
  38. */
  39. public static function staticPush($order_sn, $operator, $memo)
  40. {
  41. $service = new self();
  42. return $service->push($order_sn, $operator, $memo);
  43. }
  44. /**
  45. * 添加订单操作记录(核心方法)
  46. * @param array $data 操作记录数据
  47. * @return bool
  48. */
  49. public function addAction($data = [])
  50. {
  51. // 验证必要字段
  52. if (empty($data['order_sn'])) {
  53. return false;
  54. }
  55. // 验证操作类型
  56. if (!empty($data['action_type']) && !OrderActionEnum::isValidActionType($data['action_type'])) {
  57. return false;
  58. }
  59. // 验证用户类型
  60. if (!empty($data['user_type']) && !OrderActionEnum::isValidUserType($data['user_type'])) {
  61. return false;
  62. }
  63. // 构建操作数据
  64. $actionData = $this->buildActionData($data);
  65. // 通过仓库层保存数据
  66. return $this->repository->create($actionData);
  67. }
  68. /**
  69. * 添加用户操作记录
  70. * @param string $order_sn 订单编号
  71. * @param string $action_type 操作类型
  72. * @param string $operator 操作人
  73. * @param string $memo 备注
  74. * @param int $user_id 用户ID
  75. * @param array $extra 额外数据
  76. * @return bool
  77. */
  78. public function addUserAction($order_sn, $action_type, $operator, $memo = '', $user_id = 0, $extra = [])
  79. {
  80. return $this->addAction([
  81. 'order_sn' => $order_sn,
  82. 'action_type' => $action_type,
  83. 'operator' => $operator,
  84. 'memo' => $memo,
  85. 'user_type' => OrderActionEnum::USER_TYPE_CUSTOMER,
  86. 'operator_type' => OrderActionEnum::OPERATOR_TYPE_USER,
  87. 'user_id' => $user_id,
  88. 'extra_data' => $extra,
  89. ]);
  90. }
  91. /**
  92. * 添加管理员操作记录
  93. * @param string $order_sn 订单编号
  94. * @param string $action_type 操作类型
  95. * @param string $operator 操作人
  96. * @param string $memo 备注
  97. * @param int $admin_id 管理员ID
  98. * @param array $extra 额外数据
  99. * @return bool
  100. */
  101. public function addAdminAction($order_sn, $action_type, $operator, $memo = '', $admin_id = 0, $extra = [])
  102. {
  103. return $this->addAction([
  104. 'order_sn' => $order_sn,
  105. 'action_type' => $action_type,
  106. 'operator' => $operator,
  107. 'memo' => $memo,
  108. 'user_type' => OrderActionEnum::USER_TYPE_ADMIN,
  109. 'operator_type' => OrderActionEnum::OPERATOR_TYPE_ADMIN,
  110. 'user_id' => $admin_id,
  111. 'extra_data' => $extra,
  112. ]);
  113. }
  114. /**
  115. * 添加系统操作记录
  116. * @param string $order_sn 订单编号
  117. * @param string $action_type 操作类型
  118. * @param string $memo 备注
  119. * @param array $extra 额外数据
  120. * @return bool
  121. */
  122. public function addSystemAction($order_sn, $action_type, $memo = '', $extra = [])
  123. {
  124. return $this->addAction([
  125. 'order_sn' => $order_sn,
  126. 'action_type' => $action_type,
  127. 'operator' => 'system',
  128. 'memo' => $memo,
  129. 'user_type' => OrderActionEnum::USER_TYPE_SYSTEM,
  130. 'operator_type' => OrderActionEnum::OPERATOR_TYPE_SYSTEM,
  131. 'user_id' => 0,
  132. 'extra_data' => $extra,
  133. ]);
  134. }
  135. /**
  136. * 批量添加操作记录
  137. * @param array $batch_data 批量数据
  138. * @return bool
  139. */
  140. public function addBatchActions($batch_data)
  141. {
  142. if (empty($batch_data)) {
  143. return false;
  144. }
  145. $processedData = [];
  146. foreach ($batch_data as $data) {
  147. if (empty($data['order_sn'])) {
  148. continue;
  149. }
  150. $processedData[] = $this->buildActionData($data);
  151. }
  152. return $this->repository->createBatch($processedData);
  153. }
  154. /**
  155. * 获取订单操作记录
  156. * @param string $order_sn 订单编号
  157. * @param string $action_type 操作类型(可选)
  158. * @param string $user_type 用户类型(可选)
  159. * @param int $limit 限制数量
  160. * @return Collection
  161. */
  162. public function getOrderActions($order_sn, $action_type = '', $user_type = '', $limit = 0)
  163. {
  164. return $this->repository->findByOrderSn($order_sn, $action_type, $user_type, $limit);
  165. }
  166. /**
  167. * 获取最后一次操作记录
  168. * @param string $order_sn 订单编号
  169. * @param string $action_type 操作类型(可选)
  170. * @return mixed
  171. */
  172. public function getLastAction($order_sn, $action_type = '')
  173. {
  174. return $this->repository->findLatestByOrderSn($order_sn, $action_type);
  175. }
  176. /**
  177. * 检查操作是否存在
  178. * @param string $order_sn 订单编号
  179. * @param string $action_type 操作类型
  180. * @return bool
  181. */
  182. public function hasAction($order_sn, $action_type)
  183. {
  184. return $this->repository->existsByActionType($order_sn, $action_type);
  185. }
  186. /**
  187. * 获取操作统计数据
  188. * @param string $order_sn 订单编号
  189. * @return array
  190. */
  191. public function getActionStats($order_sn)
  192. {
  193. $stats = $this->repository->getStatisticsData($order_sn);
  194. // 添加业务逻辑处理
  195. if ($stats['total_count'] > 0) {
  196. $stats['first_action'] = end($stats['actions_data']);
  197. $stats['last_action'] = $stats['actions_data'][0];
  198. // 计算活跃度
  199. $stats['activity_score'] = $this->calculateActivityScore($stats);
  200. }
  201. return $stats;
  202. }
  203. /**
  204. * 生成操作时间线
  205. * @param string $order_sn 订单编号
  206. * @param bool $include_system 是否包含系统操作
  207. * @return array
  208. */
  209. public function getActionTimeline($order_sn, $include_system = true)
  210. {
  211. return $this->repository->getTimelineData($order_sn, $include_system);
  212. }
  213. /**
  214. * 记录订单状态变化
  215. * @param string $order_sn 订单编号
  216. * @param string $old_status 旧状态
  217. * @param string $new_status 新状态
  218. * @param string $operator 操作人
  219. * @param string $user_type 用户类型
  220. * @param int $user_id 用户ID
  221. * @param string $memo 备注
  222. * @return bool
  223. */
  224. public function recordStatusChange($order_sn, $old_status, $new_status, $operator, $user_type = OrderActionEnum::USER_TYPE_ADMIN, $user_id = 0, $memo = '')
  225. {
  226. $actionType = $this->getActionTypeByStatus($new_status);
  227. $defaultMemo = "订单状态从 {$old_status} 变更为 {$new_status}";
  228. return $this->addAction([
  229. 'order_sn' => $order_sn,
  230. 'action_type' => $actionType,
  231. 'operator' => $operator,
  232. 'memo' => $memo ?: $defaultMemo,
  233. 'user_type' => $user_type,
  234. 'user_id' => $user_id,
  235. 'extra_data' => [
  236. 'old_status' => $old_status,
  237. 'new_status' => $new_status,
  238. ],
  239. ]);
  240. }
  241. /**
  242. * 获取操作次数统计
  243. * @param string $order_sn 订单编号
  244. * @param string $action_type 操作类型
  245. * @return int
  246. */
  247. public function getActionCount($order_sn, $action_type = '')
  248. {
  249. return $this->repository->countByOrderSn($order_sn, $action_type);
  250. }
  251. /**
  252. * 获取用户操作历史
  253. * @param int $user_id 用户ID
  254. * @param string $user_type 用户类型
  255. * @param int $limit 限制数量
  256. * @return Collection
  257. */
  258. public function getUserActionHistory($user_id, $user_type = OrderActionEnum::USER_TYPE_CUSTOMER, $limit = 10)
  259. {
  260. return $this->repository->findByUser($user_id, $user_type, $limit);
  261. }
  262. /**
  263. * 清理过期操作记录
  264. * @param int $days 保留天数
  265. * @return bool
  266. */
  267. public function cleanExpiredActions($days = 90)
  268. {
  269. $expiredTime = time() - ($days * 24 * 3600);
  270. return $this->repository->deleteExpired($expiredTime);
  271. }
  272. /**
  273. * 获取高优先级操作记录
  274. * @param string $order_sn 订单编号
  275. * @return Collection
  276. */
  277. public function getHighPriorityActions($order_sn)
  278. {
  279. return $this->repository->findHighPriorityByOrderSn($order_sn);
  280. }
  281. /**
  282. * 验证操作记录数据
  283. * @param array $data 数据
  284. * @return array [bool, string] [是否有效, 错误信息]
  285. */
  286. public function validateActionData($data)
  287. {
  288. if (empty($data['order_sn'])) {
  289. return [false, '订单编号不能为空'];
  290. }
  291. if (!empty($data['action_type']) && !OrderActionEnum::isValidActionType($data['action_type'])) {
  292. return [false, '无效的操作类型'];
  293. }
  294. if (!empty($data['user_type']) && !OrderActionEnum::isValidUserType($data['user_type'])) {
  295. return [false, '无效的用户类型'];
  296. }
  297. if (!empty($data['priority']) && !OrderActionEnum::isValidPriority($data['priority'])) {
  298. return [false, '无效的优先级'];
  299. }
  300. return [true, ''];
  301. }
  302. /**
  303. * 构建操作数据
  304. * @param array $data 原始数据
  305. * @return array 处理后的数据
  306. */
  307. protected function buildActionData($data)
  308. {
  309. $actionData = [
  310. 'order_sn' => $data['order_sn'],
  311. 'operator' => $data['operator'] ?? 'unknown',
  312. 'memo' => $data['memo'] ?? '',
  313. 'action_type' => $data['action_type'] ?? OrderActionEnum::ACTION_MODIFY,
  314. 'user_type' => $data['user_type'] ?? OrderActionEnum::USER_TYPE_ADMIN,
  315. 'operator_type' => $data['operator_type'] ?? OrderActionEnum::OPERATOR_TYPE_ADMIN,
  316. 'priority' => $data['priority'] ?? OrderActionEnum::getDefaultPriority($data['action_type'] ?? OrderActionEnum::ACTION_MODIFY),
  317. 'user_id' => $data['user_id'] ?? 0,
  318. 'ip' => $data['ip'] ?? request()->ip(),
  319. 'user_agent' => $data['user_agent'] ?? request()->server('HTTP_USER_AGENT', ''),
  320. 'extra_data' => is_array($data['extra_data'] ?? '') ? json_encode($data['extra_data']) : ($data['extra_data'] ?? ''),
  321. ];
  322. // 如果没有指定操作员类型,根据用户类型自动设置
  323. if (empty($data['operator_type'])) {
  324. $actionData['operator_type'] = OrderActionEnum::getDefaultOperatorType($actionData['user_type']);
  325. }
  326. return $actionData;
  327. }
  328. /**
  329. * 根据状态获取操作类型
  330. * @param string $status 状态
  331. * @return string
  332. */
  333. protected function getActionTypeByStatus($status)
  334. {
  335. $statusMap = [
  336. 'created' => OrderActionEnum::ACTION_CREATE,
  337. 'paid' => OrderActionEnum::ACTION_PAY,
  338. 'shipped' => OrderActionEnum::ACTION_SHIP,
  339. 'received' => OrderActionEnum::ACTION_RECEIVE,
  340. 'cancelled' => OrderActionEnum::ACTION_CANCEL,
  341. 'refunded' => OrderActionEnum::ACTION_REFUND,
  342. 'completed' => OrderActionEnum::ACTION_COMPLETE,
  343. ];
  344. return $statusMap[$status] ?? OrderActionEnum::ACTION_MODIFY;
  345. }
  346. /**
  347. * 计算活跃度评分
  348. * @param array $stats 统计数据
  349. * @return float
  350. */
  351. protected function calculateActivityScore($stats)
  352. {
  353. $baseScore = $stats['total_count'] * 10;
  354. $userScore = $stats['user_count'] * 5;
  355. $adminScore = $stats['admin_count'] * 3;
  356. $systemScore = $stats['system_count'] * 1;
  357. return ($baseScore + $userScore + $adminScore + $systemScore) / 100;
  358. }
  359. // 静态方法兼容(向后兼容)
  360. public static function staticAddAction($data = [])
  361. {
  362. $service = new self();
  363. return $service->addAction($data);
  364. }
  365. public static function staticAddUserAction($order_sn, $action_type, $operator, $memo = '', $user_id = 0, $extra = [])
  366. {
  367. $service = new self();
  368. return $service->addUserAction($order_sn, $action_type, $operator, $memo, $user_id, $extra);
  369. }
  370. public static function staticAddAdminAction($order_sn, $action_type, $operator, $memo = '', $admin_id = 0, $extra = [])
  371. {
  372. $service = new self();
  373. return $service->addAdminAction($order_sn, $action_type, $operator, $memo, $admin_id, $extra);
  374. }
  375. public static function staticAddSystemAction($order_sn, $action_type, $memo = '', $extra = [])
  376. {
  377. $service = new self();
  378. return $service->addSystemAction($order_sn, $action_type, $memo, $extra);
  379. }
  380. public static function staticAddBatchActions($batch_data)
  381. {
  382. $service = new self();
  383. return $service->addBatchActions($batch_data);
  384. }
  385. public static function staticGetOrderActions($order_sn, $action_type = '', $user_type = '', $limit = 0)
  386. {
  387. $service = new self();
  388. return $service->getOrderActions($order_sn, $action_type, $user_type, $limit);
  389. }
  390. public static function staticGetLastAction($order_sn, $action_type = '')
  391. {
  392. $service = new self();
  393. return $service->getLastAction($order_sn, $action_type);
  394. }
  395. public static function staticHasAction($order_sn, $action_type)
  396. {
  397. $service = new self();
  398. return $service->hasAction($order_sn, $action_type);
  399. }
  400. public static function staticGetActionStats($order_sn)
  401. {
  402. $service = new self();
  403. return $service->getActionStats($order_sn);
  404. }
  405. public static function staticGetActionTimeline($order_sn, $include_system = true)
  406. {
  407. $service = new self();
  408. return $service->getActionTimeline($order_sn, $include_system);
  409. }
  410. public static function staticRecordStatusChange($order_sn, $old_status, $new_status, $operator, $user_type = OrderActionEnum::USER_TYPE_ADMIN, $user_id = 0, $memo = '')
  411. {
  412. $service = new self();
  413. return $service->recordStatusChange($order_sn, $old_status, $new_status, $operator, $user_type, $user_id, $memo);
  414. }
  415. public static function staticGetActionCount($order_sn, $action_type = '')
  416. {
  417. $service = new self();
  418. return $service->getActionCount($order_sn, $action_type);
  419. }
  420. public static function staticGetUserActionHistory($user_id, $user_type = OrderActionEnum::USER_TYPE_CUSTOMER, $limit = 10)
  421. {
  422. $service = new self();
  423. return $service->getUserActionHistory($user_id, $user_type, $limit);
  424. }
  425. public static function staticCleanExpiredActions($days = 90)
  426. {
  427. $service = new self();
  428. return $service->cleanExpiredActions($days);
  429. }
  430. public static function staticGetHighPriorityActions($order_sn)
  431. {
  432. $service = new self();
  433. return $service->getHighPriorityActions($order_sn);
  434. }
  435. public static function staticValidateActionData($data)
  436. {
  437. $service = new self();
  438. return $service->validateActionData($data);
  439. }
  440. }