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

Merge branch 'zengjun' into add_order_issue_filter

# Conflicts:
#	app/OrderIssue.php
ajun 5 лет назад
Родитель
Сommit
7c380a1901
61 измененных файлов с 2183 добавлено и 325 удалено
  1. 4 2
      app/Console/Commands/MakeServiceCommand.php
  2. 35 0
      app/Events/SendEmailEvent.php
  3. 1 1
      app/Http/Controllers/OrderController.php
  4. 52 0
      app/Http/Controllers/OrderFreezeController.php
  5. 47 27
      app/Http/Controllers/OrderIssueController.php
  6. 7 0
      app/Http/Controllers/OwnerController.php
  7. 18 0
      app/Http/Controllers/RegionController.php
  8. 15 1
      app/Http/Controllers/RejectedBillController.php
  9. 75 0
      app/Http/Controllers/SendEmailsController.php
  10. 119 52
      app/Http/Controllers/TestController.php
  11. 86 0
      app/Jobs/OrderFreeze.php
  12. 63 0
      app/Listeners/SendEmailListener.php
  13. 23 0
      app/MailEvent.php
  14. 63 0
      app/Notifications/SendEmailNotification.php
  15. 1 0
      app/Observers/OwnerObserver.php
  16. 40 0
      app/OrderFreeze.php
  17. 23 97
      app/OrderIssue.php
  18. 3 1
      app/Providers/AppServiceProvider.php
  19. 3 0
      app/Providers/EventServiceProvider.php
  20. 34 0
      app/Region.php
  21. 50 0
      app/Services/OrderFreezeService.php
  22. 0 4
      app/Services/OrderIssueRejectedBillService.php
  23. 14 2
      app/Services/OrderIssueService.php
  24. 1 1
      app/Services/OrderPackageService.php
  25. 5 1
      app/Services/OrderService.php
  26. 30 0
      app/Services/OwnerService.php
  27. 45 7
      app/Services/RejectedBillService.php
  28. 1 0
      app/Services/WaybillService.php
  29. 6 0
      app/UserWorkgroup.php
  30. 13 0
      database/factories/OrderIssueRejectedBillFactory.php
  31. 35 0
      database/migrations/2021_01_08_101028_create_notifications_table.php
  32. 36 0
      database/migrations/2021_01_08_110021_create_mail_events_table.php
  33. 33 0
      database/migrations/2021_01_08_110329_create_mail_event_role_table.php
  34. 43 0
      database/migrations/2021_01_08_110607_add_default_email.php
  35. 36 0
      database/migrations/2021_01_08_112003_add_default_mail_event_role.php
  36. 32 0
      database/migrations/2021_01_14_174209_create_order_issue_user_workgroup_table.php
  37. 39 0
      database/migrations/2021_01_15_100109_create_order_freezes_table.php
  38. 34 0
      database/migrations/2021_01_15_114628_create_regions_table.php
  39. 32 0
      database/migrations/2021_01_15_175210_sync_order_issue_user_workgroup.php
  40. 1 1
      resources/js/utilities/tempTip.js
  41. 31 75
      resources/views/customer/project/create.blade.php
  42. 5 5
      resources/views/customer/project/menu.blade.php
  43. 5 0
      resources/views/customer/project/part/_three.blade.php
  44. 2 0
      resources/views/emails/test.blade.php
  45. 243 0
      resources/views/maintenance/emails/index.blade.php
  46. 12 0
      resources/views/maintenance/emails/menu.blade.php
  47. 4 0
      resources/views/maintenance/menu.blade.php
  48. 58 0
      resources/views/order/index/_freezeModal.blade.php
  49. 122 0
      resources/views/order/index/freeze.blade.php
  50. 4 0
      resources/views/order/index/menu.blade.php
  51. 186 18
      resources/views/order/issue/index.blade.php
  52. 5 6
      resources/views/order/issue/recycle.blade.php
  53. 23 4
      resources/views/rejected/create.blade.php
  54. 71 15
      resources/views/test.blade.php
  55. 19 4
      resources/views/waybill/index.blade.php
  56. 4 1
      routes/apiLocal.php
  57. 14 0
      routes/web.php
  58. 60 0
      tests/Services/RejectedBillService/FindOrderByOrderIssueTest.php
  59. 51 0
      tests/Services/RejectedBillService/FindOrderByOrderPackageTest.php
  60. 45 0
      tests/Services/RejectedBillService/GetOrderInfoTest.php
  61. 21 0
      tests/Unit/Services/OrderIssueWorkGroupSync.php

+ 4 - 2
app/Console/Commands/MakeServiceCommand.php

@@ -54,9 +54,11 @@ class MakeServiceCommand extends Command
                 .PHP_EOL
                 .'use App\Traits\ServiceAppAop;'
                 .PHP_EOL
-                .'Class '.$fileName
                 .PHP_EOL
-                .'{ '
+                .'class '.$fileName
+                .PHP_EOL
+                .'{'
+                .PHP_EOL
                 .'    use ServiceAppAop;'
                 .PHP_EOL
                 .PHP_EOL.

+ 35 - 0
app/Events/SendEmailEvent.php

@@ -0,0 +1,35 @@
+<?php
+
+namespace App\Events;
+
+use Illuminate\Broadcasting\Channel;
+use Illuminate\Broadcasting\InteractsWithSockets;
+use Illuminate\Broadcasting\PresenceChannel;
+use Illuminate\Broadcasting\PrivateChannel;
+use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
+use Illuminate\Foundation\Events\Dispatchable;
+use Illuminate\Queue\SerializesModels;
+
+class SendEmailEvent
+{
+    use Dispatchable, InteractsWithSockets, SerializesModels;
+
+
+    /**
+     * SendEmailEvent constructor.
+     */
+    public function __construct()
+    {
+    }
+
+
+    /**
+     * Get the channels the event should broadcast on.
+     *
+     * @return \Illuminate\Broadcasting\Channel|array
+     */
+    public function broadcastOn()
+    {
+        return new PrivateChannel('channel-name');
+    }
+}

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

@@ -114,7 +114,7 @@ class OrderController extends Controller
                 $rejectedBill_collect->push($rejectedBill);// 保存生成的rejectedBill
                 LogService::log(__METHOD__,"生成退货单",json_encode($order),Auth::user()['id']);
                 $cms = $commodities[$order->orderno] ?? [];
-                if (count($picktotraceids[$order->orderno]) > 1 && $cms){
+                if (count($picktotraceids[$order->orderno]) > 0 && $cms){
                     $sql = <<<sql
  SELECT sum(QTY) qty,sku FROM ACT_ALLOCATION_DETAILS where ORDERNO = ? and PICKTOTRACEID = ? GROUP BY sku
 sql;

+ 52 - 0
app/Http/Controllers/OrderFreezeController.php

@@ -0,0 +1,52 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Components\AsyncResponse;
+use App\OrderFreeze;
+
+class OrderFreezeController extends Controller
+{
+    use AsyncResponse;
+    public function index()
+    {
+        $this->gate("订单管理-自动冻结");
+        $freezes = OrderFreeze::query()->with(["logistic:id,name","province:id,name","city:id,name","location:id,name"])
+            ->orderByDesc("id")->where("status",0)
+            ->paginate(request("paginate") ?? 50);
+        return view("order.index.freeze",compact("freezes"));
+    }
+
+    public function store()
+    {
+        $this->gate("订单管理-自动冻结");
+        $freeze = OrderFreeze::query()->where("logistic_id",request("logistic_id"))
+            ->where("province_id",request("province_id"))
+            ->where("city_id",request("city_id"))->where("status",0)
+            ->where("location_id",request("location_id"))->first();
+
+        if ($freeze && $freeze->id!=request("id"))$this->error("已存在冻结选项,无需重复录入");
+        $obj = [
+            "logistic_id"   => request("logistic_id"),
+            "province_id"   => request("province_id"),
+            "city_id"       => request("city_id"),
+            "location_id"   => request("location_id"),
+        ];
+        if (request("id")){
+            $freeze = OrderFreeze::query()->find(request("id"));
+            $freeze->update($obj);
+        }else $freeze = OrderFreeze::query()->create($obj);
+        app("OrderFreezeService")->refreshFreezes();
+        $freeze->load(["logistic:id,name","province:id,name","city:id,name","location:id,name"]);
+        $this->success($freeze);
+    }
+
+    public function delFreeze()
+    {
+        $this->gate("订单管理-自动冻结");
+        if (!request("id"))$this->error("非法参数");
+        OrderFreeze::query()->where("id",request("id"))->update(["status"=>1]);
+        app("OrderFreezeService")->refreshFreezes();
+        $this->success();
+    }
+}

+ 47 - 27
app/Http/Controllers/OrderIssueController.php

@@ -21,6 +21,7 @@ use App\Services\OwnerService;
 use App\Shop;
 use App\UserWorkgroup;
 use Exception;
+use Illuminate\Database\QueryException;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Cache;
@@ -377,32 +378,6 @@ class OrderIssueController extends Controller
         }
     }
 
-    public function updateLogisticNumberReturnApi(Request $request){
-        if (!Gate::allows('订单管理-问题件-编辑')) {
-            return ['success'=>false,'fail_info' => '没有对应权限'];
-        }
-        try {
-            /** @var OrderIssue $orderIssue */
-            $orderIssue = OrderIssue::query()->where('id',$request->input('id'))->first();
-            $rejectedBill = RejectedBill::query()
-                ->with('items')
-                ->where('logistic_number_return',$request->input('logisticNumberReturn'))
-                ->first();
-            app('LogService')->log(__METHOD__, __FUNCTION__, json_encode($request->getContent()));
-            if(!$rejectedBill){
-                $orderIssue->update(['logistic_number_return' => $request->input('logisticNumberReturn')]);
-                return ['success' => false, 'message' => '退回单号已修改,退回单号没有相应退件信息'];
-            }else{
-                $orderIssue->update(['logistic_number_return' => $request->input('logisticNumberReturn'),'is_new_rejecting' => '有']);
-                $orderIssue->同步退单状态();
-                return ['success' => true, 'rejectedBill' => $rejectedBill,'rejectingStatus' =>$orderIssue->rejecting_status];
-            }
-        } catch (Exception $e) {
-            app('LogService')->log(__METHOD__, __FUNCTION__,'error'. json_encode($request->getContent()).'||'.$e->getMessage().'||'.$e->getTraceAsString());
-            return ['success' => false ,'fail_info' => $e->getMessage()];
-        }
-    }
-
     public function apiUpdateValidator(array $arr)
     {
         return Validator::make($arr, [
@@ -766,7 +741,7 @@ class OrderIssueController extends Controller
             return ['success'=>false,'error'=>'没有对应权限'];
         }
         try {
-            $bool = OrderIssue::query()->whereIn('id', $request['ids'])->update(['finance_confirm' => '是']);
+            $bool = OrderIssue::query()->whereIn('id', $request['ids'])->update(['finance_confirm' => $request->flag]);
             if($bool==false)return ['success'=>false,'error'=>'财务确认失败'];
             app('LogService')->log(__METHOD__, __FUNCTION__,'财务确认'. json_encode($request->getContent()), Auth::user()['id']);
             return ['success'=>true];
@@ -794,4 +769,49 @@ class OrderIssueController extends Controller
         return ['success' =>true];
     }
 
+    public function addUserWorkgroup(Request $request)
+    {
+        $orderIssueId = $request->orderIssueId;
+        $userWorkgroupId = $request->userWorkgroupId;
+        try {
+            OrderIssue::query()->find($orderIssueId)->userWorkgroups()->attach($userWorkgroupId);
+        } catch (QueryException $e) {
+            return ['success' => false,'data' =>'事故责任方已存在'];
+        }
+        return ['success' => true,'data' =>UserWorkgroup::find($userWorkgroupId)];
+    }
+    public function destroyUserWorkgroup(Request $request)
+    {
+        $orderIssueId = $request->orderIssueId;
+        $userWorkgroupId = $request->userWorkgroupId;
+        OrderIssue::query()->find($orderIssueId)->userWorkgroups()->detach($userWorkgroupId);
+        return ['success' => true,'data' =>UserWorkgroup::find($userWorkgroupId)];
+    }
+
+    public function batchOthers(Request $request)
+    {
+        $orderIssueIds = $request->input("orderIssueIds");
+        $data = [];
+        if ($request->input("logistic_indemnity_money")) {
+            $data['logistic_indemnity_money'] = $request->input("logistic_indemnity_money");
+        }
+        if ($request->input("logistic_express_remission")) {
+            $data['logistic_express_remission'] = $request->input("logistic_express_remission");
+        }
+        if ($request->input("baoshi_indemnity_money")) {
+            $data['baoshi_indemnity_money'] = $request->input("baoshi_indemnity_money");
+        }
+        if ($request->input("baoshi_express_remission")) {
+            $data['baoshi_express_remission'] = $request->input("baoshi_express_remission");
+        }
+        OrderIssue::query()->whereIn('id',$orderIssueIds)->update($data);
+        $userWorkGroupIds = $request->input("userWorkGroupIds");
+        if (isset($userWorkGroupIds)) {
+            $orderIssues = OrderIssue::query()->whereIn('id', $orderIssueIds)->get();
+            foreach ($orderIssues as $orderIssue) {
+                $orderIssue->userWorkGroups()->sync($userWorkGroupIds);
+            }
+        }
+        return ['success' => true];
+    }
 }

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

@@ -22,6 +22,8 @@ class OwnerController extends Controller
     /**
      * Display a listing of the resource.
      *
+     * @param Request $request
+     *
      * @return Response
      */
     public function index(Request $request)
@@ -143,7 +145,10 @@ class OwnerController extends Controller
      *
      * @param Request $request
      * @param Owner $owner
+     *
      * @return Response
+     *
+     * @throws Exception
      */
     public function update(Request $request, Owner $owner)
     {
@@ -173,6 +178,7 @@ class OwnerController extends Controller
         $re = $owner->update([
             "deleted_at" => date('Y-m-d H:i:s'),
         ]);
+        app("OwnerService")->deleteAuthority($owner);
         app('LogService')->log(__METHOD__, __FUNCTION__, $owner->toJson(), Auth::user()['id']);
         return ['success' => $re];
     }
@@ -194,6 +200,7 @@ class OwnerController extends Controller
         $id = $request->input('id');
         $owner = Owner::query()->whereNotNull('deleted_at')->where('id', $id)->first();
         $owner->update(["deleted_at" => null]);
+        app("OwnerService")->createAuthority($owner);
         app('LogService')->log(__METHOD__, __FUNCTION__, json_encode($request->toArray()), Auth::user()['id']);
         return ['success' => 'true', 'owner' => $owner];
     }

+ 18 - 0
app/Http/Controllers/RegionController.php

@@ -0,0 +1,18 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Components\AsyncResponse;
+use App\Region;
+
+class RegionController extends Controller
+{
+    use AsyncResponse;
+    public function get()
+    {
+        $type = request("type");
+        $regions = Region::query();
+        if (!$type)$regions->where("type",$type);
+        $this->success($regions->get());
+    }
+}

+ 15 - 1
app/Http/Controllers/RejectedBillController.php

@@ -297,7 +297,7 @@ class RejectedBillController extends Controller
     function seekOrder(Request $request)
     {
         if (!$request['logistic_number_return'])return ['success'=>false];
-        $result = app('RejectedBillService')->getOrderInfo($request['logistic_number_return']);
+        $result = app('RejectedBillService')->findOrder($request['logistic_number_return']);
         if($result)return ['success' => true,'data' => $result];
         else return ['success'=>false];
     }
@@ -436,4 +436,18 @@ class RejectedBillController extends Controller
         return view('rejected.importRejectedNumber');
     }
 
+    public function findOrderByStoreRejectedApi(Request $request)
+    {
+        if (!$request['logistic_number_return'])return ['success'=>false];
+        /** @var RejectedBillService $service */
+        $service = app('RejectedBillService');
+        $result = $service->findOrderByStoreRejected($request['logistic_number_return']);
+        if($result)return ['success' => true,'data' => $result];
+        $result = $service->findOrderByOrderHeader($request['logistic_number_return']);
+        if($result)return ['success' => true,'data' => $result];
+        $result = $service->findOrderByOrderIssue($request['logistic_number_return']);
+        if($result)return ['success' => true,'data' => $result];
+        return ['success'=>false];
+    }
+
 }

+ 75 - 0
app/Http/Controllers/SendEmailsController.php

@@ -0,0 +1,75 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\MailEvent;
+use App\Role;
+use Illuminate\Http\Request;
+
+class SendEmailsController extends Controller
+{
+    //
+    public function index()
+    {
+        $roles = Role::all();
+        $emailEvents = MailEvent::query()->with('roles')->orderBy('id')->paginate();
+        foreach ($emailEvents as $emailEvent) {
+            $emailEvent->template = json_decode($emailEvent->template);
+            $emailEvent->remark_show = true;
+            $emailEvent->remark_edit = false;
+            $emailEvent->template_show = true;
+            $emailEvent->template_edit = false;
+            $emailEvent->role_selected = '';
+        }
+        return view('maintenance.emails.index', compact('roles', 'emailEvents'));
+    }
+
+    public function addRole(Request $request)
+    {
+        $roleId = $request->roleId;
+        $role = Role::find($roleId);
+        $eventMailId = $request->eventMailId;
+        if (MailEvent::query()->find($eventMailId)->roles()->where('roles.id', $roleId)->exists()) {
+            return ['success' => false, 'data' => '角色已存在'];
+        } else {
+            MailEvent::query()->find($eventMailId)->roles()->attach($role->id);
+            return ['success' => true, 'data' => ['role' => $role]];
+        }
+    }
+
+    public function deleteRole(Request $request)
+    {
+        $roleId = $request->roleId;
+        $role = Role::find($roleId);
+        $eventMailId = $request->eventMailId;
+        MailEvent::query()->find($eventMailId)->roles()->detach($role->id);
+        return ['success' => true, 'data' => $role];
+    }
+
+    public function updateTemplate(Request $request)
+    {
+        $model = MailEvent::query()->find($request->id);
+        $model->update([
+            'template' => $request->template,
+        ]);
+        return ['success' => true];
+    }
+
+    public function active(Request $request)
+    {
+        $model = MailEvent::query()->find($request->id);
+        $model->update([
+            'is_active' => !$model->is_active,
+        ]);
+        return ['success' => true, 'data' => !$model->is_active];
+    }
+
+    public function updateRemark(Request $request)
+    {
+        $model = MailEvent::query()->find($request->id);
+        $model->update([
+            'remark' => $request->remark,
+        ]);
+        return ['success' => true];
+    }
+}

+ 119 - 52
app/Http/Controllers/TestController.php

@@ -15,12 +15,17 @@ use App\Console\Commands\CreateOwnerReport;
 use App\Console\Commands\SyncWmsCommoditiesInformation;
 use App\Console\Commands\SyncWMSOrderTask;
 use App\Console\Commands\WasSyncWmsAsnInformation;
+use App\Events\CancelOrder;
+use App\Events\SendEmailEvent;
+use App\Http\Requests\ForeignHaiRobotic_taskUpdateRequest;
+use App\Http\Requests\TestAaRequest;
 use App\Imports\OrderTrackingImport;
 use App\InventoryAccount;
 use App\LaborReport;
 use App\Log;
 use App\Logistic;
 use App\Menu;
+use App\Notifications\SendEmailNotification;
 use App\OracleActAllocationDetails;
 use App\OracleBasCustomer;
 use App\OracleBasSKU;
@@ -159,65 +164,90 @@ sql;
             }
         });
     }
+    protected $params;
+    protected $pool;
     public function zzd()
     {
-        $model4 = factory(OwnerPriceOperation::class)->create([
-            "operation_type"=>"出库",   //操作类型
-            "strategy"      =>"特征",         //策略
-        ]);
-        $pieces = Unit::query()->where("name","件")->first();
-        $box = Unit::query()->where("name","箱")->first();
-        $single = Unit::query()->where("name","单")->first();
-        if (!$pieces){
-            $pieces = factory(Unit::class)->create(["name"=>"件"]);
-        }
-        if (!$box){
-            $box = factory(Unit::class)->create(["name"=>"箱"]);
-        }
-        if (!$single){
-            $single = factory(Unit::class)->create(["name"=>"单"]);
+        $this->params = [
+            [
+                "code"  => "test1",
+                "logistic_id" => "4",
+                "province" => "宁夏自治区",
+                "city" => "石嘴山市",
+                "district" => "花都区",
+                "wms_status" => "创建订单",
+            ],
+            [
+                "code"  => "test2",
+                "logistic_id" => "4",
+                "province" => "宁夏自治区",
+                "city" => "石嘴山市",
+                "district" => "花都区",
+                "wms_status" => "订单完成",
+            ],
+            [
+                "code"  => "test3",
+                "logistic_id" => "2",
+                "province" => "宁夏自治区",
+                "city" => "石嘴山市",
+                "district" => "花都区",
+                "wms_status" => "创建订单",
+            ],
+            [
+                "code"  => "test4",
+                "logistic_id" => "2",
+                "province" => "宁夏自治区",
+                "city" => "",
+                "district" => "",
+                "wms_status" => "创建订单",
+            ]
+        ];
+        if (!$this->params)return;
+        $this->pool = app("OrderFreezeService")->getFreezes();
+        if (isset($this->params[0][0]))$this->processUpdate();
+        $this->processCreate();
+    }
+    protected function processUpdate()
+    {
+        unset($this->params[0]);
+    }
+
+    protected function processCreate()
+    {
+        $freezeOrders = [];
+        foreach ($this->params as $param){
+            if (!$param["logistic_id"])continue;
+            if ($this->isFreeze($param))$freezeOrders[] = $param["code"];
         }
-        $item8 = factory(OwnerPriceOperationItem::class)->create([
-            "owner_price_operation_id"          => $model4->id,
-            "strategy"                          => "起步",
-            "unit_id"                           => $box->id,
-            "unit_price"                        => 5.5,
-        ]);
-        $item9 = factory(OwnerPriceOperationItem::class)->create([
-            "owner_price_operation_id"          => $model4->id,
-            "strategy"                          =>"默认",
-            "unit_id"                           => $box->id,
-            "unit_price"                        => 5.6,
-        ]);
-        $item10 = factory(OwnerPriceOperationItem::class)->create([
-            "owner_price_operation_id"          => $model4->id,
-            "strategy"                          =>"特征",
-            "unit_id"                           => $box->id,
-            "unit_price"                        => 5.7,
-        ]);
-        $owner = factory(Owner::class)->create([
-            "user_owner_group_id" => 1,
-        ]);
-        $model4->ownerPriceOperationOwners()->sync([$owner->id]);
+        $this->pushWMS($freezeOrders);
+    }
 
-        $commodity = factory(Commodity::class)->create([
-            'sku' => md5(date('Ymd').\Illuminate\Support\Str::random(3)),
-            'owner_id' => $owner->id,
-            "pack_spec" => 3
-        ]);
-        $result = app(OwnerPriceOperationService::class)
-            ->matching(["packages"=>
-                [["commodity"=>"测试","amount"=>57,"sku"=>$commodity->sku]]]
-                ,[],
-                $owner->id,"出库");
-        dd($result);
+    private function isFreeze($param)
+    {
+        $status = ['分配完成','创建订单','拣货完成','播种完成'];
+        if (array_search($param["wms_status"],$status)===false)return false;
+
+        foreach ($this->pool as $pool){
+            if ($pool["logistic_id"]!=$param["logistic_id"])continue;
+            if ($pool["province_name"] && (mb_strpos($param["province"],$pool["province_name"]) === false))continue;
+            if ($pool["city_name"] && (mb_strpos($param["city"],$pool["city_name"]) === false))continue;
+            if ($pool["location_name"] && (mb_strpos($param["district"],$pool["location_name"]) === false))continue;
+            return true;
+        }
+        return false;
     }
 
-    public function zzd1()
+    private function pushWMS($freezeOrders)
     {
-        $a = [1,2];
-        $b = [2];
-        dd(array_diff($b,$a));
+        if (!$freezeOrders)return;
+        $where = "''";
+        foreach ($freezeOrders as $f)$where .= ",'{$f}'";
+        $sql = <<<sql
+UPDATE DOC_ORDER_HEADER SET releasestatus = 'H',waveno='*',notes = CASE WHEN notes IS NULL THEN '停运' ELSE  notes||',停运' END where ORDERNO in ({$where})
+sql;
+        dd($freezeOrders,$sql);
+        LogService::log(__METHOD__,"订单同步-自动冻结",$sql);
+        DB::connection("oracle")->update($sql);
     }
 
     public function mergeCarrier()
@@ -1439,6 +1469,17 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
         $service->clearCancelledOrderTask();
     }
 
+    public function sendEmail()
+    {
+        event(new SendEmailEvent());
+    }
+
+    public function y111()
+    {
+        $controller = new SendEmailsController();
+        $controller->index();
+    }
+
     public function processOrderIssueRejectedBill()
     {
         OrderIssue::query()->withTrashed()->whereNotNull('logistic_number_return')->chunkById(200,function($orderIssues){
@@ -1522,4 +1563,30 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
             }
         });
     }
+
+    public function deleteOrderTracking()
+    {
+        $deleteId_arr = [];
+        $deleteCommoditiesId_arr = [];
+        OrderTracking::query()->with(['commodities.package'])
+            ->where('created_at','!=','0000-00-00 00:00:00')
+            ->chunkById('200',function($orderTrackings)use(&$deleteId_arr,&$deleteCommoditiesId_arr){
+                $deleteIds = [];
+                $deleteCommoditiesId = [];
+                foreach ($orderTrackings as $orderTracking) {
+                    if(!($orderTracking->commodities->package ?? false)){
+                        $deleteIds[]  = $orderTracking->id;
+                        if($orderTracking->commodities){
+                            $deleteCommoditiesId[] = $orderTracking->commodities->id;
+                        }
+                    }
+                }
+                if($deleteIds){
+                    $deleteId_arr[] = $deleteIds;
+                    $deleteCommoditiesId_arr[] = $deleteCommoditiesId;
+                    OrderTracking::query()->whereIn('id',$deleteIds)->delete();
+                    OrderPackageCommodities::query()->whereIn('id',$deleteCommoditiesId)->delete();
+                }
+            });
+    }
 }

+ 86 - 0
app/Jobs/OrderFreeze.php

@@ -0,0 +1,86 @@
+<?php
+
+namespace App\Jobs;
+
+use App\Services\LogService;
+use App\Services\OrderFreezeService;
+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\DB;
+
+class OrderFreeze implements ShouldQueue
+{
+    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+
+    protected $params;
+    protected $pool;
+    /**
+     * Create a new job instance.
+     * @param array $params
+     * @return void
+     */
+    public function __construct(array $params)
+    {
+        $this->params = $params;
+    }
+
+    /**
+     * Execute the job.
+     *
+     * @param OrderFreezeService $service
+     *
+     * @return void
+     */
+    public function handle(OrderFreezeService $service)
+    {
+        if (!$this->params)return;
+        $this->pool = $service->getFreezes();
+        if (isset($this->params[0][0]))$this->processUpdate();
+        $this->processCreate();
+    }
+
+    protected function processUpdate()
+    {
+        unset($this->params[0]);
+    }
+
+    protected function processCreate()
+    {
+        $freezeOrders = [];
+        foreach ($this->params as $param){
+            if (!$param["logistic_id"])continue;
+            if ($this->isFreeze($param))$freezeOrders[] = $param["code"];
+        }
+        $this->pushWMS($freezeOrders);
+    }
+
+    private function isFreeze($param)
+    {
+        $status = ['分配完成','创建订单','拣货完成','播种完成'];
+        if (array_search($param["wms_status"],$status)===false)return false;
+
+        foreach ($this->pool as $pool){
+            if ($pool["logistic_id"]!=$param["logistic_id"])continue;
+            if ($pool["province_name"] && (mb_strpos($param["province"],$pool["province_name"]) === false))continue;
+            if ($pool["city_name"] && (mb_strpos($param["city"],$pool["city_name"]) === false))continue;
+            if ($pool["location_name"] && (mb_strpos($param["district"],$pool["location_name"]) === false))continue;
+            return true;
+        }
+        return false;
+    }
+
+    private function pushWMS($freezeOrders)
+    {
+        if (!$freezeOrders)return;
+        $where = "''";
+        foreach ($freezeOrders as $f)$where .= ",'{$f}'";
+        $sql = <<<sql
+UPDATE DOC_ORDER_HEADER SET releasestatus = 'H',waveno='*',notes = CASE WHEN notes IS NULL THEN '停运' ELSE  notes||',停运' END where ORDERNO in ({$where})
+sql;
+        DB::connection("oracle")->update($sql);
+        LogService::log(__METHOD__,"订单同步-自动冻结",$sql);
+    }
+}

+ 63 - 0
app/Listeners/SendEmailListener.php

@@ -0,0 +1,63 @@
+<?php
+
+namespace App\Listeners;
+
+use App\Events\SendEmailEvent;
+use App\MailEvent;
+use App\Notifications\SendEmailNotification;
+use Tightenco\Collect\Support\Collection;
+
+/**
+ * 邮件发送监听器
+ * Class SendEmailListener
+ * @package App\Listeners
+ */
+class SendEmailListener
+{
+
+
+    /**
+     * SendEmailListener constructor.
+     */
+    public function __construct()
+    {
+
+    }
+
+
+    /**
+     * Handle the event.
+     *
+     * @param SendEmailEvent $event
+     * @return void
+     */
+    public function handle(SendEmailEvent $event)
+    {
+        //根据SendEmailEvent->className 从数据库中查找,判断状态是否开启
+        $emailEvent = MailEvent::query()
+            ->where('event_name', SendEmailEvent::class)
+            ->where('is_active', true)
+            ->first();
+        if ($emailEvent) {
+            /** @var MailEvent $emailEvent */
+            $users = $this->getUsers($emailEvent);
+            foreach ($users as $user) {//给这些用户发送通知
+                $user->notify(new SendEmailNotification($emailEvent->template));//邮件模板由数据库中定制的模板为准
+            }
+        }
+    }
+
+    /**
+     * 根據事件关联的角色,查询到用户
+     * @param MailEvent $emailEvent
+     * @return \Illuminate\Support\Collection|Collection
+     */
+    private function getUsers(MailEvent $emailEvent)
+    {
+        $users = collect();
+        foreach ($emailEvent->roles as $role) {
+            $users = $users->merge($role->users);
+        }
+        return $users;
+    }
+}

+ 23 - 0
app/MailEvent.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\LogModelChanging;
+use Illuminate\Database\Eloquent\Relations\BelongsToMany;
+
+class MailEvent extends Model
+{
+    use LogModelChanging;
+
+    protected $fillable = ['name', 'event_name', 'remark', 'is_active', 'template'];
+
+    /**
+     * @return BelongsToMany
+     */
+    public function roles(): BelongsToMany
+    {
+        return $this->belongsToMany(Role::class,'mail_event_role','mail_event_id','role_id');
+    }
+}

+ 63 - 0
app/Notifications/SendEmailNotification.php

@@ -0,0 +1,63 @@
+<?php
+
+namespace App\Notifications;
+
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Notifications\Messages\MailMessage;
+use Illuminate\Notifications\Notification;
+
+class SendEmailNotification extends Notification implements ShouldQueue
+{
+    use Queueable;
+
+    public $objToJson;
+
+    /**
+     * SendEmailNotification constructor.
+     * @param $objToJson
+     */
+    public function __construct($objToJson)
+    {
+        $this->objToJson = $objToJson;
+    }
+
+
+    /**
+     * Get the notification's delivery channels.
+     *
+     * @param  mixed  $notifiable
+     * @return array
+     */
+    public function via($notifiable): array
+    {
+        return ['mail'];
+    }
+
+    /**
+     * Get the mail representation of the notification.
+     *
+     * @param  mixed  $notifiable
+     * @return MailMessage
+     */
+    public function toMail($notifiable): MailMessage
+    {
+        $template = json_decode($this->objToJson);
+        return (new MailMessage)->view(
+            'emails.test', ['objToJson' => $template]
+        )->subject($template->title);
+    }
+
+    /**
+     * Get the array representation of the notification.
+     *
+     * @param  mixed  $notifiable
+     * @return array
+     */
+    public function toArray($notifiable)
+    {
+        return [
+            //
+        ];
+    }
+}

+ 1 - 0
app/Observers/OwnerObserver.php

@@ -16,6 +16,7 @@ class OwnerObserver
     {
         if(env('APP_ENV')=='production')
             app("OwnerService")->syncPush($owner);
+            app("OwnerService")->createAuthority($owner);
     }
 
     public function updated(Owner $owner)

+ 40 - 0
app/OrderFreeze.php

@@ -0,0 +1,40 @@
+<?php
+
+namespace App;
+
+use App\Traits\ModelTimeFormat;
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\LogModelChanging;
+
+class OrderFreeze extends Model
+{
+    use LogModelChanging;
+    use ModelTimeFormat;
+
+    protected $fillable = [
+        "status","logistic_id","province_id","city_id","location_id"
+    ];
+
+    const status=[
+        0 => "冻结",
+        1 => "解冻",
+    ];
+
+    public function logistic()
+    {  //承运商
+        return $this->belongsTo(Logistic::class);
+    }
+    public function province()
+    {   //省
+        return $this->belongsTo(Province::class);
+    }
+    public function city()
+    {   //市
+        return $this->belongsTo(City::class);
+    }
+    public function location()
+    {   //区
+        return $this->belongsTo(City::class)->where("type","3");
+    }
+}

+ 23 - 97
app/OrderIssue.php

@@ -5,6 +5,7 @@ namespace App;
 use App\Traits\ModelTimeFormat;
 use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\BelongsToMany;
 use Illuminate\Database\Eloquent\SoftDeletes;
 
 use App\Traits\LogModelChanging;
@@ -119,102 +120,6 @@ class OrderIssue extends Model
         return $createLog->user->name ?? '';
     }
 
-    public function 同步退单状态(){
-        $rejectedItems = [];
-        $orderItems = [];
-        $orderIssueId = $this['id'];
-        if ($this->logistic_number_return ?? false) {
-            $rejectedBillItems = RejectedBillItem::query()->with('quality')
-                ->whereHas('rejectedBill.orderIssue', function ($query) use ($orderIssueId) {
-                    $query->where('id',$orderIssueId);
-                })->get();
-            if($rejectedBillItems->where('quality.name','残次')->count() > 0){
-                $this->update(['rejecting_status' => '差异退回']);
-                return;
-            }
-            if (count($rejectedBillItems) == 0) {
-                $this->update(['rejecting_status' => '未退回']);
-                return;
-            }
-            $barcodeGoods = data_get($rejectedBillItems,'*.barcode_goods');
-            $commodityBarcodes = CommodityBarcode::query()->with('commodity')->whereIn('code',$barcodeGoods)->get();
-            $commodities = Commodity::query()->whereIn('sku',$barcodeGoods)->get();
-
-            foreach ($rejectedBillItems as $item) {
-                $barcode_goods = (string)$item->barcode_goods;
-                $commodity = $commodities->where('sku',$barcode_goods)->first();
-                if(!$commodity){
-                    $commodityBarcode = $commodityBarcodes->where('code',$barcode_goods)->first();
-                    $barcode_goods = $commodityBarcode->commodity->sku ?? $barcode_goods;
-                }
-                if (!isset($rejectedItems[$barcode_goods])){
-                    $rejectedItems[$barcode_goods] = 0;
-                }
-                $rejectedItems[(string)$barcode_goods] += $item->amount;
-            }
-        } else {
-            $this->update(['rejecting_status' => '未退回']);
-            return;
-        }
-        if ($this->order_id  ?? false) {
-            $items = OrderPackageCommodities::query()
-                ->with(['commodity','package.order.issue'])
-                ->whereHas('package.order.issue', function ($query) use ($orderIssueId) {
-                    $query->where('id', $orderIssueId);
-                })->get();
-            if (count($items) > 0) {
-                foreach ($items as $item) {
-                    $sku = $item['commodity']['sku'];
-                    if (! isset($orderItems[$sku])  ?? false){
-                        $orderItems[$sku] = 0;
-                    }
-                    $orderItems[$sku] += $item->amount;
-                }
-            } else {
-                $this->update(['rejecting_status' => '无']);
-                return;
-            }
-        }
-        $rejectedExcess = 0;    // 退回差异
-        $rejectedReview = 0;    // 退回复核  $rejectedItems == $orderItems
-        foreach ($rejectedItems as $key => $items) {
-            if ($orderItems[$key] ?? false) {
-                if ($rejectedItems[$key] == $orderItems[$key])
-                    $rejectedReview++;
-            } else
-                $rejectedExcess++;
-        }
-        if ($rejectedExcess > 0) {
-            $this->update(['rejecting_status' => '差异退回']);
-            return;
-        }
-        // 全部退回 部分退回 超量退回 差异退回 未退回 无
-        $isExcess = 0; // 超量 $orderItems < $rejectedItems
-        $isDiff = 0;   // 部分 $orderItems > $rejectedItems
-        $isAccord = 0; // 相同 $orderItems == $rejectedItems
-        $isLack = 0;   // 缺少 $orderItems != $rejectedItems
-        foreach ($orderItems as $key => $item) {
-            if ($rejectedItems[$key] ?? false) {
-                if ($orderItems[$key] < $rejectedItems[$key])
-                    $isExcess++;
-                else if ($orderItems[$key] > $rejectedItems[$key])
-                    $isDiff++;
-                else if ($orderItems[$key] == $rejectedItems[$key])
-                    $isAccord++;
-            } else
-                $isLack++;
-        }
-
-        if($isAccord == $rejectedReview && $isLack == 0 && $isExcess == 0 && $isDiff==0 && $rejectedExcess == 0 )
-            $this->update(['rejecting_status' => '全部退回']);
-        else if($isExcess > 0 && $isAccord ==  $rejectedReview && $isDiff == 0 && $isLack == 0)
-            $this->update(['rejecting_status' => '超量退回']);
-        else if($isDiff >=0 && $isAccord == $rejectedReview && $isLack >=0 && $rejectedExcess ==0 && $isExcess==0)
-            $this->update(['rejecting_status' => '部分退回']);
-        else if($isLack >= 0 && $rejectedExcess>=0 && $isDiff>=0 && $isLack>=0 && $isExcess>=0 && $rejectedReview>=0)
-            $this->update(['rejecting_status' => '差异退回']);
-    }
-
     /**
      * 同步退货状态
      */
@@ -344,13 +249,28 @@ class OrderIssue extends Model
                 if($rejectedBill){
                     if(OrderIssueRejectedBill::isExit($this->id,$logistic_number))continue;
                     $this->joinRejectedBill($logistic_number);
-                    $this->is_new_rejecting = '有';
+                    if(isset($rejectedBill->items))
+                        $this->is_new_rejecting = '有';
                 }
             }
             $this->save();
         }
     }
 
+    public function syncRejected($logistic_number)
+    {
+        $query = RejectedBill::query()->selectRaw('id');
+        if(is_array($logistic_number)){
+            $query->whereIn('logistic_number_return',$logistic_number);
+        }elseif (is_string($logistic_number)){
+            $query->where('logistic_number_return',$logistic_number);
+        }else return;
+        $items = RejectedBillItem::query()->whereIn('id_rejected_bill',$query);
+        if($items->count() > 0) $this->update(['is_new_rejecting'=>'有']);
+        elseif($items->count() == 0) $this->update(['is_new_rejecting'=>'无']);
+    }
+
+
     /**
      * @param array|string $logistic_number
      * @return array|void
@@ -358,6 +278,7 @@ class OrderIssue extends Model
     public function joinRejectedBill($logistic_number)
     {
         if(!$logistic_number)return null;
+        $this->syncRejected($logistic_number);
         if(is_array($logistic_number)){
             return $this->rejectedBills()->sync($logistic_number,false);
         }
@@ -402,4 +323,9 @@ class OrderIssue extends Model
             ->orderBy('order_issue_on_tops.updated_at', 'desc')
             ->orderBy('order_issues.id', 'desc');
     }
+
+    public function userWorkgroups(): BelongsToMany
+    {
+        return $this->belongsToMany(UserWorkgroup::class);
+    }
 }

+ 3 - 1
app/Providers/AppServiceProvider.php

@@ -76,6 +76,7 @@ use App\Services\UserService;
 use App\Services\WarehouseService;
 use App\Services\WaybillFinancialService;
 use App\Services\WeighExceptedService;
+use App\Services\OrderFreezeService;
 use Illuminate\Queue\Events\JobFailed;
 use Illuminate\Support\Facades\Queue;
 use Illuminate\Support\Facades\Schema;
@@ -155,9 +156,10 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('OracleDocWaveDetailService',OracleDocWaveDetailService::class);
         app()->singleton('OrderCommodityAssignService',OrderCommodityAssignService::class);
         app()->singleton('OrderCommodityService',OrderCommodityService::class);
-        app()->singleton('OrderIssueRejectedBillService',OrderIssueRejectedBillService::class);
+        app()->singleton('OrderFreezeService',OrderFreezeService::class);
         app()->singleton('OrderIssuePerformanceService',OrderIssuePerformanceService::class);
         app()->singleton('OrderIssueProcessLogService',OrderIssueProcessLogService::class);
+        app()->singleton('OrderIssueRejectedBillService',OrderIssueRejectedBillService::class);
         app()->singleton('OrderIssueService',OrderIssueService::class);
         app()->singleton('OrderIssueWorkLoadService',OrderIssueWorkLoadService::class);
         app()->singleton('OrderPackageCommoditiesService',OrderPackageCommoditiesService::class);

+ 3 - 0
app/Providers/EventServiceProvider.php

@@ -35,6 +35,9 @@ class EventServiceProvider extends ServiceProvider
         ModelChangedEvent::class =>[
             ModelChangedListener::class
         ],
+        'App\Events\SendEmailEvent' => [
+            'App\Listeners\SendEmailListener'
+        ],
     ];
 
     /**

+ 34 - 0
app/Region.php

@@ -0,0 +1,34 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\LogModelChanging;
+
+/**
+ * 留存:目前仅当作区级使用 后续将省市表并入此表
+ */
+class Region extends Model
+{
+    use LogModelChanging;
+
+    public $timestamps=false;
+    protected $fillable = ["parent_id","name","type","code"];
+
+    const type=[
+        1 => "省",
+        2 => "市",
+        3 => "区县",
+    ];
+
+    public function parent()
+    {   //父级
+        return $this->belongsTo(Region::class,"parent_id","id");
+    }
+
+    public function city()
+    {   //市
+        return $this->belongsTo(City::class,"parent_id","id");
+    }
+}

+ 50 - 0
app/Services/OrderFreezeService.php

@@ -0,0 +1,50 @@
+<?php 
+
+namespace App\Services;
+
+use App\Traits\ServiceAppAop;
+use Illuminate\Support\Facades\Cache;
+
+class OrderFreezeService
+{
+    use ServiceAppAop;
+
+
+    /**
+     * 获取冻结信息
+     */
+    public function getFreezes()
+    {
+        return app(CacheService::class)->getOrExecute("order_freeze_condition_pool",function (){
+            return \App\OrderFreeze::query()
+                ->with(["logistic:id,name","province:id,name","city:id,name","location:id,name"])
+                ->where("status",0)
+                ->get(["logistic_id","province_id","city_id","location_id"])->each(function (&$freeze){
+                    $freeze["logistic_name"] = $freeze->logistic ? $freeze->logistic->name : '';
+                    $freeze["province_name"] = $freeze->province ? $freeze->province->name : '';
+                    $freeze["city_name"]     = $freeze->city ? $freeze->city->name : '';
+                    $freeze["location_name"] = $freeze->location ? $freeze->location->name : '';
+                    unset($freeze->logistic,$freeze->province,$freeze->city,$freeze->location);
+                })->toArray();
+        },config("cache.expirations.rarelyChange"));
+    }
+
+    /**
+     * 刷新冻结信息
+     */
+    public function refreshFreezes()
+    {
+        if (Cache::has("order_freeze_condition_pool")){
+            $val = \App\OrderFreeze::query()
+                ->with(["logistic:id,name", "province:id,name", "city:id,name", "location:id,name"])
+                ->where("status", 0)
+                ->get()->each(function (&$freeze) {
+                    $freeze["logistic_name"] = $freeze->logistic ? $freeze->logistic->name : '';
+                    $freeze["province_name"] = $freeze->province ? $freeze->province->name : '';
+                    $freeze["city_name"] = $freeze->city ? $freeze->city->name : '';
+                    $freeze["location_name"] = $freeze->location ? $freeze->location->name : '';
+                });
+            Cache::put("order_freeze_condition_pool",$val);
+        }
+    }
+}

+ 0 - 4
app/Services/OrderIssueRejectedBillService.php

@@ -23,7 +23,6 @@ Class OrderIssueRejectedBillService
             ->where('order_issue_id',$orderIssue->id)
             ->where('logistic_number_return',$logistic_number_return)->first();
         if($orderIssueRejectedBill)return null;
-        if(!OrderIssueRejectedBill::isExit($orderIssue->id,$logistic_number_return)) $orderIssue->update(['is_new_rejecting' => '有']);
         $orderIssue->joinRejectedBill($logistic_number_return);
         $orderIssue->syncRejectingStatus();      // 问题件同步订单状态
         return OrderIssueRejectedBill::query()->with('rejectedBill.items')
@@ -118,7 +117,4 @@ Class OrderIssueRejectedBillService
         }
         $order_issues->syncRejectingStatus();
     }
-
-
-
 }

+ 14 - 2
app/Services/OrderIssueService.php

@@ -46,7 +46,7 @@ class OrderIssueService
         if ($condition['owner_id'] ?? false) {
             $owner_ids = explode(',', $condition['owner_id']);
         }
-        $query = OrderIssue::with(['top', 'userWorkGroup', 'issueType', 'logs' => function ($query) use ($arr) {
+        $query = OrderIssue::with(['top', 'userWorkgroups', 'issueType', 'logs' => function ($query) use ($arr) {
             $query->with('user')->orderByDesc('created_at');
         }, 'order' => function ($query) {
             $query->with(['shop', 'logistic', 'owner', 'packages.commodities.commodity' => function ($query) {
@@ -236,6 +236,18 @@ class OrderIssueService
             });
             $query->orWhere('second_logistic_number',$condition['sendOrderLogisticNumber']);
         }
+        if (isset($condition['finance_confirm'])) {
+            $query->where('finance_confirm', $condition['finance_confirm']);
+        }
+        if (isset($condition['user_workgroups'])) {
+
+            if (is_string($condition['user_workgroups'])) {
+                $userWorkgroupIds = explode(',', $condition['user_workgroups']);
+            }
+            $query->whereHas('userWorkgroups', function ($query) use ($userWorkgroupIds) {
+                $query->whereIn('id', $userWorkgroupIds);
+            });
+        }
         return $query;
     }
 
@@ -619,7 +631,7 @@ class OrderIssueService
                 $query->with(['logistic','shop','owner','packages'=>function($query){
                 $query->with('commodities');
             }]);
-        },'rejectedBill.items','issueType','secondOrder.packages.commodities'])->onlyTrashed()->paginate($params['paginate'] ?? 50);
+        },'orderIssueRejectedBills.rejectedBill.items','issueType','secondOrder.packages.commodities'])->onlyTrashed()->paginate($params['paginate'] ?? 50);
     }
 
     public function recoverOrderIssue($ids)

+ 1 - 1
app/Services/OrderPackageService.php

@@ -198,7 +198,7 @@ class OrderPackageService
         if(count($packages)==0)return $packages;
         try {
             $bool = OrderPackage::query()->whereIn('id', $packages)->delete();
-            $orderPackageCommodities = OrderPackageCommodities::query()->where('order_package_id',$packages)->get();
+            $orderPackageCommodities = OrderPackageCommodities::query()->whereIn('order_package_id',$packages)->get();
             $orderPackageCommoditiesService->deleteOrderCommodities($orderPackageCommodities);
             $bool ? LogService::log(__METHOD__,__FUNCTION__,'删除多余包裹 ids:'.json_encode($packages)) : null;
         } catch (\Exception $e) {

+ 5 - 1
app/Services/OrderService.php

@@ -3,6 +3,7 @@
 namespace App\Services;
 
 use App\Jobs\OrderCreateInstantBill;
+use App\Jobs\OrderFreeze;
 use App\Logistic;
 use App\OracleActAllocationDetails;
 use App\OracleDOCASNHeader;
@@ -649,7 +650,9 @@ class OrderService
         // 转换插入 3s
         if(count($created_params) > 0){
             collect($created_params)->chunk(3500)->each(function($inner_params){
-                $this->insert($inner_params->toArray());
+                $arr = $inner_params->toArray();
+                $this->insert($arr);
+                dispatch(new OrderFreeze($arr));
             });
         }
         unset($created_params);
@@ -663,6 +666,7 @@ class OrderService
         unset($update_order);
         if(count($update_params)==0)return;
         $this->batchUpdate($update_params);
+        dispatch(new OrderFreeze($update_params));
         unset($update_params);
     }
 

+ 30 - 0
app/Services/OwnerService.php

@@ -2,6 +2,7 @@
 
 namespace App\Services;
 
+use App\Authority;
 use App\OracleBasCustomer;
 use App\Owner;
 use App\User;
@@ -332,4 +333,33 @@ sql
         }
         return true;
     }
+
+    /**
+     * 同步货主时创建权限
+     *
+     * @param array|Owner $owner
+     */
+    public function createAuthority($owner)
+    {
+        Authority::query()->create([
+            'name' => "_{$owner['id']}",
+            'alias_name' => "(货主:{$owner['name']})",
+            'remark' => "(key: _{$owner['id']})",
+        ]);
+    }
+
+    /**
+     * 停用货主时删除权限
+     *
+     * @param array|Owner $owner
+     */
+    public function deleteAuthority($owner)
+    {
+        $authorities = Authority::query()->where('name',"_{$owner['id']}")
+            ->where("alias_name","like","(货主%")
+            ->get(["id"]);
+        $ids = array_column($authorities->toArray(),"id");
+        DB::table("authority_role")->whereIn("id_authority",$ids)->delete();
+        Authority::destroy($ids);
+    }
 }

+ 45 - 7
app/Services/RejectedBillService.php

@@ -12,10 +12,12 @@ use App\OrderPackage;
 use App\RejectedBill;
 use App\Services\common\BatchUpdateService;
 use App\Services\common\DataHandlerService;
+use App\StoreRejected;
 use Carbon\Carbon;
 use App\Traits\ServiceAppAop;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Query\Builder;
+use function Symfony\Component\String\s;
 
 
 Class RejectedBillService
@@ -206,11 +208,36 @@ Class RejectedBillService
      * @param string $logisticNumber
      * @return array|Builder|Model|object|null
      */
-    public function getOrderInfo($logisticNumber)
+    public function findOrderByOrderPackage($logisticNumber)
     {
+        // 本地订单的快递单号 原单退回
         $order_package_query =  OrderPackage::query()->selectRaw('order_id')->where('logistic_number',$logisticNumber);
+        /** @var Order $order */
         $order = Order::query()->whereIn('id',$order_package_query )->first();
-        if($order)return $order->toArray();
+        if($order){
+            $order = $order->toArray();
+            $order['logistic_number'] = '原单退回';
+            return $order;
+        }
+        return null;
+    }
+
+    public function findOrderByStoreRejected($logisticNumber)
+    {
+        $store_rejected_query = StoreRejected::query()->selectRaw('order_id')->where('logistic_number_return',$logisticNumber);
+        $order = Order::query()->whereIn('id',$store_rejected_query)->first();
+        if($order){
+            $order_package = OrderPackage::query()->where('order_id',$order->id)->first();
+            $order = $order->toArray();
+            $order['logistic_number'] = $order_package['logistic_number'] ?? '';
+            return $order;
+        }
+        return null;
+    }
+
+
+    public function findOrderByOrderHeader($logisticNumber)
+    {
         $act_allocation_details_query = OracleActAllocationDetails::query()->selectRaw('OrderNo')->where('pickToTraceId',$logisticNumber);
         /** @var OracleDOCOrderHeader $order_header */
         $order_header = OracleDOCOrderHeader::query()->whereIn('OrderNo',$act_allocation_details_query)->first();
@@ -221,12 +248,23 @@ Class RejectedBillService
                 'consignee_name' => $order_header['c_contact'] ?? '' ,
                 'consignee_phone' =>  $order_header['c_tel2'] ?? $order_header['c_tel1'],
                 'client_code'  => $order_header['soreference1'] ?? '',
+                'logistic_number'  => $order_header['soreference5'] ?? '',
             ];
         }
-        $order_issue_rejected_bill_query = OrderIssueRejectedBill::query()->selectRaw('order_issue_id')->where('logistic_number_return',$logisticNumber);
-        $order_issue_query = OrderIssue::query()->selectRaw('order_id')->whereIn('id',$order_issue_rejected_bill_query);
-        $order = Order::query()->whereIn('id',$order_issue_query)->first();
-        if($order)return $order;
-        else return null;
+        return null;
+    }
+    public function findOrderByOrderIssue($logisticNumberReturn)
+    {
+        // 问题件关联的退回单
+        $order_issue_rejected_bill_query = OrderIssueRejectedBill::query()->selectRaw('order_issue_id')->where('logistic_number_return',$logisticNumberReturn);
+        $oder_issue_query = OrderIssue::query()->selectRaw('order_id')->whereIn('id',$order_issue_rejected_bill_query);
+        $order = Order::query()->whereIn('id',$oder_issue_query)->first();
+        if($order){
+            $order_package = OrderPackage::query()->where('order_id',$order->id)->first();
+            $order = $order->toArray();
+            $order['logistic_number'] = $order_package['logistic_number'] ?? '';
+            return $order;
+        }
+        return null;
     }
 }

+ 1 - 0
app/Services/WaybillService.php

@@ -38,6 +38,7 @@ Class WaybillService
             'origination' => ['like' => ''],
             'destination' => ['like' => ''],
             'source_bill' => ['like' => ''],
+            'car_owner_info' => ['like' => ''],
             'created_at_start' => ['alias' => 'created_at' , 'startDate' => ':00'],
             'created_at_end' => ['alias' => 'created_at' , 'endDate' => ':59'],
             'uriType' => ['alias' => 'type'],

+ 6 - 0
app/UserWorkgroup.php

@@ -6,6 +6,7 @@ use Carbon\Carbon;
 use Illuminate\Database\Eloquent\Model;
 
 use App\Traits\LogModelChanging;
+use Illuminate\Database\Eloquent\Relations\BelongsToMany;
 
 class UserWorkgroup extends Model
 {
@@ -35,4 +36,9 @@ class UserWorkgroup extends Model
             return $this['signs']['mark'] == '是' ? true : false;
         }
     }
+
+    public function orderIssues(): BelongsToMany
+    {
+        return $this->belongsToMany(OrderIssue::class);
+    }
 }

+ 13 - 0
database/factories/OrderIssueRejectedBillFactory.php

@@ -0,0 +1,13 @@
+<?php
+
+/** @var \Illuminate\Database\Eloquent\Factory $factory */
+
+use App\Model;
+use Faker\Generator as Faker;
+
+$factory->define(\App\OrderIssueRejectedBill::class, function (Faker $faker) {
+    return [
+        'order_issue_id' => rand(0,10000),
+        'logistic_number_return' => $faker->phoneNumber
+    ];
+});

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

@@ -0,0 +1,35 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateNotificationsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('notifications', function (Blueprint $table) {
+            $table->uuid('id')->primary();
+            $table->string('type');
+            $table->morphs('notifiable');
+            $table->text('data');
+            $table->timestamp('read_at')->nullable();
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('notifications');
+    }
+}

+ 36 - 0
database/migrations/2021_01_08_110021_create_mail_events_table.php

@@ -0,0 +1,36 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateMailEventsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('mail_events', function (Blueprint $table) {
+            $table->id();
+            $table->string('name');
+            $table->string('event_name');
+            $table->string('remark')->nullable();
+            $table->boolean('is_active')->default(true);
+            $table->text('template')->nullable()->comment('邮件模板,json格式');
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('mail_events');
+    }
+}

+ 33 - 0
database/migrations/2021_01_08_110329_create_mail_event_role_table.php

@@ -0,0 +1,33 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateMailEventRoleTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('mail_event_role', function (Blueprint $table) {
+            $table->id();
+            $table->integer('mail_event_id');
+            $table->integer('role_id');
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('mail_event_role');
+    }
+}

+ 43 - 0
database/migrations/2021_01_08_110607_add_default_email.php

@@ -0,0 +1,43 @@
+<?php
+
+use App\Events\SendEmailEvent;
+use App\MailEvent;
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddDefaultEmail extends Migration
+{
+    protected $mailEvent;
+
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        //
+        $this->mailEvent = (new MailEvent([
+            'name' => '发送默认邮件',
+            'event_name' => SendEmailEvent::class,
+            'remark' => null,
+            'is_active' => true,
+            'template' => json_encode([
+                'title' => '邮件测试',
+                'description' => '这是一封测试邮件,收到不用回复'
+            ]),
+        ]))->save();
+
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        $this->mailEvent->delete();
+    }
+}

+ 36 - 0
database/migrations/2021_01_08_112003_add_default_mail_event_role.php

@@ -0,0 +1,36 @@
+<?php
+
+use App\Events\SendEmailEvent;
+use App\MailEvent;
+use App\Role;
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Schema;
+
+class AddDefaultMailEventRole extends Migration
+{
+    protected $role;
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        $this->role =  Role::query()->firstOrCreate(['name'=>'发送邮件测试']);
+        $emailEvent = MailEvent::query()->where('name', '发送默认邮件')->first();
+        $emailEvent->roles()->attach($this->role->id);
+        $this->role->users()->attach(\App\User::query()->where('name','yang')->first()->id);
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        $this->role->delete();
+    }
+}

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

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateOrderIssueUserWorkgroupTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('order_issue_user_workgroup', function (Blueprint $table) {
+            $table->bigInteger('order_issue_id');
+            $table->bigInteger('user_workgroup_id')->index();
+            $table->unique(['order_issue_id', 'user_workgroup_id'],'order_issue_user_workgroup_unique');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('order_issue_user_work_group');
+    }
+}

+ 39 - 0
database/migrations/2021_01_15_100109_create_order_freezes_table.php

@@ -0,0 +1,39 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateOrderFreezesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('order_freezes', function (Blueprint $table) {
+            $table->id();
+            $table->tinyInteger("status")->default(0)->comment("状态");
+            $table->bigInteger("logistic_id")->comment("承运商");
+            $table->bigInteger("province_id")->nullable()->comment("省");
+            $table->bigInteger("city_id")->nullable()->comment("市");
+            $table->bigInteger("location_id")->nullable()->comment("区");
+            $table->index(["status","logistic_id","province_id","city_id","location_id"],"freeze_s_l_p_c_l_index");
+            $table->timestamps();
+        });
+        \App\Authority::query()->firstOrCreate(["name"=>"订单管理-自动冻结","alias_name"=>"订单管理-自动冻结"]);
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('order_freezes');
+        \App\Authority::query()->where("name","订单管理-自动冻结")->delete();
+    }
+}

+ 34 - 0
database/migrations/2021_01_15_114628_create_regions_table.php

@@ -0,0 +1,34 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateRegionsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('regions', function (Blueprint $table) {
+            $table->id();
+            $table->bigInteger("parent_id")->nullable()->index()->comment("父级");
+            $table->string("name")->comment("名称");
+            $table->tinyInteger("type")->default(1)->comment("类型(行政区划)");
+            $table->string("code")->nullable()->comment("邮编");
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('regions');
+    }
+}

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

@@ -0,0 +1,32 @@
+<?php
+
+use App\OrderIssue;
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class SyncOrderIssueUserWorkgroup extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        $orderIssues = OrderIssue::query()->whereNotNull('user_workgroup_id')->get();
+        foreach ($orderIssues as $orderIssue) {
+            $orderIssue->userWorkgroups()->attach($orderIssue->user_workgroup_id);
+        }
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        //
+    }
+}

+ 1 - 1
resources/js/utilities/tempTip.js

@@ -134,7 +134,7 @@ const tempTip={
             this.setDuration(3000);
             this.show('网络异常:'+err);
         });
-    }
+    },
 };
 module.exports=tempTip;
 

+ 31 - 75
resources/views/customer/project/create.blade.php

@@ -394,18 +394,14 @@
                     let url = "{{url('customer/project/getPriceModel')}}";
                     let params = {id:this.ownerTemp.id};
                     window.tempTip.postBasicRequest(url,params,res=>{
-                        this._getOwners();
-                        this._getUnits();
-                        this._getCars();
-                        this._getCities();
-                        this._getLogistics();
-                        this._getProvinces();
-                        setTimeout(()=> {
-                            $(".selectpicker").selectpicker('refresh');
-                        },500);
                         if (res.owner_storage_price_models.length>0)this.selectedModel.storage = res.owner_storage_price_models;
-                        if (res.owner_price_operations.length>0)this.selectedModel.operation = res.owner_price_operations;
+                        if (res.owner_price_operations.length>0){
+                            this._loadOperation();
+                            this.selectedModel.operation = res.owner_price_operations;
+                        }
                         if (res.owner_price_expresses.length>0){
+                            this._loadExpress();
+                            if (!this.pool.logistics)this._getLogistics();
                             res.owner_price_expresses.forEach((express,i)=>{
                                 express.logistics.forEach((logistic,j)=>{
                                     express.logistics[j] = logistic.id;
@@ -416,6 +412,11 @@
                             this.selectedModel.express = res.owner_price_expresses;
                         }
                         if (res.owner_price_logistics.length>0){
+                            if (res.owner_price_expresses.length===0)this._loadLogistic();
+                            else {
+                                this._getUnits();
+                                this._getCities();
+                            }
                             res.owner_price_logistics.forEach((logistic,i)=>{
                                 logistic.logistics.forEach((l,j)=>{
                                     logistic.logistics[j] = l.id;
@@ -436,7 +437,7 @@
                     });
                 },
                 //加载仓储所需基础信息
-                _loadStorage(){
+                async _loadStorage(){
                     if (!this.pool.units)this._getUnits();
                     if (!this.isLoad && this.ownerTemp.id)this._loadPriceModel();//计费模型未被加载且项目ID存在时
                     if (!this.isLoad && !this.ownerTemp.id) this.isLoad = true;
@@ -448,24 +449,14 @@
                 //加载快递
                 _loadExpress(){
                     if (!this.pool.provinces)this._getProvinces();
-                    if (!this.pool.logistics){
-                        this._getLogistics();
-                        setTimeout(()=>{
-                            $(".selectpicker").selectpicker('refresh');
-                        },500);
-                    }
+                    if (!this.pool.logistics)this._getLogistics();
                 },
                 //加载物流
                 _loadLogistic(){
                     if (!this.pool.units) this._getUnits();
                     if (!this.pool.provinces)this._getProvinces();
                     if (!this.pool.cities)this._getCities();
-                    if (!this.pool.logistics){
-                        this._getLogistics();
-                        setTimeout(()=>{
-                            $(".selectpicker").selectpicker('refresh');
-                        },500);
-                    }
+                    if (!this.pool.logistics)this._getLogistics();
                 },
                 //加载直发车
                 _loadDirectLogistic(){
@@ -476,83 +467,48 @@
                     if (!this.pool.owners)this._getOwners();
                     if (!this.pool.logistics)this._getLogistics();
                 },
+                _setModelData(key,val){
+                    let mapping = [];
+                    val.forEach(item=>{
+                        mapping[item.id] = item.name;
+                    });
+                    this.$set(this.pool,key,val);
+                    this.$set(this.poolMapping,key,mapping);
+                },
                 //获取项目
                 _getOwners(){
                     let url = "{{url('maintenance/owner/get')}}";
-                    window.tempTip.postBasicRequest(url,{},res=>{
-                        this.pool.owners = res;
-                        let mapping = [];
-                        res.forEach(owner=>{
-                            mapping[owner.id] = owner.name;
-                        });
-                        this.poolMapping.owners = mapping;
-                        this.$forceUpdate();
-                    });
+                    window.tempTip.postBasicRequest(url,{},res=>{this._setModelData("owners",res);});
                 },
                 //获取单位
                 _getUnits(){
                     let url = "{{url('maintenance/unit/getUnits')}}";
-                    window.tempTip.postBasicRequest(url,{},res=>{
-                        this.pool.units = res;
-                        let mapping = [];
-                        res.forEach(unit=>{
-                            mapping[unit.id] = unit.name;
-                        });
-                        this.poolMapping.units = mapping;
-                        this.$forceUpdate();
-                    });
+                    window.tempTip.postBasicRequest(url,{},res=>{this._setModelData("units",res);});
                 },
                 //获取省份
                 _getProvinces(){
                     let url = "{{url('maintenance/province/get')}}";
-                    window.tempTip.postBasicRequest(url,{},res=>{
-                        this.pool.provinces = res;
-                        let mapping = [];
-                        res.forEach(province=>{
-                            mapping[province.id] = province.name;
-                        });
-                        this.poolMapping.provinces = mapping;
-                        this.$forceUpdate();
-                    });
+                    window.tempTip.postBasicRequest(url,{},res=>{this._setModelData("provinces",res);});
                 },
                 //获取城市
                 _getCities(){
                     let url = "{{url('maintenance/city/get')}}";
-                    window.tempTip.postBasicRequest(url,{},res=>{
-                        this.pool.cities = res;
-                        let mapping = [];
-                        res.forEach(city=>{
-                            mapping[city.id] = city.name;
-                        });
-                        this.poolMapping.cities = mapping;
-                        this.$forceUpdate();
-                    });
+                    window.tempTip.postBasicRequest(url,{},res=>{this._setModelData("cities",res);});
                 },
                 //获取承运商
                 _getLogistics(){
                     let url = "{{url('maintenance/logistic/get')}}";
                     window.tempTip.postBasicRequest(url,{type:''},res=>{
-                        this.pool.logistics = res;
-                        let mapping = [];
-                        res.forEach(logistic=>{
-                            mapping[logistic.id] = logistic.name;
-                        });
-                        this.poolMapping.logistics = mapping;
-                        this.$forceUpdate();
+                        this._setModelData("logistics",res);
+                        setTimeout(()=>{
+                            $(".selectpicker").selectpicker('refresh');
+                        },0);
                     });
                 },
                 //获取车型
                 _getCars(){
                     let url = "{{url('maintenance/carType/get')}}";
-                    window.axios.post(url).then(res=>{
-                        this.pool.cars = res.data;
-                        let mapping = [];
-                        res.data.forEach(car=>{
-                            mapping[car.id] = car.name;
-                        });
-                        this.poolMapping.cars = mapping;
-                        this.$forceUpdate();
-                    });
+                    window.axios.post(url).then(res=>{this._setModelData("cars",res);});
                 },
                 //保存模型
                 saveModel(){

+ 5 - 5
resources/views/customer/project/menu.blade.php

@@ -8,6 +8,10 @@
                 <li class="nav-item">
                     <a class="nav-link" href="{{url('customer/project/report')}}" :class="{active:isActive('report',3)}">报表</a>
                 </li> @endcan
+                @can('客户管理-项目-面积')
+                    <li class="nav-item">
+                        <a class="nav-link" href="{{url('customer/project/area')}}" :class="{active:isActive('area',3)}">面积</a>
+                    </li> @endcan
                 @can('客户管理-项目-查询')
                 <li class="nav-item">
                     <a class="nav-link" href="{{url('customer/project/index')}}" :class="{active:isActive('index',3)}">查询</a>
@@ -16,12 +20,8 @@
                 <li class="nav-item">
                     <a class="nav-link" href="{{url('customer/project/create')}}" :class="{active:isActive('create',3)}">录入</a>
                 </li> @endcan
-                @can('客户管理-项目-面积')
-                <li class="nav-item">
-                    <a class="nav-link" href="{{url('customer/project/area')}}" :class="{active:isActive('area',3)}">面积</a>
-                </li> @endcan
                 {{ $slot }}
             </ul>
         </div>
     </div>
-</div>
+</div>

+ 5 - 0
resources/views/customer/project/part/_three.blade.php

@@ -3,6 +3,7 @@
         <div class="card" id="storage-card">
             <div class="card-header bg-light-info">
                 <span class="pull-left font-weight-bold cursor-pointer text-secondary" @click="show('storage')"><span class="fa fa-align-justify"></span>&nbsp;仓储</span>
+                <span class="pull-right small mb-0 text-secondary">双击下方已添加内容可编辑</span>
             </div>
             <div class="card-body" id="storage">
                 <table class="table table-sm">
@@ -34,6 +35,7 @@
         <div class="card" id="operation-card">
             <div class="card-header bg-light-info">
                 <span class="pull-left font-weight-bold cursor-pointer text-secondary" @click="show('operation')"><span class="fa fa-align-justify"></span>&nbsp;作业</span>
+                <span class="pull-right small mb-0 text-secondary">双击下方已添加内容可编辑</span>
             </div>
             <div class="card-body" id="operation">
                 <div class="container-fluid">
@@ -127,6 +129,7 @@
         <div class="card" id="express-card">
             <div class="card-header bg-light-info">
                 <span class="pull-left font-weight-bold cursor-pointer text-secondary" @click="show('express')"><span class="fa fa-align-justify"></span>&nbsp;快递</span>
+                <span class="pull-right small mb-0 text-secondary">双击下方已添加内容可编辑</span>
             </div>
             <div class="card-body" id="express">
                 <table class="table table-sm">
@@ -184,6 +187,7 @@
         <div class="card" id="logistic-card">
             <div class="card-header bg-light-info">
                 <span class="pull-left font-weight-bold cursor-pointer text-secondary" @click="show('logistic')"><span class="fa fa-align-justify"></span>&nbsp;物流</span>
+                <span class="pull-right small mb-0 text-secondary">双击下方已添加内容可编辑</span>
             </div>
             <div class="card-body" id="logistic">
                 <table class="table table-sm">
@@ -264,6 +268,7 @@
         <div class="card" id="directLogistic-card">
             <div class="card-header bg-light-info">
                 <span class="pull-left font-weight-bold cursor-pointer text-secondary" @click="show('directLogistic')"><span class="fa fa-align-justify"></span>&nbsp;直发</span>
+                <span class="pull-right small mb-0 text-secondary">双击下方已添加内容可编辑</span>
             </div>
             <div class="card-body" id="directLogistic" @dblclick="editDirectLogistic()" style="cursor: pointer">
                 <div class="row">

+ 2 - 0
resources/views/emails/test.blade.php

@@ -0,0 +1,2 @@
+{{  $objToJson->title }}
+{{  $objToJson->description }}

+ 243 - 0
resources/views/maintenance/emails/index.blade.php

@@ -0,0 +1,243 @@
+@extends('layouts.app')
+@section('title')邮件@endsection
+@section('content')
+    <div id="nav2">
+        @component('maintenance.menu')@endcomponent
+        @component('maintenance.log.menu')@endcomponent
+    </div>
+    <div class="container-fluid" id="container">
+        <div class="card">
+            <div id="form_div"></div>
+            <div class="card-body">
+                @if(Session::has('successTip'))
+                    <div class="alert alert-success h1">{{Session::get('successTip')}}</div>
+                @endif
+                <table class="table table-sm table-hover table-condensed">
+                    <tr>
+                        <th>序号</th>
+                        <th>事件名</th>
+                        <th>通知角色</th>
+                        <th>事件描述</th>
+                        <th>邮件模板</th>
+                        <th>操作</th>
+                    </tr>
+                    <tr v-for="(emailEvent,i) in emailEvents">
+                        <td width="50">@{{ i+1 }}</td>
+                        <td width="50">@{{ emailEvent.name }}</td>
+                        <td width="100">
+                            <table class="table table-sm">
+                                <tr colspan="2">
+                                    <td>
+                                        <select class="form-control form-control-sm" v-model="emailEvent.role_selected">
+                                            <option v-for="role in roles" :value="role.id"> @{{ role.name }}</option>
+                                        </select>
+                                    </td>
+                                    <td>
+                                        <button class="btn btn-sm btn-primary" @click="addRole(emailEvent)">添加</button>
+                                    </td>
+                                </tr>
+                                <tr v-for="(role,j) in emailEvent.roles" v-if="j<2 || emailEvent.isShowRole">
+                                    <td>@{{ role.name }}</td>
+                                    <td>
+                                        <button class="btn btn-sm btn-outline-danger"
+                                                @click="deleteRole(role,j,emailEvent)">
+                                            删除
+                                        </button>
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td>
+                                        <div class="row" @click="showRole(i)" v-if="emailEvent.roles.length > 2">
+                                            <label class="text-center mt-0 p-0 cursor-pointer offset-5">
+                                        <span class="fa"
+                                              :class="emailEvent.isShowRole ? 'fa-angle-double-down' : 'fa-angle-double-right'"></span>
+                                                &nbsp;<span v-if="emailEvent.isShowRole">收起</span><span
+                                                    v-if="!emailEvent.isShowRole">展开</span>共@{{ emailEvent.roles.length
+                                                }} 条角色
+                                            </label>
+                                        </div>
+                                    </td>
+                                </tr>
+                            </table>
+                        </td>
+                        <td width="150">
+                            <span class="w-auto" v-show="emailEvents[i].remark_show&&emailEvent.remark"
+                                  @click="remarkShow(i,$event)">@{{ emailEvent.remark }}</span>
+                            <span v-show="emailEvents[i].remark_edit||!emailEvent.remark">
+                                <textarea width="150" class="form-control" rows="5" type="text"
+                                          @blur="remarkShow(i,$event)">@{{ emailEvent.remark }}</textarea>
+                                <button class="btn btn-sm btn-primary"
+                                        @click="updateRemark(emailEvent,$event)">修改</button>
+                            </span>
+                        </td>
+                        <td width="150">
+                        <span v-show="emailEvents[i].template_show&&emailEvent.template" @click="templateShow(i,$event)"
+                              class="w-auto">@{{ emailEvent.template }}</span>
+                            <span v-show="emailEvents[i].template_edit||!emailEvent.template">
+                            <textarea width="150" class="form-control" rows="5" type="text"
+                                      @blur="templateShow(i,$event)">@{{ emailEvent.template }}</textarea>
+                            <button class="btn btn-sm btn-primary"
+                                    @click="updateTemplate(emailEvent,$event)">修改</button>
+                        </span>
+                        </td>
+                        <td width="50">
+                            <button class="btn btn-success" v-if="emailEvent.is_active===0" @click="active(emailEvent)">
+                                启用
+                            </button>
+                            <button class="btn btn-secondary" v-if="emailEvent.is_active===1"
+                                    @click="active(emailEvent)">
+                                禁用
+                            </button>
+                        </td>
+                    </tr>
+                </table>
+            </div>
+        </div>
+    </div>
+@stop
+@section('lastScript')
+    <script>
+        new Vue({
+            el: "#container",
+            data: {
+                emailEvents: {!!  $emailEvents->toJson() !!}['data'],
+                roles: {!!  $roles->toJson() !!},
+                addRolesFlag: false,
+            },
+            methods: {
+                /**
+                 * 添加角色,并将添加的角色添加到当前时间角色列表的顶部
+                 * @param emailEvent
+                 */
+                addRole(emailEvent) {
+                    window.tempTip.postBasicRequest("{{url('maintenance/mail/addRole')}}", {
+                        roleId: emailEvent.role_selected,
+                        eventMailId: emailEvent.id
+                    }, res => {
+                        let role = res.role;
+                        if (role) {
+                            emailEvent.roles.unshift(role);
+                            return "添加关联角色:" + role.name + " 成功!";
+                        }
+                    });
+                },
+                /**
+                 * 删除角色,当前事件的指定角色删除
+                 * @param role 要删除的角色
+                 * @param index 删除角色的索引
+                 * @param emailEvent 事件
+                 */
+                deleteRole(role, index, emailEvent) {
+                    window.tempTip.postBasicRequest("{{url('maintenance/mail/deleteRole')}}", {
+                        roleId: role.id,
+                        eventMailId: emailEvent.id
+                    }, res => {
+                        emailEvent.roles.splice(index, 1);
+                        return "取消关联角色:" + role.name + " 成功!";
+                    });
+                },
+                /**
+                 * 更新模板
+                 * 隐藏模板编辑,显示模板展示,更新前端显示
+                 * @param emailEvent
+                 * @param e
+                 */
+                updateTemplate(emailEvent, e) {
+                    let textarre = $(e.target).prev().val();
+                    window.tempTip.postBasicRequest("{{url('maintenance/mail/updateTemplate')}}", {
+                        id: emailEvent.id,
+                        template: textarre,
+                    }, res => {
+                        emailEvent.template = textarre;
+                        emailEvent.template_show = true;
+                        emailEvent.template_edit = false;
+                        return "修改模板成功!";
+                    });
+
+                },
+                /**
+                 * 更新备注
+                 * 隐藏备注编辑,显示备注展示,更新备注显示
+                 * @param emailEvent
+                 * @param e
+                 */
+                updateRemark(emailEvent, e) {
+                    let textarre = $(e.target).prev().val();
+                    window.tempTip.postBasicRequest("{{url('maintenance/mail/updateRemark')}}", {
+                        id: emailEvent.id,
+                        remark: textarre,
+                    }, res => {
+                        emailEvent.remark = textarre;
+                        emailEvent.remark_show = true;
+                        emailEvent.remark_edit = false;
+                        return "修改备注成功!";
+                    });
+
+                },
+                /**
+                 * 启用/禁用指定模板
+                 * @param emailEvent
+                 */
+                active(emailEvent) {
+                    window.tempTip.postBasicRequest("{{url('maintenance/mail/active')}}", {
+                        id: emailEvent.id,
+                    }, res => {
+                        if (res) {
+                            emailEvent.is_active = 0;
+                            return "模板启用禁用!";
+                        } else {
+                            emailEvent.is_active = 1;
+                            return "模板启用成功!";
+                        }
+                    });
+                },
+                /**
+                 * 展开折叠指定模板的角色列表
+                 * @param index
+                 */
+                showRole(index) {
+                    if (this.emailEvents[index].isShowRole) {
+                        this.emailEvents[index].isShowRole = false;
+                    } else {
+                        this.emailEvents[index].isShowRole = true;
+                    }
+                    this.$forceUpdate();
+                },
+                /**
+                 * 备注编辑/显示切换
+                 * 切换为编辑时,自动聚焦到textarea
+                 * @param index
+                 * @param $event
+                 */
+                remarkShow(index, $event) {
+                    let _this = this;
+                    setTimeout(function () {
+                        _this.emailEvents[index].remark_show = !_this.emailEvents[index].remark_show;
+                        _this.emailEvents[index].remark_edit = !_this.emailEvents[index].remark_edit;
+                        setTimeout(function () {
+                            let find = $($event.target).parent().find('textarea');
+                            find.focus();
+                        }, 100)
+                    }, 100);
+                },
+                /**
+                 * 模板编辑/显示切换
+                 * 切换为编辑时,自动聚焦到textarea
+                 * @param index
+                 * @param $event
+                 */
+                templateShow(index,$event) {
+                    let _this = this;
+                    setTimeout(function () {
+                        _this.emailEvents[index].template_show = !_this.emailEvents[index].template_show;
+                        _this.emailEvents[index].template_edit = !_this.emailEvents[index].template_edit;
+                        setTimeout(function () {
+                            let find = $($event.target).parent().find('textarea');
+                            find.focus();
+                        }, 100)
+                    }, 100);
+                },
+            }
+        })
+    </script>
+@stop

+ 12 - 0
resources/views/maintenance/emails/menu.blade.php

@@ -0,0 +1,12 @@
+
+<div class="container-fluid nav3">
+    <div class="card" >
+        <ul class="nav nav-pills">
+            @can('邮件-查询')
+            <li class="nav-item">
+                <a class="nav-link" href="{{url('maintenance/mail')}}" :class="{active:isActive('',3)}">查询</a>
+            </li> @endcan
+            {{$slot}}
+        </ul>
+    </div>
+</div>

+ 4 - 0
resources/views/maintenance/menu.blade.php

@@ -94,6 +94,10 @@
                 <li class="nav-item">
                     <a class="nav-link text-muted" href="{{url('maintenance/laborCompany')}}" :class="{active:isActive('laborCompany',2)}">劳务所</a>
                 </li> @endcan
+            {{--TODO 权限--}}
+                <li class="nav-item">
+                    <a class="nav-link text-muted" href="{{url('maintenance/mail')}}" :class="{active:isActive('mail',2)}">邮件</a>
+                </li>
             @can('日志')
                 <li class="nav-item">
                     <a class="nav-link text-muted" href="{{url('maintenance/log')}}" :class="{active:isActive('log',2)}">日志</a>

+ 58 - 0
resources/views/order/index/_freezeModal.blade.php

@@ -0,0 +1,58 @@
+<div class="modal fade" tabindex="-1" role="dialog" id="modal">
+    <div class="modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable">
+        <div class="modal-content">
+            <div class="modal-header">
+                <button type="button" class="close" data-dismiss="modal">&times;</button>
+            </div>
+            <div class="modal-body">
+                <div class="row">
+                    <label class="col-2 offset-1" for="logistic_id"><span class="text-danger">*&nbsp;</span>承运商</label>
+                    <select class="col-5 form-control form-control-sm"
+                            :class="errors.logistic_id ? 'is-invalid' : ''" id="logistic_id" type="text"
+                            v-model="freeze.logistic_id">
+                            <option v-for="logistic in data.logistics" :value="logistic.id">@{{ logistic.name }}</option>
+                    </select>
+                    <span class="invalid-feedback mt-0 offset-3" role="alert" v-if="errors.logistic_id">
+                        <strong>@{{ errors.logistic_id[0] }}</strong>
+                    </span>
+                </div>
+                <div class="row mt-2">
+                    <label class="col-2 offset-1" for="province_id">省</label>
+                    <select class="col-5 form-control form-control-sm"
+                            :class="errors.province_id ? 'is-invalid' : ''" id="province_id" type="text"
+                            v-model="freeze.province_id">
+                        <option v-for="province in data.provinces" :value="province.id">@{{ province.name }}</option>
+                    </select>
+                    <span class="invalid-feedback mt-0 offset-3" role="alert" v-if="errors.province_id">
+                        <strong>@{{ errors.province_id[0] }}</strong>
+                    </span>
+                </div>
+                <div class="row mt-2">
+                    <label class="col-2 offset-1" for="city_id">市</label>
+                    <select class="col-5 form-control form-control-sm"
+                            :class="errors.city_id ? 'is-invalid' : ''" id="city_id" type="text"
+                            v-model="freeze.city_id">
+                        <option v-for="city in data.cities" :value="city.id" v-if="city.province_id == freeze.province_id">@{{ city.name }}</option>
+                    </select>
+                    <span class="invalid-feedback mt-0 offset-3" role="alert" v-if="errors.city_id">
+                        <strong>@{{ errors.city_id[0] }}</strong>
+                    </span>
+                </div>
+                <div class="row mt-2">
+                    <label class="col-2 offset-1" for="location_id">区</label>
+                    <select class="col-5 form-control form-control-sm"
+                            :class="errors.location_id ? 'is-invalid' : ''" id="location_id" type="text"
+                            v-model="freeze.location_id">
+                        <option v-for="district in data.districts" :value="district.id" v-if="city.parent_id == freeze.city_id">@{{ district.name }}</option>
+                    </select>
+                    <span class="invalid-feedback mt-0 offset-3" role="alert" v-if="errors.location_id">
+                        <strong>@{{ errors.location_id[0] }}</strong>
+                    </span>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-success" @click="submit()">提交</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 122 - 0
resources/views/order/index/freeze.blade.php

@@ -0,0 +1,122 @@
+@extends("layouts.app")
+@section('title')订单管理-自动冻结@endsection
+
+@section('content')
+    @component('order.index.menu')@endcomponent
+    <div class="card" id="container">
+        <div class="card-body">
+            <div class="container-fluid">
+
+                @include("order.index._freezeModal")
+
+                <div class="pull-left">
+                    <button class="btn btn-outline-info mb-1 mr-3" @click="openModal()"><span class="fa fa-plus"></span>&nbsp;新&nbsp;&nbsp;增</button>
+                </div>
+                <table class="table table-striped table-borderless rounded">
+                    <tr>
+                        <th>序号</th>
+                        <th>承运商</th>
+                        <th>省</th>
+                        <th>市</th>
+                        <th>区</th>
+                        <th></th>
+                    </tr>
+                    <tr v-for="(freeze,i) in freezes">
+                        <td>@{{ i+1 }}</td>
+                        <td>@{{ freeze.logistic ? freeze.logistic.name : '' }}</td>
+                        <td>@{{ freeze.province ? freeze.province.name : '' }}</td>
+                        <td>@{{ freeze.city ? freeze.city.name : '' }}</td>
+                        <td>@{{ freeze.location ? freeze.location.name : '' }}</td>
+                        <td>
+                            <button class="btn btn-sm btn-outline-danger" @click="deleteFreeze(freeze,i)">删除</button>
+                            <button class="btn btn-sm btn-outline-info" @click="openModal(freeze,i)">编辑</button>
+                        </td>
+                    </tr>
+                </table>
+                {{$freezes->links()}}
+            </div>
+        </div>
+    </div>
+@stop
+
+@section("lastScript")
+    <script>
+        new Vue({
+            el:"#container",
+            data:{
+                freezes:[
+                    @foreach($freezes as $freeze)
+                    {!! $freeze !!},
+                    @endforeach
+                ],
+                data:{},
+                freeze:{},
+                errors : {},
+            },
+            methods:{
+                openModal(model = null,index = null){
+                    if (!model)this.freeze = {};
+                    else {
+                        model.index = index;
+                        this.freeze = model;
+                    }
+                    this._load();
+                    $("#modal").modal("show");
+                },
+                _load(){
+                    if (!this.data.logistics){
+                        let url = "{{url('maintenance/logistic/get')}}";
+                        window.tempTip.postBasicRequest(url,{},res=>{
+                            this.$set(this.data,'logistics',res);
+                        });
+                    }
+                    if (!this.data.provinces){
+                        let url = "{{url('maintenance/province/get')}}";
+                        window.tempTip.postBasicRequest(url,{},res=>{
+                            this.$set(this.data,'provinces',res);
+                        });
+                    }
+                    if (!this.data.cities){
+                        let url = "{{url('maintenance/city/get')}}";
+                        window.tempTip.postBasicRequest(url,{},res=>{
+                            this.$set(this.data,'cities',res);
+                        });
+                    }
+                    if (!this.data.districts){
+                        let url = "{{url('maintenance/region/get')}}";
+                        window.tempTip.postBasicRequest(url,{type:3},res=>{
+                            this.$set(this.data,'districts',res);
+                        });
+                    }
+                },
+                submit(){
+                    if (!this.freeze.logistic_id){
+                        window.tempTip.setIndex(1099);
+                        window.tempTip.setDuration(3000);
+                        window.tempTip.show("必须选择承运商");
+                        return;
+                    }
+                    let url = "{{url('order/index/freeze')}}";
+                    window.tempTip.postBasicRequest(url,this.freeze,res=>{
+                        let msg = "新增冻结选项成功!";
+                        if (this.freeze.id){
+                            msg = "修改冻结选项成功!";
+                            this.freezes[this.freeze.index] = res;
+                        } else this.freezes.unshift(res);
+                        $("#modal").modal("hide");
+                        return msg;
+                    },true)
+                },
+                deleteFreeze(freeze,index){
+                    let url = "{{url('order/index/freeze/delFreeze')}}";
+                    window.tempTip.confirm("确定要解除该冻结条件吗?",()=>{
+                        window.tempTip.postBasicRequest(url,freeze,res=>{
+                            this.$delete(this.freezes,index);
+                            return "删除成功!";
+                        })
+                    });
+                },
+            },
+        });
+    </script>
+@stop

+ 4 - 0
resources/views/order/index/menu.blade.php

@@ -12,6 +12,10 @@
                     <li class="nav-item">
                         <a class="nav-link" href="{{url('order/index/commodityAssign')}}" :class="{active:isActive('commodityAssign',3)}">指定分配</a>
                     </li> @endcan
+                @can('订单管理-自动冻结')
+                    <li class="nav-item">
+                        <a class="nav-link" href="{{url('order/index/freeze')}}" :class="{active:isActive('freeze',3)}">自动冻结</a>
+                    </li> @endcan
             </ul>
         </div>
     </div>

+ 186 - 18
resources/views/order/issue/index.blade.php

@@ -38,6 +38,10 @@
                         <button type="button" class="btn btn-outline-dark btn-sm form-control-sm  tooltipTarget" @click="batchStoreLogsModel">
                             批量处理说明
                         </button>
+                        <span class="ml-1">
+                        <button type="button" class="btn btn-outline-dark btn-sm form-control-sm  tooltipTarget" @click="batchOthersModel">
+                            批量处理赔偿金额与事故责任方
+                        </button>
                     </span>
                     @endcan
                     <span class="ml-1">
@@ -54,9 +58,14 @@
                     @cannot('订单管理-问题件-客户不可见')
                         @can('订单管理-问题件-财务确认')
                         <span class="ml-1">
-                            <button type="button" class="btn btn-outline-dark btn-sm form-control-sm  tooltipTarget" @click="financeConfirm">
+                            <button type="button" class="btn btn-outline-dark btn-sm form-control-sm  tooltipTarget" @click="financeConfirm('是')">
                                 批量财务确认
                             </button>
+                        </span>
+                            <span class="ml-1">
+                            <button type="button" class="btn btn-outline-dark btn-sm form-control-sm  tooltipTarget" @click="financeConfirm('否')">
+                                批量财务确认取消
+                            </button>
                         </span>
                         @endcan
                         @can('订单管理-问题件-批量归档')
@@ -151,7 +160,7 @@
                         <th class="three-layer  align-middle" rowspan="2" style="min-width: 120px">宝时赔偿金额</th>
                         <th class="three-layer  align-middle" rowspan="2" style="min-width: 120px">宝时快递减免</th>
                         @cannot('订单管理-问题件-客户不可见')
-                        <th class="three-layer  align-middle" rowspan="2" style="min-width: 120px">事故责任方</th>
+                        <th class="three-layer  align-middle" rowspan="2" style="min-width: 200px">事故责任方</th>
                         <th class="align-middle" rowspan="2" style="min-width: 120px">操作</th>
                         @endcannot
                     </tr>
@@ -267,7 +276,7 @@
                             <span v-if='orderIssue.order.logistic'>@{{ orderIssue.order.logistic.name }}</span>
                         </td>
                         <td class=" hide-content p-0 td-yellow child-layer-2 align-center" valign="middle">
-                            <div v-if="orderIssue.order">
+                            <template v-if="orderIssue.order">
                                 <span  :class="orderIssue.order.packages.length > 1 ?'collapse ':''" :id="'logisticNumbers'+orderIssue.id" >
                                     <span class="m-0 p-0 d-inline-block" v-for="package in orderIssue.order.packages" >@{{ package.logistic_number }}&nbsp;&nbsp;</span>
                                 </span>
@@ -276,7 +285,7 @@
                                         @click="toggleLogisticNumbers(orderIssue.id,orderIssue.order.packages.length)">
                                     分箱@{{ orderIssue.order.packages.length }}件,点击展开
                                 </button>
-                            </div>
+                            </template>
                         </td>
                         {{--商品明细 开始--}}
                         <td class="td-yellow p-0 m-0 child-layer-2 w-50" v-if="!isShowOrderInfo && index===0" :rowspan="orderIssues.length">
@@ -382,7 +391,7 @@
                             @endcan
                         </td>
 
-                        <td class=" m-0 p-0 log-td child-layer-3  valign-middle align-center" v-on:mouseover="showAddBtn($event)" v-on:mouseleave="hideAddBtn($event)" colspan="4">
+                        <td class=" m-0 p-0 log-td child-layer-3  align-center" v-on:mouseover="showAddBtn($event)" v-on:mouseleave="hideAddBtn($event)" colspan="4">
                             @can('订单管理-问题件-处理结果添加')
                             <div class="addLogDiv row m-0 p-0 form-group" :id="'AddLog_'+orderIssue.id" style="display: none;">
                                 <input type="hidden" name="id" :value="orderIssue.id">
@@ -406,7 +415,7 @@
                                             <td class="text-muted" style="min-width: 170px">@{{ log.created_at }}</td>
                                             @can('订单管理-问题件-处理结果删除')
                                                 <td style="" class="m-0 p-0 border-0">
-                                                    <button type="button" class="btn btn-sm btn-outline-danger m-0 del-btn invisible" @click="deleteOrderIssueLog(log.id,orderIssue.id)">删</button>
+                                                    <button type="button" class="btn btn-sm btn-outline-danger m-0 del-btn invisible" @click="deleteOrderIssueLog(log,orderIssue.id)">删</button>
                                                 </td>
                                             @endcan
                                         </template>
@@ -533,10 +542,38 @@
                         </td>
                         @cannot('订单管理-问题件-客户不可见')
                             <td class="child-layer-3">
-                                <select class="form-control form-control-sm" :value="orderIssue.user_workgroup_id" @change="updateOrderIssue(orderIssue,'user_workgroup_id',$event)">
-                                    <option value></option>
-                                    <option v-for="item in userWorkGroup" :value="item.name">@{{ item.value }}</option>
-                                </select>
+                                <table class="table table-sm">
+                                    <tr colspan="2">
+                                        <td colspan="2">
+                                            <select class="form-control form-control-sm" @change="addUserWorkgroup(orderIssue,'user_workgroup_id',$event)">
+                                                <option value></option>
+                                                <option v-for="item in userWorkGroup" :value="item.name">@{{ item.value }}</option>
+                                            </select>
+                                        </td>
+                                    </tr>
+                                    <tr v-for="(user_workgroup,j) in orderIssue.user_workgroups" v-if="j<2 || orderIssue.is_show_user_workgroup">
+                                        <td>@{{ user_workgroup.name }}</td>
+                                        <td>
+                                            <button class="btn btn-sm btn-outline-danger"
+                                                    @click="deleteUserWorkgroup(user_workgroup,j,orderIssue)">
+                                                删除
+                                            </button>
+                                        </td>
+                                    </tr>
+                                    <tr>
+                                        <td colspan="2" v-if="orderIssue.user_workgroups.length > 2">
+                                            <div class="row" @click="showUserWorkgroup(orderIssue)" v-if="orderIssue.user_workgroups.length > 2">
+                                                <label class="text-center mt-0 p-0 cursor-pointer offset-5">
+                                        <span class="fa"
+                                              :class="orderIssue.is_show_user_workgroup ? 'fa-angle-double-down' : 'fa-angle-double-right'"></span>
+                                                    &nbsp;<span v-if="orderIssue.is_show_user_workgroup">收起</span><span
+                                                        v-if="!orderIssue.is_show_user_workgroup">展开</span>共@{{ orderIssue.user_workgroups.length }} 条
+                                                </label>
+                                            </div>
+                                        </td>
+                                    </tr>
+                                </table>
+
                             </td>
                             <td>
                                 @can('订单管理-问题件-编辑')
@@ -574,6 +611,46 @@
                 </div>
             </div>
         </div>
+        <div class="modal fade" id="batchOthersModel" tabindex="-1" role="dialog" aria-labelledby="othersLabel" aria-hidden="true">
+            <div class="modal-dialog  modal-dialog-centered">
+                <div class="modal-content">
+                    <div class="modal-body">
+                        <h5 class="modal-title" id="othersLabel">承运商赔偿金额</h5>
+                        <input type="number" v-model="edit.batchOthers.logistic_indemnity_money" class="form-control form-control-sm">
+                    </div>
+                    <div class="modal-body">
+                        <h5 class="modal-title" id="othersLabel">承运商快递减免</h5>
+                        <select class="form-control form-control-sm" v-model="edit.batchOthers.logistic_express_remission">
+                            <option disabled value="">请选择</option>
+                            <option v-for="item in expressRemission" :value="item">@{{ item }}</option>
+                        </select>
+                    </div>
+                    <div class="modal-body">
+                        <h5 class="modal-title" id="othersLabel">宝时赔偿金额</h5>
+                        <input type="number" v-model="edit.batchOthers.baoshi_indemnity_money" class="form-control form-control-sm">
+                    </div>
+                    <div class="modal-body">
+                        <h5 class="modal-title" id="othersLabel">宝时快递减免</h5>
+                        <select class="form-control form-control-sm" v-model="edit.batchOthers.baoshi_express_remission">
+                            <option disabled value="">请选择</option>
+                            <option v-for="item in expressRemission" :value="item">@{{ item }}</option>
+                        </select>
+                    </div>
+
+                    <div class="modal-body" >
+                        <h5 class="modal-title" id="logsLabel">事故责任方</h5>
+                        <span v-for="item in userWorkGroup">
+                             <input v-model="edit.batchOthers.userWorkGroupIds" type="checkbox" name="vehicle" :value="item.name" /> @{{ item.value }}
+                        </span>
+                    </div>
+
+                    <div class="modal-footer">
+                        <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                        <button type="button" class="btn btn-primary" data-dismiss="modal" @click="batchOthers()">确认</button>
+                    </div>
+                </div>
+            </div>
+        </div>
 
         {{--delete OrderIssue--}}
         <div class="modal fade" id="alertModal" tabindex="-1" role="dialog" aria-labelledby="alertModalLabel"
@@ -723,6 +800,13 @@
                 message:{},
                 edit:{
                     batchStoreLogs:'',
+                    batchOthers:{
+                        logistic_indemnity_money: null ,
+                        logistic_express_remission: null,
+                        baoshi_indemnity_money: null,
+                        baoshi_express_remission: null,
+                        userWorkGroupIds: []
+                    },
                     isShow:[],
                     addSendOrderIssueID:'',
                     orderIssue: {id: null,showId:''},
@@ -735,6 +819,7 @@
                     _this.regroupOrder(orderIssue.second_order);
                     _this.regroupRejectedBill(orderIssue);
                     _this.regroupLogs(orderIssue);
+                    _this.regroupUserGroup(orderIssue);
                 });
             },
             mounted: function () {
@@ -777,6 +862,7 @@
                     },
                     {name: 'logistic_number_return', type: 'input', tip: '退回单号:前或后加百分号为单个模糊搜索,否则为多条件精确搜索', placeholder: '退回单号'},
                     {name: 'send_client_code', type: 'input', tip: '二次订单号:前或后加百分号为单个模糊搜索,否则为多条件精确搜索', placeholder: '二次订单号'},
+                    {name: 'finance_confirm', type: 'select', tip: '财务却认', placeholder: '财务却认是/否', data:[{name: '是',value:'是'},{name: '否',value:'否'}]},
                 ], [
                     {name: 'created_at_end', type: 'dateTime', tip: '登记结束日期'},
                     {name: 'consignee_name', type: 'input', tip: '收货人名称:前或后加百分号为单个模糊搜索,否则为多条件精确搜索', placeholder: '收货人名称'},
@@ -785,6 +871,7 @@
                     {name: 'good_name', type: 'input', tip: '商品名:前或后加 百分号为单个模糊搜索,否则为多条件精确搜索', placeholder: '商品名'},
                     {name: 'id_quality_label', type: 'select', tip: '是否正品', placeholder: '是否正品', data: this.qualityLabel},
                     {name: 'is_imported', type: 'select', tip: '是否导入处理', placeholder: '是否导入处理', data: imported_status},
+                    {name: 'user_workgroups', type: 'select_multiple_select', tip: ['事故责任方',''], placeholder: ['事故责任方',''], data: this.userWorkGroup},
                 ],[
                     @cannot('订单管理-问题件-客户不可见')
                     {name: 'logistic_indemnity_money', type: 'select', tip: '承运商赔偿金额', placeholder: '承运商赔偿金额',data:[{name: '是',value:'是'},{name: '否',value:'否'}]},
@@ -893,6 +980,9 @@
                         orderIssue.log_is_show = false;
                     }
                 },
+                regroupUserGroup(orderIssue){
+                    orderIssue.is_show_user_workgroup = false;
+                },
                 displayDelBtn(bool,e){
                     if(bool)$(e.target).next().removeClass('d-none');
                     else {
@@ -1134,15 +1224,19 @@
                         tempTip.show('网络异常:' + err);
                     });
                 },
-                deleteOrderIssueLog(id, OrderIssueId) {
+                deleteOrderIssueLog(log, OrderIssueId) {
                     let _this = this;
                     if(!confirm('是否删除当前记录'))return;
-                    axios.post("{{url('apiLocal/order/issue/log/destroy')}}", {id: id}).then(function (res) {
+                    if(log.type === '创建'){
+                        tempTip.show('创建记录不能删除');
+                        return;
+                    }
+                    axios.post("{{url('apiLocal/order/issue/log/destroy')}}", {id: log.id}).then(function (res) {
                         if (res.data.success) {
                             _this.orderIssues.forEach(function (orderIssue) {
                                 if (orderIssue.id == OrderIssueId) {
                                     orderIssue.logs.forEach(function (item, index) {
-                                        if (item.id == id)orderIssue.logs.splice(index, 1);
+                                        if (item.id == log.id)orderIssue.logs.splice(index, 1);
                                     });
                                 }
                             })
@@ -1184,7 +1278,13 @@
                     let domObj = $(e.target).parents('.log-td');
                     if (domObj.hasClass('log-td')) {
                         domObj.find('.add-btn').show();
+                    }else{
+                        let obj = $(e.target);
+                        if(obj.hasClass('log-td')){
+                            obj.find('.add-btn').show();
+                        }
                     }
+
                 },
                 hideAddBtn(e) {
                     let domObj = $(e.target);
@@ -1332,6 +1432,14 @@
                     }
                     $("#batchStoreLogsModel").modal('show');
                 },
+                batchOthersModel(){
+                    if(this.checkData.length === 0){
+                        tempTip.setDuration(2000)
+                        tempTip.show('没有勾选内容')
+                        return;
+                    }
+                    $("#batchOthersModel").modal('show');
+                },
                 batchStoreLogs(){
                     let _this = this;
                     let data = {orderIssueIds:this.checkData,content:this.edit.batchStoreLogs};
@@ -1358,6 +1466,32 @@
                         tempTip.show('处理结果添加异常:'+error)
                     })
                 },
+                batchOthers(){
+                    let _this = this;
+                    let data = {
+                        orderIssueIds:this.checkData,
+                        logistic_indemnity_money: this.edit.batchOthers.logistic_indemnity_money,
+                        logistic_express_remission: this.edit.batchOthers.logistic_express_remission,
+                        baoshi_indemnity_money: this.edit.batchOthers.baoshi_indemnity_money,
+                        baoshi_express_remission: this.edit.batchOthers.baoshi_express_remission,
+                        userWorkGroupIds: this.edit.batchOthers.userWorkGroupIds,
+                    };
+                    window.tempTip.postBasicRequest('{{url("apiLocal/order/issue/batchOthers")}}', data, res => {
+                        if (_this.edit.batchOthers.logistic_indemnity_money) {
+                            _this.orderIssuesEdit(_this.checkData, "logistic_indemnity_money", _this.edit.batchOthers.logistic_indemnity_money);
+                        }
+                        if (_this.edit.batchOthers.logistic_express_remission) {
+                            _this.orderIssuesEdit(_this.checkData, "logistic_express_remission", _this.edit.batchOthers.logistic_express_remission);
+                        }
+                        if (_this.edit.batchOthers.baoshi_indemnity_money) {
+                            _this.orderIssuesEdit(_this.checkData, "baoshi_indemnity_money", _this.edit.batchOthers.baoshi_indemnity_money);
+                        }
+                        if (_this.edit.batchOthers.baoshi_express_remission) {
+                            _this.orderIssuesEdit(_this.checkData, "baoshi_express_remission", _this.edit.batchOthers.baoshi_express_remission);
+                        }
+                        return "批量修改完成";
+                    });
+                },
                 editSecondClientNo(orderIssue,e){
                     let value = $(e.target).val()
                     let data = {id:orderIssue.id,secondClientNo:value}
@@ -1464,23 +1598,32 @@
                         tempTip.show('处理导入出现异常'+error)
                     })
                 },
-                financeConfirm(){
+                financeConfirm(flag){
                     let _this= this
                     if(this.checkData.length === 0){
                         tempTip.setDuration(2000)
                         tempTip.show('没有勾选内容')
                         return;
                     }
-                    if(!confirm('是否进行财务确认'))return;
+                    if (flag=='是') {
+                        if (!confirm('是否进行财务确认')) return;
+                    }else{
+                        if (!confirm('是否取消财务确认')) return;
+                    }
                     let data = {ids:this.checkData};
                     tempTip.setDuration(9999);
                     tempTip.waitingTip('处理中.......');
+                    data.flag = flag;
                     axios.post('{{url('apiLocal/order/issue/financeConfirm')}}',data)
                         .then(function(response){
                             tempTip.cancelWaitingTip();
                             if(response.data.success){
                                 tempTip.setDuration(2000);
-                                tempTip.showSuccess('确认成功');
+                                if (flag=='是') {
+                                    tempTip.showSuccess('确认成功');
+                                }else{
+                                    tempTip.showSuccess('取消成功');
+                                }
                                 _this.orderIssuesEdit(data.ids,'finance_confirm','是');
                                 return;
                             }
@@ -1553,6 +1696,7 @@
                                     orderIssue.rejecting_status = response.data.data.orderIssue.rejecting_status;
                                 }
                                 _this.regroupRejectedBill(orderIssue);
+                                _this.$forceUpdate();
                                 return;
                             }
                             tempTip.setDuration(2000);
@@ -1571,9 +1715,9 @@
                             if(response.data.success){
                                 tempTip.setDuration(2000);
                                 tempTip.showSuccess('退回单号取消关联成功');
-                                if(orderIssue.rejected_bills===null)return;
+                                if(orderIssue.order_issue_rejected_bills===null)return;
                                 $.each(orderIssue.order_issue_rejected_bills,function(i,item){
-                                    if(item.logistic_number_return === logistic_number){
+                                    if(item && item.logistic_number_return === logistic_number){
                                         orderIssue.order_issue_rejected_bills.splice(i,1);
                                         _this.regroupRejectedBill(orderIssue);
                                     }
@@ -1626,6 +1770,30 @@
                             tempTip.setDuration(2000);
                             tempTip.show(error);
                         });
+                },
+                addUserWorkgroup(orderIssue,user_workgroup_id,e) {
+                    let value = $(e.target).val()
+                    window.tempTip.postBasicRequest("{{url('apiLocal/order/issue/userWorkgroups/add')}}", {
+                        orderIssueId: orderIssue.id,
+                        userWorkgroupId: value
+                    }, res => {
+                        orderIssue.user_workgroups.unshift(res);
+                        return "添加事故责任方成功!";
+                    });
+                },
+                deleteUserWorkgroup(user_workgroup,index,orderIssue) {
+                    window.tempTip.postBasicRequest("{{url('apiLocal/order/issue/userWorkgroups/delete')}}", {
+                        orderIssueId: orderIssue.id,
+                        userWorkgroupId: user_workgroup.id
+                    }, res => {
+                        orderIssue.user_workgroups.splice(index, 1);
+                        this.$forceUpdate();
+                        return "删除事故责任方成功!";
+                    });
+                },
+                showUserWorkgroup(orderIssue) {
+                    orderIssue.is_show_user_workgroup = !orderIssue.is_show_user_workgroup;
+                    this.$forceUpdate();
                 }
             }
         })

+ 5 - 6
resources/views/order/issue/recycle.blade.php

@@ -79,9 +79,9 @@
                                 </div>
                             </td>
                             <td>
-                                <div v-if="orderIssue.secondOrder">
-                                    <div v-if="orderIssue.secondOrder.packages">
-                                        <p v-for="package in orderIssue.secondOrder.packages">@{{ package.logistic_number }}</p>
+                                <div v-if="orderIssue.order_issue_rejected_bills">
+                                    <div v-for="orderIssueRejectedBill in orderIssue.order_issue_rejected_bills">
+                                        <p>@{{ orderIssueRejectedBill.logistic_number_return }}</p>
                                     </div>
                                 </div>
                             </td>
@@ -159,10 +159,9 @@
                             tempTip.setDuration(2000);
                             if (response.data.success) {
                                 tempTip.showSuccess('恢复成功');
-                                for (let i = 0; i < _this.orderIssues.length; i++) {
-                                    if(data.ids.includes(orderIssue.id))
+                                for (let i = _this.orderIssues.length -1;i >= 0;i--){
+                                    if(_this.checkData.includes(_this.orderIssues[i].id))
                                         _this.orderIssues.splice(i,1);
-
                                 }
                             } else {
                                 tempTip.show(response.data.error);

+ 23 - 4
resources/views/rejected/create.blade.php

@@ -469,7 +469,7 @@
                         if(response.data.success==='true'){
                             if(response.data.result==='true'){
                                 tempTip.okWindow('该退回单号"'+number+'"已有录入其他单','知道了')
-                            }
+                            }else _this.findOrderByStoreRejected(number);
                         }
                     }).catch(function (response) {
                         console.log(response);
@@ -983,22 +983,41 @@
                                 if(response.data.data.consignee_name)_this.billInputting.sender = response.data.data.consignee_name;
                                 if(response.data.data.consignee_phone)_this.billInputting.mobile_sender = response.data.data.consignee_phone;
                                 if(response.data.data.client_code)_this.billInputting.order_number = response.data.data.client_code;
-                                _this.billInputting.logistic_number='原单退回';
+                                if(response.data.data.logistic_number)_this.billInputting.logistic_number = response.data.data.logistic_number;
                                 tempTip.setDuration(2000);
                                 tempTip.showSuccess('原单信息已填充');
                                 return;
                             }
-                            if(!response.data.data)_this.canelOrderInfo();
+                            if(!response.data.data)_this.clearOrderInfoOrderInfo();
                             tempTip.setDuration(2000);
                             tempTip.show('请校验退回单号是否复合,复合正确才可提交');
                         });
                 },
-                canelOrderInfo(){
+                clearOrderInfoOrderInfo(){
                     this.billInputting.id_owner = null;
                     this.billInputting.id_logistic_return = null;
                     this.billInputting.sender = null;
                     this.billInputting.mobile_sender = null;
                     this.billInputting.order_number = null;
+                    this.billInputting.logistic_number = null;
+                },
+                findOrderByStoreRejected(logisticNumber){
+                    if(!logisticNumber)return;
+                    let _this = this;
+                    axios.post('{{url('apiLocal/rejectedBill/findOrderByStoreRejected')}}',{logistic_number_return:logisticNumber})
+                        .then(function (response) {
+                            if (response.data.success){
+                                if(response.data.data.owner_id)_this.billInputting.id_owner=response.data.data.owner_id;
+                                if(response.data.data.logistic_id)_this.billInputting.id_logistic_return = response.data.data.logistic_id;
+                                if(response.data.data.consignee_name)_this.billInputting.sender = response.data.data.consignee_name;
+                                if(response.data.data.consignee_phone)_this.billInputting.mobile_sender = response.data.data.consignee_phone;
+                                if(response.data.data.client_code)_this.billInputting.order_number = response.data.data.client_code;
+                                if(response.data.data.logistic_number)_this.billInputting.logistic_number = response.data.data.logistic_number;
+                                tempTip.setDuration(2000);
+                                tempTip.showSuccess('原单信息已填充');
+                                return;
+                            }
+                        });
                 }
             },
             filters:{

+ 71 - 15
resources/views/test.blade.php

@@ -1,15 +1,71 @@
-<html>
-<head>
-</head>
-
-<body>
-<form method="post" enctype="multipart/form-data" action="{{url('test/orderTrackingImportTest')}}">
-    @csrf
-    @method('post')
-    <input type="file" name="file">
-    <button type="submit">提交</button>
-</form>
-<script>
-</script>
-</body>
-</html>
+@extends('layouts.app')
+
+
+@section('content')
+    <div class="container-fluid">
+        <div class="row">
+            <div class="col-12">
+                <div class="h-1 w-100 text-center font-weight-bold mb-2 text-dark"></div>
+            </div>
+        </div>
+        <div class="row mt-2">
+            <div class="col-10">
+                <div class="row m-0" id="row">
+                    <div class="col-6">
+                        <div class="rounded p-0" id="video-1" onclick="selected(this)">
+                            测试测试
+                            <div class="rounded w-100" controls style="min-height: 500px;object-fit: fill" src="{{asset("123.mp4")}}"></div>
+                        </div>
+                    </div>
+                    <div class="col-6">
+                        <div class="rounded p-0" id="video-2" onclick="selected(this)">
+                            <video class="rounded w-100" controls style="min-height: 500px;object-fit: fill" src="{{asset("123.mp4")}}"></video>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="col-2 border-left border-3 border-primary text-center">
+                <button class="btn btn-danger" type="button" id="imgPool"></button>
+            </div>
+        </div>
+    </div>
+
+    <script>
+        let currentDom = "";
+        let hidden = false;
+        function selected(e){
+            if (currentDom === e.id)return;
+            if (currentDom)$("#"+currentDom).css('box-shadow','');
+            currentDom = e.id;
+            e.style.boxShadow = "0 0 10px 2px red";
+        }
+        document.onkeydown = function(ev) {
+            if(ev.keyCode === 32 && currentDom) {
+                ev.preventDefault();
+                html2canvas(document.getElementById(currentDom)).then(canvas=> {
+                    let base64 = canvas.toDataURL('images/png');
+                    let imgPool = $("#imgPool");
+                    if (!hidden){
+                        imgPool.after("<button class='btn btn-success mt-2 mb-0' type='button' onclick='uploadImg()'>上 传 截 图</button>");
+                        hidden = true;
+                    }
+                    imgPool.after("<div class='w-100 mt-2 h-auto' ondblclick='removeImg(this)'><img class='img-fluid images' alt='截图' src='"+base64+"'></div>");
+                });
+            }
+        };
+        function removeImg(e) {
+            e.remove();
+        }
+        function uploadImg() {
+            let list = $(".images");
+            list.each((i,dom)=>{
+                let base64 = dom.src;
+                //单次多请求上传
+            });
+        }
+    </script>
+@endsection
+
+@section('script')
+    <script src="https://cdn.bootcss.com/html2canvas/0.5.0-beta4/html2canvas.js"></script>
+@stop

+ 19 - 4
resources/views/waybill/index.blade.php

@@ -54,7 +54,7 @@
                 <tr>
                     <th class="table-header-layer-1" colspan="4"></th>
                     <th class="table-header-layer-1" colspan="11"><span class="fa fa-file-text-o"></span> 运单信息</th>
-                    <th class="table-header-layer-1" colspan="12"><span class="fa fa-truck"></span> 运输信息</th>
+                    <th class="table-header-layer-1" colspan="13"><span class="fa fa-truck"></span> 运输信息</th>
                     <th class="table-header-layer-1" colspan="5"><span class="fa fa-rmb"></span> 费用信息
                     @can('运输管理-删除')
                         <th class="table-header-layer-1" colspan="1"> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>
@@ -136,9 +136,22 @@
                     <td class="td-cool text-muted">@{{waybill.origination}}</td>
                     <td class="td-cool text-muted">@{{waybill.destination}}</td>
                     <td class="td-cool">@{{waybill.carrier}}</td>
-                    <td class="td-cool"><span v-if="waybill.type==='专线'">@{{waybill.carrier_bill}}</span>
-                        <span v-if="waybill.type==='直发车'">
-                            <span v-if="waybill.carType">@{{ waybill.carType.name }}<i v-if="waybill.carType.length">(@{{waybill.carType.length}}米)</i></span></span></td>
+                    <td class="td-cool">
+                        <span v-if="waybill.carrier_bill">
+                            @{{waybill.carrier_bill}}<span v-if="waybill.carType">/@{{ waybill.carType.name }}<i v-if="waybill.carType.length">(@{{waybill.carType.length}}米)</i></span>
+                        </span>
+{{--                        <span v-if="waybill.type==='专线'">@{{waybill.carrier_bill}}</span>--}}
+{{--                        <span v-if="waybill.type==='直发车'">--}}
+{{--                            <span v-if="waybill.carType">--}}
+{{--                                @{{ waybill.carType.name }}<i v-if="waybill.carType.length">(@{{waybill.carType.length}}米)</i>--}}
+{{--                            </span>--}}
+{{--                        </span>--}}
+                    </td>
+                    <td class="td-cool">
+                        <span v-if="waybill.type === '直发车'">
+                            @{{ waybill.car_owner_info }}
+                        </span>
+                    </td>
                     <td class="td-cool"><span v-if="waybill.warehouse_weight">@{{waybill.warehouse_weight|filterZero}}  @{{waybill.warehouse_weight_unit}}</span></td>
                     <td class="td-cool"><span v-if="waybill.carrier_weight">@{{waybill.carrier_weight|filterZero}}  @{{waybill.carrier_weight_unit}}</span></td>
                     <td class="td-cool text-center" style="position: relative" @mouseenter="btnRefreshWeightZoomOut(waybill)" @mouseleave="btnRefreshWeightZoomIn(waybill)">
@@ -380,6 +393,7 @@
                         {name:'status',type:'select',placeholder: '运单状态',data:this.status},
                         {name:'source_bill',type:'input',tip: '上游单号:可在左侧增加百分号(%)进行模糊搜索',placeholder: '上游单号'},
                         {name:'recipient',type:'input',tip: '收货人姓名:可在左侧增加百分号(%)进行模糊搜索',placeholder: '收货人姓名'},
+                        {name:'car_owner_info',type:'input',tip: '车辆信息:可在左侧增加百分号(%)进行模糊搜索',placeholder: '车辆信息'},
                     ],
                     [
                         {name:'wms_bill_number',type:'input',tip:'WMS单号:可在两侧增加百分号(%)进行模糊搜索',placeholder: 'WMS单号'},
@@ -422,6 +436,7 @@
                     {name:'destination',value: '目的地', class:"td-cool"},
                     {name:'carrier',value: '承运商', class:"td-cool"},
                     {name:'carrier_bill',value: '单号/车型', neglect: true, class:"td-cool"},
+                    {name:'car_owner_info',value: '车辆信息', neglect: true, class:"td-cool"}, // 车辆信息
                     {name:'warehouse_weight',value: '仓库计抛', neglect: true, class:"td-cool"},
                     {name:'carrier_weight',value: '承运商计抛', neglect: true, class:"td-cool"},
                     {name:'warehouse_weight_other',value: '仓库计重', neglect: true, class:"td-cool"},

+ 4 - 1
routes/apiLocal.php

@@ -20,6 +20,7 @@ Route::post('rejectedBill/apiSetIsLoadedAll', 'RejectedBillController@apiSetIsLo
 Route::post('rejectedBill/apiConfirmBeStored', 'RejectedBillController@apiConfirmBeStored');
 Route::post('rejectedBill/seekOrder','RejectedBillController@seekOrder');
 Route::post('rejectedBill/importRejectedNumber','RejectedBillController@disposeImportApi');
+Route::post('rejectedBill/findOrderByStoreRejected','RejectedBillController@findOrderByStoreRejectedApi');
 
 Route::post('logistic/numberFeatures/computeLogisticByNumber', 'LogisticNumberFeatureController@apiComputeLogisticByNumber');
 Route::post('logistic/logisticNumberReturnIsUnique', 'RejectedBillController@apiLogisticNumberReturnIsUnique');
@@ -48,7 +49,6 @@ Route::group(['prefix' => 'order'], function () {
         Route::post('endOrderIssue', 'OrderIssueController@apiEndOrderIssue');
         Route::post('getOrderInfoByClientNo', 'OrderIssueController@apiGetOrderInfoByClientNo');
         Route::post('isExistByOrderNo','OrderIssueController@isExistByOrderNoApi');
-        Route::post('updateLogisticNumberReturn','OrderIssueController@updateLogisticNumberReturnApi');
         Route::post('editSecondClientNo','OrderIssueController@editSecondClientNoApi');
         Route::post('endOrderIssues','OrderIssueController@endOrderIssuesApi');
         Route::post('editSecondLogisticNumber','OrderIssueController@editSecondLogisticNumberApi');
@@ -76,6 +76,9 @@ Route::group(['prefix' => 'order'], function () {
         Route::group(['prefix'=>'recycle'],function(){
             Route::post('recover','OrderIssueController@recoverOrderIssueApi');
         });
+        Route::post('userWorkgroups/add','OrderIssueController@addUserWorkgroup');
+        Route::post('userWorkgroups/delete','OrderIssueController@destroyUserWorkgroup');
+        Route::post('batchOthers','OrderIssueController@batchOthers');
     });
 
     Route::group(['prefix'=>'tracking'],function (){

+ 14 - 0
routes/web.php

@@ -193,6 +193,9 @@ Route::group(['prefix'=>'maintenance'],function(){
     Route::group(['prefix'=>"logistic"],function (){
         Route::post("get",'LogisticController@get');
     });
+    Route::group(['prefix'=>"region"],function (){
+        Route::post("get",'RegionController@get');
+    });
 
     Route::get('syncRedisLogs','LogController@syncRedisLogs');
     Route::resource('log', 'LogController');
@@ -218,6 +221,12 @@ Route::group(['prefix'=>'maintenance'],function(){
     Route::resource('userOwnerGroup', 'UserOwnerGroupController');
     Route::resource('processMethod', 'ProcessMethodController');
     Route::resource('feature', 'FeatureController');
+    Route::resource('mail', 'SendEmailsController');
+    Route::post('mail/addRole', 'SendEmailsController@addRole')->name('mail.addRole');
+    Route::post('mail/deleteRole', 'SendEmailsController@deleteRole')->name('mail.deleteRole');
+    Route::post('mail/updateTemplate', 'SendEmailsController@updateTemplate')->name('mail.updateTemplate');
+    Route::post('mail/updateRemark', 'SendEmailsController@updateRemark')->name('mail.updateRemark');
+    Route::post('mail/active', 'SendEmailsController@active')->name('mail.active');
 });
 Route::get('maintenance', function () {return view('maintenance.index');});
 
@@ -539,6 +548,11 @@ Route::group(['prefix'=>'order'],function(){
         Route::group(['prefix'=>'commodityAssign'],function(){
             Route::post('import','OrderCommodityAssignController@import');
         });
+
+        Route::group(['prefix'=>'freeze'],function(){
+            Route::post('delFreeze','OrderFreezeController@delFreeze');
+        });
+        Route::resource('freeze','OrderFreezeController');
     });
     /** 创建 */
     Route::group(['prefix'=>'create'],function(){

+ 60 - 0
tests/Services/RejectedBillService/FindOrderByOrderIssueTest.php

@@ -0,0 +1,60 @@
+<?php
+
+namespace Tests\Services\RejectedBillService;
+use App\Order;
+use App\OrderIssue;
+use App\OrderIssueRejectedBill;
+use App\OrderPackage;
+use App\Services\RejectedBillService;
+use Illuminate\Support\Str;
+use Tests\TestCase;
+use App\RejectedBill;
+use App\Traits\TestMockSubServices;
+
+class FindOrderByOrderIssueTest extends TestCase
+{
+    use TestMockSubServices;
+    /** @var RejectedBillService $service */
+    public $service;
+    private $data;
+    private $amount=1;
+    function setUp(): void
+    {
+        parent::setUp();
+        $this->service = app('RejectedBillService');
+        $this->data['Order']
+            = factory(Order::class)
+            ->create();
+        $this->data['OrderIssue']
+            = factory(OrderIssue::class)
+            ->create(['order_id'=>$this->data['Order']->id]);
+        $this->data['OrderIssueRejectedBill']
+            = factory(OrderIssueRejectedBill::class)
+            ->create(['order_issue_id' => $this->data['OrderIssue']['id'],'logistic_number_return' => Str::random(10)]);
+    }
+
+    public function testReturned()
+    {
+        $logistic_number_return = $this->data['OrderIssueRejectedBill']['logistic_number_return'];
+        $arr = $this->service->findOrderByOrderIssue($logistic_number_return);
+
+        $this->assertEquals($arr['logistic_id'],$this->data['Order']['logistic_id']);
+        $this->assertEquals($arr['owner_id'],$this->data['Order']['owner_id']);
+        $this->assertEquals($arr['consignee_name'],$this->data['Order']['consignee_name']);
+        $this->assertEquals($arr['consignee_phone'],$this->data['Order']['consignee_phone']);
+        $this->assertEquals($arr['client_code'],$this->data['Order']['client_code']);
+    }
+
+    function tearDown(): void
+    {
+        Order::query()->where('id',$this->data['Order']['id'])
+            ->delete();
+        OrderIssueRejectedBill::query()
+            ->where('order_issue_id',$this->data['OrderIssue']['id'])
+            ->where('logistic_number_return',$this->data['OrderIssueRejectedBill']['logistic_number_return'])
+            ->delete();
+        OrderIssue::query()->where('id',$this->data['OrderIssue']['id'])
+            ->delete();
+        parent::tearDown();
+    }
+}

+ 51 - 0
tests/Services/RejectedBillService/FindOrderByOrderPackageTest.php

@@ -0,0 +1,51 @@
+<?php
+
+namespace Tests\Services\RejectedBillService;
+use App\Order;
+use App\OrderPackage;
+use App\Services\RejectedBillService;
+use Tests\TestCase;
+use App\RejectedBill;
+use App\Traits\TestMockSubServices;
+
+class FindOrderByOrderPackageTest extends TestCase
+{
+    use TestMockSubServices;
+    /** @var RejectedBillService $service */
+    public $service;
+    private $data;
+    private $amount=1;
+    function setUp(): void
+    {
+        parent::setUp();
+        $this->service = app('RejectedBillService');
+
+        $this->data['Order']
+            = factory(Order::class )
+            ->create();
+        $this->data['OrderPackage']
+            = factory(OrderPackage::class)
+            ->create(['order_id'=>$this->data['Order']['id']]);
+    }
+
+    public function testReturned()
+    {
+        $logistic_number = $this->data['OrderPackage']['logistic_number'];
+        $arr = $this->service->findOrderByOrderPackage($logistic_number);
+        $this->assertEquals($arr['logistic_id'],$this->data['Order']['logistic_id']);
+        $this->assertEquals($arr['owner_id'],$this->data['Order']['owner_id']);
+        $this->assertEquals($arr['consignee_name'],$this->data['Order']['consignee_name']);
+        $this->assertEquals($arr['consignee_phone'],$this->data['Order']['consignee_phone']);
+        $this->assertEquals($arr['client_code'],$this->data['Order']['client_code']);
+    }
+
+    function tearDown(): void
+    {
+        Order::query()->where('id',$this->data['Order']['id']??'')
+            ->delete();
+        OrderPackage::query()
+            ->where('id',$this->data['OrderPackage']['id'] ?? '')
+            ->delete();
+        parent::tearDown();
+    }
+}

+ 45 - 0
tests/Services/RejectedBillService/GetOrderInfoTest.php

@@ -0,0 +1,45 @@
+<?php
+
+namespace Tests\Services\RejectedBillService;
+use App\Order;
+use App\OrderPackage;
+use App\Services\RejectedBillService;
+use Tests\TestCase;
+use App\RejectedBill;
+use App\Traits\TestMockSubServices;
+
+class GetOrderInfoTest extends TestCase
+{
+    use TestMockSubServices;
+    /** @var RejectedBillService $service */
+    public $service;
+    private $data;
+    private $amount=2;
+    function setUp(): void
+    {
+        parent::setUp();
+        $this->service = app('RejectedBillService');
+        $this->data['Order']
+            = factory(Order::class)->create();
+        $this->data['OrderPackage']
+            = factory(OrderPackage::class)->create(['order_id'=>$this['Order']['id']]);
+    }
+
+    public function testReturned()
+    {
+        $order = $this->service->getOrderInfo($this->data['OrderPackage']['logistic_number_return']);
+        $this->assertEquals($order->id,$this->data['Order']['id']);
+    }
+
+    function tearDown(): void
+    {
+        Order::query()
+            ->whereIn('id',data_get($this->data['Order'],'*.id')??[])
+            ->delete();
+        OrderPackage::query()
+            ->whereIn('id',data_get($this->data['OrderPackage'],'*.id')??[])
+            ->delete();
+
+        parent::tearDown();
+    }
+}

+ 21 - 0
tests/Unit/Services/OrderIssueWorkGroupSync.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace Services;
+
+
+use App\OrderIssue;
+use Tests\TestCase;
+
+class OrderIssueWorkGroupSync extends TestCase
+{
+    /**
+     * @test
+     */
+    public function testSync()
+    {
+        $orderIssues = OrderIssue::query()->whereNotNull('user_workgroup_id')->get();
+        foreach ($orderIssues as $orderIssue) {
+            $orderIssue->userWorkgroups()->attach($orderIssue->user_workgroup_id);
+        }
+    }
+}