OrderPackageReceivedSyncService.php 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. <?php
  2. namespace App\Services;
  3. use App\Jobs\LogisticAliJiSuSync;
  4. use App\Jobs\LogisticSFSync;
  5. use App\Jobs\LogisticYDSync;
  6. use App\Jobs\LogisticYTOSync;
  7. use App\Jobs\LogisticZopSync;
  8. use App\OrderPackage;
  9. use Carbon\Carbon;
  10. use Exception;
  11. use Illuminate\Database\Eloquent\Collection;
  12. use Illuminate\Support\Str;
  13. class OrderPackageReceivedSyncService
  14. {
  15. protected $logisticSFService;
  16. protected $logisticZopService;
  17. use \App\Traits\LogisticSyncTrait;
  18. /**
  19. * 同步快递信息
  20. * @param bool $is_to_init 是否为初始化数据状态 初始化同步一个月的 正常执行为15天
  21. * @param array $logistic_numbers 指定更新的单号
  22. */
  23. public function syncLogisticRoute($is_to_init = false, $logistic_numbers = [])
  24. {
  25. ini_set('max_execution_time', 2 * 60 * 60);
  26. ini_set('memory_limit', '1024M');
  27. //没有指定单号
  28. if (empty($logistic_numbers)) {
  29. $query = OrderPackage::query()
  30. ->select(['logistic_number', 'order_id', 'id'])
  31. ->with(['order' => function ($query) {
  32. return $query->select(['id', 'logistic_id'])->with('logistic:id,name,code');
  33. }]);
  34. if ($is_to_init) {//当前时间小于等于初始化时间
  35. $initDate = Carbon::parse(config('api_logistic.init_date'));
  36. //初始化查询一个月的数据
  37. $query = $query->where('created_at', '>=', $initDate)
  38. ->whereNull('received_at');
  39. } else {//查询20天以内的数据
  40. $query = $query->where('created_at', '>=', now()->subDays(config('api_logistic.querying_days'))->startOfDay())
  41. ->whereNull('received_at');
  42. }
  43. } else {//指定了单号
  44. $query = OrderPackage::query()
  45. ->select(['logistic_number', 'order_id', 'id'])
  46. ->with(['order' => function ($query) {
  47. return $query->select(['id', 'logistic_id'])->with('logistic:id,name,code');
  48. }])
  49. ->whereIn('logistic_number', $logistic_numbers);
  50. }
  51. //分块执行
  52. $query->chunkById(1000, function ($orderPackages) {
  53. //按照承运商分组
  54. $logisticNumbers = $this->buildData($orderPackages);
  55. //更新顺丰系列
  56. if (array_key_exists('SF', $logisticNumbers)) {
  57. $SFLogisticNumbers = $logisticNumbers['SF'];
  58. foreach ($SFLogisticNumbers as $logisticNumber) {
  59. LogisticSFSync::dispatch($logisticNumber);
  60. }
  61. }
  62. //更新中通
  63. if (array_key_exists('ZTO', $logisticNumbers)) {
  64. $ZTOLogisticNumbers = $logisticNumbers['ZTO'];
  65. foreach ($ZTOLogisticNumbers as $logisticNumber) {
  66. LogisticZopSync::dispatch($logisticNumber);
  67. }
  68. }
  69. //更新韵达
  70. if (array_key_exists('YUNDA', $logisticNumbers)) {
  71. $YDLogisticNumbers = $logisticNumbers['YUNDA'];
  72. foreach ($YDLogisticNumbers as $logistic_number) {
  73. LogisticYDSync::dispatch($logistic_number);
  74. }
  75. }
  76. //更新圆通
  77. if (array_key_exists('YTO', $logisticNumbers)) {
  78. $YTOLogisticNumbers = $logisticNumbers['YTO'];
  79. foreach ($YTOLogisticNumbers as $logistic_number) {
  80. if ($logistic_number) LogisticYTOSync::dispatch($logistic_number);
  81. }
  82. }
  83. });
  84. }
  85. /**
  86. * 阿里云同步快递信息
  87. * @param array $logistic_numbers 指定单号同步
  88. */
  89. public function syncLogisticRouteByAliJiSu(array $logistic_numbers = [])
  90. {
  91. //没有指定单号
  92. if (empty($logistic_numbers)) {
  93. ini_set('max_execution_time', 2 * 60 * 60);
  94. $query = OrderPackage::query()
  95. ->select(['logistic_number', 'order_id', 'id'])
  96. ->whereIn('order_id', function ($query) {
  97. $query->from('orders')->selectRaw('id')->whereIn('logistic_id', function ($builder) {
  98. $builder->from('logistics')->selectRaw('id')->where('type', '=', '快递')->whereNotIn('belong_company', ['顺丰', '中通', '韵达', '圆通', '京东']);
  99. });
  100. });
  101. $query = $query->where('created_at', '>=', now()->subDays(config('api_logistic.querying_days')))
  102. ->whereNull('received_at');
  103. } else {//指定了单号
  104. $query = OrderPackage::query()
  105. ->select(['logistic_number', 'order_id', 'id'])
  106. ->whereIn('logistic_number', $logistic_numbers);
  107. }
  108. $query->chunkById(200, function ($orderPackages) {
  109. foreach ($orderPackages as $orderPackage) {
  110. if ($orderPackage && $orderPackage->logistic_number) LogisticAliJiSuSync::dispatch($orderPackage->logistic_number);
  111. }
  112. });
  113. }
  114. public function syncLogisticRouteJD()
  115. {
  116. ini_set('max_execution_time', 60);
  117. $query = OrderPackage::query()
  118. ->select(['logistic_number', 'order_id', 'id'])
  119. ->whereIn('order_id', function ($query) {
  120. $query->from('orders')->selectRaw('id')->whereIn('logistic_id', function ($builder) {
  121. $builder->from('logistics')->selectRaw('id')->where('type', '!=', '物流')->where('belong_company', '京东');
  122. });
  123. });
  124. $query = $query->where('created_at', '>=', now()->subDays(config('api_logistic.querying_days')))
  125. ->whereNull('received_at')->where('logistic_number', 'like', 'JD%');
  126. $query->chunkById(200, function ($orderPackages) {
  127. foreach ($orderPackages as $orderPackage) {
  128. if ($orderPackage && $orderPackage->logistic_number) LogisticAliJiSuSync::dispatch($orderPackage->logistic_number);
  129. }
  130. });
  131. }
  132. /**
  133. * 根据快递单号更新状态
  134. * @param array $logisticResponses
  135. */
  136. public function update(array $logisticResponses)
  137. {
  138. foreach ($logisticResponses as $logisticResponse) {
  139. if (empty($logisticResponse)) continue;
  140. $orderPackage = OrderPackage::query()->where('logistic_number', $logisticResponse['logistic_number'])->first();
  141. //如果已经收货,状态改为已签收
  142. if ($logisticResponse['received_at'] ?? false) {
  143. $logisticResponse['status'] = '已签收';
  144. }
  145. //标记为手动更新的 status不更新
  146. if ($orderPackage->is_manual_update) {
  147. if (OrderPackage::switchStatus($orderPackage->status) > OrderPackage::switchStatus($logisticResponse['status'] ?? '生成订单')) {
  148. unset($logisticResponse['status']);
  149. }
  150. }
  151. //设置异常信息
  152. $logisticResponse = $this->setExceptionStatus($logisticResponse);
  153. //标记为单号异常
  154. if (Str::contains($orderPackage->logistic_number, ['SO', '#', '-'])) {
  155. $logisticResponse['exception_status'] = '单号异常';
  156. }
  157. //没有状态的数据赋予初始状态
  158. if (((!isset($logisticResponse['status'])) || ($logisticResponse['status'] === '')) &&
  159. $orderPackage->status === '') {
  160. $logisticResponse['status'] = '生成订单';
  161. if (!empty($orderPackage->sent_at)) {
  162. $logisticResponse['status'] = '已复核';
  163. }
  164. if (!empty($orderPackage->weighed_at)) {
  165. $logisticResponse['status'] = '已称重';
  166. }
  167. }
  168. if (isset($logisticResponse['exception_status'])) $logisticResponse['exception_status'] = OrderPackage::switchExceptionStatus($logisticResponse['exception_status']);
  169. if (isset($logisticResponse['status'])) $logisticResponse['status'] = OrderPackage::switchStatus($logisticResponse['status']);
  170. if (isset($logisticResponse['routes_length'])) unset($logisticResponse['routes_length']);
  171. if(empty($logisticResponse['transfer_status'])) unset($logisticResponse['transfer_status']);
  172. OrderPackage::query()->where('logistic_number', $logisticResponse['logistic_number'])
  173. ->update($logisticResponse);
  174. }
  175. }
  176. /**
  177. * 将orderPackage集合分类并摘取指定数据
  178. * @param Collection $orderPackages
  179. * @return array
  180. */
  181. private function buildData(Collection $orderPackages): array
  182. {
  183. $data = [];
  184. foreach ($orderPackages as $orderPackage) {
  185. try {
  186. $logisticCode = $orderPackage->order->logistic->code;
  187. } catch (Exception $e) {
  188. continue;
  189. }
  190. $key = config('api_logistic.logistic.' . $logisticCode);
  191. if (!isset($data[$key])) {
  192. $data[$key] = [];
  193. }
  194. $data[$key][] = $orderPackage->logistic_number;
  195. }
  196. return $data;
  197. }
  198. }