WorkOrderService.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. <?php
  2. namespace App\Services;
  3. use App\OrderIssue;
  4. use App\OrderIssueProcessLog;
  5. use App\OrderIssueRejectedBill;
  6. use App\OrderIssueType;
  7. use App\OrderPackage;
  8. use App\Traits\ServiceAppAop;
  9. use App\WorkOrder;
  10. use App\WorkOrderDetail;
  11. use Illuminate\Support\Facades\Auth;
  12. class WorkOrderService
  13. {
  14. use ServiceAppAop;
  15. protected $modelClass = WorkOrder::class;
  16. public $logService;
  17. public $imageService;
  18. public $commoditiesService;
  19. public $detailService;
  20. public $issueTypeService;
  21. public $orderService;
  22. public $orderIssueService;
  23. public $orderIssueProcessLogService;
  24. public function __construct(
  25. WorkOrderLogService $logService,
  26. WorkOrderImageService $imageService,
  27. WorkOrderCommoditiesService $commoditiesService,
  28. WorkOrderDetailService $detailService,
  29. OrderIssueTypeService $issueTypeService,
  30. OrderService $orderService,
  31. OrderIssueService $orderIssueService,
  32. OrderIssueProcessLogService $orderIssueProcessLogService
  33. )
  34. {
  35. $this->logService = $logService;
  36. $this->imageService = $imageService;
  37. $this->commoditiesService = $commoditiesService;
  38. $this->detailService = $detailService;
  39. $this->issueTypeService = $issueTypeService;
  40. $this->orderService = $orderService;
  41. $this->orderIssueService = $orderIssueService;
  42. $this->orderIssueProcessLogService = $orderIssueProcessLogService;
  43. }
  44. public function createOrResetWorkOrder($order, $issueType, $remark, $process_progress = '商家创建')
  45. {
  46. $workOrder = WorkOrder::query()->where('order_id', $order->id)->orderByDesc('created_at')->first();
  47. if ($workOrder) {
  48. $this->detailService->undoneTagsByWorkOrder($workOrder);
  49. $workOrder->update([
  50. 'remark' => $remark,
  51. 'order_issue_type_id' => $issueType->id,
  52. 'creator_id' => Auth::id() ?? '',
  53. 'status' => WorkOrder::$DEFAULT_STATUS,
  54. 'process_progress' => $process_progress,
  55. 'type' => $process_progress,
  56. 'last_handler_id' => Auth::id() ?? '',
  57. 'created_at' => now(),
  58. ]);
  59. return $workOrder;
  60. }
  61. return WorkOrder::query()->create([
  62. 'order_id' => $order->id,
  63. 'logistic_id' => $order->logistic_id ?? '',
  64. 'owner_id' => $order->owner_id ?? '',
  65. 'creator_id' => Auth::id() ?? '',
  66. 'remark' => $remark,
  67. 'outer_table_name' => 'orders',
  68. 'order_issue_type_id' => $issueType->id,
  69. 'uniquely_tag' => $order->code,
  70. 'status' => WorkOrder::$DEFAULT_STATUS,
  71. 'process_progress' => $process_progress,
  72. 'type' => $process_progress,
  73. 'last_handler_id' => Auth::id() ?? '',
  74. ]);
  75. }
  76. public function createAndNotification($order, $orderIssueType, $remark, $process_progress = '商家创建'): WorkOrder
  77. {
  78. /** @var WorkOrder $workOrder */
  79. $workOrder = $this->createOrResetWorkOrder($order, $orderIssueType, $remark, $process_progress);
  80. $workOrder->notification();
  81. return $workOrder;
  82. }
  83. /**
  84. * @param WorkOrder $workOrder
  85. * @param WorkOrderDetail $detail
  86. */
  87. public function end(WorkOrder $workOrder, WorkOrderDetail $detail)
  88. {
  89. $this->detailService->endDetail($detail);
  90. $workOrder->update([
  91. 'status' => WorkOrder::$END_STATUS,
  92. 'owner_tag' => WorkOrder::$DEFAULT_TAG,
  93. 'logistic_tag' => WorkOrder::$DEFAULT_TAG,
  94. 'bao_shi_tag' => WorkOrder::$DEFAULT_TAG,
  95. 'work_order_status' => 0,
  96. ]);
  97. $this->logService->createLog($detail, '完结', '完结工单');
  98. }
  99. /**
  100. * 商家完结工单
  101. * @param WorkOrderDetail $detail
  102. */
  103. public function ownerEndWorkOrderDetail(WorkOrderDetail $detail)
  104. {
  105. $detail->update([
  106. 'status' => WorkOrder::$END_STATUS,
  107. 'process_progress' => '完成',
  108. 'last_status' => WorkOrder::$TO_BO_OWNER_END_STATUS,
  109. ]);
  110. $detail->workOrder()->update([
  111. 'status' => WorkOrder::$END_STATUS,
  112. 'process_progress' => '完成',
  113. 'last_status' => WorkOrder::$TO_BO_OWNER_END_STATUS,
  114. 'owner_tag' => WorkOrder::$DEFAULT_TAG,
  115. 'logistic_tag' => WorkOrder::$DEFAULT_TAG,
  116. 'bao_shi_tag' => WorkOrder::$DEFAULT_TAG,
  117. 'work_order_status' => 0,
  118. ]);
  119. $this->detailService->endDetail($detail); // 标记为处理过
  120. $this->logService->createLog($detail, '完结', '货主完结');
  121. }
  122. /**
  123. * 商家批量完结工单
  124. * @param $details
  125. */
  126. public function ownerBatchEndWorkOrderDetails($details)
  127. {
  128. foreach ($details as $detail) {
  129. $this->ownerEndWorkOrderDetail($detail);
  130. }
  131. }
  132. public function find($id): WorkOrder
  133. {
  134. /** @var WorkOrder $item */
  135. $item = WorkOrder::query()->where('id', $id)->first();
  136. return $item;
  137. }
  138. public function getDefaultWith($id)
  139. {
  140. return WorkOrder::query()->defaultWith()->find($id);
  141. }
  142. /**
  143. * 生成问题件
  144. * @param $work_orders
  145. * @return array
  146. */
  147. public function buildOrderIssue($work_orders): array
  148. {
  149. foreach ($work_orders as $work_order) {
  150. $inner_params[] = [
  151. 'order_id' => $work_order->order_id, 'order_issue_type_id' => $work_order->order_issue_type_id, 'result_explain' => $work_order->remark,
  152. ];
  153. }
  154. if (!isset($inner_params)) return ['success' => false, 'message' => '创建问题件失败'];
  155. try {
  156. return app('OrderIssueService')->buildOrderIssue($inner_params);
  157. } catch (\Exception $e) {
  158. return ['success' => false, 'message' => '刷新页面后重试'];
  159. }
  160. }
  161. /**
  162. * 按 指定工单类型 和 唯一标识 确认工单是否存在
  163. * @param $work_order_type_id
  164. * @param $uniquely_tag
  165. * @return array|false[]
  166. */
  167. public function exists($work_order_type_id, $uniquely_tag): array
  168. {
  169. $query = WorkOrder::query()->where('work_order_type_id', $work_order_type_id);
  170. if (is_array($uniquely_tag)) $query->whereIn('uniquely_tag', $uniquely_tag);
  171. if (is_string($uniquely_tag)) $query->where('uniquely_tag', $uniquely_tag);
  172. $items = $query->get();
  173. if (count($items) > 0) {
  174. $exists_nos = $items->map(function ($item) {
  175. return $item->uniquely_tag;
  176. });
  177. return ['success' => true, 'data' => $exists_nos];
  178. }
  179. return ['success' => false];
  180. }
  181. /**
  182. * 标记已有 问题件 的工单
  183. * @param $workOrders
  184. */
  185. public function tags(&$workOrders)
  186. {
  187. $order_ids = $workOrders->map(function ($item) {
  188. return $item->order_id;
  189. });
  190. $order_issues = OrderIssue::query()->whereIn('order_id', $order_ids)->get();
  191. foreach ($order_issues as $order_issue) {
  192. $codes[$order_issue->order_id] = true;
  193. }
  194. if (!isset($codes)) return;
  195. foreach ($workOrders as &$workOrder) {
  196. if (array_key_exists($workOrder->order_id, $codes)) $workOrder->is_issue_order = true;
  197. else $workOrder->is_issue_order = false;
  198. }
  199. }
  200. /**
  201. * 判断是否拦截工单 称重
  202. * @param $logistic_number
  203. * @return bool
  204. */
  205. public function isIntercept($logistic_number): bool
  206. {
  207. $package_query = OrderPackage::query()->select('order_id')->where('logistic_number', $logistic_number);
  208. $order_issue_query = OrderIssueType::query()->select('id')->where('name', '拦截');
  209. return WorkOrder::query()->whereIn('order_id', $package_query)->whereIn('order_issue_type_id', $order_issue_query)->exists();
  210. }
  211. /**
  212. * 标记工单
  213. * @param $orders
  214. */
  215. public function tagWorkOrder(&$orders)
  216. {
  217. $orderNos = data_get($orders, '*.orderno');
  218. $workOrders = WorkOrder::query()->with('order')->whereIn('order_id', function ($query) use ($orderNos) {
  219. $query->from('orders')->select('id')->whereIn('code', $orderNos);
  220. })->get();
  221. $tags = [];
  222. $workOrders->each(function ($workOrder) use (&$tags) {
  223. $order_code = $workOrder->order->code ?? null;
  224. if ($order_code) $tags[$order_code] = true;
  225. });
  226. foreach ($orders as &$order) {
  227. if (array_key_exists($order->orderno, $tags)) $order->is_work_order = true;
  228. else $order->is_work_order = false;
  229. }
  230. }
  231. /**
  232. * 校验工单是否存在
  233. * @param $nos
  234. * @return mixed
  235. */
  236. public function checkWorkOrder($nos)
  237. {
  238. return WorkOrder::query()->defaultWith()->whereIn('order_id', function ($query) use ($nos) {
  239. $query->from('orders')->selectRaw('id');
  240. if (is_array($nos))
  241. $query->whereIn('code', $nos);
  242. else {
  243. $query->where('code', $nos);
  244. }
  245. })->get();
  246. }
  247. /**
  248. * 同步订单
  249. * @param $order_no
  250. * @return mixed
  251. */
  252. public function syncOrder($order_no)
  253. {
  254. return $this->orderService->first(['code' => $order_no]);
  255. }
  256. /**
  257. * 承运商标记在处理
  258. * @param WorkOrderDetail $detail
  259. */
  260. public function logisticHandlerTag(WorkOrderDetail $detail)
  261. {
  262. $detail->logisticTagHandle();
  263. $last_status = WorkOrder::$enums['status'][$detail->status];
  264. $detail->update([
  265. 'status' => WorkOrder::$LOGISTIC_HANDLER_STATUS,
  266. 'process_progress' => '承运商处理中',
  267. 'last_status' => $last_status,
  268. 'logistic_handle_tag' => 1,
  269. ]);
  270. $detail->workOrder()->update([
  271. 'status' => WorkOrder::$LOGISTIC_HANDLER_STATUS,
  272. 'process_progress' => '承运商处理中',
  273. 'last_status' => $last_status,
  274. 'logistic_tag' => WorkOrder::$NO_STATE_TAG,
  275. 'owner_tag' => WorkOrder::$DEFAULT_TAG,
  276. 'bao_shi_tag' => WorkOrder::$DEFAULT_TAG,
  277. 'work_order_status' => WorkOrder::$DEFAULT_TAG,
  278. ]);
  279. $detail->processLogs()->create([
  280. 'work_order_id' => $detail->work_order_id,
  281. 'work_order_detail_id' => $detail->id,
  282. 'user_id' => Auth::id(),
  283. 'content' => '承运商标记在处理',
  284. 'status' => '未同步',
  285. 'type' => '处理',
  286. ]);
  287. app(WorkOrderLogService::class)->createLog($detail, '处理', '标记处理中');
  288. }
  289. public function syncWorkOrder($rejectedBill)
  290. {
  291. /** @var OrderIssue $order_issue */
  292. $orderIssueRejectedBill = OrderIssueRejectedBill::query()->where('logistic_number_return', $rejectedBill['logistic_number_return'])->first();
  293. $order_issue = OrderIssue::query()->find($orderIssueRejectedBill->order_issue_id);
  294. if (!$order_issue || $order_issue->rejecting_status !== '全部退回') return;
  295. /** @var WorkOrderInterceptService $workOrderInterceptService */
  296. $workOrderInterceptService = app(WorkOrderInterceptService::class);
  297. /** @var WorkOrder $workOrder */
  298. $workOrder = WorkOrder::query()->where('order_id', $order_issue->order_id)->orderByDesc('created_at')->first();
  299. if (!$workOrder) return;
  300. $workOrderInterceptService->autoReviewIntercept($workOrder);
  301. }
  302. /**
  303. * 每日工单定时任务timingTask
  304. */
  305. public function timingTask()
  306. {
  307. $this->updateBaoShiHandlerTask();
  308. $this->updateLogisticHandlerTask();
  309. }
  310. private function updateLogisticHandlerTask()
  311. {
  312. // 将当日承运商处理过 且 状态为`无`的 标记为滞留状态 `滞`
  313. WorkOrder::query()->where('status', 3)
  314. ->where('logistic_tag', WorkOrder::$NO_STATE_TAG)
  315. ->update(['logistic_tag' => WorkOrder::$STRAND_TAG]);
  316. }
  317. private function updateBaoShiHandlerTask()
  318. {
  319. // 将当日宝时处理过 且 状态为`无`的 标记为滞留状态 `滞`
  320. WorkOrder::query()->whereIn('status', [1, 4])
  321. ->where('bao_shi_tag', WorkOrder::$NO_STATE_TAG)
  322. ->update(['bao_shi_tag' => WorkOrder::$STRAND_TAG]);
  323. }
  324. /**
  325. * 同步处理日志到问题件
  326. * @param WorkOrderDetail $detail
  327. */
  328. public function endOrderIssueAndSyncProcessLogs(WorkOrderDetail $detail)
  329. {
  330. /**
  331. * @var OrderIssue $order_issue
  332. * @var WorkOrder $work_order
  333. */
  334. $work_order = $detail->workOrder;
  335. $order_issue = OrderIssue::query()->where('order_id', $work_order->order_id)->first();
  336. if (!$order_issue) {
  337. $order_issue = OrderIssue::query()->create([
  338. 'order_id' => $work_order->order_id,
  339. 'result_explain' => $work_order->remark,
  340. 'imported_status' => '正常',
  341. 'order_issue_type_id' => $detail->order_issue_type_id,
  342. ]);
  343. }
  344. $process_logs = $detail->processLogs()->where('status', '未同步')->get();
  345. $order_issue->logs()->insert($process_logs->map((function ($process_log) use ($order_issue) {
  346. return [
  347. 'order_issue_id' => $order_issue->id,
  348. 'user_id' => $process_log->user_id,
  349. 'content' => $process_log->content,
  350. 'created_at' => $process_log->created_at,
  351. 'updated_at' => $process_log->updated_at,
  352. 'type' => $process_log->type,
  353. ];
  354. }))->toArray());
  355. $this->orderIssueService->endOrderIssues([$order_issue->id]);
  356. $detail->processLogs()->where('status', '未同步')->update(['status' => '同步']);
  357. }
  358. }