Просмотр исходного кода

Merge branch 'master' into zengjun

ajun 5 лет назад
Родитель
Сommit
94a71ee17c
50 измененных файлов с 1806 добавлено и 530 удалено
  1. 44 0
      app/Console/Commands/SyncOrderPackageLogisticRouteTask.php
  2. 3 0
      app/Console/Kernel.php
  3. 94 0
      app/Filters/OrderPackageFilters.php
  4. 1 1
      app/Http/Controllers/MeasureMonitorController.php
  5. 5 2
      app/Http/Controllers/OrderIssueController.php
  6. 34 0
      app/Http/Controllers/PackageLogisticController.php
  7. 46 0
      app/Http/Controllers/TestController.php
  8. 4 4
      app/Http/Controllers/WeighController.php
  9. 44 0
      app/Jobs/OrderPackageReceivedSync.php
  10. 6 1
      app/OrderPackage.php
  11. 1 4
      app/Policies/CustomerLogPolice.php
  12. 4 0
      app/Providers/AppServiceProvider.php
  13. 29 0
      app/Providers/LogisticProvider.php
  14. 206 0
      app/Services/LogisticSFService.php
  15. 32 0
      app/Services/LogisticZopService.php
  16. 11 0
      app/Services/OrderIssueService.php
  17. 137 0
      app/Services/OrderPackageReceivedSyncService.php
  18. 0 1
      app/Services/StationTaskCommodityService.php
  19. 23 0
      app/library/zop/README.md
  20. 61 0
      app/library/zop/ZopClient.php
  21. 20 0
      app/library/zop/ZopHttpUtil.php
  22. 46 0
      app/library/zop/ZopProperties.php
  23. 59 0
      app/library/zop/ZopRequest.php
  24. 5 1
      composer.json
  25. 44 468
      composer.lock
  26. 110 0
      config/api_logistic.php
  27. 32 0
      database/migrations/2020_12_16_114152_delete_status_to_order_package.php
  28. 47 0
      database/migrations/2020_12_16_114253_add_status_and_sent_and_at_and_received_at_and_execption_and_tarnsfer_status_and_remark_to_order_package.php
  29. 3 3
      resources/views/layouts/menu.blade.php
  30. 3 0
      resources/views/order/issue/index.blade.php
  31. 150 0
      resources/views/package/logistic/index.blade.php
  32. 4 1
      resources/views/package/measureMonitor/index.blade.php
  33. 1 1
      resources/views/package/measureMonitor/menu.blade.php
  34. 19 0
      resources/views/package/menu.blade.php
  35. 4 3
      resources/views/package/weigh/create.blade.php
  36. 3 2
      resources/views/package/weigh/index.blade.php
  37. 20 0
      resources/views/package/weigh/menu.blade.php
  38. 1 1
      resources/views/package/weigh/record/menu.blade.php
  39. 2 1
      resources/views/package/weigh/statistics.blade.php
  40. 0 0
      resources/views/package/weightExcepted/index.blade.php
  41. 0 0
      resources/views/package/weightExcepted/menu.blade.php
  42. 0 31
      resources/views/weight/menu.blade.php
  43. 22 5
      routes/web.php
  44. 27 0
      tests/Services/LogisticQiaoSFService/LogisticQiaoSFServiceTest.php
  45. 32 0
      tests/Services/LogisticZopService/LogisticZopServiceTest.php
  46. 87 0
      tests/Services/OrderPackageReceivedSyncService/TestGetLogisticNumbers.php
  47. 45 0
      tests/Services/OrderPackageReceivedSyncService/TestGetLogisticRoutes.php
  48. 62 0
      tests/Services/OrderPackageReceivedSyncService/TestSyncLogisticRouteApi.php
  49. 94 0
      tests/Services/OrderPackageReceivedSyncService/TestUpdate.php
  50. 79 0
      yarn.lock

+ 44 - 0
app/Console/Commands/SyncOrderPackageLogisticRouteTask.php

@@ -0,0 +1,44 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Services\OrderPackageReceivedSyncService;
+use Illuminate\Console\Command;
+
+class SyncOrderPackageLogisticRouteTask extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'syncOrderPackageLogisticRouteTask';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Command description';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @throws \Exception
+     */
+    public function handle()
+    {
+        ini_set('memory_limit','1226M');
+        (new OrderPackageReceivedSyncService)->syncLogisticRoute();
+    }
+}

+ 3 - 0
app/Console/Kernel.php

@@ -9,6 +9,7 @@ use App\Console\Commands\LogExpireDelete;
 use App\Console\Commands\MakeServiceCommand;
 use App\Console\Commands\SyncBatchTask;
 use App\Console\Commands\SyncLogCacheTask;
+use App\Console\Commands\SyncOrderPackageLogisticRouteTask;
 use App\Console\Commands\SyncUserVisitMenuLogsCacheTask;
 use App\Console\Commands\SyncWmsCommoditiesInformation;
 use App\Console\Commands\SyncWMSOrderTask;
@@ -37,6 +38,7 @@ class Kernel extends ConsoleKernel
         TestTemp::class,
         SyncBatchTask::class,
         SyncWMSOrderTask::class,
+        SyncOrderPackageLogisticRouteTask::class,
         SyncWmsCommoditiesInformation::class,
         ClearCancelledOrderTask::class,
         WasSyncWmsAsnInformation::class,
@@ -60,6 +62,7 @@ class Kernel extends ConsoleKernel
         $schedule->command('createOwnerAreaReport')->monthlyOn(25);
         $schedule->command('sync:batch')->everyMinute();
         $schedule->command('sync:order')->everyMinute();
+        $schedule->command('syncOrderPackageLogisticRouteTask')->dailyAt('12:50')();//同步快递信息到orderPackage
         $schedule->command('SyncWmsCommoditiesInformation')->everyMinute();
         $schedule->command('clear:cancelledOrder')->everyTenMinutes();
         $schedule->command('WasSyncWmsAsnInformation')->everyMinute();

+ 94 - 0
app/Filters/OrderPackageFilters.php

@@ -0,0 +1,94 @@
+<?php
+
+
+namespace App\Filters;
+
+use App\Order;
+use Illuminate\Http\Request;
+use phpDocumentor\Reflection\Types\Boolean;
+
+class OrderPackageFilters
+{
+    protected $request;
+    protected $queryBuilder;
+    protected $filters = ['logistic_number', 'status', 'received_at_start',
+        'received_at_end', 'is_weighed', 'logistic_id', 'owner_id', 'sent_at_start', 'sent_at_end', 'is_exception'];
+
+    public function __construct(Request $request)
+    {
+        $this->request = $request;
+    }
+
+    public function apply($builder)
+    {
+        $this->queryBuilder = $builder;
+        $filters = array_filter($this->request->only($this->filters));
+        foreach ($filters as $filter => $value) {
+            if (method_exists($this, $filter)) {
+                $this->$filter($value, $this->queryBuilder);
+            }
+        }
+        return $this->queryBuilder;
+    }
+
+
+    private function logistic_number($logistic_number)
+    {
+        $this->queryBuilder->where('logistic_number', $logistic_number);
+    }
+
+    private function status($status)
+    {
+        $this->queryBuilder->where('status', $status);
+    }
+
+    private function received_at_start($received_at_start)
+    {
+        $this->queryBuilder->where('received_at', '>=', $received_at_start);
+    }
+
+    private function received_at_end($received_at_end)
+    {
+        $this->queryBuilder->where('received_at', '<=', $received_at_end);
+    }
+
+    private function is_weighed($is_weighed)
+    {
+        if ($is_weighed == 'true') {
+            $this->queryBuilder->whereNotNull('weighed_at');
+        } else {
+            $this->queryBuilder->whereNull('weighed_at');
+        }
+    }
+
+    private function logistic_id($logistic_id)
+    {
+        $logistic_ids = array_filter(preg_split('/[,, ]+/is', $logistic_id));
+        $this->queryBuilder->whereIn('order_id',function($query)use($logistic_ids){
+            $query->from('orders')->select('id')->whereIn('logistic_id',$logistic_ids);
+        });
+    }
+
+    private function owner_id($owner_id)
+    {
+        $owner_ids = array_filter(preg_split('/[,, ]+/is', $owner_id));
+        $this->queryBuilder->whereIn('order_id',function($query)use($owner_ids){
+            $query->from('orders')->select('id')->whereIn('owner_id',$owner_ids);
+        });
+    }
+
+    private function sent_at_start($sent_at_start)
+    {
+        $this->queryBuilder->where('sent_at', '>=', $sent_at_start);
+    }
+
+    private function sent_at_end($sent_at_end)
+    {
+        $this->queryBuilder->where('sent_at', '<=', $sent_at_end);
+    }
+
+    private function is_exception($is_exception)
+    {
+        $this->queryBuilder->where('exception', $is_exception);
+    }
+}

+ 1 - 1
app/Http/Controllers/MeasureMonitorController.php

@@ -17,7 +17,7 @@ class MeasureMonitorController extends Controller
     {
         $measuringMachines=MeasuringMachine::query()->select('id','name','code','status')->get();
         $laravelEchoPrefix = config('database.redis.options.prefix');
-        return view('weight.measureMonitor.index',compact('laravelEchoPrefix','measuringMachines'));
+        return view('package.measureMonitor.index',compact('laravelEchoPrefix','measuringMachines'));
     }
 
     public function data(Request $request){

+ 5 - 2
app/Http/Controllers/OrderIssueController.php

@@ -650,7 +650,10 @@ class OrderIssueController extends Controller
                     $send_order_amount.=$commodities->amount.",\r\n";
                 });
             });
-
+            $userWorkgroupsName = '';
+            $order_issue->userWorkgroups->each(function ($userWorkgroup)use (&$userWorkgroupsName) {
+                $userWorkgroupsName.=($userWorkgroup->name).",\r\n";
+            });
             $json[] = [
                 isset($order_issue->created_at) ? str_split($order_issue->created_at,10)[0] :'',       // 登记日期
                 isset($order->created_at) ? str_split($order->created_at,10)[0] :'',             // 创建日期
@@ -702,7 +705,7 @@ class OrderIssueController extends Controller
                 $order_issue->logistic_express_remission,
                 $order_issue->baoshi_indemnity_money,
                 $order_issue->baoshi_express_remission,
-                $order_issue->userWorkGroup->name ?? '',
+                rtrim($userWorkgroupsName,",\r\n")
             ];
         }
         $mergeColumn = ['A','B','C','D','E','F','G','H','I','J','K','L','P','T','X','Y','Z','AA','AF','AG','AH','AI','AJ','AK'];   // 合并行

+ 34 - 0
app/Http/Controllers/PackageLogisticController.php

@@ -0,0 +1,34 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Filters\OrderPackageFilters;
+use App\Logistic;
+use App\OrderPackage;
+use App\Owner;
+use Illuminate\Http\Request;
+
+class PackageLogisticController extends Controller
+{
+    //
+
+
+    /**
+     * PackageLogisticsController constructor.
+     */
+    public function __construct()
+    {
+        $this->middleware('auth');
+    }
+
+    public function index(Request $request,OrderPackageFilters $filters)
+    {
+        $paginateParams = $request->input();
+        $orderPackages = OrderPackage::query()->filter($filters)->with(['order' => function ($query) {
+            $query->with(['logistic', 'owner', 'packages.commodities']);
+        }])->orderByDesc('id')->paginate($request->paginate ?? 50);
+        $logistics = Logistic::all();
+        $owners = Owner::all();
+        return view('package.logistic.index', compact('orderPackages', 'logistics', 'owners','paginateParams'));
+    }
+}

+ 46 - 0
app/Http/Controllers/TestController.php

@@ -59,12 +59,14 @@ use App\Services\DocWaveHeaderService;
 use App\Services\FeatureService;
 use App\Services\InventoryCompareService;
 use App\Services\LogisticService;
+use App\Services\LogisticZopService;
 use App\Services\LogService;
 use App\Services\OracleBasSkuService;
 use App\Services\OracleDocAsnHerderService;
 use App\Services\OracleDOCOrderHeaderService;
 use App\Services\OracleDocWaveDetailService;
 use App\Services\OrderCommodityService;
+use App\Services\OrderPackageReceivedSyncService;
 use App\Services\OrderPackageService;
 use App\Services\OrderService;
 use App\Services\OrderTrackingOwnerService;
@@ -1463,6 +1465,50 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
         }
     }
 
+    public function testHz(){
+        dump('start'.Carbon::now()->toDateTimeString());
+        $ownerAreaReportTask=new CreateOwnerAreaReport();
+        $ownerAreaReportTask->handle();
+        $ownerBillReportTask= new CreateOwnerBillReport();
+        $ownerBillReportTask->handle();
+        $ownerReportTask= new CreateOwnerReport();
+        $ownerReportTask->handle();
+        dump('end'.Carbon::now()->toDateTimeString());
+    }
+
+    public function testGetLogisticNumbers(): array
+    {
+        $orderPackageReceivedSyncService = new OrderPackageReceivedSyncService();
+        return $orderPackageReceivedSyncService->getLogisticNumbers();
+    }
+
+    public function test_orderPackage_updated()
+    {
+        $orderPackageReceivedSyncService = new OrderPackageReceivedSyncService();
+        $response = $orderPackageReceivedSyncService->getLogisticRoutes(['SF' => ['SF1038343374236']]);
+
+        $orderPackage = OrderPackage::query()->where('logistic_number', 'SF1038343374236')->first();
+        $orderPackage->transfer_status = json_decode($orderPackage->transfer_status);
+
+        $orderPackageReceivedSyncService->update($response);
+        $orderPackage = OrderPackage::query()->where('logistic_number', 'SF1038343374236')->first();
+        $orderPackage->transfer_status = json_decode($orderPackage->transfer_status);
+        dump($orderPackage);
+    }
+
+    public function logistic_route_sync_SF()
+    {
+        $orderPackageReceivedSyncService = new OrderPackageReceivedSyncService();
+        $orderPackageReceivedSyncService->syncLogisticRoute();
+    }
+
+    public function logistic_route_sync_ZT()
+    {
+        $service = new LogisticZopService();
+       $result = $service->get([]);
+       dd($result);
+    }
+
     public function testCancelOrder()
     {
         $service = new OracleDocWaveDetailService();

+ 4 - 4
app/Http/Controllers/PackageController.php → app/Http/Controllers/WeighController.php

@@ -17,7 +17,7 @@ use Illuminate\Support\Facades\Http;
 use Illuminate\Support\Facades\Validator;
 
 
-class PackageController extends Controller
+class WeighController extends Controller
 {
     public function index(Request $request,OwnerService $ownerService)
     {
@@ -26,14 +26,14 @@ class PackageController extends Controller
         /** @var PackageService $application */
         $application = app('PackageService');
         $packages = $application->paginate($request);
-        return view('weight.package.index',['packages'=>$packages,'owners'=>$ownerService->getIntersectPermitting(),'paginateParams'=>$paginateParams]);
+        return view('package.weigh.index',['packages'=>$packages,'owners'=>$ownerService->getIntersectPermitting(),'paginateParams'=>$paginateParams]);
     }
 
     public function create()
     {
         if(!Gate::allows('称重管理-录入')){ return redirect(url('/'));  }
         $paperBoxes=PaperBox::select('id','model')->get();
-        return view('weight.package.create',['paperBoxes'=>$paperBoxes]);
+        return view('package.weigh.create',['paperBoxes'=>$paperBoxes]);
     }
 
     /**
@@ -171,7 +171,7 @@ class PackageController extends Controller
         foreach ($ps as &$p){
             $p = json_encode($p,JSON_UNESCAPED_UNICODE);
         }
-        return view('weight.package.statistics',["packages"=>$ps,'owners'=>$owners,'logistics'=>$logistics]);
+        return view('package.weigh.statistics',["packages"=>$ps,'owners'=>$owners,'logistics'=>$logistics]);
     }
 
     public function export(Request $request){

+ 44 - 0
app/Jobs/OrderPackageReceivedSync.php

@@ -0,0 +1,44 @@
+<?php
+
+namespace App\Jobs;
+
+use App\Services\OrderPackageReceivedSyncService;
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Queue\SerializesModels;
+
+/**
+ * 同步快递路由信息任务 调用时需要延迟1h触发
+ * Class OrderPackageReceivedSync
+ * @package App\Jobs
+ */
+class OrderPackageReceivedSync implements ShouldQueue
+{
+    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+
+    protected $logisticNumbers;
+    protected $service;
+
+    /**
+     * OrderPackageReceivedSync constructor.
+     * @param $logisticNumbers
+     */
+    public function __construct($logisticNumbers)
+    {
+        $this->logisticNumbers = $logisticNumbers;
+        $this->service =  new OrderPackageReceivedSyncService();
+    }
+
+
+    /**
+     * Execute the job.
+     * @return void
+     * @throws \Exception
+     */
+    public function handle()
+    {
+        $this->service->syncLogisticRouteApi($this->logisticNumbers);
+    }
+}

+ 6 - 1
app/OrderPackage.php

@@ -22,7 +22,7 @@ class OrderPackage extends Model
     use ModelTimeFormat;
 
     protected $fillable = ['order_id','logistic_number','batch_number',
-        'batch_rule','bulk','weight','length','width','height','paper_box_id','measuring_machine_id','weighed_at','status'];
+        'batch_rule','bulk','weight','length','width','height','paper_box_id','measuring_machine_id','weighed_at','status','sent_at','received_at','exception','transfer_status','remark'];
 
     public function order(){
         return $this->belongsTo('App\Order','order_id','id');
@@ -272,4 +272,9 @@ class OrderPackage extends Model
         if(strpos($val,'null')!==false)return '';
         return $val;
     }
+
+    public function scopeFilter($query, $filters)
+    {
+        return $filters->apply($query);
+    }
 }

+ 1 - 4
app/Policies/CustomerLogPolice.php

@@ -14,10 +14,7 @@ class CustomerLogPolice
 
     public function update(User $user, CustomerLog $customerLog): bool
     {
-        $lastOne = cache()->remember($this->cache_key . $user->id, 1, function () use ($user) {
-            return CustomerLog::query()->where('user_id', $user->id)->orderByDesc('updated_at')->first();
-        });
-        return (int)$user->id === (int)$customerLog->user_id && $customerLog->id == $lastOne->id;
+        return (int)$user->id === (int)$customerLog->user_id;
     }
 
     public function destroy(User $user, CustomerLog $customerLog)

+ 4 - 0
app/Providers/AppServiceProvider.php

@@ -35,6 +35,7 @@ use App\Services\OracleActAllocationDetailService;
 use App\Services\OrderIssueProcessLogService;
 use App\Services\OrderIssueRejectedBillService;
 use App\Services\OrderIssueService;
+use App\Services\OrderPackageReceivedSyncService;
 use App\Services\OrderPackageService;
 use App\Services\OrderService;
 use App\Services\OrderIssueWorkLoadService;
@@ -201,6 +202,9 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('WarehouseService',WarehouseService::class);
         app()->singleton('WaybillFinancialService',WaybillFinancialService::class);
         app()->singleton('WeighExceptedService',WeighExceptedService::class);
+        app()->singleton('CustomerLogService',CustomerLogService::class);
+        app()->singleton('CustomerLogStatusService',CustomerLogStatusService::class);
+        app()->singleton('OrderPackageReceivedSyncService',OrderPackageReceivedSyncService::class);
     }
 
 

+ 29 - 0
app/Providers/LogisticProvider.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace App\Providers;
+
+use Illuminate\Support\ServiceProvider;
+use \Illuminate\Contracts\Support\DeferrableProvider;
+
+class LogisticProvider extends ServiceProvider implements DeferrableProvider
+{
+    /**
+     * Register services.
+     *
+     * @return void
+     */
+    public function register()
+    {
+        
+    }
+
+    /**
+     * Bootstrap services.
+     *
+     * @return void
+     */
+    public function boot()
+    {
+        //
+    }
+}

+ 206 - 0
app/Services/LogisticSFService.php

@@ -0,0 +1,206 @@
+<?php
+
+
+namespace App\Services;
+
+
+use App\Exceptions\WarningException;
+use Exception;
+use Illuminate\Http\Client\Response;
+use Illuminate\Support\Facades\Http;
+
+class LogisticSFService
+{
+    /**
+     * 顺丰字段与数据库字段的映射关心
+     * @var string[]
+     */
+    protected $protected_switch = [
+        'logistic_number' => 'mailno',
+        'transfer_status' => 'remark',
+        'received_at' => 'accept_time',
+    ];
+
+    /**
+     * 获取顺丰快递揽收数据
+     * @param array $logisticNums [logisticNums]快递单号数组
+     * @return array 快递揽收信息数组
+     * @throws Exception 未知的丰桥opCode
+     */
+    public function get(array $logisticNums): array
+    {
+        // 将$logisticNums以10个位单位进行分割,返回二维数组
+        $logisticNums_size_10 = array_chunk($logisticNums, config('api_logistic.SF.max_size', 10));
+        // 遍历二维数组批量查询顺丰接口
+        //将查询到的结果整合到一起,更新order_packages.received_at
+        $result = [];
+        foreach ($logisticNums_size_10 as $numbers) {
+            $numbersStr = implode(',', $numbers);
+            $result_10 = $this->getResultFromSF(config('api_logistic.SF.head'), $numbersStr, config('api_logistic.SF.check_word'), config('api_logistic.SF.url'));
+            $result = array_merge($result, $result_10);
+        }
+        return $result;
+    }
+
+    /**
+     * @param string $head 客户号
+     * @param string $numbers 快递单号字符串,多个以','分隔
+     * @param string $checkWord 客户秘钥
+     * @param string $url 顺丰接口地址
+     * @return array
+     * @throws Exception 未知的丰桥opCode
+     */
+    public function getResultFromSF(string $head, string $numbers, string $checkWord, string $url): array
+    {
+        $responseBody = get_object_vars(simplexml_load_string($this->sendHttpToSF($head, $numbers, $checkWord, $url))->Body)['RouteResponse'];
+        $result = [];
+        if (is_array($responseBody)) {//SF返回多个单号的查询结果
+            $result = $this->transformSFMoreToArr($responseBody, $result);
+        } else {
+            $result[] = $this->transformSFOneToArr(get_object_vars($responseBody), []);
+        }
+        return $result;
+    }
+
+    /**
+     * 构建顺丰xml请求体
+     * @param string $head
+     * @param string $number
+     * @return string
+     */
+    private function buildXmlStr(string $head, string $number): string
+    {
+        return <<<xml
+<?xml version="1.0" encoding="utf-8" ?>
+    <Request service='RouteService' lang='zh-CN'>
+    <Head>$head</Head>
+    <Body>
+    <RouteRequest
+    tracking_number="{$number}" tracking_type='1' method_type='1'
+    />
+    </Body>
+    </Request>
+xml;
+    }
+
+    /**
+     * 将单个单号的顺丰数据转换为数组
+     * @param array $routeResponse
+     * @param array $data
+     * @return array
+     * @throws Exception
+     */
+    public function transformSFOneToArr(array $routeResponse, array $data): array
+    {
+        $data['logistic_number'] = $routeResponse['@attributes'][$this->protected_switch['logistic_number']];
+        try {
+            $lastRoute = get_object_vars($routeResponse['Route'][count($routeResponse['Route']) - 1])['@attributes'];//获取最新的路由信息
+            $data = $this->switchOpCodeToStatus($lastRoute, $data);
+            $data['transfer_status'] = $this->transformRoutes($routeResponse['Route']);
+
+        } catch (Exception $e) {
+            throw new WarningException("单号没有查询到快递路由信息','LogisticSFService->transformSFOneToArr->{$data['logistic_number']}");
+        } finally {
+            return $data;
+        }
+    }
+
+    /**
+     * 转换快递路由信息
+     * @param array $routs 快递路由
+     * @return array
+     */
+    public function transformRoutes(array $routs): array
+    {
+        $result = [];
+        foreach ($routs as $route) {
+            $route = get_object_vars($route)['@attributes'];
+            $data['accept_time'] = $route['accept_time'];
+            $data['accept_address'] = $route['accept_address'];
+            $data['remark'] = $route['remark'];
+            $result[] = $data;
+        }
+        return $result;
+    }
+
+    /**
+     * 将最新路由信息转换为数组
+     * @param array $lastRoute
+     * @param array $data
+     * @return array
+     * @throws Exception
+     */
+    public function switchOpCodeToStatus(array $lastRoute, array $data): array
+    {
+        switch ($lastRoute['opcode']) {
+            case 123:
+            case 130:
+            case 3036:
+            case 31:
+            case 30:
+                $data['status'] = '在途';
+                break;
+            case 70:
+            case 33:
+                $data['status'] = '派送异常';
+                $data['exception'] = '是';
+                break;
+            case 204:
+            case 44:
+                $data['status'] = '派送中';
+                break;
+            case 50:
+                $data['status'] = '已揽收';
+                break;
+            case 607:
+            case 8000:
+            case 80:
+                $data['status'] = '已收件';
+                $data['received_at'] = $lastRoute[$this->protected_switch['received_at']];
+                break;
+            case 648:
+            case 99:
+                $data['status'] = '返回中';
+                break;
+            default:
+                throw new WarningException("未知的丰桥状态码: {$lastRoute['opcode']}->{json_encode($lastRoute)}");
+        }
+        return $data;
+    }
+
+    /**
+     * @param string $head
+     * @param string $numbers
+     * @param string $checkWord
+     * @param string $url
+     * @return Response
+     * @throws Exception
+     */
+    public function sendHttpToSF(string $head, string $numbers, string $checkWord, string $url): Response
+    {
+        $xml = $this->buildXmlStr($head, $numbers);
+        $checkingJson = $xml . $checkWord;
+        $verifyCode = base64_encode(md5($checkingJson, true));
+        try {
+            $response = Http::withHeaders(['Content-Type' => 'text/xml'])->get($url, ['xml' => $xml, 'verifyCode' => $verifyCode]);
+        } catch (Exception $e) {
+            throw new WarningException("HTTP请求顺丰接口异常->{$e->getMessage()}");
+        }
+        return $response;
+    }
+
+    /**
+     * 将多个顺丰的单号转换为数组
+     * @param array $responseBody
+     * @param array $result
+     * @return array
+     * @throws Exception
+     */
+    public function transformSFMoreToArr(array $responseBody, array $result): array
+    {
+        foreach ($responseBody as $routeResponse) {
+            $result[] = $this->transformSFOneToArr(get_object_vars($routeResponse), []);
+        }
+        return $result;
+    }
+}

+ 32 - 0
app/Services/LogisticZopService.php

@@ -0,0 +1,32 @@
+<?php
+
+
+namespace App\Services;
+
+
+use App\library\zop\ZopClient;
+use App\library\zop\ZopProperties;
+use App\library\zop\ZopRequest;
+
+class LogisticZopService
+{
+    public function get(array $logisticNums)
+    {
+
+        $url = config('api_logistic.ZTO.url');
+        $xAppKey = config('api_logistic.ZTO.x-appKey');
+        $xDataDigest = config('api_logistic.ZTO.x-dataDigest');
+
+        $properties = new ZopProperties($xAppKey, $xDataDigest);
+        $client = new ZopClient($properties);
+        $request = new ZopRequest();
+
+        $request->setUrl($url);
+        $body = json_encode([
+            'type' => 1,
+            'billCode' => '75424921258500',
+        ]);
+        $request->setBody($body);
+        return json_decode($client->execute($request));
+    }
+}

+ 11 - 0
app/Services/OrderIssueService.php

@@ -248,6 +248,17 @@ class OrderIssueService
                 $query->whereIn('id', $userWorkgroupIds);
             });
         }
+        //根据店铺名称模糊筛选
+        if (isset($condition['shop_name'])) {
+            $query->whereHas('order.shop', function ($query) use ($condition) {
+                $this->searchWay($query, $condition['shop_name'].'%', 'name');
+            });
+            if (isset($condition['shop_name_limit_time'])) {
+                $query->Where('order_issues.created_at','>=', Carbon::now()->subDays($condition['shop_name_limit_time']));
+            } else {
+                $query->Where('order_issues.created_at','>=', Carbon::now()->subDays(31));
+            }
+        }
         return $query;
     }
 

+ 137 - 0
app/Services/OrderPackageReceivedSyncService.php

@@ -0,0 +1,137 @@
+<?php
+
+
+namespace App\Services;
+
+
+use App\OrderPackage;
+use Carbon\Carbon;
+use Exception;
+use Illuminate\Database\Eloquent\Collection;
+
+class OrderPackageReceivedSyncService
+{
+    protected $logisticSFService;
+    protected $logisticZopService;
+
+    /**
+     * 同步快递信息
+     * 1 如果当前时间大于初始化时间 每日执行一次,更新order_packages中创建时间大于初始化时间,没有异常,用户未收货的全部订单的快递路由状态
+     * 2 如果当前时间小于等于初始化时间,执行初始化脚本,将数据库中全部小于等于初始化时间的数据更新
+     * @throws Exception
+     */
+    public function syncLogisticRoute()
+    {
+        $this->update($this->getLogisticRoutes($this->getLogisticNumbers()));
+    }
+
+    /**
+     * 根据传递的承运商与快递单号更新快递信息
+     * @param array $logisticNumbers 快递单号
+     * example: ['SF' => ['SF1038651915891', 'SF1038651413847', 'SF1038611050071'],'ZT'=>['75424148714142','548464120822', '75424147834290']....]
+     * @throws Exception 快递接口调用或者返回的信息有误,无法更新指定的快递路由信息
+     */
+    public function syncLogisticRouteApi(array $logisticNumbers)
+    {
+        $this->update($this->getLogisticRoutes($logisticNumbers));
+    }
+
+    /**
+     * 获取快件揽收信息
+     * @param array $request [
+     * 'SF' => ['SF1038651915891', 'SF1038651413847', 'SF1038611050071'],
+     * 'ZT'=>['75424148714142','548464120822', '75424147834290']
+     * ]
+     * @return array
+     * @throws Exception
+     */
+    public function getLogisticRoutes(array $request): array
+    {
+        $this->logisticSFService = new LogisticSFService();
+        $this->logisticZopService = new LogisticZopService();
+        $resultSF = [];
+        $resultZT = [];
+        $resultYD = [];
+        $resultYT = [];
+        $resultOther = [];
+        foreach ($request as $key => $logisticNums) {
+            switch ($key) {
+                case "SF":
+                    $resultSF = $this->logisticSFService->get($logisticNums);
+                    break;
+                case "ZTO":
+//                    $resultZT = $this->logisticZopService->get($logisticNums);
+                    $resultZT = [];
+                    break;
+                case "YD":
+                    $resultYD = [];
+                    break;
+                case "YT":
+                    $resultYT = [];
+                    break;
+                default:
+                    $resultOther = [];
+                    break;
+            }
+        }
+        return array_merge($resultSF, $resultYD, $resultYT, $resultZT, $resultOther);
+    }
+
+    public function update(array $orderPackages)
+    {
+        foreach ($orderPackages as $data) {
+            $orderPackage = OrderPackage::query()->where('logistic_number', $data['logistic_number'])->first();
+            if (isset($data['status'])) $orderPackage->status = $data['status'];
+            if (isset($data['received_at'])) $orderPackage->received_at = $data['received_at'];
+            if (isset($data['exception'])) $orderPackage->exception = $data['exception'];
+            if (isset($data['transfer_status'])) $orderPackage->transfer_status = $data['transfer_status'];
+            $orderPackage->save();
+        }
+    }
+
+    /**
+     * 查询当前日期前的快递单号并按照承运商分类
+     */
+    public function getLogisticNumbers(): array
+    {
+        //初始化时间 2020-12-31 23:59:59
+        $initDate = Carbon::parse(config('api_logistic.init_date'));
+        $data = [];
+        $query = OrderPackage::query()
+            ->with(['order' => function ($query) {
+                return $query->with('logistic');
+            }]);
+        if (Carbon::now()->lte($initDate)) {//当前时间小于等于初始化时间
+            $query = $query->where('created_at', '>=', $initDate->subMonths(1)->toDateTimeString()); //初始化查询一个月的数据
+        } else {//当前时间大于初始化时间
+            $query = $query->where('created_at', '>=', $initDate->toDateTimeString()); //大于等于初始化时间的全部快递单号
+        }
+        $query = $query
+            ->where('exception', '否')
+            ->whereNull('received_at');
+        return $this->buildData($query->get(), $data);
+    }
+
+    /**
+     * 将orderPackage集合分类并摘取指定数据
+     * @param Collection $orderPackages
+     * @param array $data
+     * @return array
+     */
+    private function buildData(Collection $orderPackages, array $data): array
+    {
+        foreach ($orderPackages as $orderPackage) {
+            try {
+                $logisticCode = $orderPackage->order->logistic->code;
+            } catch (Exception $e) {
+                continue;
+            }
+            $key = config('api_logistic.logistic.' . $logisticCode);
+            if (!isset($data[$key])) {
+                $data[$key] = [];
+            }
+            $data[$key][] = $orderPackage->logistic_number;
+        }
+        return $data;
+    }
+}

+ 0 - 1
app/Services/StationTaskCommodityService.php

@@ -52,7 +52,6 @@ class StationTaskCommodityService
             );
         }
         $this->stationTaskService->registerSubTasks($stationTasks_toAttach,$stationTaskCommodities_listByBatch);
-
     }
 
     function createByBatch(Batch $batch): Collection

+ 23 - 0
app/library/zop/README.md

@@ -0,0 +1,23 @@
+# 中通开放平台SDK(php版)
+
+## 使用方式
+
+```php
+use App\library\zop\ZopClient;
+use App\library\zop\ZopProperties;
+use App\library\zop\ZopRequest;
+
+// ZopProperties类的构造方法接收两个参数,分别是companyid和key,都需要注册中通开放平台后到个人中心查看
+$properties = new ZopProperties("kfpttestCode", "kfpttestkey==");
+$client = new ZopClient($properties);
+
+$request = new ZopRequest();
+$request->setUrl("http://58.40.16.120:9001/submitOrderCode");
+$request->setData('{"data":{"content":{"branchId":"","buyer":"","collectMoneytype":"CNY","collectSum":"12.00","freight":"10.00","id":"xfs2018031500002222333","orderSum":"0.00","orderType":"1","otherCharges":"0.00","packCharges":"1.00","premium":"0.50","price":"126.50","quantity":"2","receiver":{"address":"育德路XXX号","area":"501022","city":"四川省,XXX,XXXX","company":"XXXX有限公司","email":"yyj@abc.com","id":"130520142097","im":"yangyijia-abc","mobile":"136*****321","name":"XXX","phone":"010-222***89","zipCode":"610012"},"remark":"请勿摔货","seller":"","sender":{"address":"华新镇华志路XXX号","area":"310118","city":"上海,上海市,青浦区","company":"XXXXX有限公司","email":"ll@abc.com","endTime":1369033200000,"id":"131*****010","im":"1924656234","mobile":"1391***5678","name":"XXX","phone":"021-87***321","startTime":1369022400000,"zipCode":"610012"},"size":"12,23,11","tradeId":"2701843","type":"1","typeId":"","weight":"0.753"},"datetime":"2018-3-30 12:00:00","partner":"test","verify":"ZTO123"}}');
+
+echo $client->execute($request);
+```
+
+## 其他
+1. 该项目刚创建,功能还很不完善,如有问题请提issue
+2. 由于中通开放平台各个接口返回值格式没有统一,所以未封装返回值,未来可能会做封装

+ 61 - 0
app/library/zop/ZopClient.php

@@ -0,0 +1,61 @@
+<?php
+
+
+namespace App\library\zop;
+use App\library\zop\ZopHttpUtil;
+
+class ZopClient
+{
+    private $zopProperties;
+
+    private $httpClient;
+    /**
+     * ZopClient constructor.
+     * @param $zopProperties
+     */
+    public function __construct($zopProperties)
+    {
+        $this->zopProperties = $zopProperties;
+        $this->httpClient = new ZopHttpUtil();
+    }
+
+    public function execute($zopRequest)
+    {
+        if($zopRequest->getBody()==null) {
+            $url = $zopRequest->getUrl();
+            $params = $zopRequest->getParams();
+            $fixedParams = array();
+            foreach ($params as $k => $v) {
+                if (gettype($v) != "string") {
+                    $fixedParams += [$k => json_encode($v)];
+                } else {
+                    $fixedParams += [$k => $v];
+                }
+            }
+            $str_to_digest = "";
+            foreach ($fixedParams as $k => $v) {
+                $str_to_digest = $str_to_digest .$k ."=" .$v ."&";
+            }
+            $str_to_digest = substr($str_to_digest, 0, -1) .$this->zopProperties->getKey();
+            $data_digest = base64_encode(md5($str_to_digest, TRUE));
+            $headers = array(
+                "Content-Type: application/x-www-form-urlencoded; charset=UTF-8",
+                "x-companyid: " .$this->zopProperties->getCompanyid(),
+                "x-datadigest: " .$data_digest
+            );
+            return $this->httpClient->post($url, $headers, http_build_query($fixedParams), 2000);
+        } else{
+            $url = $zopRequest->getUrl();
+            $body = $zopRequest->getBody();
+            $str_to_digest = $body.$this->zopProperties->getKey();
+            $data_digest = base64_encode(md5($str_to_digest, TRUE));
+            $headers = array(
+                "Content-Type: application/json; charset=UTF-8",
+                "x-companyid: ".$this->zopProperties->getCompanyid(),
+                "x-datadigest: ".$data_digest
+            );
+            return $this->httpClient->post($url, $headers, $body, 2000);
+
+        }
+    }
+}

+ 20 - 0
app/library/zop/ZopHttpUtil.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace App\library\zop;
+
+class ZopHttpUtil
+{
+    public function post($url, $headers, $querystring, $timeout)
+    {
+        $ch = curl_init();
+        curl_setopt($ch, CURLOPT_URL, $url);//设置链接
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//设置是否返回信息
+        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);//设置HTTP头
+        curl_setopt($ch, CURLOPT_POST, 1);//设置为POST方式
+        curl_setopt($ch, CURLOPT_TIMEOUT_MS, $timeout);
+        curl_setopt($ch, CURLOPT_POSTFIELDS, $querystring);
+        $response = curl_exec($ch);
+        return $response;
+    }
+
+}

+ 46 - 0
app/library/zop/ZopProperties.php

@@ -0,0 +1,46 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: choco
+ * Date: 6/13/18
+ * Time: 5:47 PM
+ */
+namespace App\library\zop;
+
+
+class ZopProperties
+{
+    private $companyid;
+    private $key;
+
+    /**
+     * ZopProperties constructor.
+     * @param $companyid
+     * @param $key
+     */
+    public function __construct($companyid, $key)
+    {
+        $this->companyid = $companyid;
+        $this->key = $key;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getCompanyid()
+    {
+        return $this->companyid;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getKey()
+    {
+        return $this->key;
+    }
+
+
+
+
+}

+ 59 - 0
app/library/zop/ZopRequest.php

@@ -0,0 +1,59 @@
+<?php
+
+namespace App\library\zop;
+
+
+class ZopRequest
+{
+    private $url;
+    private $params = Array();
+    private $body;
+
+    public function addParam($k, $v)
+    {
+        $this->params += [$k => $v];
+    }
+
+    /**
+     * @param mixed $url
+     */
+    public function setUrl($url)
+    {
+        $this->url = $url;
+    }
+
+    public function setData($data)
+    {
+        $this->params = json_decode($data);
+    }
+
+    public function setBody($body)
+    {
+        $this->body = $body;
+    }
+
+    public function getBody()
+    {
+        return $this->body;
+    }
+
+
+
+    /**
+     * @return mixed
+     */
+    public function getUrl()
+    {
+        return $this->url;
+    }
+
+    /**
+     * @return array
+     */
+    public function getParams()
+    {
+        return $this->params;
+    }
+
+
+}

+ 5 - 1
composer.json

@@ -59,7 +59,11 @@
             "database/factories"
         ],
         "files": [
-            "app/Utils/helpers.php"
+            "app/Utils/helpers.php",
+            "app/library/zop/ZopClient.php",
+            "app/library/zop/ZopHttpUtil.php",
+            "app/library/zop/ZopProperties.php",
+            "app/library/zop/ZopRequest.php"
         ]
     },
     "autoload-dev": {

Разница между файлами не показана из-за своего большого размера
+ 44 - 468
composer.lock


+ 110 - 0
config/api_logistic.php

@@ -0,0 +1,110 @@
+<?php
+return [
+    'logistic'=>[
+        'ZTO' => 'ZTO',
+        'SF' => 'SF',
+        'YUNDA' => 'YUNDA',
+        'STO' => 'STO',
+        'YTO' => 'YTO',
+        'POSTB' => 'OTHER',
+        'EMS' => 'OTHER',
+        'OTHER' => 'OTHER',
+        'DFZPS' => 'OTHER',
+        'DBKD' => 'OTHER',
+        'DBWL' => 'OTHER',
+        'ANWL' => 'OTHER',
+        'ANWLDF' => 'OTHER',
+        'BSZFC' => 'OTHER',
+        'BSZFCDF' => 'OTHER',
+        'BSZX' => 'OTHER',
+        'BSZXDF' => 'OTHER',
+        'DBKDDF' => 'OTHER',
+        'DBWLDF' => 'OTHER',
+        'ECJG' => 'OTHER',
+        'GYZT' => 'OTHER',
+        'KCTZ' => 'OTHER',
+        'KHZT' => 'OTHER',
+        'KNDB' => 'OTHER',
+        'KYSY' => 'OTHER',
+        'KYSYLY' => 'OTHER',
+        'KYSYLYDF' => 'OTHER',
+        'SFCC' => 'SF',
+        'SFCCDF' => 'SF',
+        'SFGJBK' => 'SF',
+        'SFGJTH' => 'SF',
+        'SFJR' => 'SF',
+        'SFJRDF' => 'SF',
+        'SFLD' => 'SF',
+        'SFSX' => 'SF',
+        'SFSY' => 'SF',
+        'SFSYDF' => 'SF',
+        'SFSYQHD' => 'SF',
+        'SFTH' => 'SF',
+        'SFTHBJ' => 'SF',
+        'SFTHDF' => 'SF',
+        'SFTHDFBJ' => 'SF',
+        'SFTHQHD' => 'SF',
+        'SFTHZMJ' => 'SF',
+        'SFTHZMJDF' => 'SF',
+        'SHUNFENG' => 'OTHER',
+        'WPSFSY' => 'SF',
+        'WPZTO' => 'ZTO',
+        'WXWL' => 'OTHER',
+        'XJWL' => 'OTHER',
+        'XJWLDF' => 'OTHER',
+        'ZT' => 'OTHER',
+        'YCT' => 'OTHER',
+        'ZHUANGXIAN' => 'OTHER',
+        'CHANGTONG' => 'OTHER',
+        'YMDD' => 'OTHER',
+        'GUONENG' => 'OTHER',
+        'DUMMY' => 'OTHER',
+        'SANGSONG' => 'OTHER',
+        'JITU' => 'OTHER',
+        'JDKD' => 'OTHER',
+        'SXJD' => 'OTHER',
+        'EMS标准快递' => 'OTHER',
+        '圆通速递' => 'OTHER',
+        '京东快递' => 'OTHER',
+        '邮政快递包裹' => 'OTHER',
+        'SFGJBKDF' => 'SF',
+        '飞扬' => 'OTHER',
+        '测试承运商' => 'OTHER',
+        '货拉拉' => 'OTHER',
+        '运满满' => 'OTHER',
+        '马玉亮' => 'OTHER',
+        '其他' => 'OTHER',
+    ],
+    //丰桥
+    'SF' => [
+        'url' =>  'https://bspsw.sf-express.com/sfexpressService',
+        'head' =>  'BSGYLGL',
+        'check_word' =>  'DcauTQEavq5qqpFaYmltzR7gzVCTjvtz',
+        'max_size' => 10,
+        'op_code_map' => [
+            30 => '快件在【XXX营业点】已装车,准备发往 【XXX集散中心】',
+            31 => '快件到达 【XXX集散中心】',
+            33 => '派件异常原因',
+            3036 => '快件在XXX ,准备送往下一站',
+            44 => '正在派送途中,请您准备签收(派件人:XXX,电话:XXX)',
+            50 => '顺丰已收件',
+            70 => '由于XXX原因 派件不成功',
+            80 => '已签收,感谢使用顺丰,期待再次为您服务',
+            8000 => '在官网"运单资料&签收图",可查看签收人信',
+            130 => '快件到达顺丰店/站',
+            123 => '快件正送往顺丰店/站',
+            607 => '代理收件',
+            99 => '应客户要求,快件正在转寄中',
+            648 => '快件已退回/转寄,新单号为: XXX,快件正在转寄中',
+        ],
+        'received_code' => 80,
+        'error_code' => 33,
+    ],
+    //中通 https://op.zto.cn/#/Console?type=API
+    'ZTO' => [
+        'url' =>  'https://japi.zto.com/zto.open.getOrderInfo',
+        'x-appKey' => 'c51c718eb899e9f706979',
+        'x-dataDigest' => '9f664e3ab08049874aa417720840161a',
+    ],
+    'init_date' => '2021-01-18 23:59:59',
+];

+ 32 - 0
database/migrations/2020_12_16_114152_delete_status_to_order_package.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class DeleteStatusToOrderPackage extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('order_packages', function (Blueprint $table) {
+            $table->dropColumn('status');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('order_packages', function (Blueprint $table) {
+            $table->enum('status',['无','未上传','已上传','未测量','未下发','上传异常','下发异常','记录异常','已上传异常','测量异常'])->default('无')->comment('包裹信息状态');
+        });
+    }
+}

+ 47 - 0
database/migrations/2020_12_16_114253_add_status_and_sent_and_at_and_received_at_and_execption_and_tarnsfer_status_and_remark_to_order_package.php

@@ -0,0 +1,47 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddStatusAndSentAndAtAndReceivedAtAndExecptionAndTarnsferStatusAndRemarkToOrderPackage extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('order_packages', function (Blueprint $table) {
+            //
+            $table->enum('status', ['无', '已称重', '已揽收', '在途', '在途异常', '派送中', '派送异常', '返回中', '返回异常', '返回派件', '其他异常', '已收件'])->default('无')->comment('包裹信息状态');
+            $table->dateTime('sent_at')->nullable()->comment('发出时间');
+            $table->dateTime('received_at')->nullable()->comment('揽收时间');
+            $table->enum('exception', ['是', '否'])->default('否')->comment('异常状态');
+            $table->text('transfer_status')->nullable()->comment('更新信息');
+            $table->string('remark')->nullable()->comment('备注');
+            $table->index(['sent_at', 'exception']);
+            $table->index(['received_at', 'exception']);
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('order_packages', function (Blueprint $table) {
+            $table->dropColumn('status');
+            $table->dropColumn('sent_at');
+            $table->dropColumn('received_at');
+            $table->dropColumn('exception');
+            $table->dropColumn('transfer_status');
+            $table->dropColumn('remark');
+            $table->dropIndex(['sent_at', 'exception']);
+            $table->dropIndex(['received_at', 'exception']);
+        });
+    }
+}

+ 3 - 3
resources/views/layouts/menu.blade.php

@@ -23,10 +23,10 @@
                     <span class="fa fa-truck" style="color: #4c2584"></span>
                     运输管理</a></li> @endcan
         @can('称重管理')
-            <li class="nav-item"><a href="{{url("package")}}" class="nav-link"
+            <li class="nav-item"><a href="{{url("package/weigh/index")}}" class="nav-link"
                                     :class="{active:isActive('package',1)}">
-                    <span class="fa fa-balance-scale" style="color: #1b7234"></span>
-                    称重管理</a></li> @endcan
+                    <span class="fa fa-suitcase" style="color: #1b7234"></span>
+                    包裹管理</a></li> @endcan
         @can('库存管理')
             <li class="nav-item"><a href="{{url('inventory/statement/allInventory')}}" class="nav-link"
                                     :class="{active:isActive('inventory',1)}">

+ 3 - 0
resources/views/order/issue/index.blade.php

@@ -862,6 +862,9 @@
                     },
                     {name: 'logistic_number_return', type: 'input', tip: '退回单号:前或后加百分号为单个模糊搜索,否则为多条件精确搜索', placeholder: '退回单号'},
                     {name: 'send_client_code', type: 'input', tip: '二次订单号:前或后加百分号为单个模糊搜索,否则为多条件精确搜索', placeholder: '二次订单号'},
+                    {name: ['shop_name','shop_name_limit_time'], type: 'input_select', tip: ['处理结果:前或后加 百分号为单个模糊搜索,默认添加后%,否则为多条件精确搜索','查询范围越短,搜索速度越快'], placeholder: ['店铺',''],
+                        data:log_content_range,
+                        rules:[{son:{shop_name_limit_time:{default:'15',required_without_all_if:['created_at_start','created_at_end']}}}]},
                     {name: 'finance_confirm', type: 'select', tip: '财务却认', placeholder: '财务却认是/否', data:[{name: '是',value:'是'},{name: '否',value:'否'}]},
                 ], [
                     {name: 'created_at_end', type: 'dateTime', tip: '登记结束日期'},

+ 150 - 0
resources/views/package/logistic/index.blade.php

@@ -0,0 +1,150 @@
+@extends('layouts.app')
+@section('title')快递@endsection
+
+@section('content')
+    <span id="nav2">
+        @component('package.menu')@endcomponent
+    </span>
+    <div id="list">
+        <div class="container-fluid">
+            <div id="form_div"></div>
+            <table class="table table-striped table-sm text-nowrap table-hover">
+                <tr>
+                    <th>单号</th>
+                    <th>状态</th>
+                    <th>快递公司</th>
+                    <th>货主</th>
+                    <th>发出日期</th>
+                    <th>揽收日期</th>
+                    <th>称重日期</th>
+                    <th>异常标记</th>
+                    <th>快递路由</th>
+                    <th>客服备注</th>
+                </tr>
+                <tr v-for="(package,i) in packages">
+                    <td>@{{ package.logistic_number }}</td>
+                    <td>@{{ package.status }}</td>
+                    <td>@{{ package.order != null  ? package.order.logistic.name : '#' }}</td>
+                    <td>@{{ package.order != null  ? package.order.owner.name : '#' }}</td>
+                    <td>@{{ package.sent_at }}</td>
+                    <td>@{{ package.received_at }}</td>
+                    <td>@{{ package.weighed_at }}</td>
+                    <td>@{{ package.exception }}</td>
+                    <td>
+{{--                        <p v-for="log in getLogs(package.transfer_status)">@{{ log }}</p>--}}
+                        @{{ package.transfer_status | toObjected }}
+                    </td>
+                    <td>@{{ package.remark }}</td>
+                </tr>
+            </table>
+            <div class="text-info h5 btn btn">{{$orderPackages->count()}}/{{$orderPackages->total()}}</div>
+            {{$orderPackages->appends($paginateParams)->links()}}
+        </div>
+    </div>
+@endsection
+
+@section('lastScript')
+    <script type="text/javascript" src="{{mix('js/queryForm/export.js')}}"></script>
+    <script type="text/javascript" src="{{mix('js/queryForm/queryForm.js')}}"></script>
+    <script type="text/javascript" src="{{mix('js/queryForm/header.js')}}"></script>
+    <script>
+        let vue = new Vue({
+            el: "#list",
+            data: {
+                packages: {!!  $orderPackages->toJson() !!}['data'],
+                logistics: [
+                        @foreach($logistics as $logistic)
+                    {
+                        name: '{{$logistic->id}}', value: '{{$logistic->name}}'
+                    },
+                    @endforeach
+                ],
+                owners: [
+                        @foreach($owners as $owner)
+                    {
+                        name: '{{$owner->id}}', value: '{{$owner->name}}'
+                    },
+                    @endforeach
+                ],
+            },
+
+            mounted() {
+                let _this = this;
+                let data = [
+                    [
+                        /*"","","","","","","","","","",""*/
+                        {name: 'logistic_number', type: 'input', tip: '可支持多快递单号,糊模查找需要在左边打上%符号', placeholder: '快递单号'},
+                        {
+                            name: 'status',
+                            type: 'select',
+                            tip: ['输入关键词快速定位下拉列表,回车确定', '选择要显示的状态'],
+                            placeholder: '状态',
+                            data: [{name: '无', value: '无'}, {name: '已称重', value: '已称重'}, {
+                                name: '已揽收',
+                                value: '已揽收'
+                            }, {name: '在途', value: '在途'}, {name: '在途异常', value: '在途异常'}, {
+                                name: '派送中',
+                                value: '派送中'
+                            }, {name: '派送异常', value: '派送异常'}, {name: '返回中', value: '返回中'}, {
+                                name: '返回异常',
+                                value: '返回异常'
+                            }, {name: '返回派件', value: '返回派件'}, {name: '其他异常', value: '其他异常'},]
+                        },
+
+
+                        {name: 'received_at_start', type: 'dateTime', tip: '选择显示揽收时间的起始时间'},
+                        {name: 'received_at_end', type: 'dateTime', tip: '选择显示揽收时间的截止时间'},
+
+                        {
+                            name: 'is_weighed',
+                            type: 'select',
+                            tip: ['输入关键词快速定位下拉列表,回车确定', '选择要显示的状态'],
+                            placeholder: '是否称重',
+                            data: [{name: false, value: '无'}, {name: true, value: '已称重'}]
+                        },
+
+                    ], [
+                        {
+                            name: 'logistic_id',
+                            type: 'select_multiple_select',
+                            tip: ['输入关键词快速定位下拉列表,回车确定', '选择要显示的快递'],
+                            placeholder: ['快递', '定位或多选快递'],
+                            data: _this.logistics
+                        },
+                        {
+                            name: 'owner_id',
+                            type: 'select_multiple_select',
+                            tip: ['输入关键词快速定位下拉列表,回车确定', '选择要显示的货主'],
+                            placeholder: ['货主', '定位或多选货主'],
+                            data: _this.owners
+                        },
+                        {name: 'sent_at_start', type: 'dateTime', tip: '选择显示发出时间的起始时间'},
+                        {name: 'sent_at_end', type: 'dateTime', tip: '选择显示发出时间的截止时间'},
+                        {
+                            name: 'is_exception',
+                            type: 'select',
+                            tip: ['输入关键词快速定位下拉列表,回车确定', '选择要显示的状态'],
+                            placeholder: '是否有异常',
+                            data: [{name: '是', value: '是'}, {name: '否', value: '否'}]
+                        },
+                    ]
+                ];
+                _this.form = new query({
+                    el: '#form_div',
+                    condition: data,
+                });
+                _this.form.init();
+            },
+            methods:{
+                getLogs(value){
+                    return JSON.parse(value);
+                }
+            },
+            filters:{
+                toObjected:function(value){
+                    return JSON.parse(value);
+                }
+            },
+        });
+    </script>
+@endsection

+ 4 - 1
resources/views/weight/measureMonitor/index.blade.php → resources/views/package/measureMonitor/index.blade.php

@@ -2,7 +2,10 @@
 @section('title')设备@endsection
 
 @section('content')
-    @component('weight.menu')@endcomponent
+    <span id="nav2">
+        @component('package.menu')@endcomponent
+        @component('package.weigh.menu')@endcomponent
+    </span>
     <div class="page-holder w-100 d-flex flex-wrap" id="list">
         <div class="container-fluid px-xl-5">
             <section class="py-5">

+ 1 - 1
resources/views/weight/menuWeight.blade.php → resources/views/package/measureMonitor/menu.blade.php

@@ -3,7 +3,7 @@
 
 @section('content')
     <div id="nav2">
-        @component('weight.menu')
+        @component('package.menu')
         @endcomponent
         <div class="container-fluid nav3">
             <div class="card menu-third" >

+ 19 - 0
resources/views/package/menu.blade.php

@@ -0,0 +1,19 @@
+
+<div class="container-fluid nav2" id="nav2">
+    <div class="card">
+        <ul class="nav nav-pills">
+            @can('称重管理-查询')
+                <li class="nav-item">
+                    <a class="nav-link" href="{{url('package/weigh/index')}}" :class="{active:isActive('weigh',2)}">称重管理</a>
+                </li>@endcan
+                {{--TODO 权限修改--}}
+                <li class="nav-item">
+                    <a class="nav-link" href="{{url('package/logistic')}}" :class="{active:isActive('logistic',2)}">快递</a>
+                </li>
+            @can('称重管理-查看异常')
+            <li class="nav-item">
+                <a class="nav-link text-dark" href="{{url('package/relating')}}" :class="{active:isActive('relating',2)}">相关设置</a>
+            </li>@endcan
+        </ul>
+    </div>
+</div>

+ 4 - 3
resources/views/weight/package/create.blade.php → resources/views/package/weigh/create.blade.php

@@ -2,9 +2,10 @@
 @section('title')手动录入@endsection
 
 @section('content')
-    <div id="nav2">
-        @component('weight.menu')@endcomponent
-    </div>
+    <span id="nav2">
+        @component('package.menu')@endcomponent
+        @component('package.weigh.menu')@endcomponent
+    </span>
     <div class="container-fluid" id="package">
         <div class="card col-md-8 offset-md-2">
             <div class="card-body">

+ 3 - 2
resources/views/weight/package/index.blade.php → resources/views/package/weigh/index.blade.php

@@ -4,8 +4,9 @@
 
 @section('content')
     <span id="nav2">
-        @component('weight.menu')@endcomponent
-        @component('weight.package.menu')@endcomponent
+        @component('package.menu')@endcomponent
+        @component('package.weigh.menu')@endcomponent
+        @component('package.weigh.record.menu')@endcomponent
     </span>
     <div class="d-none" id="list">
         <div class="container-fluid">

+ 20 - 0
resources/views/package/weigh/menu.blade.php

@@ -0,0 +1,20 @@
+<div class="container-fluid nav3">
+    <div class="card menu-third" >
+        <ul class="nav nav-pills">
+                @can('称重管理-查询')
+                    <li class="nav-item">
+                        <a class="nav-link" href="{{url('package/weigh/index')}}" :class="{active:isActive('index',3)}">记录</a>
+                    </li>
+                    <li class="nav-item">
+                        <a class="nav-link" href="{{url('package/weigh/measureMonitor')}}" :class="{active:isActive('measureMonitor',3)}">设备</a>
+                    </li>
+                    <li class="nav-item">
+                        <a class="nav-link" href="{{url('package/weigh/statistics')}}" :class="{active:isActive('statistics',3)}">统计</a>
+                    </li>@endcan
+                @can('称重管理-录入')
+                    <li class="nav-item">
+                        <a class="nav-link text-dark" href="{{url('package/weigh/create')}}" :class="{active:isActive('create',3)}">手动录入</a>
+                    </li>@endcan
+        </ul>
+    </div>
+</div>

+ 1 - 1
resources/views/weight/package/menu.blade.php → resources/views/package/weigh/record/menu.blade.php

@@ -3,7 +3,7 @@
         <ul class="nav nav-pills">
             @can('称重管理-查询')
                 <li class="nav-item">
-                    <a class="nav-link" href="{{url('package/')}}" :class="{active:isActive('',2)}">查询</a>
+                    <a class="nav-link" href="{{url('package/weigh/index')}}" :class="{active:isActive('',4)}">查询</a>
                 </li> @endcan
         </ul>
     </div>

+ 2 - 1
resources/views/weight/package/statistics.blade.php → resources/views/package/weigh/statistics.blade.php

@@ -4,7 +4,8 @@
 
 @section('content')
     <span id="nav2">
-        @component('weight.menu')@endcomponent
+        @component('package.menu')@endcomponent
+        @component('package.weigh.menu')@endcomponent
     </span>
     <div class="d-none" id="statistics">
         <div class="container-fluid">

+ 0 - 0
resources/views/weight/weightExcepted/index.blade.php → resources/views/package/weightExcepted/index.blade.php


+ 0 - 0
resources/views/weight/weightExcepted/menu.blade.php → resources/views/package/weightExcepted/menu.blade.php


+ 0 - 31
resources/views/weight/menu.blade.php

@@ -1,31 +0,0 @@
-
-<div class="container-fluid nav2" id="nav2">
-    <div class="card">
-        <ul class="nav nav-pills">
-                @can('称重管理-查询')
-                <li class="nav-item">
-                    <a class="nav-link" href="{{url('package/')}}" :class="{active:isActive('',2)}">记录</a>
-                </li>
-                <li class="nav-item">
-                    <a class="nav-link" href="{{url('package/measureMonitor')}}" :class="{active:isActive('measureMonitor',2)}">设备</a>
-                </li>
-                <li class="nav-item">
-                    <a class="nav-link" href="{{url('package/statistics')}}" :class="{active:isActive('statistics',2)}">统计</a>
-                </li>@endcan
-                @can('称重管理-录入')
-                <li class="nav-item">
-                    <a class="nav-link text-dark" href="{{url('package/create')}}" :class="{active:isActive('create',2)}">手动录入</a>
-                </li>@endcan
-                @can('称重管理-查询')
-                <li class="nav-item">
-                    <a class="nav-link text-dark" href="{{url('package/weightExcepted/indexCreate')}}" :class="{active:isActive('weightExcepted',2)}">异常记录</a>
-                </li>@endcan
-                @can('称重管理-查看异常')
-                <li class="nav-item">
-                    <a class="nav-link text-dark" href="{{url('package/relating')}}" :class="{active:isActive('relating',2)}">相关设置</a>
-                </li>@endcan
-
-
-        </ul>
-    </div>
-</div>

+ 22 - 5
routes/web.php

@@ -324,7 +324,7 @@ Route::group(['prefix'=>'package'],function(){
     });
     /** 统计 */
     Route::group(['prefix'=>'statistics'],function(){
-        Route::any('export','PackageController@statisticsExport');
+        Route::any('export','WeighController@statisticsExport');
     });
     /** 异常 */
     Route::group(['prefix'=>'weightExcepted'],function(){
@@ -333,13 +333,30 @@ Route::group(['prefix'=>'package'],function(){
         Route::any('export/{type}','WeighExceptedController@export');
     });
 
-    Route::any('export','PackageController@export');
-    Route::get('statistics','PackageController@statistics');
-    Route::get('relating', function () {return view('weight.menuWeight');});
+    Route::any('export','WeighController@export');
+    Route::get('statistics','WeighController@statistics');
+    Route::get('relating', function () {return view('package.measureMonitor.menu');});
 
     Route::resource('measureMonitor','MeasureMonitorController');
+
+    Route::group(['prefix' => 'weigh'], function () {
+        Route::get('statistics','WeighController@statistics');
+        /** 设备 */
+        Route::group(['prefix'=>'measureMonitor'],function(){
+            Route::any('speech','MeasureMonitorController@speech');
+            Route::post('data','MeasureMonitorController@data');
+        });
+        /** 统计 */
+        Route::group(['prefix'=>'statistics'],function(){
+            Route::any('export','WeighController@statisticsExport');
+        });
+        Route::resource('measureMonitor','MeasureMonitorController');
+    });
+    Route::get('weigh/index','WeighController@index');
+    Route::resource('weigh','WeighController');
+    Route::resource('logistic','PackageLogisticController');
 });
-Route::resource('package','PackageController');
+Route::resource('package','WeighController');
 
 /** 入库 */
 Route::group(['prefix'=>'store'],function(){

+ 27 - 0
tests/Services/LogisticQiaoSFService/LogisticQiaoSFServiceTest.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace LogisticQiaoSFService;
+
+use App\Services\LogisticSFService;
+use Tests\TestCase;
+
+class LogisticQiaoSFServiceTest extends TestCase
+{
+    protected $logisticQiaoSFService;
+
+    protected function setUp(): void
+    {
+        parent::setUp(); // TODO: Change the autogenerated stub
+        $this->logisticQiaoSFService = new LogisticSFService();
+    }
+
+
+    /**
+     * @test
+     */
+    public function testGet()
+    {
+        $response = $this->logisticQiaoSFService->get(['SF1038651915891','SF1038651413847','SF1038611050071']);
+        $this->assertCount(3, $response);
+    }
+}

+ 32 - 0
tests/Services/LogisticZopService/LogisticZopServiceTest.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace LogisticZopService;
+
+use App\Services\LogisticZopService;
+use Tests\TestCase;
+
+class LogisticZopServiceTest extends TestCase
+{
+    protected $logisticZopService;
+
+    protected function setUp(): void
+    {
+        parent::setUp(); // TODO: Change the autogenerated stub
+        $this->logisticZopService = new LogisticZopService();
+    }
+
+    protected function tearDown(): void
+    {
+        parent::tearDown(); // TODO: Change the autogenerated stub
+    }
+
+    /**
+     * @test
+     */
+    public function get_test()
+    {
+        $result = $this->logisticZopService->get([]);
+        dd($result);
+    }
+
+}

+ 87 - 0
tests/Services/OrderPackageReceivedSyncService/TestGetLogisticNumbers.php

@@ -0,0 +1,87 @@
+<?php
+
+namespace Tests\Services\OrderPackageReceivedSyncService;
+
+use App\Order;
+use App\OrderPackage;
+use App\Services\OrderPackageReceivedSyncService;
+
+use Carbon\Carbon;
+use Illuminate\Database\Eloquent\Collection;
+use Tests\TestCase;
+
+class TestGetLogisticNumbers extends TestCase
+{
+
+    protected $orderPackageIds;
+    protected $orderIds;
+
+    /** @var OrderPackageReceivedSyncService $service */
+    public $service;
+
+    function setUp(): void
+    {
+        parent::setUp();
+        $this->service = app(OrderPackageReceivedSyncService::class);
+    }
+
+    public function testReturned()
+    {
+        $this->assertTrue(true);
+    }
+
+    function tearDown(): void
+    {
+        OrderPackage::destroy($this->orderPackageIds);
+        Order::destroy($this->orderPackageIds);
+        parent::tearDown();
+    }
+
+    /**
+     * 初始化测试查询结果 'init_date' => '2020-12-31 23:59:59' 2020-12-31 应改为当前对应的日期
+     * 目前判断顺丰的快递单号
+     * @test
+     */
+    public function init_test()
+    {
+        //插入初始化时间前10天的数据,每天1条 共11条
+        for ($i = 0; $i <= 10; $i++) {
+            $date = Carbon::now()->subDays($i)->toDateTimeString();
+            $order = factory(Order::class)->create(['created_at' => $date, 'logistic_id' => 47]);
+            $orderPackage = factory(OrderPackage::class)->create(['created_at' => $date, 'order_id' => $order->id]);
+            $this->orderPackageIds[] = $orderPackage->id;
+            $this->orderIds[] = $order->id;
+        }
+        $result =$this->service->getLogisticNumbers();
+        dump($result);
+        $this->assertCount(11,$result['SF']);
+    }
+
+    /**
+     * 正常查询结果 'init_date' => '2020-12-30 23:59:59' 2020-12-30 应改为当前对应的日期的前一天
+     * 目前判断顺丰的快递单号
+     * @test
+     */
+    public function normal_test()
+    {
+        //插入初始化时间前10天的数据,每天1条 共11条
+        for ($i = 0; $i <= 10; $i++) {
+            $date = Carbon::now()->subDays($i)->toDateTimeString();
+            $order = factory(Order::class)->create(['created_at' => $date, 'logistic_id' => 47]);
+            $orderPackage = factory(OrderPackage::class)->create(['created_at' => $date, 'order_id' => $order->id]);
+            $this->orderPackageIds[] = $orderPackage->id;
+            $this->orderIds[] = $order->id;
+        }
+
+        //插入初始化时间后10天的数据,每天1条 共10条
+        for ($i = 1; $i <= 10; $i++) {
+            $date = Carbon::now()->addDays($i)->toDateTimeString();
+            $order = factory(Order::class)->create(['created_at' => $date, 'logistic_id' => 47]);
+            $orderPackage = factory(OrderPackage::class)->create(['created_at' => $date, 'order_id' => $order->id]);
+            $this->orderPackageIds[] = $orderPackage->id;
+            $this->orderIds[] = $order->id;
+        }
+        $result =$this->service->getLogisticNumbers();
+        $this->assertCount(11,$result['SF']);
+    }
+}

+ 45 - 0
tests/Services/OrderPackageReceivedSyncService/TestGetLogisticRoutes.php

@@ -0,0 +1,45 @@
+<?php
+
+namespace Tests\Services\OrderPackageReceivedSyncService;
+
+use App\OrderPackage;
+use App\Services\OrderPackageReceivedSyncService;
+use Illuminate\Foundation\Testing\RefreshDatabase;
+use Tests\TestCase;
+
+class TestGetLogisticRoutes extends TestCase
+{
+    protected $order_package_ids;
+
+    /** @var OrderPackageReceivedSyncService $service */
+    public $service;
+
+    function setUp(): void
+    {
+        parent::setUp();
+        $this->service = app(OrderPackageReceivedSyncService::class);
+    }
+
+    public function testReturned()
+    {
+        $this->assertTrue(true);
+    }
+
+    function tearDown(): void
+    {
+        OrderPackage::destroy($this->order_package_ids);
+        parent::tearDown();
+    }
+
+    /**
+     * 测试顺丰接口连通性
+     * @throws \Exception
+     * @test
+     */
+    public function getMessage()
+    {
+        $data = ['SF' => ['SF1038651915891', 'SF1038651413847', 'SF1038611050071']];
+        $result = $this->service->getLogisticRoutes($data);
+        $this->assertCount(3,$result);
+    }
+}

+ 62 - 0
tests/Services/OrderPackageReceivedSyncService/TestSyncLogisticRouteApi.php

@@ -0,0 +1,62 @@
+<?php
+
+namespace Tests\Services\OrderPackageReceivedSyncService;
+use App\OrderPackage;
+use App\Services\OrderPackageReceivedSyncService;
+use Carbon\Carbon;
+use Tests\TestCase;
+
+class TestSyncLogisticRouteApi extends TestCase
+{
+    protected $order_package_ids;
+
+    /** @var OrderPackageReceivedSyncService $service */
+    public $service;
+    function setUp(): void
+    {
+        parent::setUp();
+        $this->service = app('OrderPackageReceivedSyncService');
+    }
+
+    public function testReturned()
+    {
+        $this->assertTrue(true);
+    }
+
+    function tearDown(): void
+    {
+        OrderPackage::destroy($this->order_package_ids);
+        parent::tearDown();
+    }
+
+    /**
+     * @test 测试主动更新Api
+     * @throws \Exception
+     */
+    public function testUpdate()
+    {
+        $orderPackage1 = factory(OrderPackage::class)->create(['logistic_number' => 'SF1038651915891', 'exception' => '否', 'received_at' => null,]);
+        $orderPackage2 = factory(OrderPackage::class)->create(['logistic_number' => 'SF1038651413847', 'exception' => '否', 'received_at' => null,]);
+        $orderPackage3 = factory(OrderPackage::class)->create(['logistic_number' => 'SF1038611050071', 'exception' => '否', 'received_at' => null,]);
+        $this->order_package_ids [] = $orderPackage1->id;
+        $this->order_package_ids [] = $orderPackage2->id;
+        $this->order_package_ids [] = $orderPackage3->id;
+
+        $this->service->syncLogisticRouteApi(['SF' => ['SF1038651915891', 'SF1038651413847', 'SF1038611050071']]);
+        $this->assertDatabaseHas('order_packages',[
+            'logistic_number' => 'SF1038651915891',
+            'status' => '已收件',
+            'exception' => '否',
+        ]);
+        $this->assertDatabaseHas('order_packages',[
+            'logistic_number' => 'SF1038651413847',
+            'status' => '已收件',
+            'exception' => '否',
+        ]);
+        $this->assertDatabaseHas('order_packages',[
+            'logistic_number' => 'SF1038611050071',
+            'status' => '已收件',
+            'exception' => '否',
+        ]);
+    }
+}

+ 94 - 0
tests/Services/OrderPackageReceivedSyncService/TestUpdate.php

@@ -0,0 +1,94 @@
+<?php
+
+namespace Tests\Services\OrderPackageReceivedSyncService;
+
+use App\OrderPackage;
+use App\Services\OrderPackageReceivedSyncService;
+use Carbon\Carbon;
+use Illuminate\Foundation\Testing\RefreshDatabase;
+use Tests\TestCase;
+
+class TestUpdate extends TestCase
+{
+    protected $order_package_ids;
+
+    /** @var OrderPackageReceivedSyncService $service */
+    public $service;
+
+    function setUp(): void
+    {
+        parent::setUp();
+        $this->service = app(OrderPackageReceivedSyncService::class);
+    }
+
+    public function testReturned()
+    {
+        $this->assertTrue(true);
+    }
+
+    function tearDown(): void
+    {
+        OrderPackage::destroy($this->order_package_ids);
+        parent::tearDown();
+    }
+
+    /**
+     * 测试更新
+     * @test
+     */
+    public function update()
+    {
+        $orderPackage1 = factory(OrderPackage::class)->create(['logistic_number' => 'SF1038651915891', 'exception' => '否', 'received_at' => null,]);
+        $orderPackage2 = factory(OrderPackage::class)->create(['logistic_number' => 'SF1038651413847', 'exception' => '否', 'received_at' => null,]);
+        $orderPackage3 = factory(OrderPackage::class)->create(['logistic_number' => 'SF1038611050071', 'exception' => '否', 'received_at' => null,]);
+        $this->order_package_ids [] = $orderPackage1->id;
+        $this->order_package_ids [] = $orderPackage2->id;
+        $this->order_package_ids [] = $orderPackage3->id;
+
+        $data = [];
+        $data[] = [
+            'logistic_number' => 'SF1038651915891',
+            'status' => '派送中',
+            'received_at' => Carbon::now(),
+            'exception' => '否',
+            'transfer_status' => '快件正在派送',
+        ];
+        $data[] = [
+            'logistic_number' => 'SF1038651413847',
+            'status' => '派送中',
+            'received_at' => Carbon::now(),
+            'exception' => '否',
+            'transfer_status' => '快件正在派送',
+        ];
+        $data[] = [
+            'logistic_number' => 'SF1038611050071',
+            'status' => '派送中',
+            'received_at' => Carbon::now(),
+            'exception' => '否',
+            'transfer_status' => '快件正在派送',
+        ];
+
+        $this->service->update($data);
+        $this->assertDatabaseHas('order_packages',[
+            'logistic_number' => 'SF1038651915891',
+            'status' => '派送中',
+            'received_at' => Carbon::now(),
+            'exception' => '否',
+            'transfer_status' => '快件正在派送',
+        ]);
+        $this->assertDatabaseHas('order_packages',[
+            'logistic_number' => 'SF1038651413847',
+            'status' => '派送中',
+            'received_at' => Carbon::now(),
+            'exception' => '否',
+            'transfer_status' => '快件正在派送',
+        ]);
+        $this->assertDatabaseHas('order_packages',[
+            'logistic_number' => 'SF1038611050071',
+            'status' => '派送中',
+            'received_at' => Carbon::now(),
+            'exception' => '否',
+            'transfer_status' => '快件正在派送',
+        ]);
+    }
+}

+ 79 - 0
yarn.lock

@@ -1258,6 +1258,13 @@ async-limiter@~1.0.0:
   resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd"
   integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==
 
+async-validator@~1.8.1:
+  version "1.8.5"
+  resolved "https://registry.npm.taobao.org/async-validator/download/async-validator-1.8.5.tgz?cache=0&sync_timestamp=1605751734916&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fasync-validator%2Fdownload%2Fasync-validator-1.8.5.tgz#dc3e08ec1fd0dddb67e60842f02c0cd1cec6d7f0"
+  integrity sha1-3D4I7B/Q3dtn5ghC8CwM0c7G1/A=
+  dependencies:
+    babel-runtime "6.x"
+
 async@^2.4.1, async@^2.6.2:
   version "2.6.3"
   resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
@@ -1314,6 +1321,11 @@ babel-code-frame@^6.26.0:
     esutils "^2.0.2"
     js-tokens "^3.0.2"
 
+babel-helper-vue-jsx-merge-props@^2.0.0:
+  version "2.0.3"
+  resolved "https://registry.npm.taobao.org/babel-helper-vue-jsx-merge-props/download/babel-helper-vue-jsx-merge-props-2.0.3.tgz#22aebd3b33902328e513293a8e4992b384f9f1b6"
+  integrity sha1-Iq69OzOQIyjlEyk6jkmSs4T58bY=
+
 babel-loader@^8.0.4:
   version "8.1.0"
   resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3"
@@ -1341,6 +1353,14 @@ babel-plugin-dynamic-import-node@^2.3.3:
   dependencies:
     object.assign "^4.1.0"
 
+babel-runtime@6.x:
+  version "6.26.0"
+  resolved "https://registry.npm.taobao.org/babel-runtime/download/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
+  integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
+  dependencies:
+    core-js "^2.4.0"
+    regenerator-runtime "^0.11.0"
+
 backo2@1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947"
@@ -2151,6 +2171,11 @@ core-js-compat@^3.6.2:
     browserslist "^4.8.5"
     semver "7.0.0"
 
+core-js@^2.4.0:
+  version "2.6.12"
+  resolved "https://registry.npm.taobao.org/core-js/download/core-js-2.6.12.tgz?cache=0&sync_timestamp=1607215907966&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcore-js%2Fdownload%2Fcore-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
+  integrity sha1-2TM9+nsGXjR8xWgiGdb2kIWcwuw=
+
 core-util-is@1.0.2, core-util-is@~1.0.0:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@@ -2470,6 +2495,11 @@ deep-equal@^1.0.1:
     object-keys "^1.1.1"
     regexp.prototype.flags "^1.2.0"
 
+deepmerge@^1.2.0:
+  version "1.5.2"
+  resolved "https://registry.npm.taobao.org/deepmerge/download/deepmerge-1.5.2.tgz#10499d868844cdad4fee0842df8c7f6f0c95a753"
+  integrity sha1-EEmdhohEza1P7ghC34x/bwyVp1M=
+
 deepmerge@^2.1.0:
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
@@ -2671,6 +2701,13 @@ ecc-jsbn@~0.1.1:
     jsbn "~0.1.0"
     safer-buffer "^2.1.0"
 
+echarts@^4.9.0:
+  version "4.9.0"
+  resolved "https://registry.npm.taobao.org/echarts/download/echarts-4.9.0.tgz#a9b9baa03f03a2a731e6340c55befb57a9e1347d"
+  integrity sha1-qbm6oD8Doqcx5jQMVb77V6nhNH0=
+  dependencies:
+    zrender "4.3.2"
+
 ee-first@1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@@ -2681,6 +2718,18 @@ electron-to-chromium@^1.3.483:
   resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.483.tgz#9269e7cfc1c8e72709824da171cbe47ca5e3ca9e"
   integrity sha512-+05RF8S9rk8S0G8eBCqBRBaRq7+UN3lDs2DAvnG8SBSgQO3hjy0+qt4CmRk5eiuGbTcaicgXfPmBi31a+BD3lg==
 
+element-ui@^2.14.1:
+  version "2.14.1"
+  resolved "https://registry.npm.taobao.org/element-ui/download/element-ui-2.14.1.tgz#8b5745c7366c1c1a603bb6c021286ea7187e2aa2"
+  integrity sha1-i1dFxzZsHBpgO7bAIShupxh+KqI=
+  dependencies:
+    async-validator "~1.8.1"
+    babel-helper-vue-jsx-merge-props "^2.0.0"
+    deepmerge "^1.2.0"
+    normalize-wheel "^1.0.1"
+    resize-observer-polyfill "^1.5.0"
+    throttle-debounce "^1.0.1"
+
 elliptic@^6.0.0, elliptic@^6.5.2:
   version "6.5.3"
   resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6"
@@ -4236,6 +4285,11 @@ js-yaml@^3.13.1:
     argparse "^1.0.7"
     esprima "^4.0.0"
 
+jsbarcode@^3.11.3:
+  version "3.11.3"
+  resolved "https://registry.npm.taobao.org/jsbarcode/download/jsbarcode-3.11.3.tgz#1c8fb9b5c7d4452e571930801b00e12094a7051e"
+  integrity sha1-HI+5tcfURS5XGTCAGwDhIJSnBR4=
+
 jsbn@~0.1.0:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
@@ -4988,6 +5042,11 @@ normalize-url@^3.0.0:
   resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559"
   integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==
 
+normalize-wheel@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.npm.taobao.org/normalize-wheel/download/normalize-wheel-1.0.1.tgz#aec886affdb045070d856447df62ecf86146ec45"
+  integrity sha1-rsiGr/2wRQcNhWRH32Ls+GFG7EU=
+
 npm-run-path@^2.0.0:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
@@ -6018,6 +6077,11 @@ regenerate@^1.4.0:
   resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.1.tgz#cad92ad8e6b591773485fbe05a485caf4f457e6f"
   integrity sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==
 
+regenerator-runtime@^0.11.0:
+  version "0.11.1"
+  resolved "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
+  integrity sha1-vgWtf5v30i4Fb5cmzuUBf78Z4uk=
+
 regenerator-runtime@^0.13.4:
   version "0.13.5"
   resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz#d878a1d094b4306d10b9096484b33ebd55e26697"
@@ -6147,6 +6211,11 @@ requires-port@^1.0.0:
   resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
   integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=
 
+resize-observer-polyfill@^1.5.0:
+  version "1.5.1"
+  resolved "https://registry.npm.taobao.org/resize-observer-polyfill/download/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
+  integrity sha1-DpAg3T0hAkRY1OvSfiPkAmmBBGQ=
+
 resolve-cwd@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
@@ -6955,6 +7024,11 @@ terser@^4.1.2:
     source-map "~0.6.1"
     source-map-support "~0.5.12"
 
+throttle-debounce@^1.0.1:
+  version "1.1.0"
+  resolved "https://registry.npm.taobao.org/throttle-debounce/download/throttle-debounce-1.1.0.tgz#51853da37be68a155cb6e827b3514a3c422e89cd"
+  integrity sha1-UYU9o3vmihVctugns1FKPEIuic0=
+
 through2@^2.0.0:
   version "2.0.5"
   resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
@@ -7680,3 +7754,8 @@ yeast@0.1.2:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419"
   integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk=
+
+zrender@4.3.2:
+  version "4.3.2"
+  resolved "https://registry.npm.taobao.org/zrender/download/zrender-4.3.2.tgz?cache=0&sync_timestamp=1605884245353&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fzrender%2Fdownload%2Fzrender-4.3.2.tgz#ec7432f9415c82c73584b6b7b8c47e1b016209c6"
+  integrity sha1-7HQy+UFcgsc1hLa3uMR+GwFiCcY=

Некоторые файлы не были показаны из-за большого количества измененных файлов