OrderPackageService.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. <?php
  2. namespace App\Services;
  3. use App\Logistic;
  4. use App\OracleActAllocationDetails;
  5. use App\OracleDOCOrderDetail;
  6. use App\OracleDOCOrderHeader;
  7. use App\Order;
  8. use App\OrderPackage;
  9. use App\OrderPackageCommodities;
  10. use App\OrderTracking;
  11. use App\Services\common\BatchUpdateService;
  12. use App\Services\common\DataHandlerService;
  13. use Carbon\Carbon;
  14. use App\Traits\ServiceAppAop;
  15. use Illuminate\Database\Eloquent\Builder;
  16. class OrderPackageService
  17. {
  18. use ServiceAppAop;
  19. protected $modelClass=OrderPackage::class;
  20. public function batchUpdate(array $params){
  21. return app(BatchUpdateService::class)->batchUpdate('order_packages',$params);
  22. }
  23. /**
  24. * @param string $logistic_number
  25. * @param array $values
  26. * @return OrderPackage $package
  27. */
  28. public function firstOrCreate($logistic_number, array $values){
  29. /** @var $package OrderPackage */
  30. $package = OrderPackage::query()->where('logistic_number',$logistic_number)->first();
  31. if ($package)return $package;
  32. /** @var OrderService */
  33. $order = app('OrderService')->logisticNumberFirstOrCreateOrder($logistic_number);
  34. if ($order) $values["order_id"] = $order->id;
  35. $values["logistic_number"] = $logistic_number;
  36. /** @var OrderPackage $package */
  37. $package = OrderPackage::query()->create($values);
  38. return $package;
  39. }
  40. public function createExceptionPaginate($paginate)
  41. {
  42. return OrderPackage::query()->select('id', 'status', 'logistic_number', 'measuring_machine_id', 'weighed_at', 'weight', 'length', 'width', 'height', 'bulk', 'paper_box_id')
  43. ->where('status', '上传异常')->orWhere('status', '测量异常')->orderBy('created_at', 'DESC')
  44. ->paginate($paginate);
  45. }
  46. public function issueExceptionPaginate($paginate)
  47. {
  48. return OrderPackage::query()->select('id', 'logistic_number', 'created_at', 'batch_number', 'batch_rule')
  49. ->where('status', '下发异常')->orWhere('status', '记录异常')
  50. ->orWhere('uploaded_to_wms', '异常')->orderBy('created_at', 'DESC')
  51. ->paginate($paginate);
  52. }
  53. public function getByWmsOrders($orderHeaders){
  54. $order_nos = data_get($orderHeaders,'*.orderno');
  55. return OrderPackage::query()->with('order')
  56. ->whereIn('order_id',function($query) use ($order_nos){
  57. $query->from('orders')->select('id')->whereIn('code',$order_nos);
  58. })->get();
  59. }
  60. public function create(array $params)
  61. {
  62. if(count($params) == 0)return null;
  63. try {
  64. $this->insert($params);
  65. app('LogService')->log(__METHOD__,__FUNCTION__,'批量生成 orderPackage' . count($params) . json_encode($params));
  66. } catch (\Exception $e) {
  67. app('LogService')->log(__METHOD__,__FUNCTION__,'批量生成 orderPackage error ' . json_encode($params) . $e->getMessage() . $e->getTraceAsString());
  68. } finally {
  69. $logistic_numbers = data_get($params,'*.logistic_number');
  70. unset($params);
  71. return OrderPackage::query()->whereIn('logistic_number',$logistic_numbers)->get();
  72. }
  73. }
  74. public function getByOrderNos($orderNos)
  75. {
  76. return OrderPackage::query()->with('order')
  77. ->whereIn('order_id',function($query)use($orderNos){
  78. $query->from('orders')->select('id')->whereIn('code',$orderNos);
  79. })->get();
  80. }
  81. public function update($orderClientNo,$logisticNumber)
  82. {
  83. $order = Order::query()->with('packages.commodities.commodity')->where('client_code',$orderClientNo)->first();
  84. if(!$order){
  85. $order = Order::query()->create(['client_code'=>$orderClientNo]);
  86. }
  87. $orderPackage = OrderPackage::query()->where('logistic_number',$logisticNumber)->first();
  88. if($orderPackage){return compact('orderPackage','order');}
  89. $orderPackage = OrderPackage::query()->create(['order_id'=>$order->id,'logistic_number'=>$logisticNumber]);
  90. return compact('orderPackage','order');
  91. }
  92. public function syncOrderPackage(&$orderHeaders)
  93. {
  94. $this->syncPackageByOrderHeaders($orderHeaders);
  95. }
  96. public function syncPackageByOrderHeaders(&$orderHeaders)
  97. {
  98. /** @var OrderService $orderService */
  99. $orderService = app('OrderService');
  100. if(!$orderHeaders)return;
  101. $orders = $orderService->getByWmsOrders($orderHeaders);
  102. $this->processCancelOrderPackages($orderHeaders); // 取消订单操作 及 过滤
  103. $packages = $this->getByOrderNos(data_get($orderHeaders,'*.orderno')); // 已有
  104. $this->createOrderPackage($orderHeaders,$orders,$packages); // 创建package
  105. $this->updatePackage($orderHeaders,$packages);
  106. $this->deleteUnnecessaryPackage($orderHeaders,$packages); // 删除package
  107. unset($orders,$packages); // 手动清除
  108. }
  109. public function createOrderPackage($orderHeaders,$orders,$packages)
  110. {
  111. if(!$orderHeaders)return;
  112. /**
  113. * @var DataHandlerService $dataHandlerService
  114. * @var LogisticService $logsitcService
  115. */
  116. $logisticService = app(LogisticService::class);
  117. $dataHandlerService = app(DataHandlerService::class);
  118. $orderHeaders_map = $dataHandlerService->dataHeader(['orderno'],$orderHeaders);
  119. $packages_maps = $dataHandlerService->dataHeader(['logistic_number'],$packages);
  120. $inner_params = [];
  121. /** 定制京东快递的订单 */
  122. $logistic = $logisticService->getLogisticByCodes(['JDKD'])->first();
  123. foreach ($orders as $order){
  124. $orderHeader = $dataHandlerService->getKeyValue(['orderno'=>$order->code],$orderHeaders_map);
  125. if(!$orderHeader)continue;
  126. if($orderHeader->sotatus == 90)continue;
  127. $params = $this->getInnerParams($orderHeader,$order,$packages_maps,$logistic);
  128. $inner_params = array_merge($inner_params,$params);
  129. }
  130. /** 批量添加 */
  131. if(count($inner_params)>0){
  132. try {
  133. $inner_array = array_chunk($inner_params,5000);
  134. foreach ($inner_array as $params) {
  135. $bool = $this->insert($params);
  136. $bool ? LogService::log(__METHOD__, __FUNCTION__, '批量添加 OrderPackage ' . count($inner_params) . ' || ' . json_encode($inner_params)) : null;
  137. }
  138. } catch (\Exception $e) {
  139. LogService::log(__METHOD__, __FUNCTION__, '批量添加 OrderPackage error ' . count($inner_params) . ' || ' .json_encode($e->getMessage()). json_encode($inner_params).json_encode($e->getTraceAsString()));
  140. }
  141. }
  142. }
  143. public function getInnerParams($orderHeader,$order,$packages_maps,$logistic): array
  144. {
  145. /**
  146. * @var DataHandlerService $dataHandlerService
  147. */
  148. $dataHandlerService = app('DataHandlerService');
  149. $logistic_numbers = array_diff(array_unique(data_get($orderHeader->actAllocationDetails,'*.picktotraceid')),['','*']);
  150. $date = Carbon::now()->format('Y-m-d H:i:s');
  151. $inner_params = [];
  152. $sentAtMap = [];
  153. if($orderHeader['sostatus'] == '90'){
  154. if($orderHeader['soreference5']=='')$logistic_numbers = [$orderHeader['orderno']];
  155. else $logistic_numbers = [$orderHeader['soreference5']];
  156. }
  157. /** sent_at checktime */
  158. foreach ($orderHeader->actAllocationDetails as $item){
  159. $sentAtMap[$item->picktotraceid] = $item;
  160. }
  161. /** 承运商是京东时的定制操作 */
  162. if($order['id'] == $logistic['id'] && count($logistic_numbers) == 1){
  163. $logistic_numbers = [$orderHeader['soreference5']];
  164. $sentAtMap[$orderHeader['soreference5']] = $orderHeader->actAllocationDetails->first() ?? null;
  165. }
  166. foreach ($logistic_numbers as $logistic_number){
  167. $package = $dataHandlerService->getKeyValue(['logistic_number'=>$logistic_number],$packages_maps);
  168. if(isset($package))continue;
  169. try {
  170. $data = $sentAtMap[$logistic_number];
  171. } catch (\Exception $e) {
  172. $data = null;
  173. }
  174. $inner_params[] = [
  175. 'order_id' => $order->id,
  176. 'logistic_number' => $logistic_number,
  177. 'created_at' => $date,
  178. 'updated_at' => $date,
  179. 'status' => '无',
  180. 'owner_id' => $order->owner_id,
  181. 'sent_at' => $data ? $data->checktime:null,
  182. ];
  183. }
  184. return $inner_params;
  185. }
  186. public function deleteUnnecessaryPackage($orderHeaders,$packages)
  187. {
  188. /**
  189. * @var DataHandlerService $dataHandlerService
  190. * @var OrderTrackingService $orderTrackingService
  191. * @var OrderPackageCommoditiesService $orderPackageCommoditiesService
  192. */
  193. $dataHandlerService = app(DataHandlerService::class);
  194. $orderPackageCommoditiesService = app('OrderPackageCommoditiesService');
  195. /** 获取所有的 picktotraceid WMS快递单号*/
  196. $logistic_numbers = data_get($orderHeaders,'*.actAllocationDetails.*.picktotraceid');
  197. /** WMS定制化操作 订单取消 和 京东快递*/
  198. foreach ($orderHeaders as $orderHeader) {
  199. if($orderHeader['sostatus'] == '90'){
  200. if($orderHeader['soreference5']=='')$logistic_numbers[] =$orderHeader['orderno'];
  201. else $logistic_numbers[] = $orderHeader['soreference5'];
  202. }
  203. if($orderHeader['userdefine1'] == 'JDKD'){
  204. $logistic_numbers[] = $orderHeader['soreference5'];
  205. }
  206. }
  207. /** WMS快递单号唯一化 剔除 '',' ','*'*/
  208. $logistic_numbers = array_unique(array_values($logistic_numbers));
  209. $logistic_numbers = array_diff($logistic_numbers,['',' ','*']);
  210. /** WAS数据库中已有的快递单号*/
  211. $packages_maps = $dataHandlerService->dataHeader(['logistic_number'],$packages);
  212. $exits_number = data_get($packages,'*.logistic_number');
  213. /** WMS快递单号 和 WAS的快递单号 的差集*/
  214. $packages = [];
  215. $diff_number = array_diff($exits_number,$logistic_numbers);
  216. /** 记录差集对应的OrderPackage的id*/
  217. foreach ($diff_number as $number) {
  218. $package = $dataHandlerService->getKeyValue(['logistic_number'=>$number],$packages_maps);
  219. if($package ?? false)$packages[]=$package->id;
  220. }
  221. /** 删除 OrderPackage 和 OrderPackageCommodities*/
  222. if(count($packages)==0)return;
  223. try {
  224. $bool = OrderPackage::query()->whereIn('id', $packages)->delete();
  225. $orderPackageCommodities = OrderPackageCommodities::query()->whereIn('order_package_id',$packages)->get();
  226. $orderPackageCommoditiesService->deleteOrderCommodities($orderPackageCommodities);
  227. $bool ? LogService::log(__METHOD__,__FUNCTION__,'删除多余包裹 ids:'.json_encode($packages)) : null;
  228. } catch (\Exception $e) {
  229. LogService::log(__METHOD__,__FUNCTION__,'删除多余包裹 ids:'.json_encode($packages).$e->getMessage());
  230. }
  231. }
  232. private function updatePackage($orderHeaders, $packages)
  233. {
  234. $map = $this->getSentAtMap($orderHeaders);
  235. $update_params = [];
  236. $update_params[] = ['id','sent_at'];
  237. foreach ($packages as $package) {
  238. if ($package->sent_at) continue;
  239. try {
  240. $checktime = $map[$package->logistic_number];
  241. } catch (\Exception $e) {
  242. continue;
  243. }
  244. if ($checktime) {
  245. $update_params[] = [
  246. 'id' => $package->id,
  247. 'sent_at' => $checktime,
  248. ];
  249. }else {
  250. continue;
  251. }
  252. }
  253. $this->batchUpdate($update_params);
  254. }
  255. /**
  256. * @param $orderHeaders
  257. * @return array
  258. */
  259. private function getSentAtMap($orderHeaders): array
  260. {
  261. $map = [];
  262. foreach ($orderHeaders as $orderHeader) {
  263. $actAllocationDetails = $orderHeader->actAllocationDetails;
  264. foreach ($actAllocationDetails as $actAllocationDetail) {
  265. $logistic_number = $actAllocationDetail->picktotraceid;
  266. $map[$logistic_number] = $actAllocationDetail->checktime;
  267. }
  268. }
  269. return $map;
  270. }
  271. public function processCancelOrderPackages(&$orderHeaders)
  272. {
  273. $cancelOrder = $orderHeaders->filter(function($orderHeader){
  274. return $orderHeader->wms_status == '订单取消';
  275. });
  276. $orderPackages = OrderPackage::query()->whereIn('order_id',function($query)use($cancelOrder){
  277. /** @var Builder $query */
  278. $query->from((new Order())->getTable())->where('code',data_get($cancelOrder,'*.orderno'));
  279. })->get();
  280. if($orderPackages->count() == 0)return ;
  281. $updateParams = [['id','logistic_number']];
  282. foreach ($orderPackages as $orderPackage) {
  283. if(strstr($orderPackage['logistic_number'],'cancel'))continue;
  284. $updateParams[] = ['id'=>$orderPackage['id'],'logistic_number' => $orderPackage['logistic_number'].'_cancel'];
  285. }
  286. if(count($updateParams)>0)$this->batchUpdate($updateParams);
  287. $orderHeaders = $orderHeaders->filter(function($orderHeader){
  288. return $orderHeader->wms_status != '订单取消';
  289. });
  290. $items = OrderTracking::query()->whereIn('order_package_commodity_id',function($query)use($orderPackages){
  291. /** @var Builder $query */
  292. $query->from((new OrderPackageCommodities)->getTable())->selectRaw('id')->whereIn('order_package_id',data_get($orderPackages,'*.id'));
  293. })->get();
  294. app(OrderTrackingService::class)->deleteOrderTracings($items);
  295. }
  296. }