OrderActionService.php 16 KB

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