Explorar el Código

Merge branch 'master' into zengjun

ajun hace 4 años
padre
commit
bd39b3533f

+ 1 - 0
.gitignore

@@ -35,3 +35,4 @@ yarn-error.log
 /serves/excelExportGo/go_build_main_go.exe
 /laravel-echo-server.lock
 /database/data
+/bootstrap/cache

+ 35 - 5
app/Console/Commands/AccordingToOwnersManualBack.php

@@ -45,16 +45,40 @@ class AccordingToOwnersManualBack extends Command
     {
         ini_set('max_execution_time', 2500);
         ini_set('memory_limit', '512M');
-        $ownerCodes=Owner::query()->where('is_manual_back',1)->pluck('code');//自动回传货主
-        $last_order_manual_back_at=$this->getOrderManualBackAt();//上次回传时间
+        $owners=Owner::query()->where('is_manual_back',1)->orderBy('interval_time')->get();
+        $sys_last_manual_back_time=$this->getOrderManualBackAt();//系统上次回传时间
         $now=Carbon::now()->toDateTimeString();//当前时间
+        $manualBackTime=null;
+        $ownerCodes=[];
+        foreach ($owners as $owner){
+            $intervalTime=Carbon::parse($now)->diffInMinutes(Carbon::parse($owner->last_manual_back_time));
+            if ($intervalTime>18*60 || !$owner->last_manual_back_time){ // 隔天回传情况 或者 货主上次回传时间为null
+                $manualBackTime=$sys_last_manual_back_time;
+                $ownerCodes=array_unique(data_get($owners,'*.code'));
+                break;
+            }
+            if ($owner->interval_time==30 && $intervalTime>=25 &&$intervalTime<=35){ //存在每30分钟一回传的货主
+                $manualBackTime=$owner->last_manual_back_time;
+                $ownerCodes[]=$owner->code;
+            }else if ($owner->interval_time==60 && $intervalTime>=55 &&$intervalTime<=65){ //存在每1小时一回传的货主
+                $manualBackTime=$owner->last_manual_back_time;
+                $ownerCodes[]=$owner->code;
+            }else if ($owner->interval_time==120 && $intervalTime>=115 &&$intervalTime<=125){ //存在每2小时一回传的货主
+                $manualBackTime=$owner->last_manual_back_time;
+                $ownerCodes[]=$owner->code;
+            }else if ($owner->interval_time==180 && $intervalTime>=175 &&$intervalTime<=185){ //存在每3小时一回传的货主
+                $manualBackTime=$owner->last_manual_back_time;
+                $ownerCodes[]=$owner->code;
+            }
+        }
         try {
-            $ordernos=$this->allocation($last_order_manual_back_at, $now, $ownerCodes);//分配是创建状态订单
-            $this->manualBack($last_order_manual_back_at,$now, $ownerCodes,$ordernos);//回传
+            $ordernos=$this->allocation($manualBackTime, $now, $ownerCodes);//分配是创建状态订单
+            $this->manualBack($manualBackTime,$now, $ownerCodes,$ordernos);//回传
         } catch (\Exception $e) {
-            app('LogService')->log(__METHOD__, __FUNCTION__, "自动回传失败" . $last_order_manual_back_at . ' || '
+            app('LogService')->log(__METHOD__, __FUNCTION__, "自动回传失败" . $manualBackTime . ' || '
                 .$now. ' || ' . json_encode($ownerCodes).' || ' . json_encode($e->getMessage()));
         }
+        $this->changeOwnerLastManualTime($ownerCodes,$now);//更新回传货主的回传时间
         $this->setOrderManualBackAt();//回传结束时间标记
     }
 
@@ -141,4 +165,10 @@ class AccordingToOwnersManualBack extends Command
             ->where("name", "last_order_manual_back_at")
             ->update(["value" => Carbon::now()->toDateTimeString()]);
     }
+
+    private function changeOwnerLastManualTime($ownerCodes,$now)
+    {
+        Owner::query()->whereIn('code',$ownerCodes)
+            ->update(['last_manual_back_time'=>$now]);
+    }
 }

+ 8 - 0
app/Feature.php

@@ -59,6 +59,14 @@ class Feature extends Model
             10=> 'packages.commodities.total',
             12=> "total",
             13=> "logistic.english_name",
+        ],
+        "rejected_bill" => [
+            0 => "items.name_goods",
+            5 => "items.remark",
+            7 => "remark",
+            8 => "items.amount",
+            10=> "items.total",
+            12=> "goods_amount",
         ]
     ];
 }

+ 0 - 1
app/Http/Controllers/ControlPanelController.php

@@ -247,7 +247,6 @@ COUNT(1) total FROM order_packages LEFT JOIN orders ON order_packages.order_id=o
 WHERE orders.wms_status != '订单取消'  {$where}
 AND order_packages.created_at like '{$date}%' GROUP BY date,order_packages.measuring_machine_id
 sql;
-            //todo 新写
             $info = DB::select(DB::raw($sql));
             if (empty($info)) return  $res;
             foreach ($info as $v){

+ 20 - 0
app/Http/Controllers/CustomerController.php

@@ -11,6 +11,9 @@ use App\Owner;
 use App\OwnerAreaReport;
 use App\OwnerBillReport;
 use App\OwnerFeeDetail;
+use App\OwnerFeeLogistic;
+use App\OwnerFeeOperation;
+use App\OwnerFeeOperationDetail;
 use App\OwnerReport;
 use App\Services\LogService;
 use App\Services\OwnerAreaReportService;
@@ -521,6 +524,23 @@ class CustomerController extends Controller
         $details = OwnerFeeDetail::query()->where("worked_at",">=",$startData." 00:00:00");
         if ($endDate)$details->where("worked_at","<=",$endDate." 23:59:59");
         if (count($owner)>0)$details->whereIn("owner_id",$owner);
+
+        $fee = OwnerFeeDetail::query()->where("created_at",">=",$startData." 00:00:00");
+        if ($endDate)$fee->where("created_at","<=",$endDate." 23:59:59");
+        if (count($owner)>0)$fee->whereIn("owner_id",$owner);
+        $fee->delete();
+
+        $feeQuery = OwnerFeeOperation::query()->where("worked_at",">=",$startData);
+        if ($endDate)$feeQuery->where("worked_at","<=",$endDate);
+        if (count($owner)>0)$feeQuery->whereIn("owner_id",$owner);
+        OwnerFeeOperationDetail::query()->whereIn("owner_fee_operation_id",$feeQuery)->delete();
+        $feeQuery->delete();
+
+        $fee = OwnerFeeLogistic::query()->where("created_at",">=",$startData." 00:00:00");
+        if ($endDate)$fee->where("created_at","<=",$endDate." 23:59:59");
+        if (count($owner)>0)$fee->whereIn("owner_id",$owner);
+        $fee->delete();
+
         $details->get()->each(function ($detail){
             dispatch(new ResetInstantBill($detail));
         });

+ 102 - 0
app/Http/Controllers/OrderController.php

@@ -4,19 +4,24 @@ namespace App\Http\Controllers;
 
 use App\Components\Database;
 use App\Http\Requests\OrderDelivering;
+use App\OracleActAllocationDetails;
 use App\OracleDOCOrderHeader;
 use App\OracleDOCWaveDetails;
 use App\OrderIssueType;
+use App\OrderPackage;
 use App\Services\LogisticService;
 use App\Services\LogService;
+use App\Services\OrderPackageService;
 use App\Services\OrderService;
 use App\Services\RejectedBillItemService;
 use App\Services\RejectedBillService;
+use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Gate;
 use Oursdreams\Export\Export;
+use function DeepCopy\deep_copy;
 
 class OrderController extends Controller
 {
@@ -424,4 +429,101 @@ sql;
         return["status"=>'part',"msg"=>$txt];
     }
 
+    /**
+     * 一键揽收分配
+     * @param Request $request
+     * @return array
+     */
+    public function collectUpload(Request $request): array
+    {
+        $inOrderno = $request->orderno;
+        $strict = $request->strict;
+        if (empty($inOrderno)) return ['success' => false, 'message' => '选择为空'];
+        $orderno = deep_copy($inOrderno);
+
+        /**
+         * 是否是严格模式
+         * 是
+         *          根据筛选条件
+         *           1. 状态 61 81
+         *           2. 承运商是中通
+         *           3. 有单号
+         *           4. 有复核,
+         *           5. 没揽收
+         * 否
+         * 筛选出快递单号
+         * 将快递单号调用一键揽收
+         *      如果返回异常,记录异常
+         * 调用分配
+         * 将入参与过滤结果取差集合,结果就是不复核的单号,作为错误提示返回
+         */
+        //严格模式,校验订单与包裹状态
+        if ($strict) {
+            $logisticNums = OracleActAllocationDetails::query()
+                ->select('picktotraceid')
+                ->whereIn('orderno', $orderno)
+                ->whereNotNull('picktotraceid')//有单号
+                ->whereNotNull('checktime')//有复核
+                ->whereIn('orderno', function (Builder $query) use ($orderno) {
+                    $query->from('doc_order_header')
+                        ->select('orderno')
+                        ->whereIn('orderno', $orderno)
+                        ->whereIn('carriername', ['中通(轻小包裹)', '中通', '中通速递']) // 承运商是中通
+                        ->whereBetween('sostatus', [0, 63]); //状态 0 63
+                })
+                ->pluck('picktotraceid');
+            $logisticNums = OrderPackage::query()
+                ->select('logistic_number')
+                ->whereIn('logistic_number', $logisticNums)
+                ->whereNull('transfer_status')
+                ->pluck('logistic_number');
+        }else{
+            //非严格模式 不进行任何校验
+            $logisticNums = OracleActAllocationDetails::query()
+                ->select('picktotraceid')
+                ->whereIn('orderno', $orderno)
+                ->pluck('picktotraceid');
+        }
+
+        //调用一键揽收
+        /** @var OrderPackageService $orderPackageService */
+        $orderPackageService = app('OrderPackageService');
+        $collectUpLoadResult = $orderPackageService->collectUpload($logisticNums->toArray());
+        $error = [];
+        //揽收有异常记录
+        if (!$collectUpLoadResult['success']) {
+            $error['collectUpload'] = $collectUpLoadResult['message'];
+        }
+        /** @var OrderService $orderService */
+        $orderService = app('OrderService');
+        //根据快递单号查询orderno
+        $allocationOrdernos = OrderPackage::query()
+            ->whereIn('logistic_number', $logisticNums)
+            ->leftJoin('orders', 'order_id', '=', 'orders.id')
+            ->select('orders.code')
+            ->pluck('code');
+        //调用分配接口
+        $allocationOrdernos->each(function ($orderno) use ($orderService) {
+            $orderService->allocation($orderno);
+        });
+        if ($strict) {
+            //输入的orderno与最终可以一键揽收的orderno取差集合
+            $errorOrderno =  array_diff($inOrderno, $allocationOrdernos->toArray());
+        }
+
+        $result = [];
+        if (!empty($error)) {
+            $result['success'] = false;
+            $result['error_message'] = $error;
+        }else if(!empty($errorOrderno)){
+            $result['success'] = false;
+            $result['error_message'][] = $error;
+        }
+        else {
+            $result['success']=true;
+            $result['message']='一键揽收分配完成';
+        }
+        return $result;
+    }
+
 }

+ 14 - 0
app/Http/Controllers/OwnerController.php

@@ -236,4 +236,18 @@ class OwnerController extends Controller
         $owner=app("OwnerService")->changeManualBackStatus($id,$is_manual_back);
         return ["success"=>true,"data"=>$owner];
     }
+
+    /**
+     * @param Request $request
+     * @return array
+     * 设置货主自动回传时间间隔
+     */
+    public function intervalTime(Request $request): array
+    {
+        if (!Gate::allows('货主-编辑')) return ["success"=>false,"data"=>"无权操作!"];
+        $id=$request->input('id');
+        $intervalTime=$request->input('intervalTime');
+        $owner=app("OwnerService")->changeIntervalTime($id,$intervalTime);
+        return ["success"=>true,"data"=>$owner];
+    }
 }

+ 0 - 1
app/Http/Controllers/OwnerFeeTotalController.php

@@ -70,7 +70,6 @@ class OwnerFeeTotalController extends Controller implements \App\Interfaces\Sett
 
     public function export(Request $request)
     {
-        // TODO: Implement export() method.
     }
 
     public function confirmBill(Request $request): \Illuminate\Http\RedirectResponse

+ 0 - 3
app/Http/Controllers/OwnerWaybillSettlementBillController.php

@@ -9,16 +9,13 @@ class OwnerWaybillSettlementBillController extends Controller implements \App\In
     //
     public function index(Request $request)
     {
-        // TODO: Implement index() method.
     }
 
     public function confirmBill(Request $request): \Illuminate\Http\RedirectResponse
     {
-        // TODO: Implement confirmBill() method.
     }
 
     public function export(Request $request)
     {
-        // TODO: Implement export() method.
     }
 }

+ 14 - 3
app/Http/Controllers/TestController.php

@@ -195,7 +195,18 @@ class TestController extends Controller
 
     public function test()
     {
-        dd(Notification::send(User::query()->where("name","baoshi56")->get(),
+        /** @var OwnerPriceOperationService $service */
+        $service = app("OwnerPriceOperationService");
+        $rejected = RejectedBill::query()->with("items")->find(838755);
+        list($id,$money,$taxFee) = $service->matching($rejected, Feature::MAPPING["rejected_bill"], $rejected->id_owner, "入库");
+        dd($id,$money,$taxFee);
+        dd($rejected);
+
+        $a = memory_get_usage();
+        $tmp = str_repeat('http://blog.huachen.me/', 4000);
+        $b = memory_get_usage();
+        dump($b-$a);
+        dd(Notification::send(User::query()->where("name","zhouzhendong")->get(),
             new RoutineNotification(SeeLog::query()->first()->toArray())));
         $user = Auth::user();
         $remark = "zengjunlj";
@@ -485,8 +496,8 @@ sql;
         /** @var OrderPackageService $service */
         $service = app('OrderPackageService');
        return $service->collectUpload([
-            '75803656098638',
-            '75803656098612'
+            '75810646867541',
+            '75810646197516'
         ]);
     }
 

+ 6 - 1
app/Http/Requests/GateRequest.php

@@ -4,6 +4,8 @@ namespace App\Http\Requests;
 
 use App\Services\MenuService;
 use Illuminate\Foundation\Http\FormRequest;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Log;
 
 class GateRequest extends FormRequest
 {
@@ -124,7 +126,10 @@ class GateRequest extends FormRequest
     {
         $url = null;
         //目标节点存在
-        if ($this->tracks)$url = $this->searchOrigin(app("MenuService")->getVisibleFunctionList());
+        if ($this->tracks){
+            $url = $this->searchOrigin(app("MenuService")->getVisibleFunctionList());
+            if ($url)Log::notice("同源策略跳转",["user"=>Auth::id(),"url"=>$url,"currentRoute"=>$this->currentRoute]);
+        }
         if (!$url)$url = 'denied';
         header('Location: /'.$url,true,301);
         die();

+ 55 - 0
app/Jobs/PackageCollectingAllocation.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace App\Jobs;
+
+use App\OrderPackage;
+use App\Services\OrderPackageService;
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Foundation\Bus\Dispatchable;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Support\Facades\Log;
+
+class PackageCollectingAllocation implements ShouldQueue
+{
+    use Dispatchable, InteractsWithQueue, Queueable;
+
+    /** @var OrderPackage|\stdClass $orderPackage */
+    private $orderPackage;
+
+    /** @var int|null|string */
+    private $lineNo;
+
+    /**
+     * Create a new job instance.
+     *
+     * @return void
+     */
+    public function __construct(OrderPackage $package,int $lineNo)
+    {
+        $this->orderPackage = $package;
+        $this->lineNo = $lineNo;
+    }
+
+    /**
+     * Execute the job.
+     *
+     * @return void
+     */
+    public function handle()
+    {
+        /** @var OrderPackageService $orderPackageService */
+        $orderPackageService = app('OrderPackageService');
+        $result = $orderPackageService->collectUpload([$this->orderPackage->logistic_number]);
+        if (!$result["success"]){
+            Log::warning("自动揽收失败",["message"=>$result["message"],"param"=>$this->orderPackage->logistic_number]);
+            return;
+        }
+        $result = app("OrderService")->allocation($this->orderPackage->order->code,$this->lineNo);
+        if (mb_substr($result,0,3)=='000'){
+            if (OrderPackage::query()->where("id",$this->orderPackage->id)
+                ->where("collecting_status",'0')->update(["collecting_status"=>'1'])!=1)
+                Log::warning("自动揽收异常",["message"=>"未能成功修改揽收标记","param"=>$this->orderPackage->toArray()]);
+        }else Log::warning("自动揽收失败",["message"=>"分配失败:{$result}","param"=>$this->orderPackage->order->code." : {$this->lineNo}"]);
+    }
+}

+ 34 - 17
app/Jobs/ResetInstantBill.php

@@ -7,12 +7,10 @@ use App\Order;
 use App\OwnerFeeDetail;
 use App\OwnerFeeDetailLogistic;
 use App\OwnerFeeExpress;
+use App\OwnerFeeLogistic;
 use App\Process;
-use App\Province;
 use App\RejectedBill;
-use App\Services\CacheService;
 use App\Services\OwnerPriceDirectLogisticService;
-use App\Services\OwnerPriceExpressService;
 use App\Services\OwnerPriceLogisticService;
 use App\Services\OwnerPriceOperationService;
 use App\Store;
@@ -22,12 +20,10 @@ use Illuminate\Bus\Queueable;
 use Illuminate\Contracts\Queue\ShouldQueue;
 use Illuminate\Foundation\Bus\Dispatchable;
 use Illuminate\Queue\InteractsWithQueue;
-use Illuminate\Queue\SerializesModels;
-use Illuminate\Support\Facades\Cache;
 
 class ResetInstantBill implements ShouldQueue
 {
-    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+    use Dispatchable, InteractsWithQueue, Queueable;
 
     /** @var \stdClass $detail  */
     private $detail;
@@ -79,9 +75,8 @@ class ResetInstantBill implements ShouldQueue
                     "work_tax_fee"      => $workTaxFee,
                     "logistic_tax_fee"  => $logisticInfo["logisticTaxFee"],
                 ]);
-                //向指定表插入标记 TODO
-                //if ($logisticInfo["logisticFee"] && $logisticInfo["fee_info"])OwnerFeeExpress::query()->insert($logisticInfo["fee_info"]);
-                /*if ($money>0)app("StoreService")->constructFeeInfo([
+                if ($logisticInfo["logisticFee"] && $logisticInfo["fee_info"])OwnerFeeExpress::query()->insert($logisticInfo["fee_info"]);
+                if ($money>0)app("StoreService")->constructFeeInfo([
                     "worked_at" => $order->wms_edittime ?: $order->updated_at,
                     "owner_id" => $order->owner_id,
                     "model_id"  => $id,
@@ -91,7 +86,7 @@ class ResetInstantBill implements ShouldQueue
                     "total_fee"    =>0,
                     "tax_rate"     =>0,
                     "fee_description"=>'',
-                ]);*/
+                ]);
                 //后续处理
                 OwnerFeeDetailLogistic::query()->where("owner_fee_detail_id",$this->detail->id)->delete();
                 foreach ($logisticInfo["items"] as &$item)$item["owner_fee_detail_id"] = $this->detail->id;
@@ -132,7 +127,7 @@ class ResetInstantBill implements ShouldQueue
                     $service = app("OwnerPriceLogisticService");
                     list($fee,$taxFee) = $service->matching($waybill->carrier_weight_other,$owner_id,$waybill->logistic_id,
                         $waybill->carrier_weight_unit_id_other,$provinceId, $cityId);
-                    //$this->buildWaybillFeeInfo(); TODO
+                    if (isset($GLOBALS["FEE_INFO"])) OwnerFeeLogistic::query()->create($GLOBALS["FEE_INFO"]);
                 }else{
                     /** @var OwnerPriceDirectLogisticService $service */
                     $service = app("OwnerPriceDirectLogisticService");
@@ -162,7 +157,7 @@ class ResetInstantBill implements ShouldQueue
                     "owner_price_operation_id" => $id,
                     "work_tax_fee" => $taxFee,
                 ]);
-               /* if ($money>0)$this->constructFeeInfo([
+                if ($money>0)app("StoreService")->constructFeeInfo([
                     "worked_at" => $store->updated_at,
                     "owner_id" => $store->owner_id,
                     "model_id"  => $id,
@@ -172,15 +167,15 @@ class ResetInstantBill implements ShouldQueue
                     "total_fee"    =>0,
                     "tax_rate"     =>0,
                     "fee_description"=>'',
-                ]);*/
+                ]);
                 break;
             case "rejected_bills":
                 /** @var \stdClass $rejectedBill */
                 $number = array_column(StoreRejected::query()->where("logistic_number_return",$rejectedBill->logistic_number_return)->get()->toArray(),"store_id");
-
-                foreach (Store::query()->with("storeItems")->whereIn("id",$number)->get() as $store){
-                    /** @var OwnerPriceOperationService $service */
-                    $service = app("OwnerPriceOperationService");
+                $stores = Store::query()->with("storeItems")->whereIn("id",$number)->get();
+                /** @var OwnerPriceOperationService $service */
+                $service = app("OwnerPriceOperationService");
+                foreach ($stores as $store){
                     $GLOBALS["FEE_INFO"] = [];
                     list($id,$money,$taxFee) = $service->matching($store, Feature::MAPPING["store"], $store->owner_id, "入库",0);
                     app("StoreService")->clearFeeInfo($store->asn_code);
@@ -201,6 +196,28 @@ class ResetInstantBill implements ShouldQueue
                         "fee_description"=>'',
                     ]);
                 }
+                if ($stores->count())return;
+                $rejectedBill = RejectedBill::query()->find($this->detail->outer_id);
+                $rejectedBill->loadMissing("items");
+                $GLOBALS["FEE_INFO"] = [];
+                list($id,$money,$taxFee) = $service->matching($rejectedBill, Feature::MAPPING["rejected_bill"], $rejectedBill->id_owner, "入库",0);
+                $this->detail->update([
+                    "commodity_amount" => $rejectedBill->goods_amount,
+                    "work_fee" => $money,
+                    "owner_price_operation_id" => $id,
+                    "work_tax_fee" => $taxFee,
+                ]);
+                app("StoreService")->constructFeeInfo([
+                    "worked_at" => $rejectedBill->updated_at,
+                    "owner_id" => $rejectedBill->id_owner,
+                    "model_id"  => $id,
+                    "source_number"=> null,
+                    "doc_number"   => null,
+                    "commodity_id" => 0,
+                    "total_fee"    =>0,
+                    "tax_rate"     =>0,
+                    "fee_description"=>'',
+                ]);
         }
     }
 }

+ 20 - 0
app/Order.php

@@ -42,6 +42,26 @@ class Order extends Model
      * 仓库                 warehouse_id=>DOC_ORDER_HEADER['WAREHOUSEID']
      */
 
+    const STATUS = [
+        '00' => "创建订单",
+        '10' => "部分预配",
+        '20' => "预配完成",
+        '30' => "部分分配",
+        '40' => "分配完成",
+        '50' => "部分拣货",
+        '60' => "拣货完成",
+        '61' => "播种完成",
+        '62' => "部分装箱",
+        '63' => "完全装箱",
+        '65' => "部分装车",
+        '66' => "装车完成",
+        '70' => "部分发运",
+        '80' => "完全发运",
+        '90' => "订单取消",
+        '98' => "等待释放",
+        '99' => "订单完成",
+    ];
+
     public function cancel(){
         $this['status'] = '取消';
         $this->update();

+ 5 - 4
app/OrderPackage.php

@@ -39,10 +39,11 @@ class OrderPackage extends Model
         'transfer_status',
         'owner_id',
         'uploaded_to_wms',
-        'sync_routes_flag',
-        'is_manual_update',
-        'exception_status',
-        'is_delay_deliver',
+        'sync_routes_flag',//同步物流信息标记
+        'is_manual_update',//是否手动更新状态
+        'exception_status',//异常状态
+        'is_delay_deliver',//是否延时发货
+        'collecting_status',//手动揽收状态
     ];
 
     protected $casts = [

+ 3 - 0
app/Owner.php

@@ -42,6 +42,9 @@ class Owner extends Model
         'is_check_asn',          //是否校验ASN(收货时检查此项)
         'owner_group_id',        // 所属组别
         'is_manual_back',        // 是否开启货主订单一键回传
+        'interval_time',        // 回传间隔时间(分钟为单位)
+        'last_manual_back_time', // 上次回传时间
+
     ];
     //relevance说明 0:仓储 1:作业 2:快递 3:物流 4:直发 5:系统 存储示例:["0","1"]存在仓储与作业计费
     protected $casts = [

+ 4 - 1
app/Services/DbOpenService.php

@@ -5,6 +5,7 @@ namespace App\Services;
 use App\Components\ErrorPush;
 use App\Traits\ServiceAppAop;
 use Illuminate\Database\Eloquent\Model;
+use Illuminate\Support\Facades\Log;
 
 
 class DbOpenService
@@ -34,6 +35,8 @@ class DbOpenService
 
         try {
             $response = httpPost(config('api_logistic.DB.prod.uri')['create_order'], $body, $header);
+            Log::info($body);
+            Log::info($response);
             if (!$response["result"])return null;
             return $response ?? '';
             //OracleDOCOrderHeader::query()->where('orderno', $order_no)->update(['edittime' => Carbon::now(), 'soreference5' => $mail_no]);
@@ -117,7 +120,7 @@ class DbOpenService
                 'totalWeight'       => $waybill->total_weight ?? '',
                 'totalVolume'       => '',
                 'packageService'    => $waybill->package_service ?? '',
-                'deliveryType'      => $waybill->deliveryType->name ?? '',
+                'deliveryType'      => $waybill->deliveryType->id ?? ''
             ],
             'gmtCommit'     =>  $date,
             'payType'       =>  $waybill->pay_type,

+ 0 - 1
app/Services/Express/CaiNiaoExpress.php

@@ -86,7 +86,6 @@ class CaiNiaoExpress implements expressinterface
 
     function searElectronicSingle()
     {
-        // TODO: Implement searElectronicSingle() method.
     }
 
     /**

+ 0 - 1
app/Services/Express/PDDExpress.php

@@ -6,7 +6,6 @@ namespace App\Services\Express;
 
 class PDDExpress implements ExpressInterface
 {
-    // TODO 目前获取快递单号请求参数
 
     private $app_key = '';
     private $sign_method = '';

+ 39 - 37
app/Services/OrderPackageService.php

@@ -2,6 +2,7 @@
 
 namespace App\Services;
 
+use App\Jobs\PackageCollectingAllocation;
 use App\Order;
 use App\OrderPackage;
 use App\OrderPackageCommodities;
@@ -280,12 +281,12 @@ class OrderPackageService
         foreach ($packages as $package) {
             if ($package->sent_at) continue;
             try {
-                $checktime = $map[$package->logistic_number];
+                $checktime = $map[$package->logistic_number]->checktime;
             } catch (\Exception $e) {
                 continue;
             }
             if ($checktime) {
-                $this->checkingAndProcess($package); //检查和处理揽收
+                $this->checkingAndProcess($package,$map[$package->logistic_number]->orderlineno); //检查和处理揽收
                 $update_params[] = [
                     'id' => $package->id,
                     'sent_at' => $checktime,
@@ -298,13 +299,17 @@ class OrderPackageService
     /**
      * 检查和处理揽收
      *
-     * @param OrderPackage $package
+     * @param OrderPackage|\stdClass $package
      */
-    public function checkingAndProcess(OrderPackage $package)
+    public function checkingAndProcess(OrderPackage $package, int $lineNo)
     {
-        //TODO 揽收与分配回馈时间不定 这里应该推进队列处理
-        //检查快递商来判断该快递商是否允许自动揽收发货
-        //检查揽收标记来判断是否已被揽收过
+        //校验快递商 订单状态 复核标记 揽收标记
+        $package->loadMissing("order.logistic");
+        if ($package->collecting_status == '1' || !$package->logistic_number)return;
+        if (strpos($package->order->logistic->code ?? '','ZTO') === false)return;
+        $statusMapping = array_flip(Order::STATUS);
+        if (($statusMapping[$package->order->wms_status] ?? 0) > 63)return;
+        //dispatch(new PackageCollectingAllocation($package,$lineNo));
     }
 
     /**
@@ -318,7 +323,7 @@ class OrderPackageService
             $actAllocationDetails = $orderHeader->actAllocationDetails;
             foreach ($actAllocationDetails as $actAllocationDetail) {
                 $logistic_number = $actAllocationDetail->picktotraceid;
-                $map[$logistic_number] = $actAllocationDetail->checktime;
+                $map[$logistic_number] = $actAllocationDetail;
             }
         }
         return $map;
@@ -356,7 +361,7 @@ class OrderPackageService
     }
 
     /**
-     * 中通一键揽收上传
+     * 中通一键揽收
      * 由于中通接口只支持100条的操作,本接口支持100以上
      * 如果中途调用中通接口发生异常,本方法不会停止,但在最后会返回错误信息,将执行失败的单号和原因返回
      * @param $logistic_numbers array
@@ -371,23 +376,7 @@ class OrderPackageService
                 'message' => '输入快递单号为空',
             ];
         }
-//        $orderPackageCount = OrderPackage::query()->whereIn('logistic_number', $logistic_numbers)
-//            ->whereIn('order_id', function ($query) {
-//                $query->from('orders')->select('id')->whereIn('logistic_id', function ($query) {
-//                    $query->from('logistics')->select('id')->whereIn('code', [
-//                        'ZTO',
-//                        'ZTO-1',
-//                        'WPZTO',
-//                    ]);
-//                });
-//            })->count();
-//        if ($orderPackageCount !== count($logistic_numbers)) {
-//            return [
-//                'success' => false,
-//                'message' => '输入的快递单号异常,请检查承运商是否全部为中通',
-//            ];
-//        }
-
+        //根据环境获取中通接口参数
         $url = env('APP_ENV') === 'production' ? config('api_logistic.collectUpload.ZTO.prod.url') : config('api_logistic.collectUpload.ZTO.test.url');
         $xAppKey = env('APP_ENV') === 'production' ? config('api_logistic.collectUpload.ZTO.prod.x-appKey') : config('api_logistic.collectUpload.ZTO.test.x-appKey');
         $appSecret = env('APP_ENV') === 'production' ? config('api_logistic.collectUpload.ZTO.prod.appSecret') : config('api_logistic.collectUpload.ZTO.test.appSecret');
@@ -411,25 +400,38 @@ class OrderPackageService
                 ];
             }
             try {
+                //调用中通接口
                 $response = $this->sentReqToZOP($collectUploadDTOS, $appSecret, $xAppKey, $url);
+
+                //接口返回的异常包装
+                $responseBody = json_decode($response->body());
+                if ($responseBody->statusCode === 'S210' ||//无权限
+                    $responseBody->statusCode === 'PARAM_ERROR' ||//揽收上传信息为空
+                    $responseBody->statusCode === 'SYSTEM_ERROR'//系统异常,请联系系统管理员
+                ) {
+                    //有异常包装
+                    $errorMessage[] = [
+                        'status_code' => $responseBody->statusCode,
+                        'message' => $responseBody->message,
+                        'logistic_number' => $logistic_numbers_chunked_items,
+                    ];
+                } else {
+                    //没有异常将对应包裹标记为手动揽收
+                    OrderPackage::query()
+                        ->select('weight', 'logistic_number')
+                        ->whereIn('logistic_number', $logistic_numbers_chunked_items)->update([
+                            'collecting_status' => 1,
+                        ]);
+                }
             } catch (\Exception $e) {
+                //调用异常,构建异常返回体
                 $errorMessage[] = [
                     'status_code' => 'REQUEST_ERROR',
                     'message' => [$e->getMessage()],
                     'logistic_number' => $logistic_numbers_chunked_items,
                 ];
             }
-            $responseBody = json_decode($response->body());
-            if ($responseBody->statusCode === 'S210' ||//无权限
-                $responseBody->statusCode === 'PARAM_ERROR' ||//揽收上传信息为空
-                $responseBody->statusCode === 'SYSTEM_ERROR'//系统异常,请联系系统管理员
-            ) {
-                $errorMessage[] = [
-                    'status_code' => $responseBody->statusCode,
-                    'message' => $responseBody->message,
-                    'logistic_number' => $logistic_numbers_chunked_items,
-                ];
-            }
+
         }
         if (empty($errorMessage)) {
             return ['success' => true, 'message' => '一键揽收上传成功'];

+ 1 - 0
app/Services/OwnerPriceOperationService.php

@@ -422,6 +422,7 @@ class OwnerPriceOperationService
     {
         $need = "";
         foreach (Feature::TYPE_NODE as $index){
+            if (!isset($columnMapping[$index]))continue;
             if (!$need)$need=strstr($columnMapping[$index],".",true);
             $columnMapping[$index] = ltrim(strstr($columnMapping[$index],"."),".");
         }

+ 7 - 0
app/Services/OwnerService.php

@@ -14,6 +14,7 @@ use App\OwnerStoragePriceModel;
 use App\Services\common\BatchUpdateService;
 use App\User;
 use Carbon\Carbon;
+use Doctrine\DBAL\Exception\DatabaseObjectExistsException;
 use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Support\Collection;
@@ -534,4 +535,10 @@ sql;
         else $owner->update(['is_manual_back'=>0]);
         return $owner;
     }
+    public function changeIntervalTime($id,$intervalTime)
+    {
+        $owner=Owner::query()->find($id);
+        $owner->update(['interval_time'=>$intervalTime]);
+        return $owner;
+    }
 }

+ 32 - 4
app/Services/RejectedBillService.php

@@ -349,10 +349,10 @@ class RejectedBillService
     {
         /** @var \stdClass $rejectedBill */
         $number = array_column(StoreRejected::query()->where("logistic_number_return",$rejectedBill->logistic_number_return)->get()->toArray(),"store_id");
-
-        foreach (Store::query()->with("storeItems")->whereIn("id",$number)->get() as $store){
-            /** @var OwnerPriceOperationService $service */
-            $service = app("OwnerPriceOperationService");
+        $stores = Store::query()->with("storeItems")->whereIn("id",$number)->get();
+        /** @var OwnerPriceOperationService $service */
+        $service = app("OwnerPriceOperationService");
+        foreach ($stores as $store){
             $GLOBALS["FEE_INFO"] = [];
             list($id,$money,$taxFee) = $service->matching($store, Feature::MAPPING["store"], $store->owner_id, "入库",0);
             $bill = OwnerFeeDetail::query()->where("outer_id",$store->id)->where("outer_table_name","stores")->first();
@@ -389,5 +389,33 @@ class RejectedBillService
                 "fee_description"=>'',
             ]);
         }
+        if ($stores->count())return;
+        $rejectedBill->loadMissing("items");
+        $GLOBALS["FEE_INFO"] = [];
+        list($id,$money,$taxFee) = $service->matching($rejectedBill, Feature::MAPPING["rejected_bill"], $rejectedBill->id_owner, "入库",0);
+        app("OwnerFeeDetailService")->create([
+            "owner_id" => $rejectedBill->id_owner,
+            "worked_at" => $rejectedBill->updated_at,
+            "type" => "收货",
+            "operation_bill" => null,
+            "commodity_amount" => $rejectedBill->goods_amount,
+            "work_fee" => $money,
+            "owner_price_operation_id" => $id,
+            "created_at" => date('Y-m-d H:i:s'),
+            "outer_id" => $rejectedBill->id,
+            "outer_table_name" => "rejected_bills",
+            "work_tax_fee" => $taxFee,
+        ]);
+        app("StoreService")->constructFeeInfo([
+            "worked_at" => $rejectedBill->updated_at,
+            "owner_id" => $rejectedBill->id_owner,
+            "model_id"  => $id,
+            "source_number"=> null,
+            "doc_number"   => null,
+            "commodity_id" => 0,
+            "total_fee"    =>0,
+            "tax_rate"     =>0,
+            "fee_description"=>'',
+        ]);
     }
 }

+ 35 - 0
database/migrations/2021_09_24_150620_change_owners_table_add_column_interval_time_and_last_manual_back_time.php

@@ -0,0 +1,35 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class ChangeOwnersTableAddColumnIntervalTimeAndLastManualBackTime extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('owners', function (Blueprint $table) {
+            $table->integer('interval_time')->default(30)->comment('自动回传时间');
+            $table->timestamp('last_manual_back_time')->nullable()->index()->comment('上次回传时间');
+        });
+
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('owners', function (Blueprint $table) {
+            $table->dropColumn("interval_time");
+            $table->dropColumn("last_manual_back_time");
+        });
+    }
+}

+ 32 - 0
database/migrations/2021_09_26_095833_add_column_manual_collection_status_to_order_packages_table.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddColumnManualCollectionStatusToOrderPackagesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('order_packages', function (Blueprint $table) {
+            $table->integer('collecting_status')->default(0)->comment('手动揽收标记 0:不是手动揽收 1:是手动揽收');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('order_packages', function (Blueprint $table) {
+            $table->dropColumn('collecting_status');
+        });
+    }
+}

+ 40 - 2
resources/views/maintenance/owner/index.blade.php

@@ -17,6 +17,7 @@
                         <th class="text-center">货主名</th>
                         <th class="text-center">创建时间</th>
                         <th class="text-center">订单自动回传</th>
+                        <th class="text-center">回传间隔(分)</th>
                         <th class="text-center">操作</th>
                     </tr>
                     <tr v-for="(owner,i) in owners" @click="selectTr===i+1?selectTr=0:selectTr=i+1" :class="selectTr===i+1?'focusing' : ''">
@@ -28,6 +29,17 @@
                             <span class="btn btn-sm btn-outline-secondary" @click="changeManualBackType(owner.id,owner.is_manual_back)">
                                 @{{is_manual_back_type[owner.is_manual_back]}}</span>
                         </td>
+                        <td class="text-center">
+                            <span v-if="owner.is_manual_back==1">
+                        <select  class="form-control-sm" name="interval_time" id="interval_time" @change="changeIntervalTime(owner.id,owner.interval_time)"   v-model="owner.interval_time">
+                            <option :value="30">30</option>
+                            <option :value="60">60</option>
+                            <option :value="120">120</option>
+                            <option :value="180">180</option>
+                        </select>
+
+                            </span>
+                        </td>
                         <td class="text-center">
                             @can('货主-编辑')
                             <button class="btn btn-sm btn-outline-primary" @click="edit(owner.id)">改</button> @endcan
@@ -50,7 +62,11 @@
             data:{
                 owners:[
                     @foreach( $owners as $owner )
-                    {id:'{{$owner->id}}',code:'{{$owner->code}}',name:'{{$owner->name}}',is_manual_back:'{{$owner->is_manual_back}}',group:'{{$owner->ownerGroup->name??''}}',created_at:'{{$owner->created_at}}'},
+                    {id:'{{$owner->id}}',code:'{{$owner->code}}',name:'{{$owner->name}}',
+                        is_manual_back:'{{$owner->is_manual_back}}',
+                        interval_time:'{{$owner->interval_time}}',
+                        group:'{{$owner->ownerGroup->name??''}}',
+                        created_at:'{{$owner->created_at}}'},
                     @endforeach
                 ],
                 selectTr:0,
@@ -115,7 +131,6 @@
                     })
                 },
                 changeManualBackType(id,isManualBack){
-                    console.log(isManualBack)
                     let url = '{{url('maintenance/owner/changeManualBackType')}}';
                     window.axios.post(url, {id:id,isManualBack:isManualBack})
                         .then(res => {
@@ -137,6 +152,29 @@
                         window.tempTip.show("网络错误:" + err);
                     })
                 },
+                changeIntervalTime(id,intervalTime){
+                    console.log(id,intervalTime)
+                    let url = '{{url('maintenance/owner/intervalTime')}}';
+                    window.axios.post(url, {id:id,intervalTime:intervalTime})
+                        .then(res => {
+                            if (res.data.success) {
+                                this.owners.forEach(function (owner){
+                                     if (owner.id==res.data.data.id){
+                                         owner.interval_time=res.data.data.interval_time;
+                                     }
+                                })
+                                window.tempTip.setDuration(3000);
+                                window.tempTip.showSuccess('设置回传时间成功!');
+                                this.$forceUpdate();
+                                return;
+                            }
+                            window.tempTip.setDuration(3000);
+                            window.tempTip.show('设置回传时间失败!');
+                        }).catch(err => {
+                        window.tempTip.setDuration(3000);
+                        window.tempTip.show("网络错误:" + err);
+                    })
+                },
             }
         });
     </script>

+ 20 - 1
resources/views/order/index/delivering.blade.php

@@ -44,6 +44,10 @@
                         <button class="btn btn-sm ml-1 btn-success tooltipTarget" title="订单一键回传必须满足条件:订单状态为“分配完成,部分拣货,拣货完成,播种完成”;订单未冻结;订单有快递单号"
                                 @click="manualBack()">一键回传</button>
                     @endcan
+{{--                    @can('订单管理-订单-一键揽收')--}}
+                        <button class="btn btn-sm ml-1 btn-success tooltipTarget" title="订单一键揽收必须满足条件:承运商为:“中通” 订单状态为“播种完成,部分装箱,完全装箱,部分装车,装车完成,部分发运,完全发运”;订单未冻结;订单有快递单号,快递未揽收"
+                                @click="collectUpload()">一键揽收分配</button>
+{{--                    @endcan--}}
                 </div>
                 <div class="modal fade " style="top: 20%" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
                     <div class="modal-dialog">
@@ -441,7 +445,8 @@
             methods:{
                 initData(){
                     this.orders.forEach((order)=>{
-                        if (order.c_contact && order.c_contact.length>50 && order.c_contact.substring(0,3)==='~Ag')order.is_encryption = true;
+                        if (order.c_contact && order.c_contact.length>50 && (order.c_contact.substring(0,3)==='~Ag' || order.c_contact.substring(0,1)==='#'))
+                            order.is_encryption = true;
                     });
                     let start = "{{$request["orderdate_start"] ?? ''}}";
                     let end = "{{$request["orderdate_end"] ?? ''}}";
@@ -1174,6 +1179,20 @@
                         window.tempTip.show("网络错误:" + err);
                     })
                 },
+                collectUpload(){
+                    if(checkData.length===0){tempTip.show('没有勾选记录');return;}
+                    const data = {
+                        'orderno': checkData,
+                        'strict': false,
+                    };
+                    window.axios.post("{{url('order/collectUpload')}}", data).then(res => {
+                        if (res.data.success) {
+                            tempTip.showSuccess(res.data.message)
+                        }else {
+                            tempTip.show(res.data.error_message);
+                        }
+                    });
+                },
                 isDB(item){
                     if(item.indexOf('德邦') == -1  || item.indexOf('京东') == -1) return false;
                     return  true;

+ 2 - 0
routes/web.php

@@ -130,6 +130,7 @@ Route::group(['middleware'=>'auth'],function ($route){
             Route::get('recycle','OwnerController@recycle');
             Route::post('restoreSelected', 'OwnerController@restoreSelected');
             Route::post('changeManualBackType', 'OwnerController@changeManualBackType');
+            Route::post('intervalTime', 'OwnerController@intervalTime');
         });
         /** 教程 */
         Route::group(['prefix'=>'tutorial'],function(){
@@ -798,6 +799,7 @@ Route::group(['prefix'=>'package'],function(){
         Route::post('deAllocationAll','OrderController@deAllocationAll');
         Route::post('allocation','OrderController@allocation');
         Route::post('manualBack','OrderController@manualBack');
+        Route::post('collectUpload','OrderController@collectUpload');
         Route::post('resetLogisticsGetMark','OrderController@resetLogisticsGetMark');
         Route::post('resetInterfaceReturnMark','OrderController@resetInterfaceReturnMark');
         Route::post('createRejectedBill','OrderController@createRejectedBill');