LogisticSyncTrait.php 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. <?php
  2. namespace App\Traits;
  3. use App\OrderPackage;
  4. use Illuminate\Support\Carbon;
  5. use Illuminate\Support\Str;
  6. use function DeepCopy\deep_copy;
  7. trait LogisticSyncTrait
  8. {
  9. /**
  10. * 设置 status 与 exception_status
  11. * @param array $data
  12. * @return array
  13. */
  14. public function setExceptionStatus(array $data): array
  15. {
  16. //获取快递单号
  17. $logistic_number = $data['logistic_number'];
  18. /** @var OrderPackage $orderPackage */
  19. $orderPackage = OrderPackage::query()
  20. ->with(['order'])
  21. ->where('logistic_number', $logistic_number)
  22. ->first();
  23. //这种类型的单,不需要再更新状态
  24. if ($orderPackage->exception_status === '单号异常' ||
  25. $orderPackage->exception_status === '无法获取路由') {
  26. return $data;
  27. }
  28. /** @var \Carbon\Carbon $sent_at */
  29. $sent_at = $orderPackage->sent_at;
  30. /** @var \Carbon\Carbon $issue_time 订单下发时间 */
  31. $issue_time = $orderPackage->order->created_at;
  32. /**执行该方法时,默认没有异常,
  33. *1. 之前有异常的件,
  34. * 1.1 新的状态是无异常的可以更新为正常
  35. * 1.2 新的状态是异常的可以更新为对应异常
  36. *2. 之前无异常
  37. * 2.1 新的状态无异常更新为无异常
  38. * 2.2 新的状态异常更新为对应异常
  39. */
  40. $data['exception_status'] = '';
  41. //当天的16:30
  42. $transfer_status = $data['transfer_status'] ?? [];
  43. if (empty($sent_at)) {//没复核
  44. if (empty($transfer_status)) {//没有路由信息
  45. //延迟发货
  46. $issue_time_clone = deep_copy($issue_time);
  47. if ($issue_time->gt($issue_time_clone->startOfDay()->addHours(16)->addMinutes(30))) {//下午16:30的单
  48. $issue_time_clone = deep_copy($issue_time);
  49. if ($issue_time_clone->addDay()->endOfDay()->lt(now())) {//超过第二天的24时
  50. $data['exception_status'] = '延迟发货';
  51. $data['is_delay_deliver'] = true;
  52. }
  53. } else {
  54. if ($issue_time_clone->endOfDay()->lt(now())) {//超过当天的24时
  55. $data['exception_status'] = '延迟发货';
  56. $data['is_delay_deliver'] = true;
  57. }
  58. }
  59. }
  60. } else {//复核过
  61. if (empty($transfer_status)) {//没有路由信息
  62. /** @var Carbon $temp_time */
  63. $temp_time = $orderPackage->weighed_at ?: $orderPackage->sent_at;//揽收异常以称重时间优先 没有称重以发出时间
  64. if (now()->gt($temp_time->addDay()->startOfDay()->addHours(6))) {//当前时间大于复核时间的第二天6点
  65. if (empty($orderPackage->weighed_at)) {//没有称重
  66. $data['exception_status'] = '疑似库内丢件';
  67. } else {//有称重
  68. $data['exception_status'] = '揽件异常';
  69. }
  70. }
  71. } else {//有路由信息
  72. $transfer_status = $this->sortTransferStatusByAcceptTimeDESC($transfer_status);
  73. $last_transfer_accept_time = $transfer_status[0]['accept_time'];
  74. $last_remark = $this->getLastRemark($transfer_status[0]);
  75. if (count($transfer_status) < 3) {//三条以内的不管地区 时间限制为24h
  76. if (Carbon::parse($last_transfer_accept_time)->diffInHours(now()) > 24) {
  77. $data['exception_status'] = '在途异常';
  78. }
  79. } else {
  80. //根据地区获取超时时间限制
  81. $SHORT_RESPONSE_HOURS = (function ($province) {
  82. switch ($province) {
  83. case '浙江省':
  84. case '江苏省':
  85. case '上海':
  86. case '安徽省':
  87. return 24;
  88. case '北京':
  89. case '天津':
  90. case '江西省':
  91. case '湖北省':
  92. case '湖南省':
  93. case '广东省':
  94. case '福建省':
  95. case '山东省':
  96. case '河北省':
  97. case '河南省':
  98. case '山西省':
  99. case '四川省':
  100. case '陕西省':
  101. case '重庆':
  102. case '广西壮族自治区':
  103. case '贵州省':
  104. case '云南省':
  105. case '海南省':
  106. case '吉林省':
  107. case '黑龙江省':
  108. case '辽宁省':
  109. return 72;
  110. case '青海省':
  111. case '宁夏回族自治区':
  112. case '甘肃省':
  113. case '内蒙古自治区':
  114. case '新疆维吾尔自治区':
  115. case '西藏自治区':
  116. return 120;
  117. default:
  118. return 24;
  119. }
  120. })($orderPackage->order->province);
  121. if (Carbon::parse($last_transfer_accept_time)->diffInHours(now()) > $SHORT_RESPONSE_HOURS) {
  122. $data['exception_status'] = '在途异常';
  123. }
  124. }
  125. //在途异常修正为派送异常
  126. if ((($data['exception_status'] ?? '') === '在途异常') && (($data['status'] ?? '') === '派送中')) {
  127. $data['exception_status'] = '派送异常';
  128. }
  129. //内容中有一下信息的,视为签收
  130. if (Str::contains($last_remark, ['代收', '快递柜', '驿站', '自提柜', '丰巢', '快递小屋', '合作点', '快递超市', '签收'])) {
  131. $data = $this->setStatus已签收($data, $last_transfer_accept_time);
  132. }
  133. }
  134. }
  135. //如果复核时间>前一天的23.59,则不添加异常信息
  136. if ((!empty($sent_at)) &&
  137. ($sent_at->gt(now()->subDay()->startOfDay()->addHours(23)->addMinutes(59))) &&
  138. isset($data['exception_status'])) {
  139. unset($data['exception_status']);
  140. }
  141. //邮政待揽收状态不是在途
  142. $logistic_id = $orderPackage->order->logistic_id ?? null;
  143. //判断承运商是否为邮政
  144. $data = $this->邮政实际待揽收由在途改为已复核($logistic_id, $transfer_status, $data);
  145. return $data;
  146. }
  147. /**
  148. * 按照accept_time倒序排序
  149. * @param $transfer_status
  150. * @return mixed
  151. */
  152. private function sortTransferStatusByAcceptTimeDESC($transfer_status)
  153. {
  154. usort($transfer_status, function ($a, $b) {
  155. if ($a['accept_time'] === $b['accept_time']) {
  156. return 0;
  157. }
  158. return ($a['accept_time'] > $b['accept_time']) ? -1 : 1;
  159. });
  160. return $transfer_status;
  161. }
  162. /**
  163. * 获取最新一条路由信息的remark
  164. * @param $transfer_status
  165. * @return mixed
  166. */
  167. private function getLastRemark($transfer_status)
  168. {
  169. //部分接口的remark在accept_address字段中
  170. return empty(!$transfer_status['remark']) ? $transfer_status['remark'] : $transfer_status['accept_address'];
  171. }
  172. /**
  173. * @param array $data
  174. * @param $last_transfer_accept_time
  175. * @return array
  176. */
  177. private function setStatus已签收(array $data, $last_transfer_accept_time): array
  178. {
  179. $data['exception_status'] = '';
  180. $data['status'] = '已签收';
  181. $data['received_at'] = $last_transfer_accept_time;
  182. return $data;
  183. }
  184. /**
  185. * @param $logistic_id
  186. * @param $transfer_status
  187. * @param array $data
  188. * @return array
  189. */
  190. private function 邮政实际待揽收由在途改为已复核($logistic_id, $transfer_status, array $data): array
  191. {
  192. if ((!empty($logistic_id)) && ($logistic_id === 6 || $logistic_id === 88)) {
  193. if (!empty($transfer_status)) {
  194. $this->sortTransferStatusByAcceptTimeDESC($transfer_status);
  195. $last_remark = $this->getLastRemark($transfer_status[0]);
  196. if (Str::contains($last_remark, ['等待揽收', '商品已下单'])) {
  197. $data['status'] = '已复核';
  198. }
  199. }
  200. }
  201. return $data;
  202. }
  203. }