Browse Source

Merge remote-tracking branch 'origin/master'

# Conflicts:
#	public/images/QRCodeIMG/1.png
#	public/images/QRCodeIMG/10.png
#	public/images/QRCodeIMG/2.png
#	public/images/QRCodeIMG/4.png
#	public/images/QRCodeIMG/5.png
#	resources/views/waybill/index.blade.php
dream 5 years ago
parent
commit
0855a94237
100 changed files with 8863 additions and 1446 deletions
  1. 7 0
      .gitignore
  2. 35 0
      .gitlab-ci.yml
  3. 1 1
      app/Authority.php
  4. 41 0
      app/Batch.php
  5. 0 30
      app/BillingModel.php
  6. 16 53
      app/Commodity.php
  7. 4 0
      app/CommodityBarcode.php
  8. 67 0
      app/Console/Commands/CreateOwnerAreaReport.php
  9. 85 0
      app/Console/Commands/CreateOwnerBillReport.php
  10. 125 0
      app/Console/Commands/CreateOwnerReport.php
  11. 59 0
      app/Console/Commands/FluxOrderFix.php
  12. 159 0
      app/Console/Commands/InventoryDailyLoggingOwner.php
  13. 51 0
      app/Console/Commands/LogExpireDelete.php
  14. 50 0
      app/Console/Commands/MakeServiceCommand.php
  15. 170 0
      app/Console/Commands/SyncBatchTask.php
  16. 44 0
      app/Console/Commands/SyncLogCacheTask.php
  17. 45 0
      app/Console/Commands/SyncUserVisitMenuLogsCacheTask.php
  18. 114 0
      app/Console/Commands/SyncWMSOrderTask.php
  19. 47 0
      app/Console/Commands/TestTemp.php
  20. 70 0
      app/Console/Commands/WASSyncWMSOrderInformation.php
  21. 68 0
      app/Console/Commands/WasSyncWmsAsnInformation.php
  22. 23 5
      app/Console/Kernel.php
  23. 16 0
      app/CustomField.php
  24. 14 0
      app/Customer.php
  25. 39 0
      app/Events/ClockinEvent.php
  26. 39 0
      app/Events/ClockoutEvent.php
  27. 38 0
      app/Events/ExportEvent.php
  28. 37 0
      app/Events/GuardAuditEvent.php
  29. 39 0
      app/Events/ImportEvent.php
  30. 24 0
      app/Events/ResetProcessStatisticStartDateEvent.php
  31. 5 4
      app/Events/TeamAuditEvent.php
  32. 3 9
      app/Events/WeighedEvent.php
  33. 19 1
      app/Exceptions/Handler.php
  34. 37 14
      app/Exports/Export.php
  35. 1 1
      app/Exports/InventoryBlindReceiveExcelExport.php
  36. 30 15
      app/Exports/RejectedExport.php
  37. 14 0
      app/Feature.php
  38. 29 5
      app/Http/Controllers/Auth/LoginController.php
  39. 1 1
      app/Http/Controllers/Auth/PasswordController.php
  40. 3 3
      app/Http/Controllers/Auth/RegisterController.php
  41. 4 5
      app/Http/Controllers/AuthorityController.php
  42. 88 0
      app/Http/Controllers/BatchController.php
  43. 8 3
      app/Http/Controllers/CarTypesController.php
  44. 8 8
      app/Http/Controllers/CarriersController.php
  45. 7 3
      app/Http/Controllers/CitiesController.php
  46. 226 10
      app/Http/Controllers/CommodityController.php
  47. 90 0
      app/Http/Controllers/ControlPanelController.php
  48. 4 16
      app/Http/Controllers/Controller.php
  49. 90 0
      app/Http/Controllers/CustomFieldController.php
  50. 122 0
      app/Http/Controllers/CustomerBaseController.php
  51. 435 0
      app/Http/Controllers/CustomerController.php
  52. 11 11
      app/Http/Controllers/ExcelController.php
  53. 88 0
      app/Http/Controllers/FeatureController.php
  54. 5 1
      app/Http/Controllers/HomeController.php
  55. 451 0
      app/Http/Controllers/InventoryAccountController.php
  56. 150 0
      app/Http/Controllers/InventoryCompareController.php
  57. 137 0
      app/Http/Controllers/InventoryController.php
  58. 10 10
      app/Http/Controllers/InventoryMissionController.php
  59. 3 3
      app/Http/Controllers/LaborCompanyController.php
  60. 264 112
      app/Http/Controllers/LaborReportController.php
  61. 10 10
      app/Http/Controllers/LaborReportStatusController.php
  62. 62 19
      app/Http/Controllers/LogController.php
  63. 11 7
      app/Http/Controllers/LogisticController.php
  64. 2 2
      app/Http/Controllers/LogisticNumberFeatureController.php
  65. 10 10
      app/Http/Controllers/LogisticTimingController.php
  66. 85 0
      app/Http/Controllers/MaterialBoxController.php
  67. 9 68
      app/Http/Controllers/MeasureMonitorController.php
  68. 1 1
      app/Http/Controllers/MeasuringMachineController.php
  69. 10 10
      app/Http/Controllers/OrderBinController.php
  70. 35 0
      app/Http/Controllers/OrderCommodityAssignController.php
  71. 85 0
      app/Http/Controllers/OrderCommodityController.php
  72. 295 0
      app/Http/Controllers/OrderController.php
  73. 776 0
      app/Http/Controllers/OrderIssueController.php
  74. 66 0
      app/Http/Controllers/OrderIssueOnTopController.php
  75. 70 0
      app/Http/Controllers/OrderIssuePerformanceController.php
  76. 78 0
      app/Http/Controllers/OrderIssueProcessLogController.php
  77. 11 0
      app/Http/Controllers/OrderIssueTypeController.php
  78. 12 0
      app/Http/Controllers/OrderPackageCommoditiesController.php
  79. 12 0
      app/Http/Controllers/OrderPackageController.php
  80. 253 0
      app/Http/Controllers/OrderTrackingController.php
  81. 50 0
      app/Http/Controllers/OrderTrackingOwnerController.php
  82. 76 36
      app/Http/Controllers/OwnerController.php
  83. 200 317
      app/Http/Controllers/PackageController.php
  84. 5 5
      app/Http/Controllers/PaperBoxController.php
  85. 146 68
      app/Http/Controllers/PersonnelController.php
  86. 941 0
      app/Http/Controllers/PriceModelController.php
  87. 657 296
      app/Http/Controllers/ProcessController.php
  88. 122 0
      app/Http/Controllers/ProcessMethodController.php
  89. 33 109
      app/Http/Controllers/ProcessStatisticController.php
  90. 7 3
      app/Http/Controllers/ProvincesController.php
  91. 114 64
      app/Http/Controllers/QRCodeController.php
  92. 3 3
      app/Http/Controllers/QualityLabelController.php
  93. 179 16
      app/Http/Controllers/RejectedBillController.php
  94. 58 21
      app/Http/Controllers/RejectedBillItemController.php
  95. 149 52
      app/Http/Controllers/RejectedController.php
  96. 15 5
      app/Http/Controllers/RoleController.php
  97. 85 0
      app/Http/Controllers/ShopController.php
  98. 85 0
      app/Http/Controllers/SortingStationController.php
  99. 90 0
      app/Http/Controllers/StationController.php
  100. 85 0
      app/Http/Controllers/StationRuleBatchController.php

+ 7 - 0
.gitignore

@@ -7,6 +7,9 @@
 /public/images/QRCodeIMG/*.png
 /resources/images/QRCodeIMG/*.png
 /public/mix-manifest.json
+/public/js/app.js
+/public/css/app.csscd
+/public/css/app.css
 /storage/*.key
 /vendor
 .env
@@ -22,3 +25,7 @@ yarn-error.log
 /.idea/
 /.env.example
 /.gitignore
+/public/icon/img404-thumbnail.jpg
+/public/phpMyAdmin4.8.5/
+/public/fonts
+/phpunit.xml

+ 35 - 0
.gitlab-ci.yml

@@ -0,0 +1,35 @@
+stages:
+  - build
+  - test
+  - deploy
+
+cache:
+  paths:
+    - vendor/
+
+before_script:
+  - sudo cp ci/.envCi .env
+  - sudo bash ci/installEnv.sh
+
+
+build:
+  stage: build
+  tags:
+    - was
+  script:
+    - echo "build ....."
+
+test:
+  stage: test
+  tags:
+    - was
+  script:
+    - echo "run test....."
+    - vendor/bin/phpunit --testsuite=Unit
+
+deploy:
+  stage: deploy
+  tags:
+    - was
+  script:
+    - echo "deploy ...."

+ 1 - 1
app/Authority.php

@@ -8,7 +8,7 @@ use App\Traits\ModelTimeFormat;
 class Authority extends Model
 {
     use ModelTimeFormat;
-    protected $fillable = ['name','remark','id_parent','alias_name','type','relevance'];
+    protected $fillable = ['name','remark','id_parent','alias_name','type','relevance','permission'];
     function roles(){
         return $this->belongsToMany('App\Role','authority_role','id_authority','id_role');
     }

+ 41 - 0
app/Batch.php

@@ -0,0 +1,41 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Batch extends Model
+{
+    protected $fillable = [
+        'id','code','type', 'wms_type', 'status', 'wms_status', 'wms_created_at',"remark","owner_id",
+    ];
+    public function orders(){
+        return $this->hasMany('App\Order','batch_id','id');
+    }
+    public function setProcessed(){
+        $this['status'] = '已处理';
+        $this->orders()->each(function (Order $order){
+            $order->setProcessed();
+        });
+        $this->update();
+    }
+    public function assignBins(){
+        $this->orders()->each(function (Order $order,$i){
+            $bin=new OrderBin(['order_id'=>$order['id'],'number'=>($i+1)]);
+            $bin->save();
+        });
+        return $this->orders()->count();
+    }
+    public function delete()
+    {
+        $this->orders()->each(function(Order $order){
+            $order->delete();
+        });
+        return parent::delete(); // TODO: Change the autogenerated stub
+    }
+    public function owner()
+    {
+        return $this->hasOne(Owner::class,"id","owner_id");
+    }
+
+}

+ 0 - 30
app/BillingModel.php

@@ -1,30 +0,0 @@
-<?php
-
-namespace App;
-
-use Illuminate\Database\Eloquent\Model;
-use App\Traits\ModelTimeFormat;
-
-class BillingModel extends Model
-{
-    use ModelTimeFormat;
-    protected $fillable=[
-        'carrier_id','province_id','city_id','unit_id','range_min','range_max','unit_price','initial_weight'
-    ];
-
-    public function carrier(){
-        return $this->belongsTo('App\Carrier','carrier_id','id');
-    }
-
-    public  function province(){
-        return $this->belongsTo('App\Province','province_id','id');
-    }
-
-    public  function city(){
-        return $this->belongsTo('App\City','city_id','id');
-    }
-
-    public function unit(){
-        return $this->belongsTo('App\Unit','unit_id','id');
-    }
-}

+ 16 - 53
app/Commodity.php

@@ -9,9 +9,16 @@ use App\Traits\ModelTimeFormat;
 class Commodity extends Model
 {
     use ModelTimeFormat;
-    protected $fillable=['name','sku','owner_id','created_at'];
-    protected $appends=['barcode','owner_name','owner_code'];
+    protected $fillable=['name','sku','owner_id','created_at','length','width','height','volumn',"type","pack_spec"];
+    protected $appends=['barcode'];
+//    protected $appends=['barcode','owner_name','owner_code'];
 
+    public function setNameAttribute($value){
+        $this->attributes['name']=str_replace(PHP_EOL,'',$value);
+    }
+    public function getNameAttribute($value){
+        return str_replace(array("\r\n","\n","\r","\"","&quot;"),' ',$value);
+    }
     public function barcodes()
     {
         return $this->hasMany('\App\CommodityBarcode');
@@ -20,64 +27,20 @@ class Commodity extends Model
         return $this->belongsTo('App\Owner','owner_id','id');
     }
     public function getBarcodeAttribute(){
-        return $this->barcodes()->first()['code'];
+        return $this->barcodes[0]['code']??'';
     }
     public function getOwnerNameAttribute(){
-        return $this->owner()->first()['name'];
+        return $this->owner['name']??'';
     }
     public function getOwnerCodeAttribute(){
-        return $this['owner'] ? $this['owner']['code'] : null;
-    }
-
-    static function newCommodityBy_BarcodeOwnerIdNameSku($barcode,$ownerId,$name,$sku){
-        $barcodes=rtrim($barcode,',');
-        $barcodes=explode(',',$barcodes);
-        foreach ($barcodes as $k=>$barcode){
-            if(!trim($barcode)) unset($barcodes[$k]);
-        }
-
-        $commodities=[];
-        foreach ($barcodes as $barcode){
-            if(!trim($barcode))continue;
-            $commodity=Commodity::whereHas('barcodes', function (Builder $query)use($barcode){
-                $query->where('code',$barcode);
-            })->where('name',$name)->where('owner_id',$ownerId)->first();
-            if($commodity)$commodities[]=$commodity;
-        }
-
-        if(count($barcodes)==count($commodities)&&count($commodities)>0){//过滤掉仅有一个条码相等的。
-            $commodity=$commodities[0];
-        }else{
-            $commodity=null;
-        }
-
-        if(!$commodity){
-            $commodity=new Commodity(['name'=>$name,'sku'=>$sku,'owner_id'=>$ownerId]);
-            $commodity->save();
-        }else{
-            if(!isset($commodity['name'])||(!isset($commodity['sku'])||$sku)){
-                $commodity['name']=$name;
-                $commodity['sku']=$sku;
-                $commodity->save();
-            }
-        }
-        foreach ($barcodes as $barcode){
-            if(!trim($barcode))continue;
-//            if(preg_match('/[\x{4e00}-\x{9fa5}]/u',$barcode))continue;
-            $commodityBarcode=CommodityBarcode::where('code',$barcode)->where('commodity_id',$commodity['id'])->first();
-            if(!$commodityBarcode){
-                $commodityBarcode=new CommodityBarcode(['code'=>$barcode,'commodity_id'=>$commodity['id']]);
-                $commodityBarcode->save();
-            }
-        }
-        return $commodity;
+        return $this->owner['code']??'';
     }
 
     public function newBarcode($barcode){
-        $commodityBarcode=CommodityBarcode::where('commodity_id',$this['id'])->where('code',$barcode)->first();
-        if(!$commodityBarcode){
-            $commodityBarcode=new CommodityBarcode(['commodity_id'=>$this['id'],'code'=>$barcode]);
-            $commodityBarcode->save();
+        $barcodeModel = $this->barcodes()->where('code', $barcode)->first();
+        if(!$barcodeModel){
+            return CommodityBarcode::query()->create(['commodity_id'=>$this['id'],'code'=>$barcode]);
         }
+        return $barcodeModel;
     }
 }

+ 4 - 0
app/CommodityBarcode.php

@@ -9,4 +9,8 @@ class CommodityBarcode extends Model
 {
     use ModelTimeFormat;
     protected $fillable=['code','commodity_id','created_at'];
+
+    public function commodity(){
+        return $this->belongsTo('App\Commodity','commodity_id','id');
+    }
 }

+ 67 - 0
app/Console/Commands/CreateOwnerAreaReport.php

@@ -0,0 +1,67 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\OwnerAreaReport;
+use App\Services\LogService;
+use App\Services\OwnerService;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\DB;
+
+class CreateOwnerAreaReport extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'createOwnerAreaReport';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'create owner area report';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * TODO 25号生成盘点面积记录,记录留空由人工填写
+     *
+     * @return void
+     */
+    public function handle()
+    {
+        /** @var OwnerService $ownerService */
+        $ownerService = app('OwnerService');
+        $chunks = ($ownerService->get([],["ownerStoragePriceModels"],false,true))->chunk(50);
+        $month = date('Y-m-d');
+        foreach ($chunks as $owners){
+            $date = date('Y-m-d H:i:s');
+            $createOwnerAreaReport = [];
+            foreach ($owners as $owner){
+                if (!$owner->ownerStoragePriceModels)continue;
+                foreach ($owner->ownerStoragePriceModels as $model){
+                    $createOwnerAreaReport[] = [
+                        "owner_id"              => $owner->id,
+                        "counting_month"        => $month,
+                        "user_owner_group_id"   => $owner->user_owner_group_id,
+                        "created_at"            => $date,
+                        "owner_storage_price_model_id"  => $model->id,
+                    ];
+                }
+            }
+            DB::table("owner_area_reports")->insert($createOwnerAreaReport);
+            LogService::log(__METHOD__,"客户管理-定时生成盘点记录",json_encode($createOwnerAreaReport));
+        }
+    }
+}

+ 85 - 0
app/Console/Commands/CreateOwnerBillReport.php

@@ -0,0 +1,85 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\OwnerAreaReport;
+use App\Services\LogService;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\DB;
+
+class CreateOwnerBillReport extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'createOwnerBillReport';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'create owner bill report';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * 1号生成账单确认,确认金额由人工填写 原始金额默认为:即时账单月记录金额+仓储计费与面积计算金额
+     *
+     * @return void
+     */
+    public function handle()
+    {
+        $year = (int)date('Y');
+        $month = (int)date('m');
+        if ($month == 1){
+            $year--;
+            $lastMonth = '12';
+        }else $lastMonth = ($month-1) < 10 ? "0".($month-1) : ($month-1);
+        $sql = "SELECT owner_id,SUM(work_fee)+SUM(logistic_fee) AS total FROM owner_fee_details WHERE worked_at LIKE ? AND (type = '发货' AND logistic_fee IS NOT NULL AND work_fee IS NOT NULL) OR (type <> '发货' AND work_fee IS NOT NULL)  GROUP BY owner_id";
+        $billDetails = DB::select(DB::raw($sql),[$year."-".$lastMonth."%"]);
+
+        $areas = OwnerAreaReport::query()->with("ownerStoragePriceModel")->where("counting_month","like",$year."-".$lastMonth."%")->get();
+        $map = [];
+        foreach($areas as $area){
+            if (isset($map[$area->owner_id."_".$area->counting_month])){
+                if (!$area->ownerStoragePriceModel)continue;
+                $map[$area->owner_id."_".$area->counting_month] += app('OwnerStoragePriceModelService')
+                    ->calculationAmount($area->ownerStoragePriceModel,$area->accounting_area,$area->owner_id,$area->counting_month);
+            }else{
+                if (!$area->ownerStoragePriceModel)continue;
+                $map[$area->owner_id."_".$area->counting_month] = app('OwnerStoragePriceModelService')
+                    ->calculationAmount($area->ownerStoragePriceModel,$area->accounting_area,$area->owner_id,$area->counting_month);
+            }
+        }
+
+        $chunks = array_chunk($billDetails,50);
+        foreach ($chunks as $bills){
+            $date = date('Y-m-d H:i:s');
+            $createOwnerBillReport = [];
+            foreach ($bills as $bill){
+                $key = $bill->owner_id."_".$year."-".$lastMonth;
+                $total = $bill->total;
+                if (isset($map[$key]))$total += $map[$key];
+                $createOwnerBillReport[] = [
+                    "owner_id"          => $bill->owner_id,       //项目ID
+                    "counting_month"    => $year."-".$lastMonth."-01", //结算月
+                    "initial_fee"       => $total,    //原始账单金额
+                    "created_at"        => $date,
+                ];
+            }
+            LogService::log(__METHOD__,"客户管理-生成确认账单",json_encode($createOwnerBillReport));
+            DB::table("owner_bill_reports")->insert($createOwnerBillReport);
+        }
+    }
+}

+ 125 - 0
app/Console/Commands/CreateOwnerReport.php

@@ -0,0 +1,125 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\OwnerAreaReport;
+use App\OwnerBillReport;
+use App\OwnerReport;
+use App\Services\common\BatchUpdateService;
+use App\Services\LogService;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\DB;
+
+class CreateOwnerReport extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'createOwnerReport';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'create owner report';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * TODO 1号生成或修改上月报表  此处假设每月生成报表数 不足1000,超过此数可能在SQL执行上溢出
+     *
+     * @return void
+     */
+    public function handle()
+    {
+        //转化日期格式 取得上月日期与天数 & 两月前月份
+        $year = (int)date('Y');
+        $month = (int)date('m');
+        if ($month == 1){
+            $year--;
+            $lastMonth = '12';
+        }else $lastMonth = ($month-1) < 10 ? "0".($month-1) : ($month-1);
+        $historyYear = $year;
+        if (($month-1) == 1){
+            $historyYear--;
+            $historyMonth = '12';
+        }else $historyMonth = ($month-2) < 10 ? "0".($month-2) : ($month-2);
+        $lastDay = date("d",strtotime("$year-$lastMonth +1 month -1 day"));
+
+        //获取上月面积与报表
+        $areas = OwnerAreaReport::query()->select("id","owner_id","counting_month",DB::raw("SUM(accounting_area) total,YEAR(counting_month) y,MONTH(counting_month) m"))
+            ->with(['owner'=>function($query){
+                $query->select('id',"code");
+            }])->where("counting_month","like",$year."-".$lastMonth."%")
+            ->groupBy("y","m","owner_id")->get();
+        $reports = OwnerReport::query()->where("counting_month","like",$year."-".$lastMonth."%")->orWhere("counting_month","like",$historyYear."-".$historyMonth."%")->get();
+        $bills = OwnerBillReport::query()->where("counting_month","like",$year."-".$lastMonth."%")->get();
+
+        //日均单量统计
+        $query = DB::raw("select  count(*) c,CUSTOMERID from DOC_ORDER_HEADER where EDITTIME >= to_date('".$year."-".$lastMonth."-01 00:00:00','yyyy-mm-dd hh24:mi:ss') and EDITTIME <= to_date('".$year."-".$lastMonth."-".$lastDay." 23:59:59','yyyy-mm-dd hh24:mi:ss') group by CUSTOMERID");
+        $orderStatistic = DB::connection("oracle")->select($query);
+        $map = [];
+        foreach ($orderStatistic as $item){
+            $map[$item->customerid] = $item->c;
+        }
+
+        //已存在的报表记录
+        $reportMap = [];
+        $historyReportMap = [];
+        foreach ($reports as $report){
+            if ($report->counting_month == ($historyYear."-".$historyMonth)){
+                $historyReportMap[$report->owner_id."_".$report->counting_month] = $report->current_month_counting_area;
+                continue;
+            }
+            $reportMap[$report->owner_id."_".$report->counting_month] = $report->id;
+        }
+
+        //组装账单记录
+        $billMap = [];
+        foreach ($bills as $index => $bill){
+            $bill[$bill->owner_id."_".$bill->counting_month] = $index;
+        }
+
+        //组装报表记录数据
+        $updateReports = [[
+            "id","daily_average_order_amount","current_month_counting_area","owner_bill_report_id"
+        ]];
+        $createReports = [];
+        foreach ($areas as $area){
+            $total = $area->owner ? ($map[$area->owner->code] ?? 0) : 0;
+            if ($reportMap[$area->owner_id."_".$area->counting_month] ?? false){
+                $updateReports[] = [
+                    "id"=>$reportMap[$area->owner_id."_".$area->counting_month],
+                    "total" =>$total,
+                    "daily_average_order_amount"=>round($total / $lastDay,2),
+                    "current_month_counting_area"=>$area->total ?? 0,
+                    "owner_bill_report_id" => $billMap[$area->owner_id."_".$area->counting_month] ?? 0,
+                ];
+            }else $createReports[] = [
+                "owner_id"=>$area->owner_id,
+                "counting_month"=>$area->counting_month."-01",
+                "total" =>$total,
+                "daily_average_order_amount"=>round($total / $lastDay,2),
+                "current_month_counting_area"=>$area->total ?? 0,
+                "owner_bill_report_id" => $billMap[$area->owner_id."_".$area->counting_month] ?? 0,
+                "last_month_counting_area" => $historyReportMap[$area->owner_id."_".($historyYear."-".$historyMonth)] ?? 0,
+            ];
+        }
+        //执行生成或修改
+        app(BatchUpdateService::class)->batchUpdate('owner_reports', $updateReports);
+        app('LogService')->log(__METHOD__,"客户管理-修改原有货主报表",json_encode($updateReports));
+        DB::table("owner_reports")->insert($createReports);
+        app('LogService')->log(__METHOD__,"客户管理-生成货主报表",json_encode($createReports));
+    }
+}

+ 59 - 0
app/Console/Commands/FluxOrderFix.php

@@ -0,0 +1,59 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Http\Controllers\Controller;
+use App\OracleDOCOrderHeader;
+use Carbon\Carbon;
+use Illuminate\Console\Command;
+
+class FluxOrderFix extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'FluxOrderFix';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'FluxOrderFix';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return mixed
+     */
+    public function handle()
+    {
+        $this->fixEdisendflagAtWrong();
+    }
+
+    public function fixEdisendflagAtWrong(){
+        OracleDOCOrderHeader::where('edisendflag','W')
+            ->whereNull('EDI_RESENDTIME')
+            ->where('edisendtime','>',Carbon::now()->subDays(2))
+            ->where('ediremarks2','<>','不支持的单据类型')
+        ->update(['edisendflag'=>'N','manualflag'=>'N','EDI_RESENDTIME'=>Carbon::now()]);
+
+        OracleDOCOrderHeader::where('edisendflag','W')
+            ->where('EDI_RESENDTIME','>',Carbon::now()->subDays(2))
+            ->where('edisendtime','>',Carbon::now()->subDays(2))
+            ->where('ediremarks2','<>','不支持的单据类型')
+        ->update(['edisendflag'=>'N','manualflag'=>'N']);
+    }
+}

+ 159 - 0
app/Console/Commands/InventoryDailyLoggingOwner.php

@@ -0,0 +1,159 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\CommodityBarcode;
+use App\Services\CommodityService;
+use App\Services\LogService;
+use Illuminate\Console\Command;
+use App\InventoryDailyLoggingOwner as LoggingOwner;
+use Illuminate\Support\Facades\DB;
+
+class InventoryDailyLoggingOwner extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'InventoryDailyLoggingOwner';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = '监听指定货主记录';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     *  TODO : 增量添加,每天都会重复去录入之前数据,没有限制去重条件. 因业务需要去查看每天同批货的变动
+     *
+     * @param CommodityService $commodityService
+     * @return void
+     */
+    public function handle(CommodityService $commodityService)
+    {
+        //获取需要查询的货主,键值对:code => id
+        $owners = $this->getLoggingOwners();
+        //计算数量,为0直接return
+        $let = count($owners);
+        if ($let == 0)return;
+        //拼接SQL,SELECT仅取指定字段
+        $sql = "SELECT INV_LOT.customerid,INV_LOT.sku,INV_LOT.qty,BAS_SKU.skulength,
+                BAS_SKU.skuwidth,BAS_SKU.skuhigh,BAS_SKU.cube,BAS_SKU.descr_c,BAS_SKU.alternate_sku1,BAS_SKU.grossweight,
+                INV_LOT_ATT.lotatt05
+                FROM INV_LOT
+                LEFT JOIN BAS_SKU ON INV_LOT.sku = BAS_SKU.sku AND INV_LOT.customerid = BAS_SKU.customerid
+                LEFT JOIN INV_LOT_ATT ON INV_LOT.lotnum = INV_LOT_ATT.lotnum
+                WHERE INV_LOT.customerid IN (";
+        $index = 1;
+        foreach ($owners as $code => $id){
+            $sql .= "'".$code."'";
+            if ($index != $let)$sql .= ",";
+            $index++;
+        }
+        $sql .= ")";
+        //执行获取结果:stdClass类型
+        $invLots = DB::connection('oracle')->select(DB::raw($sql));
+        //声明一个数组,作为第一次去重的容器
+        $inventoryDailyLogs = [];
+        foreach ($invLots as $invLot){
+            //以MAP形式记录进数组,货主code与商品sku作为联合主键唯一标识,如重复叠加其数量
+            if ($inventoryDailyLogs[$owners[$invLot->customerid].'-'.$invLot->sku.'-'.$invLot->lotatt05] ?? false){
+                $inventoryDailyLogs[$owners[$invLot->customerid].'-'.$invLot->sku.'-'.$invLot->lotatt05]['amount'] += $invLot->qty;
+            }else{
+                //符合的结果取此对象的关键信息存进第一个数组
+                $inventoryDailyLogs[$owners[$invLot->customerid].'-'.$invLot->sku.'-'.$invLot->lotatt05] = [
+                    'commodity' => [
+                        'owner_id'=>$owners[$invLot->customerid],
+                        'sku'=>$invLot->sku,
+                        'name'=>$invLot->descr_c,
+                        'length'=>$invLot->skulength,
+                        'width'=>$invLot->skuwidth,
+                        'height'=>$invLot->skuhigh,
+                        'volumn'=>$invLot->cube,
+                        'code'=>$invLot->alternate_sku1,
+                        'weight' => $invLot->grossweight,
+                    ],
+                    'amount' => $invLot->qty,
+                    'volumn_occupied' => 0,
+                    'gross_weight' => 0,
+                    'depository_code' => $invLot->lotatt05,
+                ];
+            }
+        }
+        //第二个数组作为批量插入使用
+        $data = [];
+        //遍历第一个数组,此时已经去重完成,直接取对应参数push进data中
+        foreach ($inventoryDailyLogs as $inventoryDailyLog){
+            //寻找己方库中是否存在对应商品,存在更新其长宽高体积,不存在录入
+            $commodity = $inventoryDailyLog['commodity'];
+            $param = ['owner_id'=>$commodity['owner_id'],'sku'=>$commodity["sku"]];
+            //体积存在为0的情况,需再次计算一次,此处体积为m³
+            if (!$commodity['volumn'] || $commodity['volumn'] == "0"){
+                $commodity['volumn'] = $commodity['length']*$commodity['width']*$commodity['height'];
+            }
+            $column = [
+                'owner_id'=>$commodity['owner_id'],
+                'sku'=>$commodity['sku'],
+                'name'=>$commodity['name'],
+                'length'=>$commodity['length'],
+                'width'=>$commodity['width'],
+                'height'=>$commodity['height'],
+                'volumn'=>$commodity['volumn'],
+            ];
+            $result = $commodityService->updateOrCreate($param,$column);
+            app('LogService')->log(__METHOD__,"同步库存每日记录时修改或生成商品",json_encode($column));
+
+            $commodity_id = $result->id;
+            //寻找对应barcode是否存在,不存在录入
+            if ($commodity['code']) CommodityBarcode::query()->firstOrCreate(['commodity_id'=>$commodity_id,'code'=>$commodity['code']]);
+            //计算总体积,商品体积×该单数量
+            $volumn_occupied = $commodity['volumn']*$inventoryDailyLog["amount"];
+            $gross_weight = $commodity['weight']*$inventoryDailyLog["amount"];
+
+            $depository = null;
+            if ($inventoryDailyLog['depository_code']){
+                $depository = app('DepositoryService')->firstOrCreate(["code"=>$inventoryDailyLog['depository_code']],[
+                    "name"=>$inventoryDailyLog['depository_code'],
+                    "code"=>$inventoryDailyLog['depository_code'],
+                ]);
+            }
+
+            $data[]  = [
+                "owner_id"=>$commodity['owner_id'],
+                "created_at"=>date('Y-m-d H:i:s'),
+                "commodity_id"=>$commodity_id,
+                "amount"=>$inventoryDailyLog['amount'],
+                "volumn_occupied"=>$volumn_occupied,
+                "gross_weight"=>$gross_weight,
+                "depository_id"=>$depository ? $depository->id : null,
+            ];
+        }
+        DB::table('inventory_daily_logs')->insert($data);
+        app('LogService')->log(__METHOD__,"同步库存每日记录",json_encode($data));
+    }
+
+    public function getLoggingOwners(){
+        $loggingOwners = LoggingOwner::with('owner')->select('id','owner_id')->where('status','启用')->get();
+        $owners = [];
+        foreach ($loggingOwners as $loggingOwner){
+            if ($loggingOwner->owner){
+                $owners[$loggingOwner->owner->code] = $loggingOwner->owner_id;
+            }
+        }
+        return $owners;
+    }
+}

+ 51 - 0
app/Console/Commands/LogExpireDelete.php

@@ -0,0 +1,51 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Http\Controllers\Controller;
+use Carbon\Carbon;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\DB;
+
+class LogExpireDelete extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'LogExpireDelete';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'LogExpireDelete';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return mixed
+     */
+    public function handle()
+    {
+        $this->deleteLog();
+    }
+
+    public function deleteLog(){
+        $expire_duration=config('logging.expire_duration');//前150天
+        $date=Carbon::now()->subDays($expire_duration)->format('Y-m-d');
+        DB::table('logs')->where('created_at','like',$date.'%')->delete();
+    }
+}

+ 50 - 0
app/Console/Commands/MakeServiceCommand.php

@@ -0,0 +1,50 @@
+<?php
+
+namespace App\Console\Commands;
+
+use Illuminate\Console\Command;
+
+class MakeServiceCommand extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'make:service {name : fileName}';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Create Service file';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return void
+     */
+    public function handle()
+    {
+        if (!file_exists(base_path('app\\Services'))){
+            mkdir('app\\Services',666,false);
+        }
+        $fileName=$this->argument('name');
+        if (!file_exists(base_path('app\\Services\\'.$fileName.'.php'))){
+            file_put_contents(base_path('app\\Services\\'.$fileName.'.php'),
+                '<?php '.PHP_EOL.PHP_EOL.'namespace App\Services; '.PHP_EOL.PHP_EOL.'Class '.$fileName.PHP_EOL.'{ '.PHP_EOL.PHP_EOL.PHP_EOL.'}');
+        }
+        else echo $this->error("ERROR: file exists;");
+    }
+}

+ 170 - 0
app/Console/Commands/SyncBatchTask.php

@@ -0,0 +1,170 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Services\BatchService;
+use App\Services\CacheService;
+use App\Services\common\BatchUpdateService;
+use App\Services\DocWaveHeaderService;
+use App\Services\LogService;
+use App\ValueStore;
+use Carbon\Carbon;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\DB;
+
+class SyncBatchTask extends Command
+{
+    protected $signature = 'sync:batch';
+
+    protected $description = 'sync wms batch task';
+
+    /** @var DocWaveHeaderService $service */
+    private $service;
+    /** @var BatchService $batchService */
+    private $batchService;
+
+    public function __construct()
+    {
+        parent::__construct();
+        $this->service = app(DocWaveHeaderService::class);
+        $this->batchService = app(BatchService::class);
+    }
+
+    public function handle()
+    {
+        $this->disposeHeader();
+        $this->disposeDetail();
+    }
+
+    private function disposeHeader()
+    {
+        //获取更新时间与WMS数据
+        $date = $this->service->getSyncDate();
+        $waves = $this->service->get(["edittime"=>$date],["edittime"=>"gtOrEqual"]);
+        if (count($waves) < 1)return;
+
+        //获取本地数据对比差异
+        $codes = array_column($waves->toArray(),"waveno");
+        $map = [];
+        $batches = $this->batchService->get(["code"=>$codes]);
+        if ($batches){
+            foreach ($batches as $batch)$map[$batch->code] = $batch->id;
+        }
+        $update = [["id","wms_status","remark","updated_at"]];
+        $insert = [];
+        foreach ($waves as $wave){
+            if (isset($map[$wave->waveno])){
+                $update[] = [
+                    "id" => $map[$wave->waveno],
+                    "wms_status" => $this->wms_status($wave),
+                    "remark"=>$wave->descr,
+                    "updated_at"=>$wave->edittime,
+                ];
+                continue;
+            }
+            $owner = app("OwnerService")->codeGetOwner($wave->customerid);
+            $insert[] = [
+                "code" => $wave->waveno,
+                "remark"=>$wave->descr,
+                "status" => '未处理',
+                "wms_status" => $this->wms_status($wave),
+                "created_at"=>$wave->addtime,
+                "updated_at"=>$wave->edittime,
+                "owner_id"=>$owner->id,
+            ];
+        }
+
+        //存在则更新
+        if (count($update)>1){
+            $bool = app(BatchUpdateService::class)->batchUpdate("batches",$update);
+            if ($bool)LogService::log(__METHOD__,"SUCCESS-同步更新波次成功",json_encode($update));
+            else{
+                LogService::log(__METHOD__,"ERROR-同步更新波次失败",json_encode($update));
+                return;
+            }
+        }
+
+        //不存在则录入
+        if ($insert){
+            $this->batchService->insert($insert);
+            LogService::log(__METHOD__,"SUCCESS-同步插入波次成功",json_encode($insert));
+        }
+        $lastDate = $waves[0]->edittime;
+        $this->service->setSyncDate($lastDate);
+    }
+
+    public function disposeDetail()
+    {
+        $date = app(CacheService::class)->getOrExecute("wave_detail_last_sync_date",function (){
+            $valueStore = ValueStore::query()->where("name","wave_detail_last_sync_date")->first();
+            return $valueStore->value ?? Carbon::now()->subSeconds(65)->toDateTimeString();
+        });
+        $sql = "SELECT WM_CONCAT(ORDERNO) orderno,WAVENO FROM DOC_WAVE_DETAILS WHERE EDITTIME > TO_DATE(?,'yyyy-mm-dd hh24:mi:ss')  GROUP BY WAVENO";
+        $details = DB::connection("oracle")->select(DB::raw($sql),[$date]);
+        if (count($details) < 1)return;
+        $map = [];
+        $nos = [];
+        foreach ($details as $detail){
+            $map[$detail->waveno] = explode(",",$detail->orderno);
+            $nos[] = $detail->waveno;
+        }
+        $batches = $this->batchService->get(["code"=>$nos]);
+        foreach ($batches as $batch){
+            app("OrderService")->update(["code"=>$map[$batch->code]],["batch_id"=>$batch->id]);
+            unset($map[$batch->code]);
+        }
+        if ($map){
+            $waveCodes = array_keys($map);
+            $waves = $this->service->get(["waveno"=>$waveCodes],["waveno"=>"in"]);
+            $insert = [];
+            foreach ($waves as $wave){
+                $owner = app("OwnerService")->codeGetOwner($wave->customerid);
+                $insert[] = [
+                    "code" => $wave->waveno,
+                    "status" => '未处理',
+                    "wms_status" => $this->wms_status($wave),
+                    "remark"=>$wave->descr,
+                    "created_at"=>$wave->addtime,
+                    "updated_at"=>$wave->edittime,
+                    "owner_id"=>$owner->id,
+                ];
+            }
+            if ($insert){
+                $this->batchService->insert($insert);
+                LogService::log(__METHOD__,"SUCCESS-同步插入波次成功",json_encode($insert));
+                $batches = $this->batchService->get(["code"=>$waveCodes]);
+                foreach ($batches as $batch){
+                    app("OrderService")->update(["code"=>$map[$batch->code]],["batch_id"=>$batch->id]);
+                }
+            }
+        }
+//        $this->batchService->assignTasks($batches);
+
+
+        ValueStore::query()->where("name","wave_last_sync_date")->update(["value"=>Carbon::now()->subSeconds(1)->toDateTimeString()]);
+    }
+
+    /**
+     * @param $wave
+     * @return string
+     */
+    public function wms_status($wave): string
+    {
+        switch ($wave->wavestatus) {
+            case 00:
+                $wms_status = '创建';
+                break;
+            case 40:
+                $wms_status = '部分收货';
+                break;
+            case 90:
+                $wms_status = '取消';
+                break;
+            case 99:
+                $wms_status = '完成';
+                break;
+            default:null;
+        }
+        return $wms_status;
+    }
+}

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

@@ -0,0 +1,44 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Log;
+use App\Services\LogService;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Redis;
+
+class SyncLogCacheTask extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'syncLogCacheTask';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Command description';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     */
+    public function handle()
+    {
+        LogService::syncRedisLogs();
+    }
+}

+ 45 - 0
app/Console/Commands/SyncUserVisitMenuLogsCacheTask.php

@@ -0,0 +1,45 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Services\LogService;
+use App\Services\CheckActiveMenuService;
+use App\UserVisitMenuLog;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Redis;
+
+class SyncUserVisitMenuLogsCacheTask extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'syncUserVisitMenuLogsCacheTask';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Command description';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     */
+    public function handle()
+    {
+        CheckActiveMenuService::sync();
+    }
+}

+ 114 - 0
app/Console/Commands/SyncWMSOrderTask.php

@@ -0,0 +1,114 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Services\OracleDOCOrderHeaderService;
+use App\Services\OrderService;
+use Carbon\Carbon;
+use Illuminate\Console\Command;
+
+class SyncWMSOrderTask extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'sync:order';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Command description';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     */
+    public function handle()
+    {
+        $is_enabled= config('sync.order_sync.cache_prefix.enabled');
+        sleep(rand(5,10));
+        if($is_enabled=='false')return;
+        $this->syncCreatedOrder();
+        $this->syncUpdatedOrder();
+    }
+
+    public function syncCreatedOrder()
+    {
+        /**
+         * @var OracleDOCOrderHeaderService $oracleDOCOrderHeaderService
+         * @var OrderService $orderService
+         */
+        $newest         = config('sync.order_sync.cache_prefix.created_at');
+        $newest_list    = config('sync.order_sync.cache_prefix.newest_list');
+        $hasKey         = config('sync.order_sync.cache_prefix.newest_has');
+        $prefixKey      = config('sync.order_sync.cache_prefix.newest');
+        ini_set('memory_limit', '512M');
+        $orderService = app('OrderService');
+        $oracleDOCOrderHeaderService = app('OracleDocOrderHeaderService');
+
+        $last_date = $orderService->getOrderSyncAt($newest,'newest');                             // 获取时间点
+
+        $orderHeaders = $oracleDOCOrderHeaderService->getWMSOrderOnStartDate($last_date);               // WMS订单
+        if($orderHeaders->count()==0)return;
+        $last_order = $orderHeaders->first();                                                           // 时间点靠后的
+        $newest_orders = $orderHeaders->where('addtime',$last_order->addtime);
+
+        $orderHeaders = $orderService->filterOrderByCache($orderHeaders,$newest_list);                  // 对比缓存
+
+        if(count($newest_orders)>0 && count($orderHeaders) >0){
+
+            $orderService->syncOrder($orderHeaders);                                                //  同步订单
+            $orderService->cancelOrderCache($newest_list,$prefixKey);                                   //  清除缓存
+            $orderService->pushOrderCache($newest_orders,$prefixKey,$hasKey,$newest_list);              //  添加缓存
+            $orderService->setOrderSyncAt($newest,$last_order->addtime,count($orderHeaders)>0);   //  更新时间
+        }
+
+    }
+
+    public function syncUpdatedOrder()
+    {
+        /**
+         * @var OracleDOCOrderHeaderService $oracleDOCOrderHeaderService
+         * @var OrderService $orderService
+         */
+        $renewal        = config('sync.order_sync.cache_prefix.updated_at');
+        $renewal_list   = config('sync.order_sync.cache_prefix.renewal_list');
+        $hasKey         = config('sync.order_sync.cache_prefix.renewal_has');
+        $prefixKey      = config('sync.order_sync.cache_prefix.renewal');
+        ini_set('memory_limit', '512M');
+
+        $orderService = app('OrderService');
+        $oracleDOCOrderHeaderService = app('OracleDocOrderHeaderService');
+
+        $last_date = $orderService->getOrderSyncAt($renewal,'renewal');                               // 获取时间点
+
+        $orderHeaders = $oracleDOCOrderHeaderService->getWMSOrderOnEditDate($last_date);                   // WMS订单
+
+        if($orderHeaders->count()==0)return;
+        $renewal_order = $orderHeaders->first();                                                            // 时间点靠后的
+        $renewal_orders =  $orderHeaders->where('edittime',$renewal_order->edittime);
+
+        $orderHeaders = $orderService->filterOrderByCache($orderHeaders,$renewal_list);                     // 对比缓存
+
+        if(count($renewal_orders)>0 && count($orderHeaders)>0){
+
+            $orderService->syncOrder($orderHeaders);                                                    // 同步订单
+            $orderService->cancelOrderCache($renewal_list,$prefixKey);                                      // 清除缓存
+            $orderService->pushOrderCache($renewal_orders,$prefixKey,$hasKey,$renewal_list);                // 添加缓存
+            $orderService->setOrderSyncAt($renewal,$renewal_order->edittime,count($orderHeaders)>0);   // 更新时间
+        }
+    }
+}

+ 47 - 0
app/Console/Commands/TestTemp.php

@@ -0,0 +1,47 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Http\Controllers\Controller;
+use App\Http\Controllers\TestController;
+use App\OracleDOCOrderHeader;
+use Carbon\Carbon;
+use Illuminate\Console\Command;
+
+class TestTemp extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'TestTemp';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'TestTemp';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return mixed
+     */
+    public function handle()
+    {
+        return (new TestController())->cleanOrderRepeat();
+    }
+
+}

+ 70 - 0
app/Console/Commands/WASSyncWMSOrderInformation.php

@@ -0,0 +1,70 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Services\LogService;
+use App\Services\OrderTrackingService;
+use Illuminate\Console\Command;
+use Illuminate\Support\Carbon;
+use Illuminate\Support\Facades\Auth;
+
+class WASSyncWMSOrderInformation extends Command
+{
+
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'WASSyncWMSOrderInformation';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = '同步WMS的订单信息';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return int
+     */
+    public function handle()
+    {
+        $this->WasSyncWmsOrder();
+    }
+
+    public function WasSyncWmsOrder(){
+
+        /** @var OrderTrackingService $orderTrackingService */
+        $orderTrackingService  = app('OrderTrackingService');
+
+        $dataInterval = intval(data_get(config('sync'), 'order_tracking_import.interval')) * 60 + 5;
+
+        $startDate = Carbon::now()->subSeconds($dataInterval);
+
+        $syncStartDate = data_get(config('sync'), 'order_tracking_import.start_at');
+
+        if($syncStartDate ?? false){
+            $syncStartDate = Carbon::parse($syncStartDate);
+            if ($startDate->lt($syncStartDate)) {
+                $startDate = $syncStartDate;
+            }
+        }
+
+//        $startDate = Carbon::parse('2020-05-06 13:16:51')->toDateTimeString();
+//        $orderTrackingService->根据设置从WMS同步追踪货主的订单($startDate);
+        $orderTrackingService->trackingWmsOrder($startDate);
+    }
+}

+ 68 - 0
app/Console/Commands/WasSyncWmsAsnInformation.php

@@ -0,0 +1,68 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\Services\LogService;
+use App\Services\OrderTrackingService;
+use App\Services\StoreService;
+use Illuminate\Console\Command;
+use Illuminate\Support\Carbon;
+use Illuminate\Support\Facades\Auth;
+
+class WasSyncWmsAsnInformation extends Command
+{
+
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'WasSyncWmsAsnInformation';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = '同步WMS的入库信息';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return int
+     */
+    public function handle()
+    {
+        $this->WasSyncWmsAsn();
+    }
+
+    public function WasSyncWmsAsn(){
+
+        /** @var StoreService $storeService */
+        $storeService  = app('storeService');
+
+        $dataInterval = intval(data_get(config('sync'), 'asn_sync.interval')) * 60 + 5;
+
+        $startDate = Carbon::now()->subSeconds($dataInterval);
+
+        $syncStartDate = data_get(config('sync'), 'asn_sync.start_at');
+
+        if($syncStartDate ?? false){
+            $syncStartDate = Carbon::parse($syncStartDate);
+            if ($startDate->lt($syncStartDate)) {
+                $startDate = $syncStartDate;
+            }
+        }
+        //$storeService->syncWmsAsnData($startDate);
+    }
+}

+ 23 - 5
app/Console/Kernel.php

@@ -2,6 +2,8 @@
 
 namespace App\Console;
 
+use App\Console\Commands\SyncBatchTask;
+use App\Console\Commands\SyncWMSOrderTask;
 use Illuminate\Console\Scheduling\Schedule;
 use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
 
@@ -13,7 +15,16 @@ class Kernel extends ConsoleKernel
      * @var array
      */
     protected $commands = [
-        //
+        \App\Console\Commands\LogExpireDelete::class,
+        \App\Console\Commands\MakeServiceCommand::class,
+        \App\Console\Commands\FluxOrderFix::class,
+        \App\Console\Commands\InventoryDailyLoggingOwner::class,
+        \App\Console\Commands\WASSyncWMSOrderInformation::class,
+        \App\Console\Commands\SyncLogCacheTask::class,
+        \App\Console\Commands\SyncUserVisitMenuLogsCacheTask::class,
+        \App\Console\Commands\TestTemp::class,
+        SyncBatchTask::class,
+        SyncWMSOrderTask::class,
     ];
 
     /**
@@ -24,8 +35,16 @@ class Kernel extends ConsoleKernel
      */
     protected function schedule(Schedule $schedule)
     {
-        // $schedule->command('inspire')
-        //          ->hourly();
+        $schedule->command('LogExpireDelete')->dailyAt('00:01');
+        $schedule->command('InventoryDailyLoggingOwner')->dailyAt('08:00');
+        $schedule->command('FluxOrderFix')->hourlyAt(1);
+        $schedule->command('WASSyncWMSOrderInformation')->everyMinute();
+        $schedule->command('syncLogCacheTask')->everyMinute();
+        $schedule->command('createOwnerReport')->monthlyOn(1);
+        $schedule->command('createOwnerBillReport')->monthlyOn(1);
+        $schedule->command('createOwnerAreaReport')->monthlyOn(25);
+        $schedule->command('sync:batch')->everyMinute();
+        $schedule->command('sync:order')->everyMinute();
     }
 
     /**
@@ -35,8 +54,7 @@ class Kernel extends ConsoleKernel
      */
     protected function commands()
     {
-        $this->load(__DIR__.'/Commands');
-
+        $this->load(__DIR__ . '/Commands');
         require base_path('routes/console.php');
     }
 }

+ 16 - 0
app/CustomField.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+class CustomField extends Model
+{
+    protected $fillable=['table',
+        'field',
+        'present_name',
+        'authority_name',
+        'authority_id',
+        'condition_field',
+        'condition_value'];
+}

+ 14 - 0
app/Customer.php

@@ -0,0 +1,14 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Customer extends Model
+{
+    protected $fillable = [
+        "code",         //客户代码
+        "name",         //客户名称
+        "company_name"  //公司名称
+    ];
+}

+ 39 - 0
app/Events/ClockinEvent.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace App\Events;
+
+use App\Http\Controllers\Controller;
+use App\LaborReport;
+use App\UserDutyCheck;
+use Illuminate\Broadcasting\Channel;
+use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
+use Illuminate\Queue\SerializesModels;
+
+
+class ClockinEvent implements ShouldBroadcast
+{
+    use  SerializesModels;
+
+    public $laborReport;
+
+    /**
+     * Create a new event instance.
+     *
+     * @param UserDutyCheck $userDutyCheck
+     */
+    public function __construct(LaborReport $laborReport)
+    {
+        $this->laborReport=$laborReport;
+    }
+
+    /**
+     * Get the channels the event should broadcast on.
+     *
+     * @return \Illuminate\Broadcasting\Channel|array
+     */
+    public function broadcastOn()
+    {
+        return new Channel($this->laborReport->userWorkgroup->token);
+    }
+
+}

+ 39 - 0
app/Events/ClockoutEvent.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace App\Events;
+
+use App\Http\Controllers\Controller;
+use App\LaborReport;
+use App\UserDutyCheck;
+use Illuminate\Broadcasting\Channel;
+use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
+use Illuminate\Queue\SerializesModels;
+
+
+class ClockoutEvent implements ShouldBroadcast
+{
+    use  SerializesModels;
+
+    public $laborReport;
+
+    /**
+     * Create a new event instance.
+     *
+     * @param UserDutyCheck $userDutyCheck
+     */
+    public function __construct(LaborReport $laborReport)
+    {
+        $this->laborReport=$laborReport;
+    }
+
+    /**
+     * Get the channels the event should broadcast on.
+     *
+     * @return \Illuminate\Broadcasting\Channel|array
+     */
+    public function broadcastOn()
+    {
+        return new Channel($this->laborReport->userWorkgroup->token);
+    }
+
+}

+ 38 - 0
app/Events/ExportEvent.php

@@ -0,0 +1,38 @@
+<?php
+
+namespace App\Events;
+
+use App\LaborReport;
+use App\UserDutyCheck;
+use Illuminate\Broadcasting\Channel;
+use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
+use Illuminate\Queue\SerializesModels;
+
+
+class ExportEvent implements ShouldBroadcast
+{
+    use  SerializesModels;
+
+    public $laborReport;
+
+    /**
+     * Create a new event instance.
+     *
+     * @return void
+     */
+    public function __construct(LaborReport $laborReport)
+    {
+        $this->laborReport=$laborReport;
+    }
+
+    /**
+     * Get the channels the event should broadcast on.
+     *
+     * @return \Illuminate\Broadcasting\Channel|array
+     */
+    public function broadcastOn()
+    {
+        return new Channel('laborReport');
+    }
+
+}

+ 37 - 0
app/Events/GuardAuditEvent.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace App\Events;
+
+use App\UserDutyCheck;
+use Illuminate\Broadcasting\Channel;
+use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
+use Illuminate\Queue\SerializesModels;
+
+
+class GuardAuditEvent implements ShouldBroadcast
+{
+    use  SerializesModels;
+
+    public $userDutyCheck;
+
+    /**
+     * Create a new event instance.
+     *
+     * @return void
+     */
+    public function __construct(UserDutyCheck $userDutyCheck)
+    {
+        $this->userDutyCheck=$userDutyCheck;
+    }
+
+    /**
+     * Get the channels the event should broadcast on.
+     *
+     * @return \Illuminate\Broadcasting\Channel|array
+     */
+    public function broadcastOn()
+    {
+        return new Channel('userDutyCheck');
+    }
+
+}

+ 39 - 0
app/Events/ImportEvent.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace App\Events;
+
+use App\LaborReport;
+use Illuminate\Broadcasting\Channel;
+use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
+use Illuminate\Queue\SerializesModels;
+
+
+class ImportEvent implements ShouldBroadcast
+{
+    use  SerializesModels;
+
+    public $laborReport;
+
+    /**
+     * Create a new event instance.
+     *
+     * @return void
+     */
+    public function __construct(LaborReport $laborReport)
+    {
+        $this->laborReport=$laborReport;
+    }
+
+    /**
+     * Get the channels the event should broadcast on.
+     *
+     * @return \Illuminate\Broadcasting\Channel|array
+     */
+    public function broadcastOn()
+    {
+        $tokenOfBroadcastEnterAndLeave=LaborReport::tokenOfBroadcastEnterAndLeave();
+        return new Channel($tokenOfBroadcastEnterAndLeave);
+        //return new Channel('laborReport');
+    }
+
+}

+ 24 - 0
app/Events/ResetProcessStatisticStartDateEvent.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace App\Events;
+
+use App\Process;
+use Illuminate\Broadcasting\InteractsWithSockets;
+use Illuminate\Foundation\Events\Dispatchable;
+use Illuminate\Queue\SerializesModels;
+
+class ResetProcessStatisticStartDateEvent
+{
+    use Dispatchable, InteractsWithSockets, SerializesModels;
+
+    public $process;
+    /**
+     * Create a new event instance.
+     * @param Process $process
+     * @return void
+     */
+    public function __construct(Process $process)
+    {
+        $this->process = $process;
+    }
+}

+ 5 - 4
app/Events/TeamAuditEvent.php

@@ -2,6 +2,7 @@
 
 namespace App\Events;
 
+use App\LaborReport;
 use App\UserDutyCheck;
 use Illuminate\Broadcasting\Channel;
 use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
@@ -12,16 +13,16 @@ class TeamAuditEvent implements ShouldBroadcast
 {
     use  SerializesModels;
 
-    public $userDutyCheck;
+    public $laborReport;
 
     /**
      * Create a new event instance.
      *
      * @return void
      */
-    public function __construct(UserDutyCheck $userDutyCheck)
+    public function __construct(LaborReport $laborReport)
     {
-        $this->userDutyCheck=$userDutyCheck;
+        $this->laborReport=$laborReport;
     }
 
     /**
@@ -31,7 +32,7 @@ class TeamAuditEvent implements ShouldBroadcast
      */
     public function broadcastOn()
     {
-        return new Channel('userDutyCheck');
+        return new Channel('laborReport');
     }
 
 }

+ 3 - 9
app/Events/WeighedEvent.php

@@ -2,12 +2,10 @@
 
 namespace App\Events;
 
-use App\Http\Controllers\Controller;
-use App\Package;
+use App\OrderPackage;
 use Illuminate\Broadcasting\Channel;
 use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
 use Illuminate\Queue\SerializesModels;
-use Illuminate\Broadcasting\PrivateChannel;
 
 class WeighedEvent implements ShouldBroadcast
 {
@@ -17,10 +15,10 @@ class WeighedEvent implements ShouldBroadcast
 
     /**
      * Create a new event instance.
-     *
+     * @param OrderPackage $package
      * @return void
      */
-    public function __construct(Package $package)
+    public function __construct(OrderPackage $package)
     {
         $this->package=$package;
     }
@@ -34,9 +32,5 @@ class WeighedEvent implements ShouldBroadcast
     {
         return new Channel('package');
     }
-//
-//    public function broadcastAs(){
-//        return "weight";        //频道别名
-//    }
 
 }

+ 19 - 1
app/Exceptions/Handler.php

@@ -2,10 +2,14 @@
 
 namespace App\Exceptions;
 
+use App\Http\Controllers\Controller;
 use Exception;
 use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
+use Illuminate\Http\Exceptions\HttpResponseException;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
+use Symfony\Component\HttpKernel\Exception\HttpException;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 use Throwable;
 
 class Handler extends ExceptionHandler
@@ -46,11 +50,25 @@ class Handler extends ExceptionHandler
      *
      * @param Request $request
      * @param Throwable $exception
-     * @return Response
+     * @return \Symfony\Component\HttpFoundation\Response
      * @throws Throwable
      */
     public function render($request, Throwable $exception)
     {
+        try{
+            if (method_exists($exception,'getStatusCode')) {
+            $code = $exception->getStatusCode();
+            Controller::logS('exception',$code,$exception->getTraceAsString().'|| '.$exception->getMessage().' ||'.json_encode($request));
+            switch ($code){
+                case 419:return response()->view('exception.login');
+                case 404:return response()->view('exception.404');
+                default: return response()->view('exception.default',compact('code'));
+            }
+            }
+            Controller::logS('exception',class_basename($exception),$exception->getTraceAsString().'|| ||'.json_encode($request));
+        }catch (\Exception $e){
+
+        }
         return parent::render($request, $exception);
     }
 }

+ 37 - 14
app/Exports/Export.php

@@ -4,20 +4,33 @@ use Maatwebsite\Excel\Concerns\FromCollection;
 use Maatwebsite\Excel\Concerns\ShouldAutoSize;
 use Maatwebsite\Excel\Concerns\WithColumnFormatting;
 use Maatwebsite\Excel\Concerns\WithCustomValueBinder;
+use Maatwebsite\Excel\Concerns\WithEvents;
 use Maatwebsite\Excel\Concerns\WithStrictNullComparison;
+use Maatwebsite\Excel\Events\AfterSheet;
 use PhpOffice\PhpSpreadsheet\Cell\StringValueBinder;
 use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
 
 class Export extends StringValueBinder implements FromCollection,
-    ShouldAutoSize,WithColumnFormatting,WithCustomValueBinder,WithStrictNullComparison
+    ShouldAutoSize,WithColumnFormatting,WithCustomValueBinder,WithStrictNullComparison,WithEvents
 {
     private $row;
     private $data;
+    private $mergeCell;
+    private $columnName;
+    private $formatNumber;
 
-    public function __construct($row,$data)
+    /*
+     * $mergeCell $columnName :合并单元格所需参数;
+     * $mergeCell 需要合并的位置数组以MAP形式存储 [开始行=>结束行]
+     * $columnName 需要合并列 与合并行数结合使用ARRAY存储 ['A','B']
+     */
+    public function __construct($row,$data,$mergeCell=null,$columnName=null,$formatNumber=['D','H','I','L','O','Q','S','T','U','V'])
     {
         $this->row = $row;
         $this->data = $data;
+        $this->mergeCell = $mergeCell;
+        $this->columnName = $columnName;
+        $this->formatNumber = $formatNumber;
     }
 
     public function collection()
@@ -41,19 +54,29 @@ class Export extends StringValueBinder implements FromCollection,
         }
         return collect($row);
     }
+    public function registerEvents(): array
+    {
+        // TODO: Implement registerEvents() method.
+        if ($this->mergeCell && $this->columnName){
+            return [
+                AfterSheet::class => function(AfterSheet $event){
+                    foreach ($this->columnName as $column){
+                        foreach ($this->mergeCell as $key=>$value){
+                            $event->sheet->getDelegate()->mergeCells($column.$key.':'.$column.$value);
+                        }
+                    }
+                }
+            ];
+        }
+        return [];
+    }
+
     public function columnFormats(): array{
-        return [
-            'D' => NumberFormat::FORMAT_TEXT,
-            'H' => NumberFormat::FORMAT_TEXT,
-            'I' => NumberFormat::FORMAT_TEXT,
-            'L' => NumberFormat::FORMAT_TEXT,
-            'O' => NumberFormat::FORMAT_TEXT,
-            'Q' => NumberFormat::FORMAT_TEXT,
-            'S' => NumberFormat::FORMAT_TEXT,
-            'T' => NumberFormat::FORMAT_TEXT,
-            'U' => NumberFormat::FORMAT_TEXT,
-            'V' => NumberFormat::FORMAT_TEXT,
-        ];
+        $formatNumber = [];
+        foreach ($this->formatNumber as $column){
+            $formatNumber[$column] = NumberFormat::FORMAT_TEXT;
+        }
+        return $formatNumber;
     }
 }
 

+ 1 - 1
app/Exports/GoodsNeateningExcelExport.php → app/Exports/InventoryBlindReceiveExcelExport.php

@@ -6,7 +6,7 @@ use App\User;
 use Illuminate\Support\Collection;
 use Maatwebsite\Excel\Concerns\FromCollection;
 
-class GoodsNeateningExcelExport implements FromCollection
+class InventoryBlindReceiveExcelExport implements FromCollection
 {
     private $data;
     public function __construct($data)

+ 30 - 15
app/Exports/RejectedExport.php

@@ -6,6 +6,7 @@ use App\RejectedBill;
 use App\RejectedBillItem;
 use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Database\Eloquent\Collection;
+use Illuminate\Support\Facades\Gate;
 use Maatwebsite\Excel\Concerns\FromCollection;
 use Maatwebsite\Excel\Concerns\ShouldAutoSize;
 use Maatwebsite\Excel\Concerns\WithColumnFormatting;
@@ -43,41 +44,55 @@ class RejectedExport extends \PhpOffice\PhpSpreadsheet\Cell\StringValueBinder im
                 $query->where('is_finished',false);
             }
         });
-        $rejectedItems->get();
+        $rejectedItems=$rejectedItems->get();
         $rejecteds = new Collection();
-        $this->prependFields($rejecteds);
-        $rejectedItems->each(function(RejectedBillItem $item)use($rejecteds){
-            $this->injectRecord($rejecteds,$item->rejectedBill,$item);
+        if($rejectedItems->isEmpty())return $rejecteds;
+        $id_owner = $rejectedItems->first()->rejectedBill['id_owner'];
+        $this->prependFields($rejecteds,$id_owner);
+        $rejectedItems->each(function(RejectedBillItem $item)use($rejecteds,$id_owner){
+            $this->injectRecord($rejecteds,$item->rejectedBill,$item,$id_owner);
         });
         return $rejecteds;
     }
     private function getByRejectedBills(){
         $rejecteds = new Collection();
-        $this->prependFields($rejecteds);
-        $this->rejectedBills->each(function(RejectedBill $rejectedBill)use($rejecteds){
-            $rejectedBill->items()->each(function (RejectedBillItem $item)use($rejecteds,$rejectedBill){
-                $this->injectRecord($rejecteds,$rejectedBill,$item);
+        $rejectedBills=$this->rejectedBills->get();
+        if($rejectedBills->isEmpty())return $rejecteds;
+        $id_owner = $rejectedBills->first()['id_owner'];
+        $this->prependFields($rejecteds,$id_owner);
+        $rejectedBills->each(function(RejectedBill $rejectedBill)use($rejecteds,$id_owner){
+            $rejectedBill->items()->each(function (RejectedBillItem $item)use($rejecteds,$rejectedBill,$id_owner){
+                $this->injectRecord($rejecteds,$rejectedBill,$item,$id_owner);
             });
         });
         return $rejecteds;
     }
-    private function prependFields($collection){
-        $collection->prepend(['日期','审核号','客户名称','订单号','姓名',
+    private function prependFields($collection,$id_owner){
+        $fieldNames=['日期','审核号','客户名称','订单号','姓名',
             '手机','原单单号','退回单号','退回公司','到付费用',
-            '是否入库','商品条码','商品名称','数量','是否正品',
+            '是否入库','商品条码','商品名称',];
+        if($id_owner==94){
+            $fieldNames=array_merge($fieldNames,['寄件方省','重量',]);
+        }
+        $fieldNames=array_merge($fieldNames,['数量','是否正品',
             '批次号','生产日期','效期','备注','退单备注','录入人']);
+        $collection->prepend($fieldNames);
         return $collection;
     }
-    private function injectRecord($collection,$bill,$item){
-        $collection->push([
-            $item['created_at'],
+    private function injectRecord($collection,$bill,$item,$id_owner){
+        $fieldValues=[$item['created_at'],
             $bill['checked_numbers'],$bill['owner_name'],
             $bill['order_number'],$bill['sender'],
             $bill['mobile_sender'],$bill['logistic_number'],
             $bill['logistic_number_return'],$bill['logistic_name'],
             $bill['fee_collected'],$bill['is_loaded_str'],
-            $item['barcode_goods'],$item['name_goods'],$item['amount'],$item['quality_label'],
+            $item['barcode_goods'],$item['name_goods'],];
+        if($id_owner==94){
+            $fieldValues=array_merge($fieldValues,[$bill['common_01'],$bill['common_02']]);
+        }
+        $fieldValues=array_merge($fieldValues,[$item['amount'],$item['quality_label'],
             $item['batch_number'],$item['made_at'],$item['validity_at'],$item['remark'],$bill['remark'],$bill['operator_name']]);
+        $collection->push($fieldValues);
         return $collection;
     }
 

+ 14 - 0
app/Feature.php

@@ -0,0 +1,14 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Feature extends Model
+{
+    protected $fillable = [
+        "type",     //类型
+        "logic",    //逻辑
+        "describe", //特征
+    ];
+}

+ 29 - 5
app/Http/Controllers/Auth/LoginController.php

@@ -11,6 +11,7 @@ use Illuminate\Http\Request;
 use Illuminate\Http\Response;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Hash;
+use Illuminate\Support\Facades\Validator;
 use Illuminate\Validation\ValidationException;
 
 class LoginController extends Controller
@@ -33,7 +34,7 @@ class LoginController extends Controller
      *
      * @var string
      */
-    protected $redirectTo = '/rejected';
+    protected $redirectTo = '/rejected/index/general';
 
     /**
      * Create a new controller instance.
@@ -53,27 +54,50 @@ class LoginController extends Controller
      * Handle a login request to the application.
      *
      * @param Request $request
-     * @return void
+     * @return array|Response|void
      *
      * @throws ValidationException
      */
     public function login(Request $request)
     {
+        $rule = [
+            $this->username() => 'required|string',
+            'password' => 'required|string',
+        ];
+        if($request['is_json']){
+            $errors=Validator::make($request->all(),$rule)->errors();
+            if($errors->count()>0){
+                return ['success'=>false,'errors'=>$errors];
+            }
+        }else{
+            $request->validate($rule);
+        }
 
         if (method_exists($this, 'hasTooManyLoginAttempts') &&
             $this->hasTooManyLoginAttempts($request)) {
             $this->fireLockoutEvent($request);
 
+            if($request['is_json']){
+                return ['success'=>false,'message'=>'登录请求过于频繁'];
+            }
             return $this->sendLockoutResponse($request);
         }
 
         if ($this->attemptLogin($request)) {
-            $this->log(__METHOD__,__FUNCTION__,'',Auth::user()['id']);
-            return $this->sendLoginResponse($request);
+            if(env('DB_USERNAME')!='developer')
+                app('LogService')->log(__METHOD__,__FUNCTION__,'',Auth::user()['id']);
+            if($request['is_json']){
+                return ['success'=>true,'url'=>url($this->redirectTo)];
+            }
+            return $this->sendLoginResponse($request)->header('Cache-Control','no-store');
         }
 
         $this->incrementLoginAttempts($request);
-        $this->log(__METHOD__,__FUNCTION__,'',Auth::user()['id']);
+        if(env('DB_USERNAME')!='developer')
+            app('LogService')->log(__METHOD__,__FUNCTION__,'',Auth::user()['id']);
+        if($request['is_json']){
+            return ['success'=>false,'errors'=>['name'=>['登录信息验证失败']]];
+        }
         return $this->sendFailedLoginResponse($request);
     }
 }

+ 1 - 1
app/Http/Controllers/Auth/PasswordController.php

@@ -54,7 +54,7 @@ class PasswordController extends Controller
                     $fail('旧密码输入不匹配');
                 }
             }],
-            'password' => 'required|confirmed|min:8',
+            'password' => 'required|confirmed|min:6',
         ];
     }
     /**

+ 3 - 3
app/Http/Controllers/Auth/RegisterController.php

@@ -55,7 +55,7 @@ class RegisterController extends Controller
         return Validator::make($data, [
             'name' => ['required', 'string', 'max:255', 'unique:users'],
             'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
-            'password' => ['required', 'string', 'min:8', 'confirmed'],
+            'password' => ['required', 'string', 'min:6', 'confirmed'],
         ]);
     }
 
@@ -90,13 +90,13 @@ class RegisterController extends Controller
         $carrierIds=$request->input('carrier')??'';
         if ($carrierIds){
             $carrierIds=explode(',',$carrierIds);
-            $user->carriers()->sync($carrierIds);
+            $user->logistics()->sync($carrierIds);
         }
         $userWorkgroupId=$request->input('userWorkgroupID');
         if ($userWorkgroupId){
             $user->userWorkgroups()->sync([$userWorkgroupId]);
         }
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),$user['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),$user['id']);
         if($headTo){return redirect(url($headTo))->with('successTip',"录入用户 {$user->name} 成功");}
         return $this->registered($request, $user)
             ?: redirect($this->redirectPath());

+ 4 - 5
app/Http/Controllers/AuthorityController.php

@@ -4,7 +4,6 @@ namespace App\Http\Controllers;
 
 use App\Authority;
 use App\Owner;
-use App\User;
 use Exception;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
@@ -69,7 +68,7 @@ class AuthorityController extends Controller
 //        $authority=new Authority($inputs);
 //        $authority->save();
 //
-//        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+//        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
 //        return redirect('maintenance/authority/create')->with('successTip',"成功录入权限“{$successName}”");
 //    }
 
@@ -82,7 +81,7 @@ class AuthorityController extends Controller
         $authority=new Authority(['alias_name'=>"(货主:{$owner['name']})",'name'=>"_{$owner['id']}",'remark'=>"(key: _{$owner['id']})"]);
         $authority->save();
 
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return redirect('maintenance/authority/create')->with('successTip',"成功录入权限: (货主:{$owner['name']})");
     }
 
@@ -142,7 +141,7 @@ class AuthorityController extends Controller
         $this->validatorUpdate($request->all())->validate();
         $authority->fill($request->all());
         $authority->update();
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return redirect('maintenance/authority/')->with('successTip',"成功修改权限“{$authority['name']}”!");
     }
 
@@ -156,7 +155,7 @@ class AuthorityController extends Controller
     public function destroy(Authority $authority)
     {
         if(!Gate::allows('权限-删除')){ return redirect(url('/'));  }
-        $this->log(__METHOD__,__FUNCTION__,$authority->toJson(),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,$authority->toJson(),Auth::user()['id']);
         $re=$authority->delete();
         return ['success'=>$re];
     }

+ 88 - 0
app/Http/Controllers/BatchController.php

@@ -0,0 +1,88 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Batch;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Gate;
+
+class BatchController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Http\Response|\Illuminate\View\View
+     */
+    public function index()
+    {
+        if(!Gate::allows('波次-查询')){ return redirect(url('/'));  }
+        $batches=Batch::orderBy('id','desc')->paginate(50);
+        return view('maintenance.batch.index',compact('batches'));
+    }
+
+    /**
+     * Show the form for creating a new resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function create()
+    {
+        //
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\Response
+     */
+    public function store(Request $request)
+    {
+        //
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  \App\Batch  $batch
+     * @return \Illuminate\Http\Response
+     */
+    public function show(Batch $batch)
+    {
+        //
+    }
+
+    /**
+     * Show the form for editing the specified resource.
+     *
+     * @param  \App\Batch  $batch
+     * @return \Illuminate\Http\Response
+     */
+    public function edit(Batch $batch)
+    {
+        //
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \App\Batch  $batch
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, Batch $batch)
+    {
+        //
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  \App\Batch  $batch
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(Batch $batch)
+    {
+        //
+    }
+}

+ 8 - 3
app/Http/Controllers/CarTypesController.php

@@ -32,7 +32,7 @@ class CarTypesController extends Controller
         $this->validatorCarType($request,$id)->validate();
         $carTypes=$request->input('CarType');
         if(CarType::create($carTypes)){
-            $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+            app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
             return redirect('maintenance/carType')->with('successTip','新车辆“'.$request->input('CarType.name').'”添加成功');
         };
     }
@@ -52,7 +52,7 @@ class CarTypesController extends Controller
         $carType=CarType::find($id);
         $carType->fill($data);
         if ($carType->save()){
-            $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+            app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
             return redirect('maintenance/carType')->with('successTip','车型“'.$request->input('CarType.name').'”修改成功');
         }
     }
@@ -61,11 +61,16 @@ class CarTypesController extends Controller
     {
         if(!Gate::allows('车型-删除')){ return redirect(url('/'));  }
         $carType=CarType::find($id);
-        $this->log(__METHOD__,__FUNCTION__,json_encode($carType),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($carType),Auth::user()['id']);
         $result=$carType->delete();
         return ['success'=>$result];
     }
 
+    public function get()
+    {
+        return CarType::query()->select("id","name","model")->get();
+    }
+
     protected  function validatorCarType(Request $request,$id){
         if ($id){$name=$id;}
         $validator=Validator::make($request->input(),[

+ 8 - 8
app/Http/Controllers/CarriersController.php

@@ -14,7 +14,7 @@ class CarriersController extends Controller
     public function index()
     {
         if(!Gate::allows('承运商-查询')){ return redirect(url('/'));  }
-            $carriers=Carrier::orderBy('id', 'DESC')->paginate(50);
+            $carriers=Carrier::query()->orderBy('id', 'DESC')->paginate(50);
             return view('maintenance.carrier.index',['carriers'=>$carriers]);
     }
 
@@ -31,8 +31,8 @@ class CarriersController extends Controller
         $id=false;
         $this->validatorCarrier($request,$id)->validate();
         $carriers=$request->input('Carrier');
-        if(Carrier::create($carriers)){
-            $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        if(Carrier::query()->create($carriers)){
+            app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
             return redirect('maintenance/carrier')->with('successTip','新承运商“'.$request->input('Carrier.name').'”添加成功');
         };
     }
@@ -40,7 +40,7 @@ class CarriersController extends Controller
     public function edit($id)
     {
         if(!Gate::allows('承运商-编辑')){ return redirect(url('/'));  }
-        $carrier=Carrier::find($id);
+        $carrier=Carrier::query()->find($id);
         return view('maintenance.carrier.edit',['carrier'=>$carrier]);
     }
 
@@ -49,10 +49,10 @@ class CarriersController extends Controller
         $this->validatorCarrier($request,$id)->validate();
         if(!Gate::allows('承运商-编辑')){ return redirect(url('/'));  }
         $data=$request->input('Carrier');
-        $carrier=Carrier::find($id);
+        $carrier=Carrier::query()->find($id);
         $carrier->fill($data);
         if ($carrier->save()){
-            $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+            app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
             return redirect('maintenance/carrier')->with('successTip','承运商“'.$request->input('Carrier.name').'”修改成功');
         }
     }
@@ -60,8 +60,8 @@ class CarriersController extends Controller
     public function destroy($id)
     {
         if(!Gate::allows('承运商-删除')){ return redirect(url('/'));  }
-        $carrier=Carrier::find($id);
-        $this->log(__METHOD__,__FUNCTION__,json_encode($carrier),Auth::user()['id']);
+        $carrier=Carrier::query()->find($id);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($carrier),Auth::user()['id']);
         $result=$carrier->delete();
         return ['success'=>$result];
     }

+ 7 - 3
app/Http/Controllers/CitiesController.php

@@ -33,7 +33,7 @@ class CitiesController extends Controller
         $this->validatorCities($request,$id)->validate();
         $cities=$request->input('City');
         if(City::create($cities)){
-            $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+            app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
             return redirect('maintenance/city')->with('successTip','新城市“'.$request->input('City.name').'”添加成功');
         };
     }
@@ -54,7 +54,7 @@ class CitiesController extends Controller
         $city=City::find($id);
         $city->fill($data);
         if ($city->save()){
-            $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+            app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
             return redirect('maintenance/city')->with('successTip','城市“'.$request->input('City.name').'”修改成功');
         }
     }
@@ -63,7 +63,7 @@ class CitiesController extends Controller
     {
         if(!Gate::allows('城市-删除')){ return redirect(url('/'));  }
         $city=City::find($id);
-        $this->log(__METHOD__,__FUNCTION__,json_encode($city),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($city),Auth::user()['id']);
         $result=$city->delete();
         return ['success'=>$result];
     }
@@ -80,4 +80,8 @@ class CitiesController extends Controller
         ]);
         return $validator;
     }
+
+    public function get(){
+        return City::query()->select("id","name","province_id")->get();
+    }
 }

+ 226 - 10
app/Http/Controllers/CommodityController.php

@@ -4,6 +4,10 @@ namespace App\Http\Controllers;
 
 use App\Commodity;
 use App\Imports\CommodityImport;
+use App\Services\CommodityBarcodeService;
+use App\Services\CommodityService;
+use App\Services\LogService;
+use App\Services\OracleBasSkuService;
 use Exception;
 use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Http\Request;
@@ -22,8 +26,8 @@ class CommodityController extends Controller
      */
     public function index()
     {
-        if(!Gate::allows('商品信息-查询')){ return redirect(url('/'));  }
-        $commodities=Commodity::orderBy('id','desc')->paginate(50);
+        if(!Gate::allows('商品信息-查询')){ return redirect(url('denied'));  }
+        $commodities=Commodity::query()->orderBy('id','desc')->paginate(50);
         return view('maintenance.commodity.index',['commodities'=>$commodities]);
     }
 
@@ -34,7 +38,7 @@ class CommodityController extends Controller
      */
     public function create()
     {
-        if(!Gate::allows('商品信息-录入')){ return redirect(url('/'));  }
+        if(!Gate::allows('商品信息-录入')){ return redirect(url('denied'));  }
         return view('maintenance.commodity.create');
     }
 
@@ -46,20 +50,20 @@ class CommodityController extends Controller
      */
     public function store(Request $request)
     {
-        if(!Gate::allows('商品信息-录入')){ return redirect(url('/'));  }
+        if(!Gate::allows('商品信息-录入')){ return redirect(url('denied'));  }
         $this->validatorCreate($request->all())->validate();
         $commodity=new Commodity($request->all());
         $commodity->save();
         $commodity->newBarcode($request->input('barcode'));
 
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return redirect('maintenance/commodity/create')->with('successTip',"成功录入商品信息:“{$request->input('name')}”");
     }
     protected function validatorCreate(array $data)
     {
         return Validator::make($data, [
             'name' => ['required', 'string', 'max:50'],
-            'barcode' => ['required', 'string', 'max:50', 'unique:commodities'],
+//            'barcode' => ['required', 'string', 'max:50', 'unique:commodities'],
         ]);
     }
     protected function validatorUpdate(array $data)
@@ -88,7 +92,7 @@ class CommodityController extends Controller
      */
     public function edit(Commodity $commodity)
     {
-        if(!Gate::allows('商品信息-编辑')){ return redirect(url('/'));  }
+        if(!Gate::allows('商品信息-编辑')){ return redirect(url('denied'));  }
         return view('maintenance.commodity.edit',['commodity'=>$commodity]);
     }
 
@@ -105,7 +109,7 @@ class CommodityController extends Controller
         $this->validatorUpdate($request->all())->validate();
         $commodity->fill($request->all());
         $commodity->update();
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return redirect('maintenance/commodity/')->with('successTip',"成功修改商品信息:“{$commodity['name']}”!");
     }
 
@@ -119,7 +123,7 @@ class CommodityController extends Controller
     public function destroy(Commodity $commodity)
     {
         if(!Gate::allows('商品信息-删除')){ return redirect(url('/'));  }
-        $this->log(__METHOD__,__FUNCTION__,$commodity->toJson(),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,$commodity->toJson(),Auth::user()['id']);
         $re=$commodity->delete();
         return ['success'=>$re];
     }
@@ -128,6 +132,13 @@ class CommodityController extends Controller
         return view('maintenance.commodity.import');
     }
 
+    public function isExist(Request $request)
+    {
+        if (app('CommodityService')->isExist($request->input()))
+            return ["success"=>true];
+        else return ["success"=>false];
+    }
+
     public function importExcel(Request $request)
     {
         $isOverride = $request->input('isOverride');
@@ -155,11 +166,216 @@ class CommodityController extends Controller
         $barcode=$request->input('barcode');
         $name = '';
         if($barcode){
-            $commodity=Commodity::whereHas('barcodes', function (Builder $query)use($barcode){
+            $commodity=Commodity::query()->whereHas('barcodes', function (Builder $query)use($barcode){
                 $query->where('code',$barcode);
             })->first();
             if($commodity&&$commodity['name']) $name=$commodity['name'];
         }
         return ['success'=>'true','name'=>$name];
     }
+
+    public function syncWMS(Request $request){
+        if(!Gate::allows('商品信息-编辑')){ return redirect(url('/'));  }
+        $owner_code = $request->owner_code ?? false;
+        $owner_id = $request->owner_id ?? false;
+        if (!$owner_code || !$owner_id)return ['success'=>false, 'data'=>"未指定货主"];
+        $this->syncOwnerCommodities($owner_id,$owner_code);
+        return ['success'=>true];
+    }
+
+    //通过货主与SKU同步 WMS商品至本地 有则比对修正,无则录入
+    public function syncOwnerCommodities($owner_id,$owner_code,$sku = null, $barcode = null){
+        ini_set('max_execution_time', '0');
+        $params = ['customerid' => $owner_code];
+        if ($sku) $params['sku'] = $sku;
+        if ($barcode) $params['alternate_sku1'] = $barcode;
+
+        /** @var OracleBasSkuService $oracleBasSkuService */
+        $oracleBasSkuService = app('OracleBasSkuService');
+        $amount = 1000;
+        $sum = $oracleBasSkuService->count($params);
+        $number = ceil($sum/$amount);
+        for ($i = 0;$i<$number; $i++){
+            $wmsCommodities = $oracleBasSkuService->getPiece($params,($i*$amount),$amount);
+            if (!$wmsCommodities)continue;
+            $this->execute($owner_id,$wmsCommodities);
+        }
+    }
+
+    private function execute($owner_id,array $wmsCommodities){
+        if (count($wmsCommodities) < 1)return;
+        $today = date('Y-m-d H:i:s');
+        $map = [];
+        $skus = [];
+        foreach ($wmsCommodities as $index => $wmsCommodity){
+            $map[$wmsCommodity->sku] = $index;
+            $skus[] = $wmsCommodity->sku;
+            $trimSku = rtrim($wmsCommodity->sku,"*");
+            if ($trimSku != $wmsCommodity->sku){
+                $skus[] = $trimSku;
+                $map[$trimSku] = $index;
+            }
+        }
+        /** @var CommodityService $commodityService */
+        $commodityService = app('CommodityService');
+        /** @var CommodityBarcodeService $commodityBarcodeService */
+        $commodityBarcodeService = app('CommodityBarcodeService');
+
+        $commodities = $commodityService->getOwnerCommodities(['owner_id' => $owner_id, 'sku'=>$skus]);
+        $updateCommodities = [];
+        $updateCommodities[] = [
+            'id', 'sku', 'name', 'length', 'width', 'height', 'volumn',"pack_spec"
+        ];
+        $barcodeMap = [];
+        $commoditiesId = [];
+        $barcodes = [];
+        foreach ($commodities as $commodity){
+            if (!isset($map[$commodity->sku]))continue;
+            $wms = $wmsCommodities[$map[$commodity->sku]];
+            $trimSku = rtrim($wms->sku,"*");
+            if (($commodity->sku != $trimSku) || ($commodity->length != $wms->skulength)
+                || ($commodity->width != $wms->skuwidth) || ($commodity->name != $wms->descr_c)
+                || ($commodity->height != $wms->skuhigh) || ($commodity->volumn != $wms->cube)
+                || ($commodity->pack_spec === null)){
+                $updateCommodities[] = [
+                    'id'=>$commodity->id,
+                    'sku'=>$trimSku,
+                    'name' => $wms->descr_c,
+                    'length' => $wms->skulength,
+                    'width' => $wms->skuwidth,
+                    'height' => $wms->skuhigh,
+                    'volumn' => $wms->cube,
+                    "pack_spec"  => $wms->packid == 'STANDARD' ? 0 : explode("/",$wms->packid)[1],
+                ];
+            }
+            if ($wms->alternate_sku1){
+                $wmsCode = rtrim($wms->alternate_sku1,"*");
+                $barcodeMap[$wmsCode] = $commodity->id;
+                $barcodes[] = $wmsCode;
+            }
+            if ($wms->alternate_sku2){
+                $wmsCode = rtrim($wms->alternate_sku2,"*");
+                $barcodeMap[$wmsCode] = $commodity->id;
+                $barcodes[] = $wmsCode;
+            }
+            $commoditiesId[] = $commodity->id;
+            unset($wmsCommodities[$map[$commodity->sku]]);
+            if (isset($map[$wms->sku]))unset($map[$commodity->sku]);
+            if (isset($map[$trimSku]))unset($map[$trimSku]);
+        }
+        unset($commodities,$skus);
+
+        if (count($updateCommodities) > 1){
+            $commodityService->batchUpdate($updateCommodities);
+            app('LogService')->log(__METHOD__,"同步商品-批量更新",json_encode($updateCommodities));
+            $commodityBarcodes = $commodityBarcodeService->get(['commodity_id'=>$commoditiesId, 'code'=>$barcodes]);
+
+            unset($commoditiesId,$barcodes);
+            foreach ($commodityBarcodes as $barcode){
+                if (($barcodeMap[$barcode->code]  ?? false) && $barcodeMap[$barcode->code] == $barcode->commodity_id){
+                    unset($barcodeMap[$barcode->code]);
+                }
+            }
+            if (count($barcodeMap) > 0){
+                $barcodeInsert = [];
+                foreach ($barcodeMap as $key => $value){
+                    $barcodeInsert[] = [
+                        'commodity_id'=>$value,
+                        'code' => $key,
+                        'created_at' => $today
+                    ];
+                }
+                $commodityBarcodeService->insert($barcodeInsert);
+                app('LogService')->log(__METHOD__,"同步商品-录入条码",json_encode($barcodeInsert));
+            }
+        }
+
+        $createCommodities = [];
+        $barcodeMap = [];
+        $skus = [];
+        $barcodes = [];
+        $barcodeIndex = [];
+
+        foreach ($map as $sku => $index){
+            if (substr($sku,-1) == "*")continue;
+            $wms = $wmsCommodities[$index];
+            $createCommodities[] = [
+                'owner_id' => $owner_id,
+                'sku' => $wms->sku,
+                'name' => $wms->descr_c,
+                'length' => $wms->skulength,
+                'width' => $wms->skuwidth,
+                'height' => $wms->skuhigh,
+                'volumn' => $wms->cube,
+                "pack_spec"  => $wms->packid == 'STANDARD' ? 0 : explode("/",$wms->packid)[1],
+                "created_at" => $today,
+            ];
+            $barcodeMap[$wms->sku] = [];
+            if ($wms->alternate_sku1){
+                $code = rtrim($wms->alternate_sku1,"*");
+                $barcodeMap[$wms->sku][] = $code;
+                $barcodes[] = $code;
+                $barcodeIndex[$code] = count($createCommodities) - 1;
+            }
+            if ($wms->alternate_sku2){
+                $code = rtrim($wms->alternate_sku2,"*");
+                $barcodeMap[$wms->sku][] = $code;
+                $barcodes[] = $code;
+                $barcodeIndex[$code] = count($createCommodities) - 1;
+            }
+            $skus[] = $wms->sku;
+            unset($wmsCommodities[$index]);
+        }
+
+        if (count($barcodes) > 0){
+            // TODO ownerBarcodeSeekCommodityGet可指定第三个参数为true 默认无差别覆盖 如若指定该布尔值true代表仅覆盖SKU空值项
+            $commodities = $commodityService->ownerBarcodeSeekCommodityGet(['id'=>$owner_id], $barcodes);
+            $updateCommodities = [];
+            $updateCommodities[] = [
+                'id', 'sku', 'name', 'length', 'width', 'height', 'volumn',
+            ];
+            foreach ($commodities as $commodity){
+                foreach ($commodity->barcodes as $code){
+                    if (isset($barcodeIndex[$code->code])){
+                        $goods = $createCommodities[$barcodeIndex[$code->code]] ?? false;
+                        if (!$goods)continue;
+                        $updateCommodities[] = [
+                            "id" => $commodity->id,
+                            'sku'=>$goods['sku'],
+                            'name' => $goods['name'],
+                            'length' => $goods['length'],
+                            'width' => $goods['width'],
+                            'height' => $goods['height'],
+                            'volumn' => $goods['volumn'],
+                            "pack_spec" => $goods["pack_spec"],
+                        ];
+                        unset($createCommodities[$barcodeIndex[$code->code]]);
+                        break;
+                    }
+                }
+            }
+            if (count($updateCommodities) > 0){
+                $commodityService->batchUpdate($updateCommodities);
+                app('LogService')->log(__METHOD__,"同步商品-批量更新",json_encode($updateCommodities));
+            }
+        }
+
+        if (count($createCommodities) > 0){
+            $commodityService->insert($createCommodities);
+            app('LogService')->log(__METHOD__,"同步商品-录入商品",json_encode($createCommodities));
+            $commodities = $commodityService->get(['owner_id'=>$owner_id , 'sku'=>$skus]);
+            $barcodeInsert = [];
+            foreach ($commodities as $commodity){
+                foreach ($barcodeMap[$commodity->sku] as $code){
+                    $barcodeInsert[] = [
+                        'commodity_id'=>$commodity->id,
+                        'code' => $code,
+                        'created_at' => $today
+                    ];
+                }
+            }
+            $commodityBarcodeService->insert($barcodeInsert);
+            app('LogService')->log(__METHOD__,"同步商品-录入条码",json_encode($barcodeInsert));
+        }
+    }
 }

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

@@ -0,0 +1,90 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Services\CheckActiveMenuService;
+use App\Services\LaborReportsCountingRecordService;
+use App\Services\OrderCountingRecordService;
+use App\Services\RealtimePendingOrdersService;
+use Carbon\Carbon;
+use DebugBar\DataFormatter\DataFormatter;
+use Illuminate\Http\Request;
+
+class ControlPanelController extends Controller
+{
+
+
+    /**
+     * ControlPanelController constructor.
+     */
+    public function __construct()
+    {
+        $this->middleware('auth');
+    }
+
+    public function index()
+    {
+        $checkActiveMenuService = app(CheckActiveMenuService::class);
+        $menus = $checkActiveMenuService->activeMenus();
+        $realtimePendingOrdersService = app(RealtimePendingOrdersService::class);
+        $warehousesOrders = $realtimePendingOrdersService->warehousesOrders();
+        $orderCountingRecordService = app(OrderCountingRecordService::class);
+        //默认查询一个月的数据
+        $start = (new Carbon())->subMonth()->addDay()->toDateString();
+        $end = (new Carbon())->toDateString();
+        $orderCountingRecords = $orderCountingRecordService->orderCountingRecords($start, $end);
+        $logisticsCountingRecords = $orderCountingRecordService->logisticsCountingRecords($start, $end);
+        $warehouseCountingRecords = $orderCountingRecordService->warehouseCountingRecords($start, $end);
+
+        $laborReportsCountingRecordService = app(LaborReportsCountingRecordService::class);
+        $laborReportsCountingRecords = $laborReportsCountingRecordService->get($start, $end, '日');
+        $laborReportsUserGroupsCount = $laborReportsCountingRecordService->userGroupsCount($start, $end);
+        return view('control.panel', compact('menus', 'warehousesOrders', 'orderCountingRecords', 'logisticsCountingRecords', 'warehouseCountingRecords', 'laborReportsCountingRecords', 'laborReportsUserGroupsCount'));
+    }
+
+    public function orderCountingRecordsApi(Request $request)
+    {
+        $orderCountingRecordService = app(OrderCountingRecordService::class);
+        $start = Carbon::parse($request->start)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->start;
+        $end = Carbon::parse($request->end)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->end;
+        $orderCountingRecords = $orderCountingRecordService->orderCountingRecords($start, $end, null, $request->unit, null);
+        return compact('orderCountingRecords');
+    }
+
+    public function logisticsCountingRecordsApi(Request $request)
+    {
+        $orderCountingRecordService = app(OrderCountingRecordService::class);
+        $start = Carbon::parse($request->start)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->start;
+        $end = Carbon::parse($request->end)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->end;
+        $logisticsCountingRecords = $orderCountingRecordService->logisticsCountingRecords($start, $end);
+        return compact('logisticsCountingRecords');
+    }
+
+    public function warehouseCountingRecordsApi(Request $request)
+    {
+        $orderCountingRecordService = app(OrderCountingRecordService::class);
+        $start = Carbon::parse($request->start)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->start;
+        $end = Carbon::parse($request->end)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->end;
+        $warehouseCountingRecords = $orderCountingRecordService->warehouseCountingRecords($start, $end);
+        return compact('warehouseCountingRecords');
+    }
+
+    public function laborReportsCountingRecordApi(Request $request)
+    {
+        $laborReportsCountingRecordService = app(LaborReportsCountingRecordService::class);
+        $start = Carbon::parse($request->start)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->start;
+        $end = Carbon::parse($request->end)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->end;
+        $unit = $request->unit;
+        $laborReportsCountingRecords = $laborReportsCountingRecordService->get($start, $end, $unit);
+        return compact('laborReportsCountingRecords');
+    }
+
+    public function laborReportsUserGroupsCountApi(Request $request)
+    {
+        $laborReportsCountingRecordService = app(LaborReportsCountingRecordService::class);
+        $start = Carbon::parse($request->start)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->start;
+        $end = Carbon::parse($request->end)->gt(Carbon::now()) ? Carbon::now()->toDateString() : $request->end;
+        $laborReportsUserGroupsCount = $laborReportsCountingRecordService->userGroupsCount($start, $end);
+        return compact('laborReportsUserGroupsCount');
+    }
+}

+ 4 - 16
app/Http/Controllers/Controller.php

@@ -3,6 +3,7 @@
 namespace App\Http\Controllers;
 
 use App\Log;
+use App\Services\LogService;
 use App\User;
 use Illuminate\Foundation\Bus\DispatchesJobs;
 use Illuminate\Routing\Controller as BaseController;
@@ -17,26 +18,13 @@ class Controller extends BaseController
 {
     use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
     static public function logS($method,$type,$description,$id_user=null){
-        (new Log([
-            'operation'=>$method,
-            'type'=>$type,
-            'description'=>$description,
-            'id_user'=>$id_user,
-            'ip'=>Request::ip()
-        ]))->save();
+        app('LogService')->log($method,$type,$description,$id_user=null);
     }
     public function log($method,$type,$description,$id_user=null){
-        (new Log([
-            'operation'=>$method,
-            'type'=>$type,
-            'description'=>$description,
-            'id_user'=>$id_user,
-            'ip'=>Request::ip()
-        ]))->save();
+        app('LogService')->log($method,$type,$description,$id_user);
     }
     public function apiError($method,$description){
-        $this->log($method,'apiError',$description);
+        app('LogService')->log($method,'apiError',$description);
         return ['success'=>'false','fail_info'=>$description];
     }
-
 }

+ 90 - 0
app/Http/Controllers/CustomFieldController.php

@@ -0,0 +1,90 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\CustomField;
+use Illuminate\Http\Request;
+
+class CustomFieldController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function index()
+    {
+        //
+    }
+    public function indexAtRejectedBill()
+    {
+        $customFields=CustomField::where('table','rejected_bills')->get();
+        return view('rejected.customField.index',compact('customFields'));
+    }
+
+    /**
+     * Show the form for creating a new resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function create()
+    {
+        //
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\Response
+     */
+    public function store(Request $request)
+    {
+        //
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  \App\CustomField  $customField
+     * @return \Illuminate\Http\Response
+     */
+    public function show(CustomField $customField)
+    {
+        //
+    }
+
+    /**
+     * Show the form for editing the specified resource.
+     *
+     * @param  \App\CustomField  $customField
+     * @return \Illuminate\Http\Response
+     */
+    public function edit(CustomField $customField)
+    {
+        //
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \App\CustomField  $customField
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, CustomField $customField)
+    {
+        //
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  \App\CustomField  $customField
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(CustomField $customField)
+    {
+        //
+    }
+}

+ 122 - 0
app/Http/Controllers/CustomerBaseController.php

@@ -0,0 +1,122 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Services\LogService;
+use Illuminate\Http\Request;
+use Illuminate\Http\Response;
+use Illuminate\Support\Facades\Gate;
+use Illuminate\Support\Facades\Validator;
+
+class CustomerBaseController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return Response
+     */
+    public function index()
+    {
+        if(!Gate::allows('客户-查询')){ return redirect('denied');  }
+        $customers = app('CustomerService')->paginate();
+        return response()->view('maintenance.customer.index',compact("customers"));
+    }
+
+    /**
+     * Show the form for creating a new resource.
+     *
+     * @return Response
+     */
+    public function create()
+    {
+        if(!Gate::allows('客户-录入')){ return redirect('denied');  }
+        return response()->view('maintenance.customer.create');
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  Request  $request
+     * @return Response
+     */
+    public function store(Request $request)
+    {
+        if(!Gate::allows('客户-录入')){ return redirect('denied');  }
+        $this->validator($request->input())->validate();
+        app('CustomerService')->create([
+            "code"=>$request->input("code"),
+            "name"=>$request->input("name"),
+            "company_name"=>$request->input("company_name"),
+        ]);
+        LogService::log(__METHOD__,"录入客户",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
+        return response()->redirectTo("maintenance/customer")->with("successTip","成功创建客户“".$request->input("name")."”");
+    }
+
+    /**
+     * Show the form for editing the specified resource.
+     *
+     * @param  int  $id
+     * @return Response
+     */
+    public function edit($id)
+    {
+        if(!Gate::allows('客户-编辑')){ return redirect('denied');  }
+        $customer = app('CustomerService')->find($id);
+        return response()->view('maintenance.customer.create',compact("customer"));
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  Request  $request
+     * @param  int  $id
+     * @return Response
+     */
+    public function update(Request $request, $id)
+    {
+        if(!Gate::allows('客户-编辑')){ return redirect('denied');  }
+        $this->validator($request->input(),$id)->validate();
+        $result = app('CustomerService')->update(["id"=>$id],[
+            "code"=>$request->input("code"),
+            "name"=>$request->input("name"),
+            "company_name"=>$request->input("company_name"),
+        ]);
+        if ($result == 1){
+            LogService::log(__METHOD__,"修改客户",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
+            return response()->redirectTo("maintenance/customer")->with("successTip","成功修改客户“".$request->input("name")."”的信息");
+        }
+        return response()->view("exception.default",["code"=>"509"]);
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  int  $id
+     * @return array
+     */
+    public function destroy($id)
+    {
+        if(!Gate::allows('客户-删除')){ return ["success"=>false,"data"=>"无权操作!"];  }
+        $result = app('CustomerService')->destroy($id);
+        if ($result == 1){
+            LogService::log(__METHOD__,"删除客户",$id);
+            return ["success"=>true];
+        }
+        return ["success"=>false,"data"=>"删除了“".$result."”行"];
+    }
+
+    private function validator(array $params, $id = null)
+    {
+        return Validator::make($params,[
+            'code'=>['required',$id?"unique:customers,code,$id":'unique:customers,code','max:20'],
+            'name'=>['required','max:20'],
+        ],[
+            'required'=>':attribute 为必填项',
+            'max'=>':attribute 字符过多或输入值过大',
+            'unique'=>':attribute 已存在',
+        ],[
+            'code'=>'客户代码',
+            'name'=>'客户名称',
+        ]);
+    }
+}

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

@@ -0,0 +1,435 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Owner;
+use App\Services\LogService;
+use App\Services\OwnerAreaReportService;
+use App\Services\OwnerBillReportService;
+use App\Services\OwnerReportService;
+use App\Services\OwnerService;
+use Exception;
+use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Http\Request;
+use Illuminate\Http\Response;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Gate;
+use Illuminate\Support\Facades\Http;
+use Illuminate\Support\Facades\Validator;
+
+class CustomerController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     * @param Request $request
+     * @return Response
+     */
+    public function projectReport(Request $request)
+    {
+        if(!Gate::allows('客户管理-项目-报表')){ return view('customer.index');  }
+        $withs = ["ownerBillReport","owner"=>function($query){
+            /** @var Builder $query */
+            $query->select("id","name","deleted_at","created_at","customer_id","user_owner_group_id")
+                ->with(["customer","userOwnerGroup"]);
+        }];
+        $ownerGroups = app('UserOwnerGroupService')->getSelection();
+        $customers = app('CustomerService')->getSelection();
+        $owners = app('OwnerService')->getSelection();
+        $reports = app("OwnerReportService")->paginate($request->input(),$withs);
+        $params = $request->input();
+        return response()->view('customer.project.report',compact("reports","ownerGroups","customers","owners","params"));
+    }
+
+    public function projectReportExport(Request $request)
+    {
+        if(!Gate::allows('客户管理-项目-报表')){ return redirect('denied');  }
+        /** @var OwnerReportService $service */
+        $service = app('OwnerReportService');
+        $withs = ["ownerBillReport","owner"=>function($query){
+            /** @var Builder $query */
+            $query->select("id","name","deleted_at","created_at","customer_id","user_owner_group_id")
+                ->with(["customer","userOwnerGroup"]);
+        }];
+        if ($request->checkAllSign ?? false){
+            $params = $request->input();
+            unset($params['checkAllSign']);
+            $reports = $service->get($params,$withs);
+        }else $reports = $service->get(["id"=>$request->data ?? ''],$withs);
+        $column = ["项目小组","客户","子项目","状态","创建日期","在库时长","结算月","日均单量","结算月上月盘点面积","结算月盘点面积","初始账单金额","确认账单金额","确认日期"];
+        $list = [];
+        foreach ($reports as $report){
+            $list[] = [
+                $report->owner ? ($report->owner->userOwnerGroup ? $report->owner->userOwnerGroup->name : '') : '',
+                $report->owner ? ($report->owner->customer ? $report->owner->customer->name : '') : '',
+                $report->owner ? $report->owner->name : '',
+                $report->owner ? ($report->owner->deleted_at ? "冻结" : "激活") : '',
+                $report->owner ? (string)$report->owner->created_at : '',
+                $report->owner ? ($report->owner->created_at ? ((new \DateTime())->diff(new \DateTime($report->owner->created_at))->days)." 天"  : '') : '',
+                $report->counting_month,
+                $report->daily_average_order_amount,
+                $report->last_month_counting_area,
+                $report->current_month_counting_area,
+                $report->ownerBillReport ? $report->ownerBillReport->initial_fee : '',
+                $report->ownerBillReport ? $report->ownerBillReport->confirm_fee : '',
+                $report->ownerBillReport ? (string)$report->ownerBillReport->updated_at : '',
+            ];
+        }
+        $post = Http::post(config('go.export.url'),['type'=>'base','data'=>json_encode(["row"=>$column,"list"=>$list],JSON_UNESCAPED_UNICODE)]);
+        if ($post->status() == 500){
+            throw new Exception($post->header("Msg"));
+        }
+        return response($post,200, [
+            "Content-type"=>"application/octet-stream",
+            "Content-Disposition"=>"attachment; filename=客户项目报表-".date('ymdHis').'.xlsx',
+        ]);
+    }
+
+    public function projectIndex()
+    {
+        if(!Gate::allows('客户管理-项目-查询')){ return redirect('denied');  }
+        /** @var OwnerService $service */
+        $service = app('OwnerService');
+        $owners = $service->paginate(['customer_id'=>true],['customer',"userOwnerGroup","ownerStoragePriceModels","ownerAreaReport"=>function($query){
+            $month = date('Y-m');
+            /** @var Builder $query */
+            $query->where("counting_month","like",$month."%");
+        }]);
+        return response()->view('customer.project.index',compact("owners"));
+    }
+
+    public function projectIndexExport(Request $request)
+    {
+        if(!Gate::allows('客户管理-项目-查询')){ return redirect('denied');  }
+        /** @var OwnerService $service */
+        $service = app('OwnerService');
+        $withs = ['customer',"userOwnerGroup","ownerStoragePriceModels","ownerAreaReport"=>function($query){
+            $month = date('Y-m');
+            /** @var Builder $query */
+            $query->where("counting_month","like",$month."%");
+        }];
+        $params = $request->input();
+        $params['customer_id']=true;
+        if ($request->checkAllSign ?? false) unset($params['checkAllSign']);
+        else $params = ["id"=>$request->data ?? ''];
+        $owners = $service->get($params,$withs);
+        $column = ["客户","税率","项目","货主代码","合同号","创建日期","销售名称","公司全称","联系人","联系电话","项目小组","用仓类型","当月结算面积","月单量预警","是否激活","项目描述"];
+        $list = [];
+        foreach ($owners as $owner){
+            $list[] = [
+                $owner->customer ? $owner->customer->name : '',
+                $owner->tax_rate,
+                $owner->name,
+                $owner->code,
+                $owner->contract_number,
+                $owner->created_at,
+                $owner->salesman,
+                $owner->customer ? $owner->customer->company_name : '',
+                $owner->linkman,
+                $owner->phone_number,
+                $owner->userOwnerGroup ? $owner->userOwnerGroup->name : '',
+                implode(",",array_unique(array_column(($owner->ownerStoragePriceModels)->toArray(),"using_type"))),
+                $owner->ownerAreaReport ? $owner->ownerAreaReport->accounting_area : '',
+                $owner->waring_line_on,
+                $owner->deleted_at ? '否' : '是',
+                $owner->description
+            ];
+        }
+        $post = Http::post(config('go.export.url'),['type'=>'base','data'=>json_encode(["row"=>$column,"list"=>$list],JSON_UNESCAPED_UNICODE)]);
+        if ($post->status() == 500){
+            throw new Exception($post->header("Msg"));
+        }
+        return response($post,200, [
+            "Content-type"=>"application/octet-stream",
+            "Content-Disposition"=>"attachment; filename=客户报表-".date('ymdHis').'.xlsx',
+        ]);
+    }
+
+    public function projectCreate()
+    {
+        if(!Gate::allows('客户管理-项目-录入')){ return redirect('denied');  }
+        $customers = app('CustomerService')->getSelection();
+        $ownerGroups = app('UserOwnerGroupService')->getSelection();
+        $storagePriceModels = app('OwnerStoragePriceModelService')->getSelection(["id","counting_type","using_type","minimum_area","price","unit_id"],["unit"=>function($query){$query->select("id","name");}]);
+        $owner = null;
+        return response()->view('customer.project.create',compact("customers","ownerGroups","storagePriceModels","owner"));
+    }
+
+    public function seekOwner(Request $request)
+    {
+        $params = $request->input();
+        $params["customer_id"] = true;
+        $owner = app('OwnerService')->first($params,["customer_id"=>"null"]);
+        if ($owner)return ["success"=>true,"data"=>$owner];
+        else return ["success"=>false];
+    }
+
+    public function projectStore(Request $request)
+    {
+        if(!Gate::allows('客户管理-项目-录入')){ return redirect('denied');  }
+        $this->validator($request->input())->validate();
+        $params = $request->input();
+        if ($params["id"]){
+            /** @var Owner $owner */
+            $owner = app('OwnerService')->find($params["id"]);
+            app('OwnerService')->update($owner,[
+                "customer_id"           => $params["customer_id"],
+                "tax_rate"              => $params["tax_rate"],
+                "contract_number"       => $params["contract_number"],
+                "salesman"              => $params["salesman"],
+                "linkman"               => $params["linkman"],
+                "phone_number"          => $params["phone_number"],
+                "user_owner_group_id"   => $params["owner_group_id"],
+                "waring_line_on"        => $params["waring_line_on"],
+                "description"           => $params["description"],
+            ],[
+                "ownerStoragePriceModels" => explode(',',$params["owner_storage_price_model_id"])
+            ]);
+            $msg = "成功更新“".$owner->name."”的信息!";
+            LogService::log(__METHOD__,"客户管理-修改货主",json_encode($params,JSON_UNESCAPED_UNICODE));
+        }else{
+            $owner = app('OwnerService')->create([
+                "name"                  => $params["name"],
+                "code"                  => $params["code"],
+                "customer_id"           => $params["customer_id"],
+                "tax_rate"              => $params["tax_rate"],
+                "contract_number"       => $params["contract_number"],
+                "salesman"              => $params["salesman"],
+                "linkman"               => $params["linkman"],
+                "phone_number"          => $params["phone_number"],
+                "user_owner_group_id"   => $params["owner_group_id"],
+                "waring_line_on"        => $params["waring_line_on"],
+                "description"           => $params["description"],
+            ],[
+                "ownerStoragePriceModels" => explode(',',$params["owner_storage_price_model_id"])
+            ]);
+            $msg = "成功创建“".$owner->name."”项目!";
+            LogService::log(__METHOD__,"客户管理-增加货主",json_encode($params,JSON_UNESCAPED_UNICODE));
+        }
+        return response()->redirectTo('customer/project/index')->with('successTip',$msg);
+    }
+
+    //获取货主下所有相关计费模型
+    public function getOwnerPriceModel(Request $request)
+    {
+        $owner = new Owner();
+        $owner->id = $request->id;
+        $owner->load(["ownerPriceOperations","ownerPriceExpresses","ownerPriceLogistics","ownerPriceDirectLogistics"]);
+        return ["success"=>true,"data"=>["ownerPriceOperations"=>$owner->ownerPriceOperations,
+            "ownerPriceExpresses"=>$owner->ownerPriceExpresses,
+            "ownerPriceLogistics"=>$owner->ownerPriceLogistics,
+            "ownerPriceDirectLogistics"=>$owner->ownerPriceDirectLogistics]];
+    }
+
+    public function projectEdit($id)
+    {
+        if(!Gate::allows('客户管理-项目-编辑')){ return redirect('denied');  }
+        /** @var Owner $owner */
+        $owner = app('OwnerService')->find($id);
+        $owner->owner_storage_price_model_id = $owner->getOwnerStoragePriceModelIds();
+        $customers = app('CustomerService')->getSelection();
+        $ownerGroups = app('UserOwnerGroupService')->getSelection();
+        $storagePriceModels = app('OwnerStoragePriceModelService')->getSelection(["id","counting_type","using_type","minimum_area","price","unit_id"],["unit"=>function($query){$query->select("id","name");}]);
+        return response()->view('customer.project.create',compact("customers","ownerGroups","storagePriceModels",'owner'));
+    }
+
+    public function projectArea(Request $request)
+    {
+        if(!Gate::allows('客户管理-项目-面积')){ return redirect('denied');  }
+        $areas = app('OwnerAreaReportService')->paginate($request->input(),["owner"=>function($query){$query->with(["customer","ownerStoragePriceModels"]);}]);
+        $ownerGroups = app('UserOwnerGroupService')->getSelection();
+        $customers = app('CustomerService')->getSelection();
+        $owners = app('OwnerService')->getSelection();
+        $params = $request->input();
+        return response()->view('customer.project.area',compact("areas","ownerGroups","customers","owners","params"));
+    }
+
+    public function updateArea(Request $request)
+    {
+        if(!Gate::allows('客户管理-项目-面积-编辑')){ return ["success"=>false,'data'=>"无权操作!"];  }
+        if (!($request->id ?? false) || !($request->area ?? false)) return ["success"=>false,'data'=>"传递错误!"];
+        $values = $request->area ?? null;
+        if (!$values)return ["success"=>true,"data"=>$values];
+        foreach ($values as $column=>$value){
+            if ($value && (!is_numeric($value) || $value<0))return ["success"=>false,'data'=>$column."非数字或小于0!"];
+        }
+        $accounting_area = ((int)$values["area_on_tray"]*205) + ((int)$values["area_on_half_tray"]*1.8) + ((int)$values["area_on_flat"]*1.3);
+        $values["accounting_area"] = $accounting_area;
+        $row = app('OwnerAreaReportService')->update(["id"=>$request->id],$values);
+        if ($row==1){
+            LogService::log(__METHOD__,"客户管理-修改面积",json_encode($request->input()));
+            return ["success"=>true,"data"=>$values];
+        }
+        return ["success"=>false,"data"=>"影响了".$row."条数据!"];
+    }
+
+    public function projectAreaExport(Request $request)
+    {
+        if(!Gate::allows('客户管理-项目-面积')){ return redirect('denied');  }
+        $params = $request->input();
+        if ($request->checkAllSign)unset($params['checkAllSign']);
+        else $params = ["id"=>$request->data];
+        /** @var OwnerAreaReportService $serves */
+        $serves = app('OwnerAreaReportService');
+        $areas = $serves->get($params,["owner"=>function($query){$query->with(["customer","ownerStoragePriceModels","userOwnerGroup"]);}]);
+
+        $column = ["状态","项目组","客户","子项目","结算月","录入时间","用仓类型","货物整托","货物半托","平面区面积","结算面积"];
+        $list = [];
+        foreach ($areas as $area){
+            $list[] = [
+                $area->status,
+                $area->owner ? ($area->owner->userOwnerGroup ? $area->owner->userOwnerGroup->name : '') : '',
+                $area->owner ? ($area->owner->customer ? $area->owner->customer->name : '') : '',
+                $area->owner ? $area->owner->name : '',
+                $area->counting_month,
+                $area->updated_at,
+                $area->owner ? implode(",",array_unique(array_column(($area->owner->ownerStoragePriceModels)->toArray(),"using_type"))) : '',
+                $area->area_on_tray,
+                $area->area_on_half_tray,
+                $area->area_on_flat,
+                $area->accounting_area,
+            ];
+        }
+
+        $post = Http::post(config('go.export.url'),['type'=>'base','data'=>json_encode(["row"=>$column,"list"=>$list],JSON_UNESCAPED_UNICODE)]);
+        if ($post->status() == 500){
+            throw new Exception($post->header("Msg"));
+        }
+        return response($post,200, [
+            "Content-type"=>"application/octet-stream",
+            "Content-Disposition"=>"attachment; filename=项目面积报表-".date('ymdHis').'.xlsx',
+        ]);
+    }
+
+    public function financeInstantBill(Request $request)
+    {
+        if(!Gate::allows('客户管理-财务-即时账单')){ return redirect('denied');  }
+        $params = $request->input();
+        $shops = app('ShopService')->getSelection();
+        $customers = app('CustomerService')->getSelection();
+        $owners = app('OwnerService')->getSelection();
+        $details = app('OwnerFeeDetailService')->paginate($params,["owner"=>function($query){$query->with("customer");},"shop","processMethod","logistic"]);
+        return response()->view('customer.finance.instantBill',compact("details","params","shops","customers","owners"));
+    }
+
+    public function financeInstantBillExport(Request $request)
+    {
+        if(!Gate::allows('客户管理-财务-即时账单')){ return redirect('denied');  }
+        $params = $request->input();
+        if ($request->checkAllSign)unset($params['checkAllSign']);
+        else $params = ["id"=>$request->data];
+        $sql = app('OwnerFeeDetailService')->getSql($params);
+
+        $row = ["客户", "项目", "作业时间", "类型","店铺", "单号(发/收/退/提)", "收件人", "收件人电话", "商品数量",
+            "物流/快递单号", "体积", "重量", "承运商", "操作费", "物流费", "合计"];
+        $column = ["customer_name", "owner_name", "worked_at", "type","shop_name", "operation_bill", "consignee_name", "consignee_phone", "commodity_amount",
+            "logistic_bill", "volume", "weight", "logistic_name", "work_fee", "logistic_fee", "total"];
+        $rule = ["work_fee"=>"mysqlDate"];
+
+        $post = Http::post(config('go.export.url'),['type'=>'unify','sql'=>$sql, 'connection'=>'mysql',
+            'row'=>json_encode($row,JSON_UNESCAPED_UNICODE), 'column'=>json_encode($column), 'rule'=>json_encode($rule)]);
+        if ($post->status() == 500){
+            throw new Exception($post->header("Msg"));
+        }
+        return response($post,200, [
+            "Content-type"=>"application/octet-stream",
+            "Content-Disposition"=>"attachment; filename=即时账单记录-".date('ymdHis').'.xlsx',
+        ]);
+    }
+
+    public function financeBillConfirmation(Request $request)
+    {
+        if(!Gate::allows('客户管理-财务-账单确认')){ return redirect('denied');  }
+        $params = $request->input();
+        $ownerGroups = app('UserOwnerGroupService')->getSelection();
+        $customers = app('CustomerService')->getSelection();
+        $owners = app('OwnerService')->getSelection();
+        $bills = app('OwnerBillReportService')->paginate($params,["owner"=>function($query){
+            /** @var Builder $query */
+            $query->with(["customer","userOwnerGroup"]);
+        }]);
+        return response()->view('customer.finance.billConfirmation',compact("params","owners","ownerGroups","customers","bills"));
+    }
+
+    public function financeBillConfirmationExport(Request $request)
+    {
+        if(!Gate::allows('客户管理-财务-账单确认')){ return redirect('denied');  }
+        $params = $request->input();
+        if ($request->checkAllSign)unset($params['checkAllSign']);
+        else $params = ["id"=>$request->data];
+        /** @var OwnerBillReportService $serves */
+        $serves = app('OwnerBillReportService');
+        $bills = $serves->get($params,["owner"=>function($query){
+            /** @var Builder $query */
+            $query->with(["customer","userOwnerGroup"]);
+        }]);
+
+        $column = ["项目小组","客户","子项目","结算月","录入日期","原始账单金额","确认账单金额","差额","状态"];
+        $list = [];
+        foreach ($bills as $bill){
+            $list[] = [
+                $bill->owner ? ($bill->owner->userOwnerGroup ? $bill->owner->userOwnerGroup->name : '') : '',
+                $bill->owner ? ($bill->owner->customer ? $bill->owner->customer->name : '') : '',
+                $bill->owner ? $bill->owner->name : '',
+                $bill->counting_month,
+                $bill->updated_at,
+                $bill->initial_fee,
+                $bill->confirm_fee,
+                $bill->difference,
+                $bill->confirmed == '是' ? '已确认' : '未确认',
+            ];
+        }
+
+        $post = Http::post(config('go.export.url'),['type'=>'base','data'=>json_encode(["row"=>$column,"list"=>$list],JSON_UNESCAPED_UNICODE)]);
+        if ($post->status() == 500){
+            throw new Exception($post->header("Msg"));
+        }
+        return response($post,200, [
+            "Content-type"=>"application/octet-stream",
+            "Content-Disposition"=>"attachment; filename=客户账单报表-".date('ymdHis').'.xlsx',
+        ]);
+    }
+
+    public function updateBillReport(Request $request)
+    {
+        if(!Gate::allows('客户管理-财务-账单确认-编辑')){ return ["success"=>false,'data'=>"无权操作!"];  }
+        if (!$request->confirm_fee || !is_numeric($request->confirm_fee) || $request->confirm_fee<0)return ["success"=>false,"data"=>"非法金额参数"];
+        $date = date('Y-m-d H:i:s');
+        app('OwnerBillReportService')->update(["id"=>$request->id],["confirm_fee"=>$request->confirm_fee,"difference"=>DB::raw($request->confirm_fee.'- initial_fee'),"updated_at"=>$date]);
+        LogService::log(__METHOD__,"客户管理-修改账单报表",json_encode($request->input()));
+        return ["success"=>true,"data"=>$date];
+    }
+
+    public function billConfirm(Request $request)
+    {
+        if(!Gate::allows('客户管理-财务-账单确认-完结')){ return ["success"=>false,'data'=>"无权操作!"];  }
+        if (!($request->id ?? false))return["success"=>false,"data"=>"非法参数"];
+        app('OwnerBillReportService')->update(["id"=>$request->id],["confirmed"=>"是"]);
+        LogService::log(__METHOD__,"客户管理-确认账单",json_encode($request->input()));
+        $bill =  app('OwnerBillReportService')->first(["id"=>$request->id,"confirmed"=>"是"]);
+        app('OwnerAreaReportService')->lockArea(null, $bill->owner_id, $bill->counting_month);
+        LogService::log(__METHOD__,"客户管理-锁定账单的所有面积",json_encode($bill,JSON_UNESCAPED_UNICODE));
+        return ["success"=>true];
+    }
+
+    private function validator(array $params){
+        $id = $params['id'] ?? null;
+        $validator=Validator::make($params,[
+            'id' => ['required_without_all:code,name'],
+            'code'=>['required','max:50',$id ? "unique:owners,code,$id":'unique:owners,code'],
+            'name'=>['required','max:50'],
+            'customer_id'=>['required'],
+            'owner_group_id'=>['required'],
+            'tax_rate' => ['required','numeric'],
+        ],[
+            'required'=>':attribute 为必填项',
+            'unique'=>':attribute 已存在',
+        ],[
+            'code'=>'项目代码',
+            'name'=>'项目名称',
+            'customer_id'=>'客户',
+            'owner_group_id'=>'工作组',
+            'tax_rate' => '税率'
+        ]);
+        return $validator;
+    }
+}

+ 11 - 11
app/Http/Controllers/ExcelController.php

@@ -2,8 +2,8 @@
 
 namespace App\Http\Controllers;
 
-use App\Exports\GoodsNeateningExcelExport;
-use App\GoodsNeateningExcel;
+use App\Exports\InventoryBlindReceiveExcelExport;
+use App\InventoryBlindReceiveExcel;
 use Carbon\Carbon;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\DB;
@@ -59,17 +59,17 @@ class ExcelController extends Controller
             array_push($goodsesExcelArray,[$barcode,$obj['weight']??'',($obj['id']??'').' '
                 ,($obj['key'])??'',($obj['time'])??'', ($url)??'']);
         }
-        Excel::store(new GoodsNeateningExcelExport($goodsesExcelArray),'exportedJson.xlsx','public');
+        Excel::store(new InventoryBlindReceiveExcelExport($goodsesExcelArray),'exportedJson.xlsx','public');
         return ['result'=>'success'];
     }
 
     /**
      * Display the specified resource.
      *
-     * @param  \App\GoodsNeateningExcel  $goodsNeateningExcel
+     * @param  \App\InventoryBlindReceiveExcel  $goodsNeateningExcel
      * @return \Illuminate\Http\Response
      */
-    public function show(GoodsNeateningExcel $goodsNeateningExcel)
+    public function show(InventoryBlindReceiveExcel $goodsNeateningExcel)
     {
         //
     }
@@ -77,10 +77,10 @@ class ExcelController extends Controller
     /**
      * Show the form for editing the specified resource.
      *
-     * @param  \App\GoodsNeateningExcel  $goodsNeateningExcel
+     * @param  \App\InventoryBlindReceiveExcel  $goodsNeateningExcel
      * @return \Illuminate\Http\Response
      */
-    public function edit(GoodsNeateningExcel $goodsNeateningExcel)
+    public function edit(InventoryBlindReceiveExcel $goodsNeateningExcel)
     {
         //
     }
@@ -89,10 +89,10 @@ class ExcelController extends Controller
      * Update the specified resource in storage.
      *
      * @param  \Illuminate\Http\Request  $request
-     * @param  \App\GoodsNeateningExcel  $goodsNeateningExcel
+     * @param  \App\InventoryBlindReceiveExcel  $goodsNeateningExcel
      * @return \Illuminate\Http\Response
      */
-    public function update(Request $request, GoodsNeateningExcel $goodsNeateningExcel)
+    public function update(Request $request, InventoryBlindReceiveExcel $goodsNeateningExcel)
     {
         //
     }
@@ -100,10 +100,10 @@ class ExcelController extends Controller
     /**
      * Remove the specified resource from storage.
      *
-     * @param  \App\GoodsNeateningExcel  $goodsNeateningExcel
+     * @param  \App\InventoryBlindReceiveExcel  $goodsNeateningExcel
      * @return \Illuminate\Http\Response
      */
-    public function destroy(GoodsNeateningExcel $goodsNeateningExcel)
+    public function destroy(InventoryBlindReceiveExcel $goodsNeateningExcel)
     {
         //
     }

+ 88 - 0
app/Http/Controllers/FeatureController.php

@@ -0,0 +1,88 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\Request;
+use Illuminate\Http\Response;
+use Illuminate\Support\Facades\Gate;
+
+class FeatureController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return Response
+     */
+    public function index()
+    {
+        if(!Gate::allows('特征-查询')){ return redirect('denied');  }
+        return response()->view("maintenance.feature.index");
+    }
+
+    /**
+     * Show the form for creating a new resource.
+     *
+     * @return Response
+     */
+    public function create()
+    {
+        if(!Gate::allows('特征-录入')){ return redirect('denied');  }
+        return response()->view("maintenance.feature.create");
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\Response
+     */
+    public function store(Request $request)
+    {
+        //
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  int  $id
+     * @return \Illuminate\Http\Response
+     */
+    public function show($id)
+    {
+        //
+    }
+
+    /**
+     * Show the form for editing the specified resource.
+     *
+     * @param  int  $id
+     * @return \Illuminate\Http\Response
+     */
+    public function edit($id)
+    {
+        //
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  int  $id
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, $id)
+    {
+        //
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  int  $id
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy($id)
+    {
+        //
+    }
+}

+ 5 - 1
app/Http/Controllers/HomeController.php

@@ -28,6 +28,10 @@ class HomeController extends Controller
             if(!Gate::allows('运输管理-查询')){ return view('home');}
             return redirect(url('waybill'));
         }
-        return redirect(url('rejected'));
+        return redirect(url('rejected/index/general'));
+    }
+    public function home()
+    {
+        return view('home');
     }
 }

+ 451 - 0
app/Http/Controllers/InventoryAccountController.php

@@ -0,0 +1,451 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Exports\Export;
+use App\InventoryAccount;
+use App\InventoryAccountMission;
+use App\Services\InventoryAccountService;
+use App\Services\OwnerService;
+use Exception;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Gate;
+use Illuminate\Support\Facades\Http;
+use Illuminate\Support\Facades\Redis;
+use Maatwebsite\Excel\Facades\Excel;
+
+class InventoryAccountController extends Controller
+{
+    public function __construct()
+    {
+        app()->singleton('inventoryAccountService', InventoryAccountService::class);
+    }
+
+    //创建盘点任务
+    public function createStockInventoryMission(Request $request)
+    {
+        if (!Gate::allows("库存管理-盘点")) {
+            return redirect(url('/'));
+        }
+//        $date_start=$request->input('formData.date_start');
+//        $date_end=$request->input('formData.date_end');
+//        $ownerId=$request->input('formData.owner_id')[0];
+        $date_start = $request->input('date_start');
+        $date_end = $request->input('date_end');
+        $ownerId = $request->input('owner_id');
+        $location = $request->input('location');
+        $barcode = $request->input('barcode');
+        $inventoryAccount = app('inventoryAccountService')->createMission($date_start, $date_end, $ownerId, $location, $barcode);
+        $inventoryAccount = InventoryAccount::with('owner')->find($inventoryAccount->id);
+        if (is_null($inventoryAccount)) return ['success' => false, 'data' => '参数错误!'];
+        return ['success' => true, 'data' => $inventoryAccount];
+    }
+
+    //删除盘点任务
+    public function deleteStockInventoryMission($id)
+    {
+        if (!Gate::allows('库存管理-盘点')) {
+            return ['success' => 0, 'status' => '没有权限'];
+        }
+        if (is_null($id)) {
+            return ['success' => false, 'data' => '传入id为空'];
+        }
+        $inventoryAccount = InventoryAccount::where('id', $id)->delete();
+        return ['success' => true, 'data' => $inventoryAccount];
+    }
+
+    public function inventoryChecked(Request $request)
+    {
+        if (!Gate::allows('库存管理-盘点-项目审核')) {
+            return ['success' => false, 'msg' => '没有权限'];
+        }
+        $id = $request->id;
+        if (is_null($id)) {
+            return ['success' => false, 'msg' => '传入id为空'];
+        }
+        $inventoryAccount = InventoryAccount::query()->where('id', $id)->update([
+            'auditor' => Auth::user()['id'],
+            'status' => '已审核',
+        ]);
+        if ($inventoryAccount == 1) {
+            $inventoryAccount = InventoryAccount::query()->with('userAuditor')->find($id);
+            return ['success' => true, 'data' => $inventoryAccount];
+        } else {
+            return ['success' => false, 'msg' => '审核失败!'];
+        }
+    }
+
+    //盘点-任务页面
+    public function mission(Request $request, OwnerService $ownerService)
+    {
+        if (!Gate::allows("库存管理-盘点")) {
+            return redirect(url('/'));
+        }
+        $paginateParams = $request->input();
+        $queryParam = $request->all();
+        $inventoryAccounts = app('inventoryAccountService')->paginate($queryParam);
+        $owners = $ownerService->getSelection();
+        return view('inventory.stockInventory.mission', compact('owners', 'inventoryAccounts', 'paginateParams'));
+    }
+
+    //进入盘点中或复盘页面
+    public function enterStockInventory($id, Request $request)
+    {
+        if (!Gate::allows('库存管理-盘点')) {
+            return redirect(url('/'));
+        }
+        if (!$id) return ['success' => false, 'data' => '参数错误!'];
+        $inventoryAccount = InventoryAccount::with('owner')->find($id);
+        $inventoryAccountMissions = InventoryAccountMission::with(['commodity.barcodes', 'stockInventoryPersons'])->where('inventory_account_id', $id)->orderBy('difference_amount', 'desc')->get();
+        return view('inventory.stockInventory.inventoryMission', compact('inventoryAccount', 'inventoryAccountMissions'));
+    }
+
+    public function enterBlindReceive($id)
+    {
+        if (!Gate::allows('库存管理-盘点')) {
+            return redirect(url('/'));
+        }
+        if (!$id) return ['success' => false, 'data' => '参数错误!'];
+        $inventoryAccount = InventoryAccount::with('owner')->find($id);
+        return view('inventory.stockInventory.blindReceive', compact('inventoryAccount'));
+    }
+
+    //依据盘点任务id进行 --盘点
+    public function stockInventory(Request $request)
+    {
+        if (!Gate::allows('库存管理-盘点')) {
+            return redirect(url('/'));
+        }
+        $location = $request->input('location');
+        $barcode = $request->input('barcode');
+        $inventoryId = $request->input('inventoryId');
+        $count = $request->input('count');
+        $id = $request->input('id');
+        if (is_null($count)) return ['success' => false, 'data' => '盘点数不能为空!'];
+        /** @var InventoryAccountService $inventoryAccountService */
+        $inventoryAccountService = app('inventoryAccountService');
+        $inventoryAccountMission = $inventoryAccountService->stockInventory($id, $location, $barcode, $count, $inventoryId);
+        if (!$inventoryAccountMission) return ['success' => false, 'data' => '参数错误!'];
+        /** @var InventoryAccountService $inventoryService */
+        $inventoryService = app('inventoryAccountService');
+        $inventoryAccount = $inventoryService->updateInventory($inventoryId);
+        $stockInventoryPersons = $inventoryAccountMission->stockInventoryPersons;
+        return ['success' => true, 'inventoryMission' => $inventoryAccountMission, 'inventory' => $inventoryAccount, 'stockInventoryPersons' => $stockInventoryPersons];
+    }
+
+    public function baseOnBlindReceive(Request $request)
+    {
+        if (!Gate::allows('库存管理-盘点')) {
+            return redirect(url('/'));
+        }
+        $location = $request->input('location');
+        $inventoryId = $request->input('inventoryId');
+        $owner_code = $request->input('owner_code');
+        $goodses = $request->input('goodses');
+        if (!$location) return ['success' => false, 'fail_info' => '盘点库位不存在!'];
+        if (count($goodses) < 1) return ['success' => false, 'fail_info' => '盘点商品不存在!'];
+        //dd($location,$owner_code,$goodses,$inventoryId,$owner_id);
+        /** @var InventoryAccountService $inventoryAccountMission */
+        $inventoryAccountService = app('inventoryAccountService');
+        $inventoryAccountMissions = $inventoryAccountService->baseOnBlindReceive($location, $owner_code, $goodses, $inventoryId);
+        if (count($inventoryAccountMissions) < 0) return ['success' => false, 'fail_info' => '盲收盘点失败!'];
+        /** @var InventoryAccountService $inventoryService */
+        $inventoryService = app('inventoryAccountService');
+        $inventoryAccount = $inventoryService->updateInventory($inventoryId);
+        if ($inventoryAccountMissions && $inventoryAccount)
+            $stockInventoryPersons = $inventoryAccountMissions[0]->stockInventoryPersons;
+        return ['success' => true, 'inventoryMissions' => $inventoryAccountMissions, 'inventory' => $inventoryAccount, 'stockInventoryPersons' => $stockInventoryPersons];
+    }
+
+    //根据该库存和产品条码查询该条盘点记录??
+    public function searchStockInventoryRecord(Request $request)
+    {
+        if (!Gate::allows('库存管理-盘点')) {
+            return redirect(url('/'));
+        }
+        $location = $request->input('location');
+        $barcode = $request->input('barcode');
+        $inventoryId = $request->input('inventoryId');
+        /** @var InventoryAccountService $application */
+        $application = app('inventoryAccountService');
+        $inventoryAccountMissions = $application->searchStockInventoryRecord($location, $barcode, $inventoryId);
+        if ($inventoryAccountMissions->isEmpty()) return ['success' => false, 'data' => '没有找到相应记录!'];
+//        $stockInventoryPersons=$inventoryAccountMissions->stockInventoryPersons;
+//        return ['success'=>true,'data'=>$inventoryAccountMissions,'stockInventoryPersons'=>$stockInventoryPersons];
+        return ['success' => true, 'data' => $inventoryAccountMissions];
+    }
+
+    //盘点任务导出
+    public function stockInventoryExport(Request $request)
+    {
+        if (!Gate::allows('库存管理-盘点')) {
+            return redirect(url('/'));
+        }
+        ini_set('max_execution_time', 3500);
+        ini_set('memory_limit', '3526M');
+        if ($request->checkAllSign) {
+            $request->offsetUnset('checkAllSign');
+            $queryParam = $request->all();
+            $inventoryAccounts = app('inventoryAccountService')->get($queryParam);
+        } else {
+            $queryParam = $request->all();
+            $inventoryAccounts = app('inventoryAccountService')->some($queryParam);
+        }
+        $row = [[
+            'id' => '盘点编号',
+            'status' => '盘点状态',
+            'created_at' => '创建时间',
+            'owner_id' => '货主',
+            'type' => '任务类型',
+            'start_at' => '起始时间',
+            'end_at' => '结束时间',
+            'total' => '记录数',
+            'processed' => '已盘数',
+            'surplus' => '剩余数',
+            'difference' => '复盘差异',
+            'returned' => '复盘归位',
+        ]];
+        $list = [];
+        for ($i = 0; $i < count($inventoryAccounts); $i++) {
+            $inventoryAccount = $inventoryAccounts[$i];
+            $w = [
+                'id' => isset($inventoryAccount->id) ? $inventoryAccount->id : '',
+                'status' => isset($inventoryAccount->status) ? $inventoryAccount->status : '',
+                'created_at' => isset($inventoryAccount->created_at) ? $inventoryAccount->created_at : '',
+                'owner_id' => isset($inventoryAccount->owner->name) ? $inventoryAccount->owner->name : '',
+                'type' => isset($inventoryAccount->type) ? $inventoryAccount->type : '',
+                'start_at' => isset($inventoryAccount->start_at) ? $inventoryAccount->start_at : '',
+                'end_at' => isset($inventoryAccount->end_at) ? $inventoryAccount->end_at : '',
+                'total' => isset($inventoryAccount->total) ? $inventoryAccount->total : '',
+                'processed' => isset($inventoryAccount->processed) ? $inventoryAccount->processed : '',
+                'surplus' => isset($inventoryAccount->surplus) ? $inventoryAccount->surplus : '',
+                'difference' => isset($inventoryAccount->difference) ? $inventoryAccount->difference : '',
+                'returned' => isset($inventoryAccount->returned) ? $inventoryAccount->returned : '',
+            ];
+            $list[$i] = $w;
+        }
+        return Excel::download(new Export($row, $list), date('YmdHis', time()) . '-盘点任务记录单.xlsx');
+    }
+
+    public function stockInventoryEnd(Request $request)
+    {
+        if (!Gate::allows('库存管理-盘点-结束初盘')) {
+            return ['success' => false, 'data' => '没有权限'];
+        }
+        $id = $request->input('id');
+        if (!$id) return ['success' => false, 'data' => '参数错误!'];
+        $inventoryAccount = InventoryAccount::query()->where('id', $id)->update(['status' => '复盘中']);
+        app('LogService')->log(__METHOD__, '结束初盘任务' . __FUNCTION__, json_encode($request->toArray()), Auth::user()['id']);
+        if ($inventoryAccount > 0) return ['success' => true, 'data' => '复盘中'];
+        return ['success' => false, 'data' => '参数错误!'];
+    }
+
+    public function syncOwners(OwnerService $ownerService)
+    {
+        if (!Gate::allows('库存管理-盘点')) {
+            return redirect(url('/'));
+        }
+        $owners = $ownerService->syncOwnersData();
+        if (!$owners) return ['success' => false, 'data' => '同步货主失败!'];
+        return ['success' => true, 'data' => $owners];
+    }
+
+    public function 修改质量状态(Request $request)
+    {
+        if (!Gate::allows('库存管理-盘点')) {
+            return redirect(url('/'));
+        }
+        $id = $request->input('id');
+        $location = $request->location;
+        $sku = $request->sku;
+        $quality = $request->quality;
+        $ownerCode = $request->ownerCode;
+        $inventoryAccountMission = app('inventoryAccountService')->修改质量状态($id, $location, $sku, $quality, $ownerCode);
+        app('LogService')->log(__METHOD__, __FUNCTION__, json_encode($request->toArray()), Auth::user()['id']);
+        if ($inventoryAccountMission == null) return ['success' => false, 'data' => 'WMS中不存在该条记录!'];
+        return ['success' => true, 'data' => '质量状态修改成功'];
+
+    }
+
+    public function 完结盘点任务($id)
+    {
+        if (!Gate::allows('库存管理-盘点-完结')) {
+            return ['success' => false, 'status' => '没有权限'];
+        }
+        if (!$id) return ['success' => false, 'status' => '参数错误!'];
+        $inventoryAccount = app('inventoryAccountService')->完结盘点任务($id);
+        if (!$inventoryAccount) return ['success' => false, 'status' => '修改完结状态失败!'];
+        return ['success' => true, 'data' => $inventoryAccount];
+
+    }
+
+    public function 增加系统之外的盘点记录(Request $request)
+    {
+        if (!Gate::allows('库存管理-盘点')) {
+            return ['success' => false, 'data' => '没有权限'];
+        }
+        $location = $request->input('location');
+        $barcode = $request->input('barcode');
+        $inventoryId = $request->input('inventoryId');
+        $count = $request->input('count');
+        $owner_code = $request->input('owner_code');
+        $param = $request->input('param');
+        if (is_null($count)) return ['success' => false, 'data' => '盘点数不能为空!'];
+        $inventoryAccountMission = app('inventoryAccountService')->增加系统之外的盘点记录($location, $barcode, $inventoryId, $count, $owner_code, $param);
+        if (!$inventoryAccountMission) return ['success' => false, 'data' => '添加系统之外的库位记录失败!'];
+        $inventoryAccountMission = InventoryAccountMission::with(['commodity.barcodes', 'stockInventoryPersons'])->where('id', $inventoryAccountMission->id)->first();
+        $stockInventoryPersons = $inventoryAccountMission->stockInventoryPersons;
+        return ['success' => true, 'inventoryAccountMission' => $inventoryAccountMission, 'stockInventoryPersons' => $stockInventoryPersons];
+    }
+
+    public function 盘点选中任务(Request $request)
+    {
+        if (!Gate::allows('库存管理-盘点')) {
+            return ['success' => false, 'data' => '没有权限'];
+        }
+        $id = $request->input('id');
+        $count = $request->count;
+        $inventoryId = $request->input('inventoryId');
+        $produced_at = $request->input('produced_at');
+        $valid_at = $request->input('valid_at');
+        $batch_number = $request->input('batch_number');
+        if (is_null($count)) return ['success' => false, 'data' => '盘点数不能为空!'];
+        if ($produced_at || $valid_at || $batch_number) {
+            /** @var InventoryAccountService $inventoryAccountMission */
+            $inventoryAccountService = app('inventoryAccountService');
+            $inventoryAccountMission = $inventoryAccountService->盘点生产日期_失效日期_批号有改动任务($id, $count, $inventoryId, $produced_at, $valid_at, $batch_number);
+            if (!$inventoryAccountMission) return ['success' => false, 'data' => '盘点生产日期_失效日期_批号有改动任务失败!'];
+            /** @var InventoryAccountService $inventoryService */
+            $inventoryService = app('inventoryAccountService');
+            $inventoryAccount = $inventoryService->updateInventory($inventoryId);
+            $stockInventoryPersons = $inventoryAccountMission[0]->stockInventoryPersons;
+            return ['success' => true, 'inventoryMission' => $inventoryAccountMission, 'inventory' => $inventoryAccount, 'stockInventoryPersons' => $stockInventoryPersons];
+        } else {
+            /** @var InventoryAccountService $inventoryAccountMission */
+            $inventoryAccountService = app('inventoryAccountService');
+            $inventoryAccountMission = $inventoryAccountService->盘点选中任务($id, $count, $inventoryId);
+            if (!$inventoryAccountMission) return ['success' => false, 'data' => '盘点选中任务失败!'];
+            /** @var InventoryAccountService $inventoryService */
+            $inventoryService = app('inventoryAccountService');
+            $inventoryAccount = $inventoryService->updateInventory($inventoryId);
+            $stockInventoryPersons = $inventoryAccountMission->stockInventoryPersons;
+            return ['success' => true, 'inventoryMission' => $inventoryAccountMission, 'inventory' => $inventoryAccount, 'stockInventoryPersons' => $stockInventoryPersons];
+        }
+    }
+
+    public function 删除盘点记录(Request $request)
+    {
+        if (!Gate::allows('库存管理-盘点-删除')) {
+            return ['success' => false, 'data' => '没有权限'];
+        }
+        $inventoryAccountMissionId = $request->input('inventoryAccountMissionId');
+        $inventoryAccountId = $request->input('inventoryAccountId');
+        if (is_null($inventoryAccountMissionId)) {
+            return ['success' => false, 'data' => '传入id为空'];
+        }
+        /** @var InventoryAccountService $inventoryService */
+        $inventoryService = app('inventoryAccountService');
+        $inventoryAccountMission = $inventoryService->删除盘点记录($inventoryAccountMissionId, $inventoryAccountId);
+        return ['success' => true, 'data' => $inventoryAccountMission];
+    }
+
+    public function 跳过盘点记录(Request $request)
+    {
+        if (!Gate::allows('库存管理-盘点')) {
+            return ['success' => false, 'data' => '没有权限'];
+        }
+        $inventoryAccountMissionId = $request->inventoryAccountMissionId;
+        $inventoryAccountId = $request->input('inventoryAccountId');
+        if (is_null($inventoryAccountMissionId)) {
+            return ['success' => false, 'data' => '传入id为空'];
+        }
+        /** @var InventoryAccountService $inventoryService */
+        $inventoryService = app('inventoryAccountService');
+        $inventoryAccountMission = $inventoryService->跳过盘点记录($inventoryAccountMissionId, $inventoryAccountId);
+        return ['success' => true, 'inventoryAccountMission' => $inventoryAccountMission];
+    }
+
+    public function 确认盘点差异(Request $request)
+    {
+        if (!Gate::allows('库存管理-盘点')) {
+            return ['success' => false, 'data' => '没有权限'];
+        }
+        $inventoryAccountMissionId = $request->inventoryAccountMissionId;
+        $inventoryAccountId = $request->input('inventoryAccountId');
+        if (is_null($inventoryAccountMissionId)) {
+            return ['success' => false, 'data' => '传入id为空'];
+        }
+        /** @var InventoryAccountService $inventoryService */
+        $inventoryService = app('inventoryAccountService');
+        $inventoryAccountMission = $inventoryService->确认盘点差异($inventoryAccountMissionId, $inventoryAccountId);
+        return ['success' => true, 'inventoryAccountMission' => $inventoryAccountMission];
+    }
+
+    public function 批量跳过或确认差异(Request $request)
+    {
+        if (!Gate::allows('库存管理-盘点')) {
+            return ['success' => false, 'data' => '没有权限'];
+        }
+        $checkData = $request->checkData;
+        if (is_null($checkData)) {
+            return ['success' => false, 'data' => '传入勾选盘点记录为空'];
+        }
+        $marks = [];
+        foreach ($checkData as $inventoryMission) {
+            array_push($marks, $inventoryMission['mark']);
+        }
+        if (in_array('确认差异', $marks) || in_array('跳过', $marks) || in_array('无差异', $marks) || in_array('已复盘无差异', $marks)) return ['success' => false, 'data' => '传入勾选盘点记录存在不可操作项!'];
+        /** @var InventoryAccountService $inventoryService */
+        $inventoryService = app('inventoryAccountService');
+        $inventoryAccountMissions = $inventoryService->批量跳过或确认差异($checkData);
+        return ['success' => true, 'inventoryAccountMissions' => $inventoryAccountMissions];
+    }
+
+    public function exportInventoryAccountMission(Request $request)
+    {
+        if (!Gate::allows("库存管理-盘点")) {
+            return redirect(url('/'));
+        }
+        $post = Http::post(config('go.export.url'), ['type' => 'inventoryAccountMission', 'data' => $request->data]);
+        if ($post->status() == 500) {
+            throw new Exception($post->header("Msg"));
+        }
+        return response($post, 200, [
+            "Content-type" => "application/octet-stream",
+            "Content-Disposition" => "attachment; filename=库存盘点记录-" . date('ymdHis') . '.xlsx',
+        ]);
+    }
+
+    public function searchCommodityByBarcode(Request $request)
+    {
+        if (!Gate::allows('库存管理-盘点')) {
+            return ['success' => false, 'data' => '没有权限'];
+        }
+        $barcode = $request->input('barcode');
+        $owner_code = $request->input('owner_code');
+        /** @var InventoryAccountService $inventoryService */
+        $inventoryService = app('inventoryAccountService');
+        $commodity = $inventoryService->searchCommodityByBarcode($barcode, $owner_code);
+        if ($commodity) {
+            return ['success' => true, 'data' => $commodity];
+        } else {
+            return ['success' => false, 'data' => '输入的条码没有对应商品!'];
+        }
+    }
+    //根据库位批量盘点该库位下盘点记录
+    public function batchStockByLocation(Request $request)
+    {
+        if (!Gate::allows('库存管理-盘点')) return ['success' => false, 'msg' => '没有权限'];
+        $missions=$request->mission;
+        $inventoryId=$request->inventoryId;
+        if (!$inventoryId||count($missions)<1) return ['success' => false, 'msg' => '参数错误'];
+        /** @var InventoryAccountService $inventoryService */
+        $inventoryService = app('inventoryAccountService');
+        $inventoryMissions=$inventoryService->batchStockByLocation($missions,$inventoryId);
+        $inventoryService = app('inventoryAccountService');
+        $inventoryAccount = $inventoryService->updateInventory($inventoryId);
+        $stockInventoryPersons = $inventoryMissions[0]->stockInventoryPersons;
+        return ['success' => true, 'inventoryMission' => $inventoryMissions, 'inventory' => $inventoryAccount, 'stockInventoryPersons' => $stockInventoryPersons];
+    }
+}

+ 150 - 0
app/Http/Controllers/InventoryCompareController.php

@@ -0,0 +1,150 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Imports\InventoryCompareImport;
+use App\InventoryCompare;
+use App\Services\OwnerService;
+use Exception;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Gate;
+use Illuminate\Support\Facades\Http;
+use Maatwebsite\Excel\Facades\Excel;
+
+class InventoryCompareController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function index()
+    {
+        //
+    }
+
+    /**
+     * Show the form for creating a new resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function create()
+    {
+        //
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\Response
+     */
+    public function store(Request $request)
+    {
+        //
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  \App\InventoryCompare  $inventoryCompare
+     * @return \Illuminate\Http\Response
+     */
+    public function show(InventoryCompare $inventoryCompare)
+    {
+        //
+    }
+
+    /**
+     * Show the form for editing the specified resource.
+     *
+     * @param  \App\InventoryCompare  $inventoryCompare
+     * @return \Illuminate\Http\Response
+     */
+    public function edit(InventoryCompare $inventoryCompare)
+    {
+        //
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \App\InventoryCompare  $inventoryCompare
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, InventoryCompare $inventoryCompare)
+    {
+        //
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  \App\InventoryCompare  $inventoryCompare
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(InventoryCompare $inventoryCompare)
+    {
+        //
+    }
+    function inventoryCompare(Request $request,OwnerService $ownerService){
+        if (!Gate::allows('库存管理-库存-库存对比')){return redirect(url('/')); }
+        $owners = $ownerService->getSelection();
+        $inventoryCompares=app('InventoryCompareService')->getInventoryCompare($request->all());
+        $param = $request->input();
+        return view('inventory.statement.inventoryCompare',compact('owners','inventoryCompares','param'));
+    }
+    function importExcel(Request $request){
+        if (!Gate::allows('库存管理-库存-库存对比')){return redirect(url('/')); }
+//        $owner_id=$request->owner_id;
+//        if(!$owner_id) return '<h1 class="text-danger">导入Excel失败<br><p style="color: red">您还未选择相应货主!</p></h1>';
+        $fileSuffix = $request->file()['file']->getClientOriginalExtension();
+        if (in_array($fileSuffix, ['xlsx', 'xlsm', 'xltx', 'xltm', 'xls', 'xlt', 'ods', 'ots', 'slk', 'xml', 'gnumeric', 'htm', 'html', 'csv', 'tsv'])) {
+            ini_set('max_execution_time', 2100);
+            ini_set('memory_limit', '512M');
+            $extension = $request->file()['file']->getClientOriginalExtension();
+            $extension[0] = strtoupper($extension[0]);
+            Excel::import(new InventoryCompareImport(), $request->file('file')->path(), null, $extension);
+            if (Cache::has('error')) {
+                return '<h1 class="text-danger">导入Excel失败<br><p style="color: red">' . Cache::pull('error') . '</p></h1>';
+            } else {
+                $exception = Cache::get('exception');
+//                if ($exception){
+                    $a = '';
+                    for ($i = 0; $i < count($exception); $i++) {
+                        $a .= implode(',', $exception[$i]) . '&#10';
+                    };
+                    app('LogService')->log(__METHOD__, __FUNCTION__, json_encode($request->toArray()), Auth::user()['id']);
+                    return '<h1 class="text-danger">导入Excel成功<br><textarea style="width: 50%;height: 50%">' . $a . '</textarea></h1>';
+//                }else {
+//                    return '<h1 class="text-danger">导入Excel成功</h1>';
+//                }
+
+            }
+        } else {
+            return '<h1 class="text-danger">失败<br><p style="color: red">不支持该文件类型</p></h1>';
+        }
+    }
+
+    public function exportInventoryCompare(Request $request){
+        if (!Gate::allows('库存管理-库存-库存对比')){return redirect(url('/')); }
+        if ($request->checkAllSign){
+            $params = $request->input();
+            unset($params['checkAllSign']);
+            $sql=app('InventoryCompareService')->getSql($params);
+        }else{
+            $sql=app('InventoryCompareService')->getSql(['id'=>$request->data]);
+        }
+        $post = Http::post(config('go.export.url'),['type'=>'inventoryCompare','sql'=>$sql]);
+        if ($post->status() == 500){
+            throw new Exception($post->header("Msg"));
+        }
+        return response($post,200, [
+            "Content-type"=>"application/octet-stream",
+            "Content-Disposition"=>"attachment; filename=库存对比记录-".date('ymdHis').'.xlsx',
+        ]);
+    }
+}

+ 137 - 0
app/Http/Controllers/InventoryController.php

@@ -0,0 +1,137 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\OracleBasCustomer;
+use App\Owner;
+use App\Services\AllInventoryService;
+use App\Services\InventoryDailyLogService;
+use App\Services\InventoryService;
+use App\Services\OwnerService;
+use Exception;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Gate;
+use Illuminate\Support\Facades\Http;
+
+class InventoryController extends Controller
+{
+    public function __construct()
+    {
+        app()->singleton('inventoryService',InventoryService::class);
+        app()->singleton('AllInventoryService',AllInventoryService::class);
+
+    }
+    //动库报表
+    public function changeInventory(Request $request){
+        if(!Gate::allows("库存管理-库存")){ return redirect(url('/'));  }
+        $oracleActTransactingLogs=app('inventoryService')->paginate($request->input());
+        $oracleActTransactingLogs=json_encode($oracleActTransactingLogs);
+//        $owners=OracleBasCustomer::query()->select('customerid','descr_c')->where('customer_type','OW')->where('active_flag','Y')->get();
+        $owners=Owner::filterAuthorities()->select(['code', 'name'])->get();
+        $isTotalStock=false;
+        $page = $request->page ?? 1;
+        return view('inventory.statement.changeInventory',compact('oracleActTransactingLogs','page','owners','isTotalStock'));
+    }
+    //全部库存
+    public function allInventory(Request $request){
+        if(!Gate::allows("库存管理-库存")){ return redirect(url('/'));  }
+
+        /** @var AllInventoryService $service */
+        $service = app('AllInventoryService');
+        $oracleActTransactingLogs= $service->paginate($request->input());
+        $oracleActTransactingLogs=json_encode($oracleActTransactingLogs);
+//        $owners=OracleBasCustomer::query()->select('customerid','descr_c')->where('customer_type','OW')->where('active_flag','Y')->get();
+        $owners=Owner::filterAuthorities()->select(['code', 'name'])->get();
+        $isTotalStock=true;
+        $page = $request->page ?? 1;
+        return view('inventory.statement.changeInventory',compact('oracleActTransactingLogs','page','owners','isTotalStock'));
+    }
+    public function exportData(Request $request){
+        if(!Gate::allows("库存管理-库存")){ return redirect(url('/'));  }
+        if ($request->checkAllSign){
+            $params = $request->input();
+            unset($params['checkAllSign']);
+            $sql=app('inventoryService')->getSql($request->input());
+            $post = Http::post(config('go.export.url'),['type'=>'inventory','sql'=>$sql]);
+        }else {
+            $post = Http::post(config('go.export.url'), ['type' => 'inventory', 'data' => $request->data]);
+        }
+        if ($post->status() == 500){
+            throw new \Exception($post->header("Msg"));
+        }
+        return response($post, 200, [
+            "Content-type" => "application/octet-stream",
+            "Content-Disposition" => "attachment; filename=库存记录-" . date('ymdHis') . '.xlsx',
+        ]);
+    }
+    public function exportAllInventory(Request $request){
+        if(!Gate::allows("库存管理-库存")){ return redirect(url('/'));  }
+        if ($request->checkAllSign){
+            $params = $request->input();
+            unset($params['checkAllSign']);
+            $sql=app('AllInventoryService')->getSql($request->input());
+            $post = Http::post(config('go.export.url'),['type'=>'allInventory','sql'=>$sql]);
+        }else{
+            $post = Http::post(config('go.export.url'),['type'=>'allInventory','data'=>$request->data]);
+        }
+        if ($post->status() == 500){
+            throw new Exception($post->header("Msg"));
+        }
+        return response($post,200, [
+            "Content-type"=>"application/octet-stream",
+            "Content-Disposition"=>"attachment; filename=全部库存-".date('ymdHis').'.xlsx',
+        ]);
+    }
+
+    /*
+     *  库存体积
+     */
+    function dailyLog(Request $request,OwnerService $ownerService){
+        if (!Gate::allows('库存管理-库存体积')){return redirect(url('/')); }
+        /** @var InventoryDailyLogService*/
+        $inventoryDailyLogs = app('InventoryDailyLogService')->paginate($request->input());
+        $owners = $ownerService->getSelection();
+        $param = $request->input();
+        return view('inventory.statement.dailyLog',compact('inventoryDailyLogs','owners','param'));
+    }
+
+    //获取记录监听货主
+    function getLoggingOwner(){
+        $loggingOwners = app('InventoryDailyLogService')->getInventoryDailyLoggingOwner('owner_id');
+        return array_column($loggingOwners->toArray(),'owner_id');
+    }
+    //添加记录监听货主
+    function addLoggingOwner(Request $request){
+        if (!Gate::allows('库存管理-库存体积-管理监听货主')){return redirect(url('/')); }
+        $owner_id = $request->owner_id;
+        if (!$owner_id || !is_numeric($owner_id))return ['success'=>false,'data'=>'传递参数错误!'];
+        $loggingOwner = app('InventoryDailyLogService')->firstOrCreate(['owner_id'=>$owner_id]);
+        if (!$loggingOwner)return ['success'=>false,'data'=>'录入失败!'];
+        return ['success'=>true,'data'=>$loggingOwner->owner_id];
+    }
+    //导出库存体积记录
+    public function exportDailyLog(Request $request){
+        if (!Gate::allows('库存管理-库存体积')){return redirect(url('/')); }
+        if ($request->checkAllSign){
+            $params = $request->input();
+            unset($params['checkAllSign']);
+            $sql=app('InventoryDailyLogService')->getSql($params);
+
+        }else $sql=app('InventoryDailyLogService')->getSql(['id'=>$request->data]);
+
+        $row = ["货主","日期","商品名称","商品编码","商品条码","属性仓","在库数量","长","宽","高","体积","总占用体积","总毛重"];
+        $column = ["owner_name", "created_at", "commodity_name", "commodity_sku", "commodity_barcode_code","depository_name",
+            "amount", "commodity_length", "commodity_width", "commodity_height", "commodity_volumn", "volumn_occupied", "gross_weight"];
+        $rule = ["created_at"=> "mysqlDate"];
+        $post = Http::post(config('go.export.url'),['type'=>'unify','sql'=>$sql, 'connection'=>'mysql',
+            'row'=>json_encode($row,JSON_UNESCAPED_UNICODE), 'column'=>json_encode($column), 'rule'=>json_encode($rule)]);
+
+        if ($post->status() == 500){
+            throw new Exception($post->header("Msg"));
+        }
+        return response($post,200, [
+            "Content-type"=>"application/octet-stream",
+            "Content-Disposition"=>"attachment; filename=库存体积记录-".date('ymdHis').'.xlsx',
+        ]);
+    }
+}

+ 10 - 10
app/Http/Controllers/WMSReflectReceiveSkuController.php → app/Http/Controllers/InventoryMissionController.php

@@ -2,10 +2,10 @@
 
 namespace App\Http\Controllers;
 
-use App\WMSReflectReceiveSku;
+use App\InventoryAccountMission;
 use Illuminate\Http\Request;
 
-class WMSReflectReceiveSkuController extends Controller
+class InventoryMissionController extends Controller
 {
     /**
      * Display a listing of the resource.
@@ -41,10 +41,10 @@ class WMSReflectReceiveSkuController extends Controller
     /**
      * Display the specified resource.
      *
-     * @param  \App\WMSReflectReceiveSku  $wMSReflectReceiveSku
+     * @param  \App\InventoryAccountMission  $inventoryMission
      * @return \Illuminate\Http\Response
      */
-    public function show(WMSReflectReceiveSku $wMSReflectReceiveSku)
+    public function show(InventoryAccountMission $inventoryMission)
     {
         //
     }
@@ -52,10 +52,10 @@ class WMSReflectReceiveSkuController extends Controller
     /**
      * Show the form for editing the specified resource.
      *
-     * @param  \App\WMSReflectReceiveSku  $wMSReflectReceiveSku
+     * @param  \App\InventoryAccountMission  $inventoryMission
      * @return \Illuminate\Http\Response
      */
-    public function edit(WMSReflectReceiveSku $wMSReflectReceiveSku)
+    public function edit(InventoryAccountMission $inventoryMission)
     {
         //
     }
@@ -64,10 +64,10 @@ class WMSReflectReceiveSkuController extends Controller
      * Update the specified resource in storage.
      *
      * @param  \Illuminate\Http\Request  $request
-     * @param  \App\WMSReflectReceiveSku  $wMSReflectReceiveSku
+     * @param  \App\InventoryAccountMission  $inventoryMission
      * @return \Illuminate\Http\Response
      */
-    public function update(Request $request, WMSReflectReceiveSku $wMSReflectReceiveSku)
+    public function update(Request $request, InventoryAccountMission $inventoryMission)
     {
         //
     }
@@ -75,10 +75,10 @@ class WMSReflectReceiveSkuController extends Controller
     /**
      * Remove the specified resource from storage.
      *
-     * @param  \App\WMSReflectReceiveSku  $wMSReflectReceiveSku
+     * @param  \App\InventoryAccountMission  $inventoryMission
      * @return \Illuminate\Http\Response
      */
-    public function destroy(WMSReflectReceiveSku $wMSReflectReceiveSku)
+    public function destroy(InventoryAccountMission $inventoryMission)
     {
         //
     }

+ 3 - 3
app/Http/Controllers/LaborCompanyController.php

@@ -46,7 +46,7 @@ class LaborCompanyController extends Controller
         $laborCompany=new LaborCompany($request->all());
         $laborCompany->save();
 
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return redirect('maintenance/laborCompany/create')->with('successTip',"成功录入劳务所“{$request->input('name')}”");
     }
     protected function validatorCreate(array $data)
@@ -97,7 +97,7 @@ class LaborCompanyController extends Controller
         $this->validatorUpdate($request->all())->validate();
         $laborCompany->fill($request->all());
         $laborCompany->update();
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return redirect('maintenance/laborCompany/')->with('successTip',"成功修改劳务所“{$laborCompany['name']}”!");
     }
 
@@ -111,7 +111,7 @@ class LaborCompanyController extends Controller
     public function destroy(LaborCompany $laborCompany)
     {
         if(!Gate::allows('物流公司-删除')){ return redirect(url('/'));  }
-        $this->log(__METHOD__,__FUNCTION__,$laborCompany->toJson(),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,$laborCompany->toJson(),Auth::user()['id']);
         $re=$laborCompany->delete();
         return ['success'=>$re];
     }

+ 264 - 112
app/Http/Controllers/LaborReportController.php

@@ -2,144 +2,296 @@
 
 namespace App\Http\Controllers;
 
+use App\Events\ClockoutEvent;
+use App\Events\GuardAuditEvent;
+use App\Events\TeamAuditEvent;
 use App\Exports\Export;
+use App\LaborCompany;
 use App\LaborReport;
+use App\LaborReportStatus;
+use App\Services\common\ExportService;
+use App\Services\LaborReportService;
 use App\UserDutyCheck;
 use App\UserWorkgroup;
 use Carbon\Carbon;
+use Exception;
 use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Gate;
+use Illuminate\Support\Facades\Http;
 use Maatwebsite\Excel\Facades\Excel;
 
 class LaborReportController extends Controller
 {
-    //超15天精确查询抽离 cloumn前提:数据库字段名必须与request内字段名一致
-    public function preciseQuery(string $column,Request $request,$laborReports){
-        $today=Carbon::now()->subDays(15);
-        $laborReportsTem=clone $laborReports;
-        $laborReportsTem=$laborReportsTem->where($column,'like','%'.$request->input($column).'%')->where('created_at','>',$today->format('Y-m-d'));
-        if($laborReportsTem->count()==0
-            ||$laborReportsTem->first()[$column]==$request->input($column)){
-            $laborReports=$laborReports->where($column,$request->input($column));
-        }else{
-            $laborReports=$laborReportsTem;
-        }
-        return $laborReports;
-    }
-
-    public function conditionQuery(Request $request,$laborReports){
-        if ($request->input('enter_number')){
-            $laborReports=$this->preciseQuery('enter_number',$request,$laborReports);
-        }
-        if ($request->input('user_workgroup_id')){
-            $laborReports=$this->preciseQuery('user_workgroup_id',$request,$laborReports);
-        }
-        if ($request->input('created_at_start')){
-            $created_at_start=$request->input('created_at_start')." 00:00:00";
-            $laborReports=$laborReports->where('created_at','>=',$created_at_start);
-        }
-        if ($request->input('created_at_end')){
-            $created_at_end=$request->input('created_at_end')." 23:59:59";
-            $laborReports=$laborReports->where('created_at','<=',$created_at_end);
-        }
-        if ($request->input('mobile_phone')){
-            $laborReports=$laborReports->where('mobile_phone',$request->input('mobile_phone'));
-        }
-        if ($request->input('identity_number')){
-            $laborReports=$this->preciseQuery('identity_number',$request,$laborReports);
-        }
-        return $laborReports;
+    public function __construct()
+    {
+        app()->singleton('laborReportService',LaborReportService::class);
     }
     /**
      * Display a listing of the resource.
-     *@param  \Illuminate\Http\Request  $request
-     * @return \Illuminate\Http\Response
+     * @param  Request $request
+     * @return void
      * 临时工报表
      */
     public function index(Request $request)
     {
-        if (!Gate::allows('人事管理-临时工报表 ')){return redirect(url('/')); }
-        if ($request->input()){
-            $laborReports=LaborReport::orderBy('id','DESC');
-            $laborReports=$this->conditionQuery($request,$laborReports);
-            $laborReports=$laborReports->paginate($request->input('paginate')?$request->input('paginate'):50);
-            $userWorkGroups=UserWorkgroup::select('id','name')->get();
-            return view('personnel.laborReport.index',['laborReports'=>$laborReports,'userWorkGroups'=>$userWorkGroups,'request'=>$request->input()]);
+        if(!Gate::allows('人事管理-临时工报表')){ view('personnel/index');  }
+        $paginateParams=$request->input();
+        $user=Auth::user();
+        if (!$user)return redirect('/');
+        $laravelEchoPrefix = config('database.redis.options.prefix');
+        $tokenOfBroadcastEnterAndLeave='';
+        if(Gate::allows('人事管理-临时工报表-可见全部组')||Gate::allows('人事管理-门卫审核')){
+            $tokenOfBroadcastEnterAndLeave=LaborReport::tokenOfBroadcastEnterAndLeave();
         }
-        $laborReports=LaborReport::with(['userWorkgroup','user'])->orderBy('id','DESC')->paginate(50);
+        $userWorkgroupIds=$user->getPermittingWorkgroupIds(Gate::allows('人事管理-临时工报表-可见全部组'));
+        $permittingWorkgroups=UserWorkgroup::whereIn('id',$userWorkgroupIds)->get();
+        if($permittingWorkgroups->isEmpty())$permittingWorkgroups="[]";
+        $laborReports=app('laborReportService')->paginate($request->input());
         foreach ($laborReports as $laborReport){
-            $date=Carbon::parse($laborReport->check_in_at)->format('Y-m-d');
-            $userDutyCheckStart=UserDutyCheck::where('user_id',$laborReport->user_id)->where('workgroup_id',$laborReport->user_workgroup_id)->where('checked_at','>=',$date." 11:00".":00")
-                ->where('checked_at','<=',$date." 14:00:00")->where('type','登出')->first();
-            $userDutyCheckEnd=UserDutyCheck::where('user_id',$laborReport->user_id)->where('workgroup_id',$laborReport->user_workgroup_id)->where('checked_at','>=',$date." 11:00".":00")
-                ->where('checked_at','<=',$date." 14:00:00")->where('type','登入')->first();
-            if ($userDutyCheckStart['checked_at']==null){
-                $laborReport->beginLunch=null;
-            }else{
-                $laborReport->beginLunch=date('H:i',strtotime($userDutyCheckStart['checked_at']));
+            if (!$laborReport->group_user_id){
+                //2小时之内组长未审核实行软删除
+                $tenMinutesLater=Carbon::parse($laborReport->created_at)->subHours(-2)->format('Y-m-d H:i:s');
+                if (Carbon::now()->format('Y-m-d H:i:s')>$tenMinutesLater){
+                    $laborReport->delete();
+                    app('LogService')->log(__METHOD__,"组长未审核该条记录将在10分钟后实行软删除__".__FUNCTION__,$laborReport->toJson(),Auth::user()['id']);
+                }
             }
-            if ($userDutyCheckEnd['checked_at']==null){
-                $laborReport->endLunch=null;
-            }else{
-                $laborReport->endLunch=date('H:i',strtotime($userDutyCheckEnd['checked_at']));
+            $addOneHourCheckedAt=Carbon::parse($laborReport->userDutyCheck['checked_at'])->subHours(-1)->format('Y-m-d H:i:s');
+            if (!$laborReport->userDutyCheck['verify_user_id']&&Carbon::now()->format('Y-m-d H:i:s')>$addOneHourCheckedAt){
+                $laborReport->delete();
+                app('LogService')->log(__METHOD__,"进场门卫未审核该条记录将在一小时后实行软删除__".__FUNCTION__,$laborReport->toJson(),Auth::user()['id']);
             }
         }
-        $userWorkGroups=UserWorkgroup::select('id','name')->get();
-        return view('personnel/laborReport/index',['laborReports'=>$laborReports,'userWorkGroups'=>$userWorkGroups,]);
+        $totalWorkingHours=$this->getTotalWorkingHours($request->input());
+        $laborCompanies=LaborCompany::query()->get();
+        $userWorkGroups=UserWorkgroup::query()->select('id','name')->get();
+        return view('personnel/laborReport/index',compact('laborReports','userWorkGroups','laborCompanies','laravelEchoPrefix','permittingWorkgroups','paginateParams','tokenOfBroadcastEnterAndLeave','totalWorkingHours'));
+    }
+    public function getTotalWorkingHours($param){
+        $totalLaborReports=app('laborReportService')->get($param);
+        $totalWorkingHours=0;
+        foreach ($totalLaborReports as $totalLaborReport){
+            $totalWorkingHours=$totalWorkingHours+$totalLaborReport->thisRoundRecordWorkingTime;
+        }
+        return $totalWorkingHours;
+    }
+    public function export(Request $request){
+        if (!Gate::allows('人事管理-临时工报表')){return redirect(url('/')); }
+        if ($request->checkAllSign){
+            $params = $request->input();
+            unset($params["checkAllSign"]);
+            $laborReports=app('laborReportService')->get($params);
+        }else{
+            $laborReports=app('laborReportService')->get(["id"=>$request->data]);
+        }
+        $row = ['本次工作时长','小组','临时工','电话','身份证号','劳务所','进场时间','进组时间','退组时间','进组取整时间','退组取整时间','退场时间','审核时间','审核人','晚饭时间(分)','在线时长','进场编号','备注'];
+        $list = [];
+        foreach ($laborReports as $laborReport){
+            $list[] = [
+                $laborReport->working_duration,
+                $laborReport->userWorkgroup ? $laborReport->userWorkgroup->name : null,
+                $laborReport->name,
+                $laborReport->mobile_phone,
+                $laborReport->identity_number,
+                $laborReport->laborCompany ? $laborReport->laborCompany->name : null,
+                $laborReport->enter_at,
+                $laborReport->check_in_at,
+                $laborReport->check_out_at,
+                $laborReport->round_check_in_at,
+                $laborReport->round_check_out_at,
+                $laborReport->exit_at,
+                $laborReport->verify_at,
+                $laborReport->user ? $laborReport->user->name : null,
+                (string)$laborReport->relax_time,
+                $laborReport->online_duration,
+                $laborReport->enter_number,
+                $laborReport->remark,
+            ];
+        }
+        return app(ExportService::class)->json($row,$list,"临时工报表记录");
+    }
+
+    //门卫打卡审核
+    public function guardClockAudit(Request $request){
+        if(!Gate::allows('人事管理-门卫审核')){ return ["success"=>false,"data"=>"您无此权限操作!!!"];  }
+        $id=$request->input('id');
+        $userDutyCheckId=$request->input('user_duty_check_id');
+        $laborReportStatus=new LaborReportStatus([
+            'labor_report_id'=>$id,
+            'status'=>'已入场',
+        ]);
+        $laborReportStatus->save();
+        app('LogService')->log(__METHOD__,"门卫打卡审核修改当前临时工报表状态".__FUNCTION__,json_encode($laborReportStatus),Auth::user()['id']);
+        $userDutyCheck=UserDutyCheck::find($userDutyCheckId);
+        $userDutyCheck->verify_user_id=Auth::user()['id'];
+        $userDutyCheck->update();
+        app('LogService')->log(__METHOD__,"门卫打卡审核".__FUNCTION__,json_encode($userDutyCheck),Auth::user()['id']);
+        event(new GuardAuditEvent($userDutyCheck));
+        return ["success"=>true,"data"=>$userDutyCheck->verify_user_id];
+    }
+    //打卡组长审核
+    public function groupClockAudit(Request $request){
+        if(!Gate::allows('人事管理-组长审核')){ return ["success"=>false,"data"=>"您无此权限操作!"];  }
+        $id=$request->input('id');
+        $laborReport=LaborReport::find($id);
+        $laborReport->group_user_id=Auth::user()['id'];
+        $laborReport->verify_at=date('Y-m-d H:i:s');
+        $laborReport->update();
+        $laborReport->verifyPerson=Auth::user()['name'];
+        app('LogService')->log(__METHOD__,"打卡组长审核".__FUNCTION__,json_encode($laborReport),Auth::user()['id']);
+        event(new TeamAuditEvent($laborReport));
+        return ["success"=>true,"data"=>$laborReport];
+    }
+    //打卡组长审核(特定组添加备注)
+    public function addRemarkAndGroupClock(Request $request){
+        if(!Gate::allows('人事管理-组长审核')){ return ["success"=>false,"data"=>"您无此权限操作!"];  }
+        $id=$request->input('id');
+        $remark=$request->input('remark');
+        if(!$remark){ return ["success"=>false,"data"=>"您还未添加任何备注,请返回添加备注!"];  }
+        $laborReport=LaborReport::find($id);
+        $laborReport->group_user_id=Auth::user()['id'];
+        $laborReport->verify_at=date('Y-m-d H:i:s');
+        $laborReport->update();
+        /**
+         * @var LaborReportService $laborReportService
+         */
+        $laborReportService=app(LaborReportService::class);
+        $laborReportService->addOrUpdateRemark($remark,$id);
+        $laborReport->verifyPerson=Auth::user()['name'];
+        app('LogService')->log(__METHOD__,"打卡组长审核并添加相应备注".__FUNCTION__,json_encode($laborReport),Auth::user()['id']);
+        event(new TeamAuditEvent($laborReport));
+        return ["success"=>true,"data"=>$laborReport];
+    }
+
+    //组长点击退组
+    public function groupExport(Request $request){
+        if(!Gate::allows('人事管理-组长审核')){ return ["success"=>false,"data"=>"您无此权限操作!"];  }
+        $id=$request->input('id');
+        $laborReport=LaborReport::query()->find($id);
+        $laborReportStatus=new LaborReportStatus([
+            'labor_report_id'=>$id,
+            'status'=>'已退组',
+        ]);
+        $laborReportStatus->save();
+        app('LogService')->log(__METHOD__,"报表记录退组对应状态".__FUNCTION__,json_encode($laborReportStatus),Auth::user()['id']);
+        $check_out_at=Carbon::now()->format('Y-m-d H:i:s');
+        $check_in_at=$laborReport->check_in_at;
+        $laborReport->check_out_at=$check_out_at;
+        $online_duration=round(Carbon::parse($check_out_at)->diffInSeconds(Carbon::parse($check_in_at))/3600,2);
+        $round_time=round(Carbon::parse($laborReport->round_check_out_at)->diffInSeconds(Carbon::parse($laborReport->round_check_in_at))/3600,2);
+        $laborReport->working_duration=$this->minusLunchTime($laborReport,$round_time);
+        if ($laborReport['enter_at']){
+            $enter_at=$laborReport['enter_at'];
+            $laborReport->online_duration=round(Carbon::parse($check_out_at)->diffInSeconds(Carbon::parse($enter_at))/3600,2);
+        }else{
+            $laborReport->online_duration=$online_duration;
+        }
+        $laborReport->update();
+        $laborReport->is_exportGroup=$laborReport->getIsExportGroupAttribute();
+        app('LogService')->log(__METHOD__,"退组".__FUNCTION__,json_encode($laborReport),Auth::user()['id']);
+        event(new ClockoutEvent($laborReport));
+        return ["success"=>true,"data"=>$laborReport];
+    }
 
+    //晚19点后组长点击退场,判断是否有晚餐情况
+    public function groupExportEnsure(Request $request){
+        if(!Gate::allows('人事管理-组长审核')){ return ["success"=>false,"data"=>"您无此权限操作!"];  }
+        $id=$request->input('id');
+        $relax_time=$request->input('relax_time');
+        if(!$relax_time){ return ["success"=>false,"data"=>"未选择确切晚饭时间,请重新选择!"];  }
+        $laborReport=LaborReport::find($id);
+        $laborReportStatus=new LaborReportStatus([
+            'labor_report_id'=>$id,
+            'status'=>'已退组',
+        ]);
+        $laborReportStatus->save();
+        app('LogService')->log(__METHOD__,"报表记录退组对应状态".__FUNCTION__,json_encode($laborReportStatus),Auth::user()['id']);
+        $check_out_at=Carbon::now()->format('Y-m-d H:i:s');
+        $check_in_at=$laborReport->check_in_at;
+        $laborReport->check_out_at=$check_out_at;
+        $online_duration=round(Carbon::parse($check_out_at)->diffInSeconds(Carbon::parse($check_in_at))/3600,2);
+        $round_time=round(Carbon::parse($laborReport->round_check_out_at)->diffInSeconds(Carbon::parse($laborReport->round_check_in_at))/3600,2);
+        if ($relax_time){
+            $laborReport->relax_time=$relax_time;
+            $laborReport->working_duration=$this->minusLunchTime($laborReport,$round_time)-$relax_time/60;//减去晚饭时间
+        }else{
+            $laborReport->working_duration=$this->minusLunchTime($laborReport,$round_time);
+        }
+        if ($laborReport->enter_at){
+            $enter_at=$laborReport['enter_at'];
+            $laborReport->online_duration=round(Carbon::parse($check_out_at)->diffInSeconds(Carbon::parse($enter_at))/3600,2);
+        }else{
+            $laborReport->online_duration=$online_duration;
+        }
+        $laborReport->update();
+        $laborReport->is_exportGroup=$laborReport->getIsExportGroupAttribute();
+        app('LogService')->log(__METHOD__,"退组".__FUNCTION__,json_encode($laborReport),Auth::user()['id']);
+        event(new ClockoutEvent($laborReport));
+        return ["success"=>true,"data"=>$laborReport];
     }
 
-    public function export($id,Request $request){
-        if (!Gate::allows('人事管理-临时工报表 ')){return redirect(url('/')); }
-        ini_set('max_execution_time',3500);
-        ini_set('memory_limit','3526M');
-        if ($id==-1){
-            $id=[];
-            $laborReports=LaborReport::select('id');
-            $laborReports=$this->conditionQuery($request,$laborReports);
-            $laborReports=$laborReports->get();
-            foreach ($laborReports as $laborReports){
-                array_push($id,$laborReports->id);
-            }
-        }else $id = explode( ',',$id);
-        if (!$id)return ;
-        $row=[[
-            'id'=>'ID',
-            'created_at'=>'创建时间',
-            'enter_number'=>'进厂编号',
-            'user_workgroup_name'=>'小组',
-            'name'=>'临时工',
-            'mobile_phone'=>'电话',
-            'identity_number'=>'身份证号',
-            'labor_company'=>'劳务所',
-            'check_in_at'=>'打卡时间',
-            'verify_at'=>'审核时间',
-            'group_user_id'=>'审核人',
-            'check_out_at'=>'退场时间',
-            'online_duration'=>'在线时长',
-            'working_duration'=>'本次工作时长',
-        ]];
-        $list=[];
-        for ($i=0; $i<count($id);$i++){
-            $laborReport=LaborReport::with(['userWorkgroup','user'])->find($id[$i]);
-            $w=[
-                'id'=>isset($laborReport->id)?$laborReport->id:'',
-                'created_at'=>isset($laborReport->created_at)?$laborReport->created_at:'',
-                'enter_number'=>isset($laborReport->enter_number)?$laborReport->enter_number:'',
-                'user_workgroup_name'=>isset($laborReport->userWorkgroup->name)?$laborReport->userWorkgroup->name:'',
-                'name'=>isset($laborReport->name)?$laborReport->name:'',
-                'mobile_phone'=>isset($laborReport->mobile_phone)?$laborReport->mobile_phone:'',
-                'identity_number'=>isset($laborReport->identity_number)?$laborReport->identity_number:'',
-                'labor_company'=>isset($laborReport->labor_company)?$laborReport->labor_company:'',
-                'check_in_at'=>isset($laborReport->check_in_at)?$laborReport->check_in_at:'',
-                'verify_at'=>isset($laborReport->verify_at)?$laborReport->verify_at:'',
-                'group_user_id'=>isset($laborReport->user->name)?$laborReport->user->name:'',
-                'check_out_at'=>isset($laborReport->check_out_at)?$laborReport->check_out_at:'',
-                'online_duration'=>isset($laborReport->online_duration)?$laborReport->online_duration:'',
-                'working_duration'=>isset($laborReport->working_duration)?$laborReport->working_duration:'',
-            ];
-            $list[$i]=$w;
+    //工作时长减午饭休息时间
+    public function minusLunchTime($laborReport,$hour){
+        $checkInTime=$laborReport->check_in_at;
+        $checkOutTime=$laborReport->check_out_at;
+        $checkOutTime=Carbon::parse($checkOutTime)->format('H');
+        $checkInTime=Carbon::parse($checkInTime);
+        if ($checkInTime->lessThanOrEqualTo($checkInTime->clone()->setHours(11)->setMinutes(30))&&(int)$checkOutTime>=13){
+            $hour=$hour-1;
+        }
+        return $hour;
+    }
+    public function updateLaborCompany(Request $request){
+        if(!Gate::allows('人事管理-临时工报表-修改劳务所')){ return ["success"=>false,"data"=>"您无此权限操作!"];  }
+        $param=$request->input();
+        $enter_number=$request->enter_number;
+        app('laborReportService')->修改劳务所($param);
+        $laborReport=LaborReport::query()->where('enter_number',$enter_number)->first();
+        if ($laborReport->labor_company_id==$request->input('laborCompanyId')){
+            $labor_company=LaborCompany::query()->find($request->input('laborCompanyId'))->value('name');
+            return ['success'=>true,'data'=>$laborReport,'labor_company'=>$labor_company];
+        }else{
+            return ['success'=>true,'data'=>'修改劳务所失败'];
+        }
+    }
+    public function 删除($id){
+        if(!Gate::allows('人事管理-临时工报表-删除')){return['success'=>false,'data'=>'没有权限'];}
+        if(is_null($id)){return ['success'=>false,'data'=>'传入id为空'];}
+        $laborReport=app('laborReportService')->删除($id);
+        if ($laborReport>0)return ['success'=>true,'data'=>$laborReport];
+        return ['success'=>true,'data'=>'删除报表失败'];
+    }
+
+    //回收站
+    function recycle(Request $request){
+        if(!Gate::allows('人事管理-临时工报表-删除')){ return redirect('/');  }
+        $paginateParams=$request->input();
+        $laborReports=LaborReport::query()->with(['user','userDutyCheck','userWorkgroup','laborCompany'])->onlyTrashed()->paginate($request->paginate??50);
+        return view('personnel.laborReport.recycle',compact('laborReports','paginateParams'));
+    }
+
+    //回收站恢复
+    function recover(Request $request){
+        if(!Gate::allows('人事管理-临时工报表-删除')){ return redirect('/');  }
+        $checkData=$request->checkData;
+        app('LogService')->log(__METHOD__,"回收站恢复临时工报表记录_".__FUNCTION__,json_encode($request->input()),Auth::user()['id']);
+        return ['success'=>LaborReport::withTrashed()->whereIn('id',$checkData)->restore()];
+    }
+    public function changeLaborReportRemark(Request $request){
+        if(!Gate::allows('人事管理-临时工报表-编辑备注')){return ['success'=>'false','fail_info'=>'没有权限'];}
+        $laborReportId = $request->input('id');
+        $laborReportRemark = $request->input('remark');
+        if(is_null($laborReportId) ){
+            return ['success'=>false,'fail_info'=>'参数异常'];
         }
-        return Excel::download(new Export($row,$list),date('YmdHis', time()).'-临时工报表记录单.xlsx');
+        $laborReport=LaborReport::find($laborReportId);
+        /**
+         * @var LaborReportService $laborReportService
+         */
+        $laborReportService=app(LaborReportService::class);
+        $laborReportService->addOrUpdateRemark($laborReportRemark,$laborReportId);
+        app('LogService')->log(__METHOD__,'添加或者修改临时工报表备注'.__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        return ['success'=>true,'status'=>$laborReport];
     }
 }

+ 10 - 10
app/Http/Controllers/WMSReflectReceiveController.php → app/Http/Controllers/LaborReportStatusController.php

@@ -2,10 +2,10 @@
 
 namespace App\Http\Controllers;
 
-use App\WMSReflectReceive;
+use App\LaborReportStatus;
 use Illuminate\Http\Request;
 
-class WMSReflectReceiveController extends Controller
+class LaborReportStatusController extends Controller
 {
     /**
      * Display a listing of the resource.
@@ -41,10 +41,10 @@ class WMSReflectReceiveController extends Controller
     /**
      * Display the specified resource.
      *
-     * @param  \App\WMSReflectReceive  $wMSReflectReceive
+     * @param  \App\LaborReportStatus  $laborReportStatus
      * @return \Illuminate\Http\Response
      */
-    public function show(WMSReflectReceive $wMSReflectReceive)
+    public function show(LaborReportStatus $laborReportStatus)
     {
         //
     }
@@ -52,10 +52,10 @@ class WMSReflectReceiveController extends Controller
     /**
      * Show the form for editing the specified resource.
      *
-     * @param  \App\WMSReflectReceive  $wMSReflectReceive
+     * @param  \App\LaborReportStatus  $laborReportStatus
      * @return \Illuminate\Http\Response
      */
-    public function edit(WMSReflectReceive $wMSReflectReceive)
+    public function edit(LaborReportStatus $laborReportStatus)
     {
         //
     }
@@ -64,10 +64,10 @@ class WMSReflectReceiveController extends Controller
      * Update the specified resource in storage.
      *
      * @param  \Illuminate\Http\Request  $request
-     * @param  \App\WMSReflectReceive  $wMSReflectReceive
+     * @param  \App\LaborReportStatus  $laborReportStatus
      * @return \Illuminate\Http\Response
      */
-    public function update(Request $request, WMSReflectReceive $wMSReflectReceive)
+    public function update(Request $request, LaborReportStatus $laborReportStatus)
     {
         //
     }
@@ -75,10 +75,10 @@ class WMSReflectReceiveController extends Controller
     /**
      * Remove the specified resource from storage.
      *
-     * @param  \App\WMSReflectReceive  $wMSReflectReceive
+     * @param  \App\LaborReportStatus  $laborReportStatus
      * @return \Illuminate\Http\Response
      */
-    public function destroy(WMSReflectReceive $wMSReflectReceive)
+    public function destroy(LaborReportStatus $laborReportStatus)
     {
         //
     }

+ 62 - 19
app/Http/Controllers/LogController.php

@@ -3,25 +3,78 @@
 namespace App\Http\Controllers;
 
 use App\Log;
+use App\Services\LogService;
 use Exception;
+use Illuminate\Contracts\Foundation\Application;
+use Illuminate\Contracts\Pagination\LengthAwarePaginator;
+use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Http\RedirectResponse;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
+use Illuminate\Routing\Redirector;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Gate;
 use Illuminate\Support\Facades\Validator;
+use function GuzzleHttp\Psr7\str;
 
 class LogController extends Controller
 {
     /**
      * Display a listing of the resource.
      *
-     * @return Response
+     * @param Request $request
+     * @return Application|LengthAwarePaginator|\Illuminate\Contracts\View\Factory|\Illuminate\View\View
      */
-    public function index()
+    public function index(Request $request)
     {
-        if(!Gate::allows('日志-查询')){ return redirect(url('/'));  }
-        $logs=Log::orderBy('id','desc')->paginate(55);
-        return view('maintenance.log.index',['logs'=>$logs]);
+        if (!Gate::allows('日志-查询')) {
+            return redirect(url('/'));
+        }
+        //没有查询条件,默认展示最近50条
+        if (!$request->has('created_at_start') &&
+            !$request->has('created_at_end') &&
+            !$request->has('operation') &&
+            !$request->has('type') &&
+            !$request->has('description') &&
+            !$request->has("is_exception")
+        ) {
+            $logs = Log::query()
+                ->orderBy('id', 'desc')
+                ->paginate(50);
+            return view('maintenance.log.index', ['logs' => $logs]);
+        }
+        //不传开始时间提示错误信息并返回
+        if (!$request->has('created_at_start')) {
+            session()->flash('warning', '请选择开始时间');
+            return view('maintenance.log.index', ['logs' => null]);
+        }
+        $query = Log::query();
+        if ($request->has('operation')) {
+            $query->where('operation', 'like', $request->operation . '%');
+        }
+        if ($request->has('type')) {
+            $query->where('type', 'like', $request->type . '%');
+        }
+        if ($request->has('description')) {
+            $str = $request->description;
+            $str = trim($str, '\\');
+            $str = str_replace('\\', '\\\\', $str);
+            $query->where('description', 'like', '%' . $str . '%');
+        }
+        if ($request->has('created_at_start')) {
+            $query->where('created_at', '>=', $request->created_at_start);
+        }
+        if ($request->has('created_at_end')) {
+            $query->where('created_at', '<=', $request->created_at_end);
+        }
+        if ($request->has("is_exception")){
+            $query->where(function(Builder $query){
+                $query->where("type","like","ERROR%")->orWhere("type","like","EXCEPTION%");
+            });
+        }
+        $query->orderByDesc('id');
+        $logs = $query->paginate($request->paginate??50);
+        return view('maintenance.log.index', ['logs' => $logs]);
     }
 
     /**
@@ -32,22 +85,12 @@ class LogController extends Controller
      */
     public function show(Log $log)
     {
-        return view('maintenance.log.show',['log'=>$log]);
+        return view('maintenance.log.show', ['log' => $log]);
     }
 
-
-    /**
-     * Remove the specified resource from storage.
-     *
-     * @param Log $log
-     * @return array|Response
-     * @throws Exception
-     */
-    public function destroy(Log $log)
+    public function syncRedisLogs()
     {
-//        if(!Gate::allows('物流公司-删除')){ return redirect(url('/'));  }
-//        $this->log(__METHOD__,__FUNCTION__,$log->toJson(),Auth::user()['id']);
-//        $re=$log->delete();
-//        return ['success'=>$re];
+        LogService::syncRedisLogs();
+        return redirect('maintenance/log');
     }
 }

+ 11 - 7
app/Http/Controllers/LogisticController.php

@@ -48,21 +48,25 @@ class LogisticController extends Controller
         $logistic=new Logistic($request->all());
         $logistic->save();
 
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return redirect('maintenance/logistic/create')->with('successTip',"成功录入物流公司“{$request->input('name')}”");
     }
     protected function validatorCreate(array $data)
     {
         return Validator::make($data, [
+            'type' => ["required"],
             'name' => ['required', 'string', 'max:50', 'unique:logistics'],
             'code' => ['nullable', 'string', 'max:50', 'unique:logistics,code'],
+            'delivery_fee' => ['nullable', 'numeric', 'min:0'],
         ]);
     }
-    protected function validatorUpdate(array $data)
+    protected function validatorUpdate(array $data,$id)
     {
         return Validator::make($data, [
-            'name' => ['required', 'string', 'max:50'],
-            'code' => ['nullable', 'string', 'max:50'],
+            'type' => ["required"],
+            'name' => ['required', 'string', 'max:50',"unique:logistics,name,$id"],
+            'code' => ['nullable', 'string', 'max:50',"unique:logistics,code,$id"],
+            'delivery_fee' => ['nullable', 'numeric', 'min:0'],
         ]);
     }
     /**
@@ -98,10 +102,10 @@ class LogisticController extends Controller
     public function update(Request $request, Logistic $logistic)
     {
         if(!Gate::allows('物流公司-编辑')){ return redirect(url('/'));  }
-        $this->validatorUpdate($request->all())->validate();
+        $this->validatorUpdate($request->all(),$logistic->id)->validate();
         $logistic->fill($request->all());
         $logistic->update();
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return redirect('maintenance/logistic/')->with('successTip',"成功修改物流公司“{$logistic['name']}”!");
     }
 
@@ -115,7 +119,7 @@ class LogisticController extends Controller
     public function destroy(Logistic $logistic)
     {
         if(!Gate::allows('物流公司-删除')){ return redirect(url('/'));  }
-        $this->log(__METHOD__,__FUNCTION__,$logistic->toJson(),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,$logistic->toJson(),Auth::user()['id']);
         $re=$logistic->delete();
         return ['success'=>$re];
     }

+ 2 - 2
app/Http/Controllers/LogisticNumberFeatureController.php

@@ -103,7 +103,7 @@ class LogisticNumberFeatureController extends Controller
         if($numberLength<$featureConsideringLength)
             $featureConsideringLength=$numberLength;
         if(!$logisticNumber){
-            $this->log(__METHOD__, 'error', '创建退货快递单号特征时,单号传入了空值');
+            app('LogService')->log(__METHOD__, 'error', '创建退货快递单号特征时,单号传入了空值');
             return null;
         };
         $featuresCreated=[];
@@ -120,7 +120,7 @@ class LogisticNumberFeatureController extends Controller
     private function createFeature(int $logisticId,string $featureName, string $value,int $weight)
     {
         if(!$value){
-            $this->log(__METHOD__, 'error', "创建退货快递单号特征{$featureName}时,特征值为空");
+            app('LogService')->log(__METHOD__, 'error', "创建退货快递单号特征{$featureName}时,特征值为空");
             return null;
         };
         $feature=LogisticNumberFeature::where('logistic_id',$logisticId)

+ 10 - 10
app/Http/Controllers/WMSWaybillOrderController.php → app/Http/Controllers/LogisticTimingController.php

@@ -2,10 +2,10 @@
 
 namespace App\Http\Controllers;
 
-use App\WMSWaybillOrder;
+use App\LogisticTiming;
 use Illuminate\Http\Request;
 
-class WMSWaybillOrderController extends Controller
+class LogisticTimingController extends Controller
 {
     /**
      * Display a listing of the resource.
@@ -41,10 +41,10 @@ class WMSWaybillOrderController extends Controller
     /**
      * Display the specified resource.
      *
-     * @param  \App\WMSWaybillOrder  $wMSWaybillOrder
+     * @param  \App\LogisticTiming  $logisticTiming
      * @return \Illuminate\Http\Response
      */
-    public function show(WMSWaybillOrder $wMSWaybillOrder)
+    public function show(LogisticTiming $logisticTiming)
     {
         //
     }
@@ -52,10 +52,10 @@ class WMSWaybillOrderController extends Controller
     /**
      * Show the form for editing the specified resource.
      *
-     * @param  \App\WMSWaybillOrder  $wMSWaybillOrder
+     * @param  \App\LogisticTiming  $logisticTiming
      * @return \Illuminate\Http\Response
      */
-    public function edit(WMSWaybillOrder $wMSWaybillOrder)
+    public function edit(LogisticTiming $logisticTiming)
     {
         //
     }
@@ -64,10 +64,10 @@ class WMSWaybillOrderController extends Controller
      * Update the specified resource in storage.
      *
      * @param  \Illuminate\Http\Request  $request
-     * @param  \App\WMSWaybillOrder  $wMSWaybillOrder
+     * @param  \App\LogisticTiming  $logisticTiming
      * @return \Illuminate\Http\Response
      */
-    public function update(Request $request, WMSWaybillOrder $wMSWaybillOrder)
+    public function update(Request $request, LogisticTiming $logisticTiming)
     {
         //
     }
@@ -75,10 +75,10 @@ class WMSWaybillOrderController extends Controller
     /**
      * Remove the specified resource from storage.
      *
-     * @param  \App\WMSWaybillOrder  $wMSWaybillOrder
+     * @param  \App\LogisticTiming  $logisticTiming
      * @return \Illuminate\Http\Response
      */
-    public function destroy(WMSWaybillOrder $wMSWaybillOrder)
+    public function destroy(LogisticTiming $logisticTiming)
     {
         //
     }

+ 85 - 0
app/Http/Controllers/MaterialBoxController.php

@@ -0,0 +1,85 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\MaterialBox;
+use Illuminate\Http\Request;
+
+class MaterialBoxController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function index()
+    {
+        //
+    }
+
+    /**
+     * Show the form for creating a new resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function create()
+    {
+        //
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\Response
+     */
+    public function store(Request $request)
+    {
+        //
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  \App\MaterialBox  $materialBox
+     * @return \Illuminate\Http\Response
+     */
+    public function show(MaterialBox $materialBox)
+    {
+        //
+    }
+
+    /**
+     * Show the form for editing the specified resource.
+     *
+     * @param  \App\MaterialBox  $materialBox
+     * @return \Illuminate\Http\Response
+     */
+    public function edit(MaterialBox $materialBox)
+    {
+        //
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \App\MaterialBox  $materialBox
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, MaterialBox $materialBox)
+    {
+        //
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  \App\MaterialBox  $materialBox
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(MaterialBox $materialBox)
+    {
+        //
+    }
+}

+ 9 - 68
app/Http/Controllers/MeasureMonitorController.php

@@ -2,25 +2,20 @@
 
 namespace App\Http\Controllers;
 
-use App\Events\TeamAuditEvent;
-use App\Events\WeighedEvent;
 use App\MeasuringMachine;
-use App\Package;
+use App\OrderPackage;
 use Illuminate\Http\Request;
-use Illuminate\Support\Facades\DB;
-use Illuminate\Support\Facades\Gate;
 require_once '../app/library/baidu-api-speech/AipSpeech.php';
 class MeasureMonitorController extends Controller
 {
 
     /**
      * Display a listing of the resource.
-     *
      * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
      */
-    public function index(Request $request)
+    public function index()
     {
-        $measuringMachines=MeasuringMachine::select('id','name','code','status')->get();
+        $measuringMachines=MeasuringMachine::query()->select('id','name','code','status')->get();
         $laravelEchoPrefix = config('database.redis.options.prefix');
         return view('weight.measureMonitor.index',compact('laravelEchoPrefix','measuringMachines'));
     }
@@ -28,10 +23,12 @@ class MeasureMonitorController extends Controller
     public function data(Request $request){
         $measuring_machine_id=$request->input('id');
         if ($measuring_machine_id){
-            $package=Package::with('owner','paperBox','measuringMachine')->where('measuring_machine_id',$measuring_machine_id)->orderBy('id','DESC')->first();
+            $package=OrderPackage::with(['order'=>function($query){
+                $query->with('owner','logistic');
+            },'paperBox','measuringMachine'])->where('measuring_machine_id',$measuring_machine_id)->orderBy('id','DESC')->first();
             if (!$package){
-                $measuringMachine=MeasuringMachine::where('id',$measuring_machine_id)->first();
-                $package=new Package();
+                $measuringMachine=MeasuringMachine::query()->where('id',$measuring_machine_id)->first();
+                $package=new OrderPackage();
                 if ($measuringMachine)$package->measuringMachine=$measuringMachine;
             }
             return $package;
@@ -42,7 +39,7 @@ class MeasureMonitorController extends Controller
 
     public function speech(Request $request){
         $logistic=$request->input('logistic');
-        if (!$logistic)return '';
+        if (!$logistic)$logistic='空';
         if (file_exists("storage/".$logistic.'.mp3')){
             return "/storage/".$logistic.'.mp3';
         }
@@ -59,60 +56,4 @@ class MeasureMonitorController extends Controller
         }
         return "/storage/".$logistic.'.mp3';
     }
-
-    /**
-     * Store a newly created resource in storage.
-     *
-     * @param  \Illuminate\Http\Request  $request
-     * @return \Illuminate\Http\Response
-     */
-    public function store(Request $request)
-    {
-        //
-    }
-
-    /**
-     * Display the specified resource.
-     *
-     * @param  int  $id
-     * @return \Illuminate\Http\Response
-     */
-    public function show($id)
-    {
-        //
-    }
-
-    /**
-     * Show the form for editing the specified resource.
-     *
-     * @param  int  $id
-     * @return \Illuminate\Http\Response
-     */
-    public function edit($id)
-    {
-        //
-    }
-
-    /**
-     * Update the specified resource in storage.
-     *
-     * @param  \Illuminate\Http\Request  $request
-     * @param  int  $id
-     * @return \Illuminate\Http\Response
-     */
-    public function update(Request $request, $id)
-    {
-        //
-    }
-
-    /**
-     * Remove the specified resource from storage.
-     *
-     * @param  int  $id
-     * @return \Illuminate\Http\Response
-     */
-    public function destroy($id)
-    {
-        //
-    }
 }

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

@@ -95,7 +95,7 @@ class MeasuringMachineController extends Controller
     {
         if(!Gate::allows('测量设备-删除')){ return redirect(url('/'));  }
         $measuringMachine=MeasuringMachine::find($id)->delete();
-        $this->log(__METHOD__,__FUNCTION__,json_encode($measuringMachine),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($measuringMachine),Auth::user()['id']);
         if ($measuringMachine)return ['success'=>true];
     }
 

+ 10 - 10
app/Http/Controllers/WMSWaybillController.php → app/Http/Controllers/OrderBinController.php

@@ -2,10 +2,10 @@
 
 namespace App\Http\Controllers;
 
-use App\WMSWaybill;
+use App\OrderBin;
 use Illuminate\Http\Request;
 
-class WMSWaybillController extends Controller
+class OrderBinController extends Controller
 {
     /**
      * Display a listing of the resource.
@@ -41,10 +41,10 @@ class WMSWaybillController extends Controller
     /**
      * Display the specified resource.
      *
-     * @param  \App\WMSWaybill  $wMSWaybill
+     * @param  \App\OrderBin  $orderBin
      * @return \Illuminate\Http\Response
      */
-    public function show(WMSWaybill $wMSWaybill)
+    public function show(OrderBin $orderBin)
     {
         //
     }
@@ -52,10 +52,10 @@ class WMSWaybillController extends Controller
     /**
      * Show the form for editing the specified resource.
      *
-     * @param  \App\WMSWaybill  $wMSWaybill
+     * @param  \App\OrderBin  $orderBin
      * @return \Illuminate\Http\Response
      */
-    public function edit(WMSWaybill $wMSWaybill)
+    public function edit(OrderBin $orderBin)
     {
         //
     }
@@ -64,10 +64,10 @@ class WMSWaybillController extends Controller
      * Update the specified resource in storage.
      *
      * @param  \Illuminate\Http\Request  $request
-     * @param  \App\WMSWaybill  $wMSWaybill
+     * @param  \App\OrderBin  $orderBin
      * @return \Illuminate\Http\Response
      */
-    public function update(Request $request, WMSWaybill $wMSWaybill)
+    public function update(Request $request, OrderBin $orderBin)
     {
         //
     }
@@ -75,10 +75,10 @@ class WMSWaybillController extends Controller
     /**
      * Remove the specified resource from storage.
      *
-     * @param  \App\WMSWaybill  $wMSWaybill
+     * @param  \App\OrderBin  $orderBin
      * @return \Illuminate\Http\Response
      */
-    public function destroy(WMSWaybill $wMSWaybill)
+    public function destroy(OrderBin $orderBin)
     {
         //
     }

+ 35 - 0
app/Http/Controllers/OrderCommodityAssignController.php

@@ -0,0 +1,35 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Imports\UpdatePickZone;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Gate;
+use Maatwebsite\Excel\Facades\Excel;
+
+class OrderCommodityAssignController extends Controller
+{
+    public function index()
+    {
+        if(!Gate::allows('指定分配-查询')){ return redirect(url('denied'));  }
+        $assigns = app("OrderCommodityAssignService")->paginate();
+        return view("order.index.index",compact("assigns"));
+    }
+
+    public function import(Request $request)
+    {
+        if(!Gate::allows('指定分配-编辑')){ return ["success"=>false,"data"=>"无权操作!"];  }
+        $fileSuffix=$request->file('file')->getClientOriginalExtension();
+        if ($fileSuffix != 'xlsx' && $fileSuffix != 'xls' && $fileSuffix != 'csv')
+            return ['success'=>false,'data'=>'不支持该文件类型'];
+        ini_set('max_execution_time',2500);
+        ini_set('memory_limit','1526M');
+        $fileSuffix = ucwords($fileSuffix);
+
+        Excel::import(new UpdatePickZone(),$request->file('file')->path(),null,$fileSuffix);
+        if (Cache::has('commodityAssign'))return Cache::pull('commodityAssign');
+
+        return ["success"=>false,"data"=>"导入发生错误,数据无响应"];
+    }
+}

+ 85 - 0
app/Http/Controllers/OrderCommodityController.php

@@ -0,0 +1,85 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\OrderCommodity;
+use Illuminate\Http\Request;
+
+class OrderCommodityController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function index()
+    {
+        //
+    }
+
+    /**
+     * Show the form for creating a new resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function create()
+    {
+        //
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\Response
+     */
+    public function store(Request $request)
+    {
+        //
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  \App\OrderCommodity  $orderCommodity
+     * @return \Illuminate\Http\Response
+     */
+    public function show(OrderCommodity $orderCommodity)
+    {
+        //
+    }
+
+    /**
+     * Show the form for editing the specified resource.
+     *
+     * @param  \App\OrderCommodity  $orderCommodity
+     * @return \Illuminate\Http\Response
+     */
+    public function edit(OrderCommodity $orderCommodity)
+    {
+        //
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \App\OrderCommodity  $orderCommodity
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, OrderCommodity $orderCommodity)
+    {
+        //
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  \App\OrderCommodity  $orderCommodity
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(OrderCommodity $orderCommodity)
+    {
+        //
+    }
+}

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

@@ -0,0 +1,295 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\OracleBasCustomer;
+use App\OracleDOCOrderHeader;
+use App\OracleDOCWaveDetails;
+use App\OrderIssueType;
+use App\Services\LogService;
+use App\Services\OrderService;
+use App\Services\RejectedBillItemService;
+use App\Services\RejectedBillService;
+use Exception;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Gate;
+use Illuminate\Support\Facades\Http;
+
+class OrderController extends Controller
+{
+    public function delivering(Request $request){
+        if(!Gate::allows('订单管理-查询')){ return view('order/index');  }
+        /** @var OrderService $orderService */
+        $orderService = app('OrderService');
+        $request = $request->input();
+        $owners = app('OwnerService')->getSelection(['id','code']);
+        $codes = array_column($owners->toArray(),'code');
+        if ($request['customerid'] ?? false){
+            $arr = explode(',',$request['customerid']);
+            $request['customerid'] = [];
+            foreach ($arr as $value){
+                if (in_array($value,$codes))$request['customerid'][] = $value;
+            }
+            if (count($request['customerid']) < 1)$request['customerid'] = [''];
+        }else $request['customerid'] = $codes;
+
+        $result = $orderService->paginate($request);
+        $picktotraceids = $result['picktotraceids'];
+        $orders = $result['orders'];
+        $orderIssueNos =  $orderService->返回有问题件的订单号($orders);
+        $commodities = $result['commodities'];
+        $customers=app('OracleBasCustomerService')->getCustomers($codes);
+        $page = $request["page"] ?? 1;
+        $codes=DB::connection('oracle')->table('BAS_CODES')->select('code','codename_c')->where('codeid','SO_STS')->orderBy('code','asc')->get();
+        $orderIssueType = OrderIssueType::all();
+        return view('order/index/delivering',compact('orders','customers','request','codes','commodities','page','picktotraceids','orderIssueType','orderIssueNos'));
+    }
+
+    //导出
+    public function export(Request $request){
+        $is_merge = $request->is_merge ?? false;
+        /** @var OrderService $orderService */
+        $orderService = app('OrderService');
+        $req = ['type'=>'order'];
+        if ($is_merge && $is_merge == 'true')$req["createFormat"] = "merge";
+        if ($request->data){
+            $req["sql"] = $orderService->getSql(['data'=>$request->data]);
+        }else{
+            $req["sql"] = $orderService->getSql($request->input());
+        }
+        $post = Http::post(config('go.export.url'),$req);
+        if ($post->status() == 500){
+            throw new Exception($post->header("Msg"));
+        }
+        return response($post,200, [
+            "Content-type"=>"application/octet-stream",
+            "Content-Disposition"=>"attachment; filename=订单记录-".date('ymdHis').'.xlsx',
+        ]);
+    }
+
+    public function createRejectedBill(Request $request){
+        if(!Gate::allows('订单管理-订单-生成退货单')){ return ['success'=>false,'data'=>'您无权操作!'];  }
+        /** @var OrderService $orderService */
+        $orderService = app('OrderService');
+        $result = $orderService->get(['data' => $request->data]);
+
+        /** @var RejectedBillService $rejectedBillService */
+        $rejectedBillService = app('RejectedBillService');
+
+        /** @var RejectedBillItemService $rejectedBillItemService */
+        $rejectedBillItemService = app('RejectedBillItemService');
+
+        $commodities = $result['commodities'];
+        $rejectedBillItems = [];
+        //分箱号
+        $picktotraceids = json_decode($result['picktotraceids'],true);
+        $rejectedBill_collect = collect();// 保存生成的rejectedBill
+        foreach ($result['orders'] as $order){
+            //不存在时将当前快递单号视为分箱号
+            if (!($picktotraceids[$order->orderno] ?? false))$picktotraceids[$order->orderno] = [$order->soreference5];
+            //获取货主与快递方
+            $owner = app('OwnerService')->firstOrCreate(['name' => $order->customer_descr_c],
+                ['name' => $order->customer_descr_c, 'code' => $order->customer_descr_c]);
+            $logistic = app('LogisticService')->firstOrCreate(['name' => $order->carriername],
+                ['name' => $order->carriername, 'code' => $order->carriername]);
+            foreach ($picktotraceids[$order->orderno] as $orderno){
+                $rejectedBill = $rejectedBillService->create([
+                    'id_owner' => $owner->id,
+                    'sender' => $order->c_contact,
+                    'logistic_number_return' => $orderno,
+                    'id_logistic_return' => $logistic->id,
+                    'order_number' => $order->soreference1,
+                    'mobile_sender' => empty($order->c_tel2)?$order->c_tel1:$order->c_tel2,
+                    'logistic_number' => '原单退回',//$order->soreference1
+                    'remark' => $order->notes,
+                    'is_loaded' =>0,
+                    "id_operator" => Auth::id(),
+                ]);
+                $rejectedBill_collect->push($rejectedBill);// 保存生成的rejectedBill
+                LogService::log(__METHOD__,"生成退货单",json_encode($order),Auth::user()['id']);
+                if ($commodities[$order->orderno] ?? false){
+                    foreach ($commodities[$order->orderno] as $orderCommodities){
+                        array_push($rejectedBillItems,[
+                            'id_rejected_bill' => $rejectedBill->id,
+                            'barcode_goods' => $orderCommodities['alternate_sku1'],
+                            'name_goods' => $orderCommodities['descr_c'],
+                            'amount' => $orderCommodities['qtyordered'],
+                            'id_quality_label' => 1,
+                            'created_at' => date('Y-m-d H:i:s'),
+                        ]);
+                    }
+                }
+            }
+        }
+        $rejectedBillItemService->insert($rejectedBillItems);
+        LogService::log(__METHOD__,"批量生成退货单详情",json_encode($rejectedBillItems),Auth::user()['id']);
+        $rejectedBill_collect->each(function($rejectedBill)use($rejectedBillService){
+            $rejectedBillService->syncOrderIssue($rejectedBill);
+        });
+        return ['success'=>true];
+    }
+
+    public function isRejectedBillExist(Request $request){
+        if(!Gate::allows('订单管理-订单-生成退货单')){ return redirect(url('/'));  }
+        /** @var RejectedBillService $rejectedBillService */
+        $rejectedBillService = app('RejectedBillService');
+        $rejectedBills = $rejectedBillService->get(['order_number' => $request->data]);
+        if (count($rejectedBills) == 0)return ['success'=>true];
+        return ['success'=>false, 'data'=>json_encode(array_column($rejectedBills->toArray(),'order_number'))];
+    }
+
+    //批量备注追加
+    public function batchComments(Request $request){
+        if(!Gate::allows('订单管理-批量备注')){ return redirect(url('/'));  }
+        $checkData=$request->input('checkData');
+        $content=$request->input('content');
+        $ordersNotNull=OracleDOCOrderHeader::query()->select('OrderNo','Notes')->whereIn('orderno',$checkData)
+            ->whereNotNull('notes')->get();
+        OracleDOCOrderHeader::query()->select('OrderNo','Notes')->whereIn('orderno',$checkData)
+            ->whereNull('notes')->update(['notes'=>$content]);
+        $ordersNotNullArr=array_column($ordersNotNull->toArray(),'orderno');
+        $ordersNullArr=array_diff($checkData,$ordersNotNullArr);
+        $data=[];
+        foreach ($ordersNotNull as $order){
+            OracleDOCOrderHeader::query()->where('orderno',$order->orderno)->update(["notes"=>($order->notes).",".$content]);
+            app('LogService')->log(__METHOD__,'批量备注追加修改'.__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+            $order->notes=($order->notes).",".$content;
+            array_push($data,$order);
+        }
+        foreach ($ordersNullArr as $order){
+            array_push($data,["orderno"=>$order,'notes'=>$content]);
+        }
+        return $data;
+    }
+    //批量冻结
+    public function freezeAll(Request $request){
+        if(!Gate::allows('订单管理-编辑')){ return redirect(url('/'));  }
+        $checkData=$request->input('checkData')??'';
+        //冻结条件只局限于 分配完成sostatus=40  创建订单sostatus=00  拣货完成sostatus=60  播种完成sostatus=61
+        $sostatus=['40','00','60','61'];
+        $orders=OracleDOCOrderHeader::select('OrderNo','SoStatus')->whereIn('orderno',$checkData)->whereIn('SoStatus',$sostatus)->get();
+        if(count($checkData)!=count($orders))return ['success'=>false,'fail_info'=>"勾选订单有不可冻结订单"];
+        foreach ($orders as $order){
+            $waveno=OracleDOCOrderHeader::where('orderno',$order->orderno)->value('waveno');
+            if ($waveno && $waveno!='*'){
+                OracleDOCWaveDetails::where('waveno',$waveno)->where('orderno',$order->orderno)->delete();
+                app('LogService')->log(__METHOD__,'批量冻结删除波次号'.__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+            }
+            $is_freeze=OracleDOCOrderHeader::where('orderno',$order->orderno)->update(['releasestatus'=>'H','waveno'=>'*']);
+            app('LogService')->log(__METHOD__,'批量冻结修改'.__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+            if (!$is_freeze)return ['success'=>false,'fail_info'=>"数据 {$order['orderno']} 更新失败"];
+        }
+        return ['success'=>true];
+    }
+    //批量取消分配
+    public function deAllocationAll(Request $request){
+        if(!Gate::allows('订单管理-编辑')){ return redirect(url('/'));  }
+        $checkData=$request->input('checkData')??'';
+        //取消分配条件只局限于 分配完成sostatus=40 和 部分分配sostatus=30
+        $sostatus=['30','40'];
+        $orders=OracleDOCOrderHeader::select('OrderNo','SoStatus')->whereIn('orderno',$checkData)->whereIn('SoStatus',$sostatus)->get();
+        if(count($checkData)!=count($orders))return ['success'=>false,'fail_info'=>"勾选订单有不可取消分配订单"];
+        foreach ($orders as $order){
+            $is_deAllocation=$this->isDeAllocation($order->orderno);
+            $waveno=OracleDOCOrderHeader::where('orderno',$order->orderno)->value('waveno');
+            if ($waveno && $waveno!='*'){
+                OracleDOCWaveDetails::where('waveno',$waveno)->where('orderno',$order->orderno)->delete();
+                app('LogService')->log(__METHOD__,'批量取消分配删除波次号'.__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+            }
+            $deAllocation=OracleDOCOrderHeader::where('orderno',$order->orderno)->update(['sostatus'=>'00','waveno'=>'*']);
+            app('LogService')->log(__METHOD__,'批量取消分配'.__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+            if (!$is_deAllocation||!$deAllocation)return ['success'=>false,'fail_info'=>"数据 {$order['orderno']} 更新失败"];
+        }
+        return ['success'=>true];
+    }
+    //冻结
+    public function freeze(Request $request){
+        if(!Gate::allows('订单管理-编辑')){ return redirect(url('/'));  }
+        $orderno=$request->input('orderno');
+        $waveno=$request->input('waveno');
+        if ($waveno && $waveno!='*'){
+            OracleDOCWaveDetails::where('waveno',$waveno)->where('orderno',$orderno)->delete();
+            app('LogService')->log(__METHOD__,'冻结删除波次号'.__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        }
+        OracleDOCOrderHeader::where('orderno',$orderno)->update(['releasestatus'=>'H','waveno'=>'*']);
+        app('LogService')->log(__METHOD__,'冻结'.__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        return ['success'=>true];
+    }
+    public function thaw(Request $request){
+        if(!Gate::allows('订单管理-编辑')){ return redirect(url('/'));  }
+        $orderno = $request->orderno;
+        if (!is_array($orderno)) {
+            $orderno = [$orderno];
+        }
+        OracleDOCOrderHeader::query()->whereIn('orderno',$orderno)->update(['releasestatus'=>'N']);
+        app('LogService')->log(__METHOD__,'解冻'.__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        return ['success'=>true];
+    }
+
+    //重置快递获取标记
+    public function resetLogisticsGetMark(Request $request){
+        if(!Gate::allows('订单管理-编辑')){ return redirect(url('/'));  }
+        $orderno=$request->orderno;
+        OracleDOCOrderHeader::query()->whereIn('orderno',$orderno)->where('edisendflag2','W')->update(['edisendflag2'=>'N']);
+        app('LogService')->log(__METHOD__,'解冻'.__FUNCTION__,json_encode($orderno),Auth::user()['id']);
+        return ['success'=>true];
+    }
+
+    //取消分配
+    public function deAllocation(Request $request){
+        if(!Gate::allows('订单管理-编辑')){ return redirect(url('/'));  }
+        $orderno=$request->input('orderno');
+        $waveno=$request->input('waveno');
+        if ($waveno && $waveno!='*'){
+            OracleDOCWaveDetails::where('waveno',$waveno)->where('orderno',$orderno)->delete();
+            app('LogService')->log(__METHOD__,'取消分配删除波次号'.__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        }
+        OracleDOCOrderHeader::where('orderno',$orderno)->update(['sostatus'=>'00','waveno'=>'*']);
+        app('LogService')->log(__METHOD__,'取消分配'.__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        $is_deAllocation=$this->isDeAllocation($orderno);
+        if($is_deAllocation) return ['success'=>true];
+
+    }
+    //调用sp取消选中订单的分配
+    public function isDeAllocation($orderno){
+        $username=config('database.connections.oracle.username');
+        $password=config('database.connections.oracle.password');
+        $host=config('database.connections.oracle.host');
+        $service_name=config('database.connections.oracle.service_name');
+        $conn=oci_connect($username,$password,$host.'/'.$service_name,'utf8'); //连接oracle数据库
+        $IN_Warehouse='';
+        $IN_Process_Action_C='' ;
+        $IN_Process_By_C='By OrderNO';
+        $IN_WaveNO_C='';
+        $IN_OrderNO_C=$orderno;
+        $IN_OrderLineNO_C='';
+        $IN_AllocationDetailsID='';
+        $IN_Language='';
+        $IN_UserID='';
+        $OUT_Return_Code='';
+        $sql_sp="begin SPSO_DEALLOCATION_PROCESS(:IN_Warehouse,:IN_Process_Action_C,:IN_Process_By_C,
+        :IN_WaveNO_C,:IN_OrderNO_C,:IN_OrderLineNO_C,:IN_AllocationDetailsID,:IN_Language,:IN_UserID,:OUT_Return_Code); end;";
+        $stmt = oci_parse($conn, $sql_sp);
+        oci_bind_by_name($stmt,':IN_Warehouse',$IN_Process_Action_C);
+        oci_bind_by_name($stmt,':IN_Process_Action_C',$IN_Warehouse);
+        oci_bind_by_name($stmt,':IN_Process_By_C',$IN_Process_By_C);
+        oci_bind_by_name($stmt,':IN_WaveNO_C',$IN_WaveNO_C);
+        oci_bind_by_name($stmt,':IN_OrderNO_C',$IN_OrderNO_C);
+        oci_bind_by_name($stmt,':IN_OrderLineNO_C',$IN_OrderLineNO_C);
+        oci_bind_by_name($stmt,':IN_AllocationDetailsID',$IN_AllocationDetailsID);
+        oci_bind_by_name($stmt,':IN_Language',$IN_Language);
+        oci_bind_by_name($stmt,':IN_UserID',$IN_UserID);
+        oci_bind_by_name($stmt,':OUT_Return_Code',$OUT_Return_Code,300);
+        oci_execute($stmt);
+        if (substr($OUT_Return_Code,0,3) != '000'){
+            app('LogService')->log(__METHOD__,'调用sp根据订单取消分配失败'.__FUNCTION__,"ORDERNO:".$orderno."ERROR:".$OUT_Return_Code);
+            return false;
+        }
+        oci_close($conn);
+        return true;
+
+    }
+
+}

+ 776 - 0
app/Http/Controllers/OrderIssueController.php

@@ -0,0 +1,776 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Imports\OrderIssueImport;
+use App\Logistic;
+use App\OracleDOCOrderHeader;
+use App\Order;
+use App\OrderIssue;
+use App\OrderIssueProcessLog;
+use App\OrderIssueType;
+use App\OrderPackage;
+use App\Owner;
+use App\QualityLabel;
+use App\RejectedBill;
+use App\Services\common\ExportService;
+use App\Services\LogService;
+use App\Services\OrderIssueProcessLogService;
+use App\Services\OrderIssueService;
+use App\Services\OrderPackageService;
+use App\Services\OrderService;
+use App\Services\OwnerService;
+use App\Shop;
+use App\UserWorkgroup;
+use Exception;
+use Illuminate\Http\Request;
+use Illuminate\Support\Arr;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Gate;
+use Illuminate\Support\Facades\Http;
+use Illuminate\Support\Facades\Validator;
+use Maatwebsite\Excel\Facades\Excel;
+
+class OrderIssueController extends Controller
+{
+
+    public function index(Request $request)
+    {
+        if (!Gate::allows('订单管理-问题件-查询')) {
+            return redirect(url('/'));
+        }
+        /** @var OrderIssueService $orderIssueService */
+        $orderIssueService = app('OrderIssueService');
+        $owners = app(OwnerService::class)->getAuthorizedOwners();
+        $orderIssues = $orderIssueService->paginate($request->all());
+        $orderIssueType = OrderIssueType::all();
+        $qualityLabel = QualityLabel::all();
+        $logistics = Logistic::all();
+        $userWorkgroup = UserWorkgroup::all();
+        return view('order/issue/index', compact('owners', 'orderIssues', 'orderIssueType', 'qualityLabel','userWorkgroup','logistics'));
+    }
+
+    public function create()
+    {
+        if (!Gate::allows('订单管理-订单问题件生成')) {
+            return redirect(url('/'));
+        }
+        $types = OrderIssueType::all();
+        $meg = ['success' => true];
+        $userWorkGroup = UserWorkgroup::all();
+        $logistic = Logistic::all();
+        $owners = Owner::all();
+        return view('order.issue.create', compact('types', 'meg', 'userWorkGroup', 'logistic', 'owners'));
+    }
+
+    public function store(Request $request)
+    {
+        if (!Gate::allows('订单管理-订单问题件生成')) {
+            return redirect(url('/'));
+        }
+        /** @var OrderIssueService $orderIssueService */
+        $orderIssueService = app('OrderIssueService');
+        $orderIssueService->validatorCreate($request)->validate();
+        $orderIssue = null;
+        if ($request->filled('logistic_number_return')) {
+            $orderIssue = $orderIssueService->createByLogisticNumber($request->all());
+        } else {
+            $orderIssue = $orderIssueService->create($request->all());
+        }
+        OrderIssueProcessLog::query()->create(['order_issue_id' => $orderIssue['id'], 'user_id' => Auth::user()['id'], 'content' => '创建订单问题件', 'type' => '创建']);
+        return redirect('order/issue/index');
+    }
+
+    public function edit($id)
+    {
+        if (!Gate::allows('订单管理-问题件-编辑')) {
+            return redirect(url('/'));
+        }
+        $orderIssue = OrderIssue::query()->with(['order','secondOrder.packages.commodities.commodity'])->where('id', $id)->first();
+        $order = $orderIssue->order;
+        $secondOrder = $orderIssue->secondOrder;
+        $rejectedBill = RejectedBill::query()->where('id', $orderIssue->rejected_bill_id)->first();
+        $userWorkgroup = UserWorkgroup::all();
+        $orderIssueType = OrderIssueType::all();
+        $owners = Owner::all();
+        $shops = Shop::all();
+        $logistics = Logistic::all();
+        return view('order/issue/edit', compact('orderIssue', 'owners', 'userWorkgroup', 'shops', 'logistics', 'orderIssueType', 'order', 'secondOrder', 'rejectedBill'));
+    }
+
+    public function batchImport(Request $request)
+    {
+        if (!Gate::allows('订单管理-问题件-导入-Excel导入')) {
+            return redirect(url('/'));
+        }
+        $file = $request->file('file');
+        $fileSuffix = $file->getClientOriginalExtension();
+        if (in_array($fileSuffix, ['xlsx', 'xlsm', 'xltx', 'xltm', 'xls', 'xlt', 'ods', 'ots', 'slk', 'xml', 'gnumeric', 'htm', 'html', 'csv', 'tsv'])) {
+            ini_set('max_execution_time', 2100);
+            ini_set('memory_limit', '512M');
+            $extension = $request->file()['file']->getClientOriginalExtension();
+            $extension[0] = strtoupper($extension[0]);
+            Excel::import(new OrderIssueImport(), $request->file('file')->path(), null, $extension);
+            if (Cache::has('error')) {
+                return '<h1 class="text-danger">导入Excel失败<br><p style="color: red">' . Cache::pull('error') . '</p></h1>';
+            } else {
+                $exception = Cache::get('exception');
+                $a = '';
+                for ($i = 0; $i < count($exception); $i++) {
+                    $a .= implode(',', $exception[$i]) . '&#10';
+                };
+                app('LogService')->log(__METHOD__, __FUNCTION__, json_encode($request->toArray()), Auth::user()['id']);
+                return '<h1 class="text-danger">导入Excel成功<br><textarea style="width: 50%;height: 50%">' . $a . '</textarea></h1>';
+            }
+        } else {
+            return '<h1 class="text-danger">失败<br><p style="color: red">不支持该文件类型</p></h1>';
+        }
+    }
+
+    public function exportOrderIssue(Request $request)
+    {
+        ini_set('max_execution_time', 2500);
+        ini_set('memory_limit', '1526M');
+        if (!Gate::allows('订单管理-问题件-查询')) {
+            return redirect(url('/'));
+        }
+        if ($request->checkAllSign){
+            $params = $request->input();
+            unset($params['checkAllSign']);
+
+            $sqlList = app('OrderIssueService')->getSqlList($params);
+        }else{
+            $sqlList = app('OrderIssueService')->getSqlList(['id'=>$request->data,"is_handle"=>true]);
+        }
+        $post = Http::post(config('go.export.url'),['type'=>'orderIssue','sqlList'=>json_encode($sqlList),'createFormat'=>'merge']);
+        if ($post->status() == 500){
+            throw new Exception($post->header("Msg"));
+        }
+        return response($post,200, [
+            "Content-type"=>"application/octet-stream",
+            "Content-Disposition"=>"attachment; filename=订单问题件-".date('ymdHis').'.xlsx',
+        ]);
+    }
+
+    public function excelImport()
+    {
+        if (!Gate::allows('订单管理-问题件-导入')) {
+            return redirect(url('/'));
+        }
+        return view('order.issue.import');
+    }
+
+    public function apiOrderIssueTag(Request $request)
+    {
+        if (!Gate::allows('订单管理-订单问题件生成')) {
+            return ['success' => false, 'fail_info' => '没有对应权限'];
+        }
+        if (!$request->input('orderNos')) {
+            return ['success' => false, 'fail_info' => '没有传入的订单编号'];
+        }
+        /** @var OrderIssueService $orderIssueService */
+        $orderIssueService = app(OrderIssueService::class);
+        $exits_orderNos = $orderIssueService->校验问题件是否存在_WMS订单号_返回存在的订单号($request->input('orderNos'));
+        $count = OracleDOCOrderHeader::query()->with('oracleBASCode')->whereIn('OrderNo',$request['orderNos'])->whereHas('oracleBASCode',function($query){
+            $query->whereNotIn('codename_c',['完全装箱','订单完成','完全发运','分配完成']);
+        })->count();
+        if($count>0)return ['success'=>false,'fail_info'=>'勾选的订单中有没有完成的订单,请取消勾选'];
+        if(count($exits_orderNos)>0){
+            return ['success'=>false,'fail_info'=>'标记问题件存在已有订单号','exitsOrderNos' =>$exits_orderNos];
+        }
+        return $orderIssueService->orderIssueTag($request->all());
+    }
+
+    public function apiDestroy(Request $request)
+    {
+        if (!Gate::allows('订单管理-问题件-删除')) {
+            return ['success' => false, 'fail_info' => '没有对应权限'];
+        }
+        if (!($request->has('id'))) {
+            return ['success' => 'false', 'fail_info' => '没有问题题件相关的参数'];
+        }
+        $orderIssue = OrderIssue::query()->where('id', $request->input('id'))->first();
+        $bool = $orderIssue->delete();
+        if ($bool) {
+            app('LogService')->log(__METHOD__, __FUNCTION__, json_encode($request->toArray()), Auth::user()['id']);
+            return ['success' => 'true'];
+        } else {
+            return ['success' => 'false', 'fail_info' => '删除问题单出现异常,请联系管理员'];
+        }
+    }
+
+    public function updateApi(Request $request)
+    {
+        if (!Gate::allows('订单管理-问题件-编辑')) {
+            return ['success' => false, 'fail_info' => '没有对应权限'];
+        }
+        try {
+            $data =  $request->only([
+                'order_issue_type_id','owner_id','logistic_id', 'logistic_number_return','result_explain','final_status','second_order_id','second_client_no',
+                'logistic_indemnity_money','logistic_express_remission','baoshi_indemnity_money','baoshi_express_remission','user_workgroup_id'
+            ]);
+            $orderIssue = OrderIssue::query()->find($request->id);
+            $orderIssue->update($data);
+            $orderIssue->同步退单状态();
+            app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request));
+            return  ['success' => true];
+        } catch (Exception $e) {
+            app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request)."||".$e->getMessage().'||'.$e->getTraceAsString());
+            return  ['success' => false ,'fail_info' => $e->getMessage()];
+        }
+    }
+
+    public function apiEndOrderIssue(Request $request)
+    {
+        if (!Gate::allows('订单管理-问题件-编辑')) {
+            return ['success' => false, 'fail_info' => '没有对应的权限'];
+        }
+        if (!$request->has('ids')) {
+            return ['success' => false, 'fail_info' => '没有传入对应的参数'];
+        }
+        $count = OrderIssue::query()->whereIn('id', $request->input('ids'))->where('final_status', '已解决')->count();
+        if ($count > 0) {
+            return ['success' => false, 'fail_info' => '勾选的内容中已有完结的订单问题件,取消勾选后重试'];
+        } else {
+            OrderIssue::query()->whereIn('id', $request->input('ids'))->update(['final_status' => '已解决']);
+            foreach ($request->input('ids') as $id) {
+                OrderIssueProcessLog::query()->create(['order_issue_id' => $id, 'user_id' => Auth::user()['id'], 'type' => '结束', 'content' => '完结订单']);
+            }
+            app('LogService')->log(__METHOD__, __FUNCTION__, json_encode($request->toArray()), Auth::user()['id']);
+            return ['success' => true];
+        }
+    }
+
+    public function apiDisposeOrderIssue(Request $request)
+    {
+        if (!Gate::allows('订单管理-问题件-编辑')) {
+            return ['success' => false, 'fail_info' => '没有对应权限'];
+        }
+        if (!$request->has('id')) {
+            return ['success' => false, 'fail_info' => '没有传入对应参数'];
+        }
+        try {
+            OrderIssue::query()
+                ->where('id', $request->input('id'))
+                ->update(['is_new_rejecting' => '已处理']);
+            app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->getContent()));
+            return ['success'=>true];
+        } catch (Exception $e) {
+            app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->getContent())."||".$e->getMessage()."||".$e->getTraceAsString());
+            return ['success' => false,'fail_info' => $e->getMessage()];
+        }
+    }
+
+    public function apiGetOrderInfoByClientNo(Request $request)
+    {
+        if (!$request->filled('clientNo')) {
+            return ['success' => false, 'fail_info' => '缺失WMS订单参数无法查询'];
+        }
+        $orderInfo = app(OrderService::class)->findOrCreateByClientCode($request->input('clientNo'));
+        if (!$orderInfo) {
+            return ['success' => true, 'message' => '没有对应的订单信息'];
+        }else{
+            return ['success' => true, 'data' => $orderInfo];
+        }
+    }
+
+    public function apiOrderIssueHasClientCode(Request $request)
+    {
+        if (!$request->filled('clientCode')) {
+            return ['success' => false, 'fail_info' => '缺少对应的参数或条件'];
+        }
+        /** @var $orderService OrderService*/
+        $orderService = app('OrderService');
+        $clientCode = $request->input('clientCode');
+        $order = Order::query()->where('client_code', $clientCode)->first();
+        if ($order) {
+            if (OrderIssue::query()->where('order_id', $order['id'])->count()) {
+                return ['success' => false, 'fail_info' => '该客户订单号已有对应的订单问题件'];
+            }
+            $order = $orderService->findOrCreateByClientCode($clientCode);
+            return ['success' => true, 'order' => $order];
+        } else {
+            $orderHeader = OracleDOCOrderHeader::query()->where('SOReference1', $clientCode)->first();
+            if (!$orderHeader) {
+                return ['success' => false, 'fail_info' => '该客户订单号没有对应的订单信息'];
+            } else {
+                $order = $orderService->findOrCreateByClientCode($clientCode);
+                $rejectedBill = $orderService->getRejectedBillOfClientCode($clientCode);
+                return ['success' => true, 'order' => $order, 'rejectedBill' => $rejectedBill];
+            }
+        }
+    }
+
+    public function apiOrderIssueHasLogisticNumberReturn(Request $request)
+    {
+        if (!$request->filled('logisticNumberReturn')) {
+            return ['success' => false, 'fail_info' => '缺少对应的参数或条件'];
+        }
+        $logisticNumberReturn = $request->input('logisticNumberReturn');
+        $rejectedBill = RejectedBill::with('items')->where('logistic_number_return', $logisticNumberReturn)->first();
+        if ($rejectedBill) {
+            $orderIssue = OrderIssue::query()->where('rejected_bill_id', $rejectedBill->id)->first();
+
+            if ($orderIssue) {
+                return ['success' => false, 'fail_info' => '该退回单号已有对应的问题件'];
+            } else {
+                $orderService = app('OrderService');
+                $order = $orderService->findOrCreteByLogisticNumberReturn($logisticNumberReturn);
+                return ['success' => true, 'order' => $order, 'rejectedBill' => $rejectedBill];
+            }
+        } else {
+            return ['success' => true, 'meg' => '没有对应的退回单号,不与WMS同步'];
+        }
+    }
+
+    public function isExistByOrderNoApi(Request $request){
+        if (!Gate::allows('订单管理-订单问题件生成')) {
+            return ['success'=>false,'fail_info' => '没有对应权限'];
+        }
+        $orderNos = $request->input('orderNos');
+        $orderIssues =OrderIssue::query()->with('order')
+            ->whereHas('order',function($query) use ($orderNos){
+                $query->whereIn('code',$orderNos);
+            })->get();
+
+        if($orderIssues->count() == 0){
+            return ['success'=>true ];
+        }else{
+            $is_exist_orderNos = '';
+            foreach ($orderIssues as $orderIssue) {
+                $is_exist_orderNos.= $orderIssue->order->code.',';
+            }
+            $is_exist_orderNos = rtrim($is_exist_orderNos,',');
+            $is_exist_orderNos .= ';';
+            return ['success'=>false,'fail_info'=>'选中的订单已有存在的问题件:'.$is_exist_orderNos];
+        }
+    }
+
+    public function updateColumnApi(Request $request)
+    {
+        if (!Gate::allows('订单管理-问题件-编辑')) {
+            return ['success'=>false,'fail_info' => '没有对应权限'];
+        }
+        try {
+            OrderIssue::query()
+                ->where('id', $request->input('id'))
+                ->update([$request->input('column') => $request->input('value')]);
+            app('LogService')->log(__METHOD__,'更新问题件',json_encode($request->getContent()));
+            return ['success' => true];
+        } catch (Exception $e) {
+            app('LogService')->log(__METHOD__,'更新问题件error',json_encode($request->getContent()).'||'.$e->getMessage().'||'.$e->getTraceAsString());
+            return ['success' => false, $e->getMessage()];
+        }
+    }
+
+    public function batchDestroyApi(Request $request)
+    {
+        if (!Gate::allows('订单管理-问题件-删除')) {
+            return ['success'=>false,'fail_info' => '没有对应权限'];
+        }
+        try {
+            OrderIssue::query()->whereIn('id', $request->input('ids'))->delete();
+            app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->getContent()));
+            return ['success' => true];
+        } catch (Exception $e) {
+            app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->getContent())."||".$e->getMessage()."||".$e->getTraceAsString());
+            return ['success' => false,'fail_info' => $e->getMessage()];
+        }
+    }
+
+    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, [
+            'order_issue_type_id' => ['required'],
+            'handle_status' => ['nullable'],
+            'result_explain' => ['nullable'],
+            'logistic_indemnity_money' => ['nullable', 'numeric'],
+            'logistic_express_remission' => ['nullable'],
+            'baoshi_indemnity_money' => ['nullable', 'numeric'],
+            'baoshi_express_remission' => ['nullable'],
+        ], [
+            'required' => [':attribute 为必填项', ':attribute'],
+            'numeric' => [':attribute  为可确认的数值', ':attribute']
+        ], [
+            'order_issue_type_id' => '问题类别',
+            'handle_status' => '处理状态',
+            'result_explain' => '处理结果说明',
+            'logistic_indemnity_money' => '承运商赔偿金额',
+            'logistic_express_remission' => '承运商快递减免',
+            'baoshi_indemnity_money' => '宝时赔偿金额',
+            'baoshi_express_remission' => '宝时快递减免',
+        ]);
+    }
+
+    public function apiUpdateValidatorRejectedBill(array $arr){
+        return Validator::make($arr, [
+            'logistic_number_return'=>['required'],
+            'id_logistic_return'=>['required'],
+        ], [
+            'required' => [':attribute 为必填项', ':attribute'],
+        ], [
+            'logistic_number_return'=> '退回单号',
+            'id_logistic_return'=> '退回单号承运商',
+        ]);
+    }
+
+    public function endOrderIssuesApi(Request $request)
+    {
+        if (!Gate::allows('订单管理-问题件-编辑')) {
+            return ['success'=>false,'fail_info' => '没有对应权限'];
+        }
+        $orderIssue_ids = $request->input('ids');
+        $bool = app(OrderIssueService::class)->isExistOrderIssueTypeIsEnd($orderIssue_ids);
+        if($bool)return ['success'=>false,'fail_info'=> '需要完结的订单问题件中已有完结的订单问题件'];
+        $bool = app(OrderIssueService::class)->endOrderIssues($orderIssue_ids);
+        if($bool == 0) return ['success'=>false,'fail_info' => '操作失败'];
+        $params = ['ids'=>$orderIssue_ids,'content'=>'完结订单','type'=>'结束'];
+        $logs = app(OrderIssueProcessLogService::class)->create($params);
+        return ['success'=>true,'logs'=>$logs];
+    }
+
+    public function editSecondClientNoApi(Request $request)
+    {
+        if(!Gate::allows('订单管理-问题件-编辑')){
+            return ['success'=>false,'fail_info'=>'没有对应权限'];
+        }
+        $secondClientNo = $request->input('secondClientNo');
+        try {
+            app(OrderIssueService::class)->editOrderIssueSecondClientNo($request->id,$secondClientNo);
+            $order = Order::query()->with('packages.commodities.commodity')->where('client_code',$secondClientNo)->first();
+            if (!$order) {
+                return ['success' => true, 'message' => '二次客户单号已修改,没有对应的订单信息'];
+            } else {
+               return ['success' => true, 'order' => $secondClientNo =='' ? null : $order];
+            }
+        } catch (Exception $e) {
+            app('LogService')->log(__METHOD__, __FUNCTION__, json_encode($request->getContent()).$e->getMessage().$e->getTraceAsString());
+            return  ['success' =>false ,'fail_info' => $e->getMessage()];
+        }
+    }
+
+    public function editSecondLogisticNumberApi(Request $request)
+    {
+        if(!Gate::allows('订单管理-问题件-编辑'))
+            return ['success'=>false,'fail_info'=>'没有对应权限'];
+        /** @var OrderIssueService $service */
+        $service = app(OrderIssueService::class);
+        try {
+            $message = $service->updateSecondLogisticNumber($request->input('id'), $request->logistic_number);
+            app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->getContent()));
+            return $message;
+        } catch (Exception $e) {
+            app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->getContent()).$e->getMessage().$e->getTraceAsString());
+            return ['success'=>false,$e->getMessage()];
+        }
+    }
+
+    public function disposeImportApi(Request $request)
+    {
+        if(!Gate::allows('订单管理-问题件-编辑'))
+            return ['success'=>false,'fail_info'=>'没有对应权限'];
+        return app(OrderIssueService::class)->disposeImport($request->input('ids'));
+    }
+
+    public function importPasteDataApi(Request $request)
+    {
+        if (!Gate::allows('订单管理-问题件-导入-文本导入'))
+            return ['success'=>false,'fail_info'=>'没有对应权限'];
+        $rows = $request->input('rows');
+        $logistic_numbers = [];
+        $types = [];
+        $maps = [];
+        $errors = [];
+        $orderIssueTypes = OrderIssueType::all();
+        $orderIssueType_map = [];
+        foreach ($orderIssueTypes as $orderIssueType) {
+            $orderIssueType_map[$orderIssueType->name] = $orderIssueType;
+        }
+        $array = explode("\n",$request->input('pasteDataText')); //拆分行
+        /** @var OrderIssueService $service */
+        $service =  app(OrderIssueService::class);
+        foreach ($array as $i => $str) {
+//            $string= preg_replace('/[\s,\,\,]+/','*++*',$str);
+//            $items = explode('*++*',$string);
+            $items=[];
+
+            preg_match('/^(\w*?)[\s,,;;]([\x{4e00}-\x{9fa5}]*?)[\s,,;;](.*?)[\s,,;;](\w*?)$/u', $str, $items);
+            if(count($items) == 0){
+                preg_match('/^(\w*?)[\s,,;;]([\x{4e00}-\x{9fa5}]*?)[\s,,;;](.*?)$/u', $str, $items);
+            }
+            array_shift($items);
+            $head = '第'.($i+1).'行';
+            if(count($items)<count($rows)-1){
+                $errors[$head] = ['数据不完整'];
+                unset($items);
+                continue;
+            }
+            $map = [];
+            foreach ($rows as $index=>$row) {
+                if($row === '原始运单号'){
+                    if(!$items[$index]){
+                        $errors[$head][]='快递单号为空';
+                        $map =[];
+                    }
+                    $logistic_numbers = [$items[$index]];
+                    $exist_logistic =  $service->校验问题件是否存在_快递单号_返回存在的快递单号($logistic_numbers);
+                    $orderHeaders=OracleDOCOrderHeader::query()->with('actAllocationDetails')->whereHas('actAllocationDetails',function($query)use($logistic_numbers){
+                        $query->whereIn('picktotraceid',$logistic_numbers);
+                    })->get();
+                    if(count($exist_logistic) > 0){
+                        $errors[$head][]='快递单号存在对应的问题件';
+                        $map =[];
+                    }else if($orderHeaders->count()==0){
+                        $errors[$head][]='快递单号不存在对应的发运订单';
+                        $map =[];
+                    }
+                    $logistic_numbers[] = $items[$index];
+                    $map['logistic_number'] = $items[$index];
+                }
+                if($row==='情况说明'){
+                    if(!$items[$index]){
+                        $errors[$head][]='情况说明为空';
+                        $map =[];
+                    }
+                    $map['result_explain'] = $items[$index];
+                }
+                if($row==='自定义订单号'){
+                    if($items[$index]??false){
+                        $map['custom_code'] = $items[$index];
+                    }
+                }
+                if($row==='问题类别'){
+                    if(!$items[$index]){
+                        $errors[$head][]='问题类别为空';
+                        $map = [];
+                    }else{
+                        $type =  $orderIssueType_map[$items[$index]] ?? null;
+                        if(!$type){
+                            $errors[$head][]='问题类型不存在';
+                            $map = [];
+                        }
+                    }
+                    $types[] =$items[$index];
+                    $map['type'] = $items[$index];
+                }
+            }
+            if(count($map)!==0)$maps[] = $map;
+        }
+//        if(count($errors)>0)
+        if(count($errors)>0) return ['success'=>false,'fail_info'=>$errors];
+        try {
+            foreach ($maps as $map) {
+                $logistic_number = $map['logistic_number'];
+                $result_explain = $map['result_explain'];
+                $type = $map['type'];
+                $custom_code = $map['custom_code'] ?? null;
+                $service->createOrderIssue($logistic_number, $type, $result_explain,'导入未处理',$custom_code,$request['hiddenTag'] ?? null);
+            }
+            return ['success'=>true];
+        } catch (Exception $e) {
+            app('LogService')->log(__METHOD__,__FUNCTION__,'文本导入问题件失败'.json_encode($request->getContent().$e->getMessage().$e->getTraceAsString()));
+            return ['success'=>false,'fail_info'=>$e->getMessage()];
+        }
+    }
+
+    public function exportJsonExcel(Request $request)
+    {
+        if (!Gate::allows('订单管理-问题件-查询')) {
+            return redirect(url('/'));
+        }
+        $params = $request->input();
+        if ($request->checkAllSign){
+            $params = $request->input();
+            unset($params['checkAllSign']);
+        }else{
+            $params['id'] = $request['data'];
+            $params['is_handle'] = true;
+        }
+        /** @var OrderIssueService $service */
+        $service = app('OrderIssueService');
+        $order_Issues  = $service->getJsonObj($params);
+        return $this->getJson($order_Issues);
+    }
+
+    public function getJson($order_Issues){
+        $json = [];
+        $row = [
+            '登记日期','创建日期','客户','客户订单号','原始承运商','收货人','收货电话','省','市','区','收货人地址',
+            '原始运单号','原始商品','原始商品名称','原始商品数量',
+            '退回单号', '退单商品名','退单商品条码','退单商品数量','是否正品','退单状态','退单备注',
+            '操作类型','说明','操作者','情况说明','问题类别',
+            '二次订单号','二次承运商','二次运单号','二次商品条码','二次商品名','二次商品数量',
+            '最终状态', '承运商赔偿金额', '承运商快递减免', '宝时赔偿金额', '宝时快递减免','事故责任方'
+        ];
+        foreach ($order_Issues as $order_issue){
+            $order =  $order_issue->order;
+            $orderPackages = $order_issue->order->packages ?? collect();
+            $logistic_numbers = '';$order_sku  = '';$order_sku_name  = '';$order_sku_amount  = '';
+            $orderPackages->each(function($package,$index)use(&$logistic_numbers,&$order_sku,&$order_sku_name,&$order_sku_amount){
+                if(!str_starts_with('null',$package->logistic_number))$logistic_numbers.=$package->logistic_number.",\r\n";
+                $package->commodities->each(function($commodities)use(&$order_sku,&$order_sku_name,&$order_sku_amount){
+                    $commodity = $commodities->commodity ?? '';
+                    $order_sku.= ($commodity->sku ?? '').",\r\n";
+                    $order_sku_name.= ($commodity->name ?? '').",\r\n";
+                    $order_sku_amount.= ($commodities->amount ?? '').",\r\n";
+                });
+            });
+            $rejected_logistic_number = $order_issue->rejectedBill->logistic_number_return ?? '';
+
+            $rejected_Bill_remark = '';
+            $rejected_is_checked = '';
+            $rejected_name = ''; $rejected_barcode = '';$rejected_amount = '';
+            if($order_issue->rejectedBill){
+                $order_issue->rejectedBill->items->each(function($item)use(&$rejected_name,&$rejected_barcode, &$rejected_amount,&$rejected_Bill_remark,&$rejected_is_checked){
+                    $rejected_name.= $item->name_goods.",\r\n";
+                    $rejected_barcode.= $item->barcode_goods.",\r\n";
+                    $rejected_amount.= $item->amount.",\r\n";
+                    $rejected_Bill_remark.= $item->remark.",\r\n";
+                    $rejected_is_checked.= $item->quality->name.",\r\n";
+                });
+            }
+            $log_type = ''; $log_content = '';$log_user = '';
+            $order_issue->logs->each(function($log)use(&$log_type, &$log_content,&$log_user){
+                $log_type.=$log->type.",\r\n";
+                $log_content.=$log->content.",\r\n";
+                $log_user.=$log->user->name.",\r\n";
+            });
+            $send_order = $order_issue->secondOrder ??  new Order();
+            $send_order_numbers = '';$send_order_sku ='';$send_order_name ='';$send_order_amount = '';
+            $send_order->packages->each(function($package)use(&$send_order_numbers ,&$send_order_sku ,&$send_order_name ,&$send_order_amount ){
+                $send_order_numbers.=($package->logistic_number).",\r\n";
+                $package->commodities->each(function ($commodities)use( &$send_order_sku ,&$send_order_name ,&$send_order_amount ){
+                    $commodity = $commodities->commodity;
+                    $send_order_sku.=$commodity->sku.",\r\n";
+                    $send_order_name.=$commodity->name.",\r\n";
+                    $send_order_amount.=$commodities->amount.",\r\n";
+                });
+            });
+
+            $json[] = [
+                isset($order_issue->created_at) ? str_split($order_issue->created_at,10)[0] :'',       // 登记日期
+                isset($order->created_at) ? str_split($order->created_at,10)[0] :'',             // 创建日期
+                $order->owner->name ?? '',      // 客户
+                $order->client_code,              // 客户订单号
+                $order->logistic->name ?? '',   // 原始承运商
+                $order->consignee_name,         // 收货人
+                $order->consignee_phone,        // 收货电话
+                $order->province,               // 省
+                $order->city,                   // 市
+                $order->district,               // 区
+                $order->address,                // 收货人地址
+
+                rtrim($logistic_numbers,",\r\n"),              //原始运单号
+                rtrim($order_sku,",\r\n"),                     //原始商品
+                rtrim($order_sku_name,",\r\n"),                //原始商品名称
+                rtrim($order_sku_amount,",\r\n"),              //原始商品数量
+
+                //,'退单商品名','退单商品条码','退单商品数量','退单状态','退单备注'
+                $rejected_logistic_number,                      //退回单号
+                rtrim($rejected_name,",\r\n"),        // 退单商品名
+                rtrim($rejected_barcode,",\r\n") ,    // 退单商品条码
+                rtrim($rejected_amount,",\r\n"),      // 退单商品数量
+                rtrim($rejected_is_checked,",\r\n"),  // 是否正品
+                rtrim($rejected_Bill_remark,",\r\n"),   // 退单备注
+
+                $order_issue->rejecting_status ,                                // 退单状态
+
+                // '操作类型','情况说明','问题类别',
+                rtrim($log_type,",\r\n"),                        //操作类型
+                rtrim($log_content,",\r\n"),                     //情况说明
+                rtrim($log_user,",\r\n"),                        //操作者
+
+                // '情况说明','问题类别',
+                $order_issue->result_explain,                               // 情况说明
+                $order_issue->issueType->name ?? '',                                   // 问题类别
+
+                // '二次订单号','二次承运商','二次运单号','二次商品条码','二次商品名','二次商品数量',
+                $order_issue->secondOrder->client_code ?? '',                //二次订单号
+                $order_issue->secondOrder->logistic->name ?? '',             //二次承运商
+                rtrim($send_order_numbers,",\r\n") ,                                        //二次运单号
+                rtrim($send_order_sku,",\r\n"),                                             // 二次商品条码
+                rtrim($send_order_name,",\r\n"),                                            // 二次商品名
+                rtrim($send_order_amount,",\r\n"),                                          // 二次商品数量
+
+                //'最终状态', '承运商赔偿金额', '承运商快递减免', '宝时赔偿金额', '宝时快递减免','事故责任方'
+                $order_issue->final_status??'',
+                $order_issue->logistic_indemnity_money ,
+                $order_issue->logistic_express_remission,
+                $order_issue->baoshi_indemnity_money,
+                $order_issue->baoshi_express_remission,
+                $order_issue->userWorkGroup->name ?? '',
+            ];
+        }
+        $mergeColumn = ['A','B','C','D','E','F','G','H','I','J','K','L','P','T','X','Y','Z','AA','AF','AG','AH','AI','AJ','AK'];   // 合并行
+        return app(ExportService::class)->json($row,$json,"订单问题件");
+    }
+
+    public function recycleBin(Request $request)
+    {
+        if (!Gate::allows('订单管理-问题件-删除')) {
+            return redirect(url('/'));
+        }
+        /**
+         * @var OrderIssueService $service
+         */
+        $service = app('OrderIssueService');
+        $orderIssues = $service->getRecycleBinPaginate($request->input());
+        $paginate = $request['paginate'] ?? 50;
+        return view('order.issue.recycle',compact('orderIssues','paginate'));
+    }
+
+    public function recoverOrderIssueApi(Request $request)
+    {
+        if (!Gate::allows('订单管理-问题件-删除')) {
+            return ['success'=>false,'error'=>'没有对应权限'];
+        }
+        /**
+         * @var OrderIssueService $service
+         */
+        $service = app('OrderIssueService');
+        return  $service->recoverOrderIssue($request['ids']);
+    }
+
+    public function financeConfirmApi(Request $request)
+    {
+        if (!Gate::allows('订单管理-问题件-财务确认')) {
+            return ['success'=>false,'error'=>'没有对应权限'];
+        }
+        try {
+            $bool = OrderIssue::query()->whereIn('id', $request['ids'])->update(['finance_confirm' => '是']);
+            if($bool==false)return ['success'=>false,'error'=>'财务确认失败'];
+            app('LogService')->log(__METHOD__, __FUNCTION__,'财务确认'. json_encode($request->getContent()), Auth::user()['id']);
+            return ['success'=>true];
+        } catch (Exception $e) {
+            app('LogService')->log(__METHOD__,'Error'. __FUNCTION__,'财务确认 Error'. json_encode($request->getContent()).' || '.json_encode($e->getMessage()).' || '.json_encode($e->getTraceAsString()), Auth::user()['id']);
+            return ['success'=>false,'error'=>$e->getMessage()];
+        }
+    }
+}

+ 66 - 0
app/Http/Controllers/OrderIssueOnTopController.php

@@ -0,0 +1,66 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\OrderIssueOnTop;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Gate;
+
+class OrderIssueOnTopController extends Controller
+{
+
+    public function index()
+    {
+    }
+
+    public function create()
+    {
+    }
+
+    public function store(Request $request)
+    {
+    }
+
+    public function show(OrderIssueOnTop $orderIssueOnTop)
+    {
+    }
+
+    public function edit(OrderIssueOnTop $orderIssueOnTop)
+    {
+    }
+
+    public function update(Request $request, OrderIssueOnTop $orderIssueOnTop)
+    {
+    }
+
+    public function destroy(OrderIssueOnTop $orderIssueOnTop)
+    {
+    }
+
+    public function apiDestroy(Request $request){
+        if (!Gate::allows('订单管理-问题件-置顶')) {
+            ['success' => false, 'fail_info' => '没有对应权限'];
+        }
+        if (!$request->has('id')) {
+            return ['success' => false, 'fail_info' => '没有传入对应的id'];
+        }
+        OrderIssueOnTop::where('id', $request->input('id'))->delete();
+        return ['success' => true];
+    }
+
+    public function apiStore(Request $request){
+        if (!Gate::allows('订单管理-问题件-置顶')) {
+            return ['success' => false, 'fail_info' => '没有对应权限'];
+        }
+        if (!$request->filled('id')) {
+            return ['success' => false, 'fail_info' => '没有传入对应参数'];
+        } else if (!$request->filled('remark')) {
+            return ['success' => false, 'fail_info' => '没有写入备注'];
+        }
+        $orderIssueOnTop = OrderIssueOnTop::create(['order_issue_id' => $request->input('id'), 'remark' => $request->input('remark')]);
+        if ($orderIssueOnTop) {
+            return ['success' => true];
+        }
+        return ['success' => false, 'fail_info' => '置顶失败'];
+    }
+}

+ 70 - 0
app/Http/Controllers/OrderIssuePerformanceController.php

@@ -0,0 +1,70 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Services\OrderIssuePerformanceService;
+use App\Services\OrderIssueWorkLoadService;
+use Illuminate\Http\Request;
+use Exception;
+use Illuminate\Support\Facades\Gate;
+use Illuminate\Support\Facades\Http;
+
+class OrderIssuePerformanceController extends Controller
+{
+
+    public function __construct()
+    {
+        app()->singleton('OrderIssueWorkLoadService', OrderIssueWorkLoadService::class);
+        app()->singleton('service', OrderIssuePerformanceService::class);
+    }
+
+    public function index(Request $request)
+    {
+        if (!Gate::allows('订单管理-问题件-绩效统计')) {
+            return redirect(url('/'));
+        }
+        /** @var OrderIssuePerformanceService $service */
+        $service = app('OrderIssuePerformanceService');
+        $performance = $service->paginate($request->all());
+        $options = ['timeFrame' => $request->input('timeFrame'), 'create_start' => $request->input('create_start') ?? '', 'create_end' => $request->input('create_end') ?? ''];
+        return view('order.issue.performance', compact('performance', 'options'));
+    }
+
+    public function export(Request $request)
+    {
+        /** @var OrderIssuePerformanceService  $orderIssuePerformanceService */
+        $orderIssuePerformanceService = app(OrderIssuePerformanceService::class);
+        $sql = $orderIssuePerformanceService->getSql($request->all());
+        $row = ['客服','客户','创建数','处理数','完结数','总数'];
+        $column = ['userName','ownerName','created','process','end','sumNumber'];
+        $post = Http::post(config('go.export.url'),['type'=>'unify','sql'=>$sql, 'connection'=>'mysql',
+            'row'=>json_encode($row,JSON_UNESCAPED_UNICODE), 'column'=>json_encode($column)]);
+        if ($post->status() == 500){
+            throw new Exception($post->header("Msg"));
+        }
+        return response($post,200, [
+            "Content-type"=>"application/octet-stream",
+            "Content-Disposition"=>"attachment; filename=客服绩效-".date('ymdHis').'.xlsx',
+        ]);
+    }
+
+    public function workLoadPage(Request $request)
+    {
+        if (!Gate::allows('订单管理-问题件-工作量')) {
+            return redirect(url('/'));
+        }
+        /** @var OrderIssueWorkLoadService $workLoadService */
+        $workLoadService = app('OrderIssueWorkLoadService');
+        $workLoads = $workLoadService->paginate($request->all());
+        $users = $workLoadService->getUsers();
+        $owners = $workLoadService->getOwners();
+        $options =$workLoadService->getOptions($request->all());
+        return view('order/issue/workload', compact('workLoads', 'owners', 'users','options'));
+    }
+
+    public function exportWorkLoad(Request $request)
+    {
+        $workLoadService = app('OrderIssueWorkLoadService');
+        return $workLoadService->exportWorkLoad($request->all());
+    }
+}

+ 78 - 0
app/Http/Controllers/OrderIssueProcessLogController.php

@@ -0,0 +1,78 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\OrderIssueProcessLog;
+use App\Services\LogService;
+use App\Services\OrderIssueProcessLogService;
+use App\User;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Gate;
+
+class OrderIssueProcessLogController extends Controller
+{
+
+
+    public function apiStore(Request $request)
+    {
+        if (!Gate::allows('订单管理-问题件-编辑')) {
+            return ['success' => false, 'fail_info' => '没有对应的权限'];
+        }
+        if ($request->filled(['id', 'content'])) {
+            try {
+                $log = OrderIssueProcessLog::query()->create([
+                    'order_issue_id' => $request->input('id'),
+                    'content' => $request->input('content'),
+                    'user_id' => Auth::user()['id'],
+                    'type' => '处理',
+                ]);
+                if ($log) {
+                    $log->user = $log->hasOne(User::class, 'id', 'user_id')->first();
+                }
+                app('LogService')->log(__METHOD__, __FUNCTION__, json_encode($request->getContent()));
+                return ['success' =>true,'data' =>$log ];
+            } catch (\Exception $e) {
+                app('LogService')->log(__METHOD__, __FUNCTION__, json_encode($request->getContent()) .'||'.$e->getMessage().'||'.$e->getTraceAsString());
+                return ['success' => false, 'fail_info' => $e->getMessage()];
+            }
+        } else {
+            return ['success' => false, 'fail_info' => '没有传入对应参数'];
+        }
+    }
+
+    public function apiDestroy(Request $request){
+        if(!$request->filled('id')){
+            return ['success'=>false,'fail_info'=>'没有传入对应参数'];
+        }
+        OrderIssueProcessLog::query()->where('id',$request->input('id'))->delete();
+        app('LogService')->log(__METHOD__, __FUNCTION__, json_encode($request->getContent()));
+        return ['success'=>true];
+    }
+
+    public function batchStoreApi(Request $request){
+        if (!Gate::allows('订单管理-问题件-编辑')) {
+            return ['success' => false, 'fail_info' => '没有对应的权限'];
+        }
+        /** @var OrderIssueProcessLogService $service */
+        $service = app(OrderIssueProcessLogService::class);
+
+        try {
+            $data = $service->batchStoreAndReturnLogs($request->all());
+            $logs = OrderIssueProcessLog::query()
+                ->with('user')
+                ->whereIn('id',data_get($data,'*.id'))
+                ->get();
+            $result_data = [];
+            foreach ($logs as $log) {
+                $result_data[$log->order_issue_id] =$log;
+            }
+            app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->getContent()));
+            return ['success' => true,'logs' => $result_data];
+        } catch (\Exception $e) {
+            app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->getContent()).'||'.$e->getMessage()."||".$e->getTraceAsString());
+            return ['success' => false,$e->getMessage()];
+        }
+    }
+
+}

+ 11 - 0
app/Http/Controllers/OrderIssueTypeController.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\OrderIssueType;
+use Illuminate\Http\Request;
+
+class OrderIssueTypeController extends Controller
+{
+
+}

+ 12 - 0
app/Http/Controllers/OrderPackageCommoditiesController.php

@@ -0,0 +1,12 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\OrderPackageCommodities;
+use Illuminate\Http\Request;
+
+class OrderPackageCommoditiesController extends Controller
+{
+
+
+}

+ 12 - 0
app/Http/Controllers/OrderPackageController.php

@@ -0,0 +1,12 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\OrderPackage;
+use Illuminate\Http\Request;
+
+class OrderPackageController extends Controller
+{
+
+
+}

+ 253 - 0
app/Http/Controllers/OrderTrackingController.php

@@ -0,0 +1,253 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Logistic;
+use App\Order;
+use App\OrderTracking;
+use App\Services\LogService;
+use App\Services\OrderTrackingService;
+use App\Services\OwnerService;
+use App\UploadFile;
+use Exception;
+use Illuminate\Http\Request;
+use Illuminate\Support\Carbon;
+use Illuminate\Support\Facades\Gate;
+use Illuminate\Support\Facades\Http;
+use Intervention\Image\Facades\Image;
+use Ramsey\Uuid\Uuid;
+
+class OrderTrackingController extends Controller
+{
+
+    public function index(Request $request)
+    {
+        /**
+         * @var OrderTrackingService $service
+         */
+        if (!Gate::allows('订单管理-跟踪'))
+            return redirect(url('/'));
+        $owners =  app(OwnerService::class)->getAuthorizedOwners();
+        $service = app('OrderTrackingService');
+        $service->fillInOrderTracking();
+        $trackOrders = $service->paginate($request->input());
+        $trackOrders->map(function($trackOrder){
+            if($trackOrder->uploadFile){
+                if(!str_starts_with($trackOrder->uploadFile->url,'http')){
+                    $trackOrder->uploadFile->url = asset('/storage'.$trackOrder->uploadFile->url);
+                }
+            }
+        });
+        $logistics = Logistic::all();
+        return view('order.tracking.index', compact('owners', 'trackOrders','logistics'));
+    }
+
+    public function logisticUpdateApi(Request $request)
+    {
+        if (!Gate::allows('订单管理-跟踪-物流公司编辑'))
+            return redirect(url('/'));
+        try {
+            $message = app(OrderTrackingService::class)->updateOrderTracingAndSyc($request->input('id'),$request->input('param'),$request->input('value'));
+            app('LogService')->log(__METHOD__, __FUNCTION__, '更新成功' . json_encode($request->getContent()) );
+            return $message;
+        } catch (\Exception $e) {
+            app('LogService')->log(__METHOD__, __FUNCTION__, '更新失败' . json_encode($request->getContent()) .'||'.$e->getMessage().'||'.$e->getTraceAsString());
+            return ['success' => false];
+        }
+    }
+
+    public function warehouseUpdateApi(Request $request)
+    {
+        if (!Gate::allows('订单管理-跟踪-仓库编辑'))
+            return redirect(url('/'));
+        try {
+            $message = app(OrderTrackingService::class)->updateOrderTracingAndSyc($request->input('id'),$request->input('param'),$request->input('value'));
+            app('LogService')->log(__METHOD__, __FUNCTION__, '更新成功' . json_encode($request->getContent()));
+            return $message;
+        } catch (\Exception $e) {
+            app('LogService')->log(__METHOD__, __FUNCTION__, '更新失败' . json_encode($request->getContent()) .'||'.$e->getMessage().'||'.$e->getTraceAsString());
+            return ['success' => false];
+        }
+    }
+
+    public function updateLogisticIdApi(Request $request)
+    {
+        if (!Gate::allows('订单管理-跟踪-仓库编辑'))
+            return ['success'=>false,'fail_info'=>'没有对应权限'];
+        try {
+            $logistic = Logistic::query()->where('name',$request['value'])->first();
+            $order = Order::query()->whereHas('packages.commodities.orderTracking',function($query)use($request){
+                $query->where('id',$request['id']);
+            })->first();
+            $order->update(['logistic_id'=>$logistic->id]);
+            app('LogService')->log(__METHOD__, __FUNCTION__, '更新成功' . json_encode($request->getContent()));
+            return ['success'=>true];
+        } catch (\Exception $e) {
+            app('LogService')->log(__METHOD__, __FUNCTION__, '更新失败' . json_encode($request->getContent()) .'||'.$e->getMessage().'||'.$e->getTraceAsString());
+            return ['success' => false,'fail_info'=>$e->getMessage()];
+        }
+
+    }
+
+    public function upload(Request $request)
+    {
+        if (!Gate::allows('订单管理-跟踪-物流公司编辑'))
+            return ['success'=>false,'fail_info'=>'没有对应权限'];
+        $file=$request->file('file');
+        /** @var OrderTracking $orderTracking */
+        $orderTracking = OrderTracking::query()->with('uploadFile')->find($request['id']);
+        if(!$orderTracking){
+            return ['success'=>false,'error'=>'未找到该追踪件'];
+        }
+        if($orderTracking->uploadFile){
+            return ['success'=>false,'error'=>'该运单已存在照片!'];
+        }
+        if(!$file){
+            return ['success'=>false,'error'=>'照片不能为空!'];
+        }
+        if(!$file->isValid()){
+            return ['success'=>false,'error'=>'找不到照片'];
+        }
+        $tmpFile = $file->getRealPath();
+        if(!is_uploaded_file($tmpFile)){
+            return ['success'=>false,'error'=>'文件错误'];
+        }
+        $fileExtension=$file->getClientOriginalExtension();
+        $fileName=date('ymd').'-'.Uuid::uuid1(); // 文件名生成
+        $thumbnailName=storage_path('app/public/files/'.$fileName.'-thumbnail.'.$fileExtension);
+        $commonName=storage_path('app/public/files/'.$fileName.'-common.'.$fileExtension);
+        $bulkyName=storage_path('app/public/files/'.$fileName.'-bulky.'.$fileExtension);
+        $result=move_uploaded_file ($tmpFile ,$bulkyName);
+        if($result) {
+            $img = Image::make($bulkyName);
+            if ($img->height() > $img->width()) {
+                $img->heighten(250)->save($commonName);
+            } else {
+                $img->widen(250)->save($commonName);
+            }
+            $img->heighten(28)->save($thumbnailName);
+            $uploadFile=new UploadFile([
+                "table_name"=>"order_trackings",
+                "table_id"=>$orderTracking->order_client_code,
+                "url"=>'/files/'.$fileName,
+                "type"=>$fileExtension,
+            ]);
+            if ($uploadFile->save()){
+                app('LogService')->log(__METHOD__, '追踪件 图片上传' . __FUNCTION__, json_encode($request));
+            }
+            $uploadFile->url=asset('/storage'.$uploadFile->url);
+            return ['success'=>true,'data'=>$uploadFile];
+        }
+        return ['success'=>false,'error'=>'图片上传失败'];
+    }
+
+    public function export(Request $request)
+    {
+        if (!Gate::allows('订单管理-跟踪'))
+            return redirect(url('/'));
+        /** @var OrderTrackingService $service */
+        $service = app(OrderTrackingService::class);
+        $orderTrackings = $service->getOrderTrackings($request->input());
+//        $column = ['owners_name','order_client_code','web_order_number','pick_up_at','sale','client','sku','sku_name','amount','order_remark',
+//            'gross_weight','bulk','pallet_total','logistic_name','logistic_number','city','planning_sent_at','is_on_duty_shift','is_arrival','signed_at','receive_bill_status','remark'];
+        $rule = ["pick_up_at"=> "mysqlDate",'planning_sent_at'=>"mysqlDate"];
+
+        $row = ['公司','订单号','WEB+订单号','提货日期','销售','客户','SKU','物料描述','数量','订单备注','重量','体积',
+            '托盘合计','运输方式','运输单号','到达城市','应送达时间','是否赶上卡班','到货情况','签收日期','签收单情况','备注'];
+        $mergeColumn = ['A','B','C','D','E','F','J','N','P','P','Q','R','S','T','U','V','M'];
+        $mergeRow = [];
+        $list=[];
+        $start_row = 0;
+        $order_client_code_temp = '';
+        $row_count = 0;
+        foreach ($orderTrackings as $index=> $orderTracking) {
+            $logistic =  $orderTracking->commodities->package->order->logistic->name ?? '';
+            if($order_client_code_temp==''){
+                $order_client_code_temp=$orderTracking->order_client_code;
+                $row_count=1;
+            }else if($order_client_code_temp==$orderTracking->order_client_code){
+                $row_count++;
+                if($index == $orderTrackings->count()-1){
+                    if($row_count>1){
+                        $end_row=$index+2;
+                        $start_row = $index+3-$row_count;
+                        $mergeRow[(string)($start_row)]=(string)($end_row);
+                    }
+                }
+            }else if($order_client_code_temp!=$orderTracking->order_client_code){
+                if($row_count>1){
+                    $end_row=$index+1;
+                    $start_row = $index+2-$row_count;
+                    $mergeRow[(string)($start_row)]=(string)($end_row);
+                }
+                $start_row=$index+2;
+                $row_count=1;
+                $order_client_code_temp = $orderTracking->order_client_code;
+            }
+
+            $order_client_code = $orderTracking->web_order_number?'':$orderTracking->order_client_code;
+            $web_order_number = $orderTracking->web_order_number??'';
+            $pick_up_at=str_split($orderTracking->pick_up_at,10)[0];
+            $planning_sent_at=str_split($orderTracking->planning_sent_at,10)[0];
+            $signed_at=str_split($orderTracking->signed_at,10)[0];
+            $logistic_number =$orderTracking->commodities->package->logistic_number;
+            if($logistic=='新杰物流'||$logistic=='新杰物流到付'){
+                $logistic_number = $orderTracking->order_client_code;
+            }
+            if(str_starts_with('null',$logistic_number)){
+                $logistic_number = '';
+            }
+            $list[]=[
+                $orderTracking->owner->name ?? '',
+                $order_client_code,
+                $web_order_number,
+                $pick_up_at=='0000-00-00'?'':$pick_up_at,
+                $orderTracking->sale,
+                $orderTracking->client,
+                $orderTracking->commodities->commodity->sku ?? '',
+                $orderTracking->commodities->commodity->name ?? '',
+                $orderTracking->commodities->amount ?? '',
+                $orderTracking->order_remark,
+                $orderTracking->gross_weight,
+                $orderTracking->bulk,
+                $orderTracking->pallet_total,
+                $orderTracking->commodities->package->order->logistic->name ??'',
+                $logistic_number,
+                $orderTracking->commodities->package->order->city ?? '',
+                $planning_sent_at=='0000-00-00'?'':$planning_sent_at,
+                $orderTracking->is_on_duty_shift,
+                $orderTracking->is_arrival,
+                $signed_at=='0000-00-00'?'':$signed_at,
+                $orderTracking->receive_bill_status,
+                $orderTracking->remark,
+            ];
+        }
+        $post=Http::post(config('go.export.url'),['type'=>'base','data'=>json_encode(['row'=>$row,'list'=>$list,'mergeColumn'=>$mergeColumn,'mergeRow'=>$mergeRow],JSON_UNESCAPED_UNICODE),
+            'createFormat'=>'merge']);
+
+        if ($post->status() == 500){
+            throw new Exception($post->header("Msg"));
+        }
+        return response($post,200, [
+            "Content-type"=>"application/octet-stream",
+            "Content-Disposition"=>"attachment; filename=订单跟踪件-".date('ymdHis').'.xlsx',
+        ]);
+    }
+
+    public function destroyImg(Request $request)
+    {
+        if(!Gate::allows('订单管理-跟踪-物流公司编辑'))
+            return ['success'=>false,'error'=>'没有对应权限'];
+        $orderTracking = OrderTracking::query()->where('id',$request['id'])->first();
+        if(!$orderTracking){
+            return ['success'=>false,'error'=>'没有找到对应id'];
+        }
+        try {
+            return ['success'=>UploadFile::query()->where('table_name', 'order_trackings')->where('table_id', $orderTracking->order_client_code)->delete()];
+        } catch (Exception $e) {
+            app('LogService')->log(__METHOD__,__FUNCTION__,'追踪件删除照片'.json_encode($e->getMessage()).json_encode($e->getTraceAsString()));
+            return ['success'=>false,'error'=>$e->getMessage()];
+        }
+    }
+}
+

+ 50 - 0
app/Http/Controllers/OrderTrackingOwnerController.php

@@ -0,0 +1,50 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\OrderTrackingOwner;
+use App\Owner;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Gate;
+
+class OrderTrackingOwnerController extends Controller
+{
+
+    public function updateStatusApi(Request $request)
+    {
+        if (!Gate::allows('订单管理-跟踪-监听')) {
+            return ['success' => false, 'fail_info' => '权限不足'];
+        }
+        if (!$request->filled('owner_id') || !$request->filled('status')) {
+            return ['success' => false, 'fail_info' => '没有传入对应参数'];
+        }
+
+        $orderTrackingOwner = OrderTrackingOwner::query()->where('owner_id',$request->input('owner_id'))->first();
+        if ($orderTrackingOwner ?? false) {
+            $success = $orderTrackingOwner->update(['status' => $request->input('status')]);
+            return ['success' => $success];
+        }
+
+        $data = ['owner_id' => $request->input('owner_id'), 'status' => $request->input('status')];
+        $success = $orderTrackingOwner = OrderTrackingOwner::query()->create($data) != null;
+        return ['success' => $success];
+    }
+
+    public function getAllApi()
+    {
+        if (!Gate::allows('订单管理-跟踪-监听')) {
+            return ['success' => false, 'fail_info' => '权限不足'];
+        }
+        $user = Auth::user();
+        $owner_ids = $user ? app('UserService')->getPermittingOwnerIds($user) : [];
+        $owner = Owner::query()->with('orderTrackingOwner')
+            ->whereIn('id',$owner_ids)
+            ->whereHas('orderTrackingOwner',function ($query){$query->where('status','启用');})
+            ->select('id')
+            ->get();
+        return  data_get($owner,'*.id');
+    }
+}
+
+

+ 76 - 36
app/Http/Controllers/OwnerController.php

@@ -21,17 +21,29 @@ class OwnerController extends Controller
      *
      * @return Response
      */
-    public function index()
+    public function index(Request $request)
     {
-        if(!Gate::allows('货主-查询')){ return redirect(url('/'));  }
-        $owners=Owner::orderBy('id','desc')->paginate(25);
-        return view('maintenance.owner.index',['owners'=>$owners]);
+        if (!Gate::allows('货主-查询')) {
+            return redirect(url('/'));
+        }
+        $query = Owner::query()
+            ->orderBy('id', 'desc')
+            ->whereNull('deleted_at');
+        if ($request->has('name')) {
+            $query->where('name', 'like', $request->name . '%');
+        }
+        if ($request->has('code')) {
+            $query->where('code', 'like', $request->code . '%');
+        }
+        $owners = $query->paginate($request->paginate);
+        return view('maintenance.owner.index', ['owners' => $owners]);
     }
 
-
     public function create()
     {
-        if(!Gate::allows('货主-录入')){ return redirect(url('/'));  }
+        if (!Gate::allows('货主-录入')) {
+            return redirect(url('/'));
+        }
         return view('maintenance.owner.create');
     }
 
@@ -43,22 +55,25 @@ class OwnerController extends Controller
      */
     public function store(Request $request)
     {
-        if(!Gate::allows('货主-录入')){ return redirect(url('/'));  }
+        if (!Gate::allows('货主-录入')) {
+            return redirect(url('/'));
+        }
         $this->validatorCreate($request->all())->validate();
-        $owner=new Owner($request->all());
+        $owner = new Owner($request->all());
         $owner->save();
 //        event(new CustomerStoreEvent($owner));
         event(new CustomerStored($owner));
-        $authority=new Authority([
-            'name'=>"_{$owner['id']}",
-            'alias_name'=>"(货主:{$owner['name']})",
-            'remark'=>"(key: _{$owner['id']})",
+        $authority = new Authority([
+            'name' => "_{$owner['id']}",
+            'alias_name' => "(货主:{$owner['name']})",
+            'remark' => "(key: _{$owner['id']})",
         ]);
         $authority->save();
 
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
-        return redirect('maintenance/owner/create')->with('successTip',$request->input('name')??'');
+        app('LogService')->log(__METHOD__, __FUNCTION__, json_encode($request->toArray()), Auth::user()['id']);
+        return redirect('maintenance/owner/create')->with('successTip', $request->input('name') ?? '');
     }
+
     protected function validatorCreate(array $data)
     {
         return Validator::make($data, [
@@ -66,22 +81,19 @@ class OwnerController extends Controller
             'name' => ['required', 'string', 'max:50'],
         ]);
     }
-    protected function validatorUpdate(array $data,$id)
+
+    protected function validatorUpdate(array $data, $id)
     {
         return Validator::make($data, [
             'name' => ['required', 'string', 'max:50'],
-            'code'=>['required', 'string', 'max:50',"unique:owners,code,$id"]
+            'code' => ['required', 'string', 'max:50', "unique:owners,code,$id"]
         ]);
     }
-    /**
-     * Display the specified resource.
-     *
-     * @param Owner $owner
-     * @return Response
-     */
-    public function show(Owner $owner)
+
+    public function getOwners()
     {
-        //
+        $owners = app('OwnerService')->getSelection(['id', 'code', 'name']);
+        return $owners;
     }
 
     /**
@@ -92,8 +104,10 @@ class OwnerController extends Controller
      */
     public function edit(Owner $owner)
     {
-        if(!Gate::allows('货主-编辑')){ return redirect(url('/'));  }
-        return view('maintenance.owner.edit',['owner'=>$owner]);
+        if (!Gate::allows('货主-编辑')) {
+            return redirect(url('/'));
+        }
+        return view('maintenance.owner.edit', ['owner' => $owner]);
     }
 
     /**
@@ -105,13 +119,15 @@ class OwnerController extends Controller
      */
     public function update(Request $request, Owner $owner)
     {
-        if(!Gate::allows('货主-编辑')){ return redirect(url('/'));  }
-        $this->validatorUpdate($request->all(),$owner->id)->validate();
+        if (!Gate::allows('货主-编辑')) {
+            return redirect(url('/'));
+        }
+        $this->validatorUpdate($request->all(), $owner->id)->validate();
         $owner->fill($request->all());
         $owner->update();
         event(new CustomerStored($owner));
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
-        return redirect('maintenance/owner/')->with('successTip',"成功修改货主{$owner['name']}!");
+        app('LogService')->log(__METHOD__, __FUNCTION__, json_encode($request->toArray()), Auth::user()['id']);
+        return redirect('maintenance/owner/')->with('successTip', "成功修改货主{$owner['name']}!");
     }
 
     /**
@@ -123,11 +139,35 @@ class OwnerController extends Controller
      */
     public function destroy(Owner $owner)
     {
-        if(!Gate::allows('货主-删除')){ return redirect(url('/'));  }
-        $authority=Authority::where('name',"_{$owner['id']}")->first();
-        if($authority)$authority->delete();
-        $this->log(__METHOD__,__FUNCTION__,$owner->toJson(),Auth::user()['id']);
-        $re=$owner->delete();
-        return ['success'=>$re];
+        if (!Gate::allows('货主-删除')) {
+            return redirect(url('/'));
+        }
+        $re = $owner->update([
+            "deleted_at" => date('Y-m-d H:i:s'),
+        ]);
+        app('LogService')->log(__METHOD__, __FUNCTION__, $owner->toJson(), Auth::user()['id']);
+        return ['success' => $re];
+    }
+
+    public function recycle()
+    {
+        if (!Gate::allows('货主-删除')) {
+            return redirect(url('/'));
+        }
+        $owners = Owner::query()->orderBy('id', 'desc')->whereNotNull('deleted_at')->paginate(25);
+        return view('maintenance.owner.recycle', ['owners' => $owners]);
+    }
+
+    public function restoreSelected(Request $request)
+    {
+        if (!Gate::allows('货主-删除')) {
+            return ['success' => 'false', 'fail_info' => "没有权限"];
+        }
+        $id = $request->input('id');
+        $owner = Owner::query()->whereNotNull('deleted_at')->where('id', $id)->update([
+            "deleted_at" => null,
+        ]);
+        app('LogService')->log(__METHOD__, __FUNCTION__, json_encode($request->toArray()), Auth::user()['id']);
+        return ['success' => 'true', 'owner' => $owner];
     }
 }

+ 200 - 317
app/Http/Controllers/PackageController.php

@@ -2,91 +2,33 @@
 
 namespace App\Http\Controllers;
 
-use App\Events\WeighedEvent;
-use App\Exports\Export;
-use App\Logistic;
-use App\Owner;
-use App\Package;
+use App\OrderPackage;
 use App\PaperBox;
-use Box\Spout\Common\Helper\Escaper\XLSX;
-use Box\Spout\Common\Type;
-use Box\Spout\Writer\Common\Creator\WriterEntityFactory;
-use Box\Spout\Writer\Common\Creator\WriterFactory;
+use App\Services\OrderPackageService;
+use App\Services\OwnerService;
+use App\Services\PackageService;
+use App\Services\PackageStatisticsService;
 use Carbon\Carbon;
+use Exception;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Auth;
-use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Gate;
+use Illuminate\Support\Facades\Http;
 use Illuminate\Support\Facades\Validator;
-use Maatwebsite\Excel\Facades\Excel;
-use Box\Spout\Common\Entity\Row;
 
 
 class PackageController extends Controller
 {
-    //超15天精确查询抽离 cloumn前提:数据库字段名必须与request内字段名一致
-    public function preciseQuery(string $column,Request $request,$packages){
-        $today=Carbon::now()->subDays(15);
-        $packagesTem=clone $packages;
-        $packagesTem=$packagesTem->where($column,'like','%'.$request->input($column).'%')->where('created_at','>',$today->format('Y-m-d'));
-        if($packagesTem->count()==0
-            ||$packagesTem->first()[$column]==$request->input($column)){
-            $packages=$packages->where($column,$request->input($column));
-        }else{
-            $packages=$packagesTem;
-        }
-        return $packages;
-    }
-
-    public function conditionQuery(Request $request,$packages){
-        if ($request->input('logistic_number')){
-            $packages=$this->preciseQuery('logistic_number',$request,$packages);
-        }
-        if ($request->input('delivery_number')){
-            $packages=$this->preciseQuery('logistic_number',$request,$packages);
-        }
-        if ($request->input('created_at_start')){
-            $created_at_start=$request->input('created_at_start')." 00:00:00";
-            $packages=$packages->where('created_at','>=',$created_at_start);
-        }
-        if ($request->input('created_at_end')){
-            $created_at_end=$request->input('created_at_end')." 23:59:59";
-            $packages=$packages->where('created_at','<=',$created_at_end);
-        }
-        if ($request->input('owner_id')){
-            $packages=$packages->where('owner_id',$request->input('owner_id'));
-        }
-        if ($request->input('batch_number')){
-            $packages=$this->preciseQuery('batch_number',$request,$packages);
-        }
-        return $packages;
-    }
-
-    /**
-     * Display a listing of the resource.
-     *
-     * @return \Illuminate\Http\Response
-     */
-    public function index(Request $request)
+    public function index(Request $request,OwnerService $ownerService)
     {
         if(!Gate::allows('称重管理-查询')){ return redirect(url('/'));  }
-        if ($request->input()){
-            $packages=Package::orderBy('id','DESC');
-            $packages=$this->conditionQuery($request,$packages);
-            $packages=$packages->paginate($request->input('paginate')?$request->input('paginate'):50);
-            $owners=Owner::select('id','name')->get();
-            return view('weight.package.index',['packages'=>$packages,'owners'=>$owners,'request'=>$request->input()]);
-        }
-        $packages=Package::orderBy('id','DESC')->paginate(50);
-        $owners=Owner::select('id','name')->get();
-        return view('weight.package.index',['packages'=>$packages,'owners'=>$owners]);
+        $paginateParams = $request->input();
+        /** @var PackageService $application */
+        $application = app('PackageService');
+        $packages = $application->paginate($request);
+        return view('weight.package.index',['packages'=>$packages,'owners'=>$ownerService->getSelection(),'paginateParams'=>$paginateParams]);
     }
 
-    /**
-     * Show the form for creating a new resource.
-     *
-     * @return \Illuminate\Http\Response
-     */
     public function create()
     {
         if(!Gate::allows('称重管理-录入')){ return redirect(url('/'));  }
@@ -97,8 +39,8 @@ class PackageController extends Controller
     /**
      * Store a newly created resource in storage.
      *
-     * @param  \Illuminate\Http\Request  $request
-     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
+     * @param Request $request
+     * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|void
      */
     public function store(Request $request)
     {
@@ -106,223 +48,163 @@ class PackageController extends Controller
         $this->validator($request)->validate();
         $logistic_number=$request->input('logistic_number');
         $weight=$request->input('weight');
-        $batch_number=$request->input('batch_number');
+        $batch_number=strtoupper($request->input('batch_number'));
+        $order_code=$request->input('order_code');
         $paper_box_id=$request->input('paper_box_id');
-        $isSamePackBatch=$request->input('is_same_pack_batch');
+//        $isSamePackBatch=$request->input('is_same_pack_batch');
         if($logistic_number&&$batch_number)return redirect('package/create')->with('successError','录入失败!波次号和快递单号只能填一项!');
         $package=null;
+        $successTip = '操作成功';
+
+        /** @var OrderPackage $package */
+        if ($order_code){
+            $package=OrderPackage::query()->with(['order'=>function($query)use($order_code){
+                $query->where('code',$order_code) ;
+            }])->first();
+        }else{
+            if($batch_number){
+                $package=OrderPackage::query()->where('batch_number',$batch_number)->first();
+
+            }elseif($logistic_number){
+                $package=OrderPackage::query()->where('logistic_number',$logistic_number)->first();
+            }
+        }
+        $accomplishToWMS=new Api\thirdPart\flux\PackageController();
+
+
         if($batch_number){
-            $package=Package::where('batch_number',$batch_number)->first();
-        }elseif($logistic_number){
-            $package=Package::where('logistic_number',$logistic_number)->first();
+            app('LogService')->log(__METHOD__,'活动波次开始同步_'.__FUNCTION__,json_encode($package),Auth::user()['name']);
+//            $this->syncBatch($package->batch_number,$weight,null,null,null,Carbon::now(),null);
+            $result=$accomplishToWMS->markWMSOnBatch($batch_number,$weight);
+
+
+
+            OrderPackage::createPackagesFromBatchCode($batch_number,$weight);
+
+
+            if($package&&$package->isActivityBatch())
+                $package->unifyThisMeasureUnderSameBatch();
+
+            if ($result['result']){
+                Controller::logS(__METHOD__,'SUCCESS_'.__FUNCTION__,'批量更改波次上传成功'.$batch_number);
+                $successTip = "批量录入波次成功!波次号:$batch_number";
+                return redirect('package/create')->with('successTip', $successTip);
+            }
+            Controller::logS(__METHOD__,'error_'.__FUNCTION__,'批量更改波次上传异常:'.$result['message'].$batch_number);
+
+            return redirect('package/create')->with('successError','录入失败!'.$result['message']);
         }
         if (!$package && !$logistic_number)return redirect('package/create')->with('successError','录入失败!系统内没有对应波次的包裹!');
-        $successTip = '操作成功';
         if ($package){
-            $accomplishToWMS=new \App\Http\Controllers\Api\thirdPart\flux\PackageController();
-            if ($isSamePackBatch||($package->batch_rule&&strstr($package->batch_rule,'组合'))){
-                $this->log(__METHOD__,'活动波次开始同步_'.__FUNCTION__,json_encode($package),Auth::user()['name']);
-                $this->syncBatch($package->batch_number,$weight,null,null,null,Carbon::now(),$paper_box_id);
+            if(!$package->batch_number)$package->batch_number=$batch_number;
+            //if(!$package->order_code)$package->order_code=$order_code;
+            $package->fetchAllFromOracle();
+            $package->weight=$weight;
+            if(!$package->paper_box_id)$package->paper_box_id=$paper_box_id;
+            $result=$accomplishToWMS->accomplishToWMS($package);
+            if ($result['result']){
+                $package->status="已上传";
             }else{
-                if($batch_number){
-                    return redirect('package/create')->with('successError','录入失败!该波次不是组合提总!');
-                }
-                $package->weight=$weight;
-                $package->paper_box_id=$paper_box_id;
-                $package->batch_number=$batch_number;
-                $result=$accomplishToWMS->accomplishToWMS($package);
-                if ($result['result']=='success'){
-                    if ($package->status=="记录异常")$package->status="已上传异常";
-                    else $package->status="已上传";
-                }else{
-                    $package->status="上传异常";
-                }
+                $package->status="上传异常";
             }
+            $package->save();
+            app('LogService')->log(__METHOD__,'create_'.__FUNCTION__,json_encode($package),Auth::user()['name']);
+//            event(new WeighedEvent($package));
+
         }else{
-            $package=new Package([
-                'logistic_number'=>$logistic_number,
+
+            /** @var OrderPackageService */
+            $package = app('OrderPackageService')->firstOrCreate($logistic_number,[
                 'weight'=>$weight,
-                'paper_box_id'=>$paper_box_id,
-                'batch_number'=>$batch_number
+                'weighed_at'=>Carbon::now(),
+                'status'=>"已上传",
             ]);
-            $successTip = "新建称重记录成功!单号:$logistic_number";
+            $package->fetchAllFromOracle();
+            $result=$accomplishToWMS->accomplishToWMS($package);
+            $str = "录入包裹成功!";
+            $str .= $package['logistic_number']?"快递单号:{$package['logistic_number']}":'';
+            $str .= $order_code?", 订单号:{$order_code}":'';
+            if(!$result||$result['result']=='false'){
+                $package['status'] = '上传失败';
+                $str = "录入包裹失败!";
+                $str .= $package['logistic_number']?"快递单号:{$package['logistic_number']}":'';
+                $str .= $order_code?", 订单号:{$order_code}":'';
+                app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($package).json_encode($result).$str,Auth::user()['name']);
+            }
+            $package->save();
+            $successTip = $str;
+
+
         }
-        $package->save();
-        $this->log(__METHOD__,'create_'.__FUNCTION__,json_encode($package),Auth::user()['name']);
-        event(new WeighedEvent($package));
+
+
         return redirect('package/create')->with('successTip', $successTip);
     }
 
-
     public function statistics(Request $request){
-        $packages=Package::select(DB::raw('owner_id,logistic_id,COUNT(logistic_id) AS count'))->whereNotNull('owner_id');
-        if($request->input('owner_id')){
-            $owners_id=$id = explode( ',',$request->input('owner_id'));
-            $packages=$packages->whereIn('owner_id',$owners_id);
-        }
-        if($request->input('logistic_id')){
-            $logistics_id=$id = explode( ',',$request->input('logistic_id'));
-            $packages=$packages->whereIn('logistic_id',$logistics_id);
+        $packages = app('PackageStatisticsService')->get($request->input());
+        $owners=app('OwnerService')->getSelection();
+        $logistics=app('LogisticService')->getSelection();
+        $ownerTemp = [];
+        foreach ($owners as $owner){
+            $ownerTemp[$owner->id] = $owner->name;
         }
-        if($request->input('date_start')){
-            $packages=$packages->where('created_at','>=',$request->input('date_start'));
+        $ps = [];
+        $logisticsTemp = [];
+        foreach ($packages as $package){
+            if (!($logisticsTemp[$package->logistic_id] ?? false))$logisticsTemp[$package->logistic_id] = true;
+            if ($ps[$package->owner_id] ?? false){
+                $ps[$package->owner_id][$package->logistic_id] = $package->count;
+                $ps[$package->owner_id]["sum"] += (int)$package->count;
+            }else{
+                $ps[$package->owner_id] = [
+                    $package->logistic_id => $package->count,
+                    "sum" => (int)$package->count,
+                    "owner_id" => $package->owner_id,
+                    "owner_name" => $ownerTemp[$package->owner_id]
+                ];
+            }
         }
-        if($request->input('date_end')){
-            $packages=$packages->where('created_at','<=',$request->input('date_end'));
+        foreach ($logistics as $index => $logistic){
+            if (!($logisticsTemp[$logistic->id] ?? false))unset($logistics[$index]);
         }
-        $packages=$packages->groupBy(['owner_id','logistic_id'])->get();
-        $owners=Owner::get();
-        $logistics=Logistic::get();
-        if ($request->input('checkSign')){
-            $logistics=$this->checkLogistic($packages);
-            if ($request->input('checkSign')=="-1"){
-                $excel=$this->statisticExport($packages,$owners,$logistics);
-                return $excel;
-            }
-            $id=$id = explode( ',',$request->input('checkSign'));
-            $packages=Package::select(DB::raw('owner_id,logistic_id,COUNT(logistic_id) AS count'))
-                ->whereIn('owner_id',$id)->groupBy(['owner_id','logistic_id'])->get();
-            $logistics=$this->checkLogistic($packages);
-            $excel=$this->statisticExport($packages,$owners,$logistics);
-            return $excel;
-
+        foreach ($ps as &$p){
+            $p = json_encode($p,JSON_UNESCAPED_UNICODE);
         }
-        return view('weight.package.statistics',["packages"=>$packages,'owners'=>$owners,'logistics'=>$logistics]);
+        return view('weight.package.statistics',["packages"=>$ps,'owners'=>$owners,'logistics'=>$logistics]);
     }
 
-    /*
-     * 根据packages统计记录删选物流公司
-     */
-    public function checkLogistic($packages){
-        $logisticIds=[];
-        foreach ($packages as $package){
-            $isLogistic=true;
-            for ($i=0;$i<count($logisticIds);$i++){
-                if ($package->logistic_id==$logisticIds[$i]){
-                    $isLogistic=false;
-                    break;
-                }
-            }
-            if ($isLogistic){
-                array_push($logisticIds,$package->logistic_id);
-            }
+    public function export(Request $request){
+        if(!Gate::allows('称重管理-查询')){ return '没有权限';  }
+        if ($request->checkAllSign ?? false){
+            $params = $request->input();
+            unset($params['checkAllSign']);
+            $sql = app('PackageService')->getSql($params);
+        }else{
+            $sql=app('PackageService')->getSql(['id'=>$request->data]);
         }
-        $logistics=Logistic::whereIn('id',$logisticIds)->get();
-        return $logistics;
-    }
-
-    /**
-     * Display the specified resource.
-     *
-     * @param  \App\Package  $packages
-     * @return \Illuminate\Http\Response
-     */
-    public function show(Package $packages)
-    {
-        //
-    }
-
-    /**
-     * Show the form for editing the specified resource.
-     *
-     * @param  \App\Package  $packages
-     * @return \Illuminate\Http\Response
-     */
-    public function edit(Package $packages)
-    {
-        //
-    }
-
-    /**
-     * Update the specified resource in storage.
-     *
-     * @param  \Illuminate\Http\Request  $request
-     * @param  \App\Package  $packages
-     * @return \Illuminate\Http\Response
-     */
-    public function update(Request $request, Package $packages)
-    {
-        //
-    }
-
-    /**
-     * Remove the specified resource from storage.
-     *
-     * @param  \App\Package  $packages
-     * @return \Illuminate\Http\Response
-     */
-    public function destroy(Package $packages)
-    {
-        //
-    }
+        $row = ["货主","快递单号","波次号","订单号","物流公司","设备","重(KG)","长(cm)","宽(cm)","高(cm)","体积(cm³)","纸箱","状态","波次规则","称重时间","收件人","收件人电话"];
+        $column = ["owner_name", "logistic_number", "batch_number", "order_code", "logistic_name","measuring_machine_name",
+            "weight", "length", "width", "height", "bulk", "paper_box_name", "status","batch_rule","weighed_at","order_consignee_name","order_consignee_phone"];
+        $rule = ["weighed_at"=> "mysqlDate"];
+        $post = Http::post(config('go.export.url'),['type'=>'unify','sql'=>$sql, 'connection'=>'mysql',
+            'row'=>json_encode($row,JSON_UNESCAPED_UNICODE), 'column'=>json_encode($column), 'rule'=>json_encode($rule)]);
 
-    public function export($id,Request $request){
-        if(!Gate::allows('称重管理-查询')){ return '没有权限';  }
-        ini_set('max_execution_time',3500);
-        ini_set('memory_limit','3526M');
-        if ($id==-1){
-            $id=[];
-            $packages=Package::select('id');
-            $packages=$this->conditionQuery($request,$packages);
-            $packages=$packages->get();
-            foreach ($packages as $package){
-                array_push($id,$package->id);
-            }
-        }else $id = explode( ',',$id);
-        if (!$id)return ;
-        $row=[[
-            'id'=>'ID',
-            'owner_name'=>'货主',
-            'logistic_number'=>'快递单号',
-            'delivery_number'=>'发货单号',
-            'batch_number'=>'波次号',
-            'batch_rule'=>'波次规则',
-            'created_at'=>'操作时间',
-            'recipient'=>'收件人',
-            'recipient_mobile'=>'收件人电话',
-            'logistic_name'=>'承运商',
-            'measuringMachine_name'=>'设备',
-            'weight'=>'重量(KG)',
-            'length'=>'长(CM)',
-            'width'=>'宽(CM)',
-            'height'=>'高(CM)',
-            'bulk'=>'体积(CM³)',
-            'paperBox_name'=>'纸箱',
-            'status'=>'状态',
-        ]];
-        $list=[];
-        for ($i=0; $i<count($id);$i++){
-            $package=Package::find($id[$i]);
-            $w=[
-                'id'=>isset($package->id)?$package->id:'',
-                'owner_name'=>isset($package->owner_name)?$package->owner_name:'',
-                'logistic_number'=>isset($package->logistic_number)?$package->logistic_number:'',
-                'delivery_number'=>isset($package->delivery_number)?$package->delivery_number:'',
-                'batch_number'=>isset($package->batch_number)?$package->batch_number:'',
-                'batch_rule'=>isset($package->batch_rule)?$package->batch_rule:'',
-                'created_at'=>isset($package->created_at)?$package->created_at:'',
-                'recipient'=>isset($package->recipient)?$package->recipient:'',
-                'recipient_mobile'=>isset($package->recipient_mobile)?$package->recipient_mobile:'',
-                'logistic_name'=>isset($package->logistic_name)?$package->logistic_name:'',
-                'measuringMachine_name'=>isset($package->measuringMachine_name)?$package->measuringMachine_name:'',
-                'weight'=>isset($package->weight)?$package->weight:'',
-                'length'=>isset($package->length)?$package->length:'',
-                'width'=>isset($package->width)?$package->width:'',
-                'height'=>isset($package->height)?$package->height:'',
-                'bulk'=>isset($package->bulk)?$package->bulk:'',
-                'paperBox_name'=>isset($package->paperBox_name)?$package->paperBox_name:'',
-                'status'=>isset($package->status)?$package->status:''
-            ];
-            $list[$i]=$w;
+        if ($post->status() == 500){
+            throw new Exception($post->header("Msg"));
         }
-        return Excel::download(new Export($row,$list),date('YmdHis', time()).'-称重记录单.xlsx');
+        return response($post,200, [
+            "Content-type"=>"application/octet-stream",
+            "Content-Disposition"=>"attachment; filename=包裹信息-".date('ymdHis').'.xlsx',
+        ]);
     }
     protected function validator(Request $request){
         $validator=Validator::make($request->input(),[
-            'logistic_number'=>['nullable','max:50'],
+            'logistic_number'=>['required_without_all:batch_number,order_code'],
+            'order_code'=>['required_without_all:logistic_number,batch_number'],
             'weight'=>'required|min:0|max:999999|numeric',
             'paper_box_id'=>'nullable|integer',
-            'batch_number'=>['required_without:logistic_number']
+            'batch_number'=>['required_without_all:logistic_number,order_code']
         ],[
             'required'=>':attribute 为必填项',
             'max'=>':attribute 字符过多或输入值过大',
@@ -330,82 +212,83 @@ class PackageController extends Controller
             'min'=>':attribute 不得为负',
             'numeric'=>':attribute 应为数字',
             'unique'=>':attribute 已存在',
-            'required_without'=>':attribute 与快递单号至少填一项'
+            'required_without_all'=>':attribute 与快递单号或订单号至少选一项'
         ],[
             'logistic_number'=>'快递单号',
             'weight'=>'重量',
             'paper_box_id'=>'纸箱',
             'batch_number'=>'波次号',
+            'order_code'=>'订单号',
         ]);
         return $validator;
     }
 
-    public function syncBatch($batch_number,$weight,$max,$centre,$min,$date,$paperBox_id){
-        $accomplishToWMS=new \App\Http\Controllers\Api\thirdPart\flux\PackageController();
-        $packageBatch=Package::where('batch_number',$batch_number)->first();
-        if(!$packageBatch)return;
-        $newValues = ['weight' => $weight];
-        if($max)$newValues['length']=$max;
-        if($centre)$newValues['width']=$centre;
-        if($min)$newValues['height']=$min;
-        if($date)$newValues['weighed_at']=$date;
-        if($paperBox_id)$newValues['paper_box_id']=$paperBox_id;
-        if($max&&$centre&&$min){
-            $newValues['bulk']=$max*$centre*$min;
-        }
-        $weightChanged=$packageBatch['weight']!=$weight;
-        Package::where('batch_number',$batch_number)->update($newValues);
-        $packageBatch['forceUpload']=$weightChanged;
-        $result=$accomplishToWMS->accomplishToWMS($packageBatch);
-        if ($result['result']=='success'){
-            $newValues['status']='已上传';
-            Controller::logS(__METHOD__,'SUCCESS_'.__FUNCTION__,'批量更改波次上传成功'.json_encode($packageBatch));
+    public function statisticsExport(Request $request){
+        if(!Gate::allows('称重管理-查询')){ return '没有权限';  }
+        /** @var PackageStatisticsService $service */
+        $service = app('PackageStatisticsService');
+
+        if ($request->checkAllSign){
+            $params = $request->input();
+            unset($params['checkAllSign']);
+            $data = $service->get($params);
         }else{
-            $newValues['status']='上传异常';
-            Controller::logS(__METHOD__,'error_'.__FUNCTION__,'批量更改波次上传异常:'.json_encode($packageBatch));
+            /**@var PackageStatisticsService */
+            $data = $service->get(['owner_id'=>$request->data]);
         }
-        Package::where('batch_number',$batch_number)->update($newValues);
 
-    }
+        $owners=app('OwnerService')->getSelection();
+        $ownerTemp = [];
+        foreach ($owners as $owner){
+            $ownerTemp[$owner->id] = $owner->name;
+        }
 
-    public function statisticExport($packages,$owners,$logistics){
-        if (!$packages||!$owners||!$logistics) return;
-        $row=[[]];
-        $row[0]['owner']='货主';
-        $row[0]['sum']='总计';
-        foreach ($logistics as $logistic){
-            $row[0][$logistic->id]=$logistic->name;
+
+        $logisticsTemp = [];
+        $ps = [];
+        foreach ($data as $package){
+            if (!($logisticsTemp[$package->logistic_id] ?? false))$logisticsTemp[$package->logistic_id] = true;
+            if ($ps[$package->owner_id] ?? false){
+                $ps[$package->owner_id][$package->logistic_id] = $package->count;
+                $ps[$package->owner_id]["sum"] += (int)$package->count;
+            }else{
+                $ps[$package->owner_id] = [
+                    $package->logistic_id => $package->count,
+                    "sum" => (int)$package->count,
+                    "owner_id" => $package->owner_id,
+                    "owner_name" => $ownerTemp[$package->owner_id]
+                ];
+            }
         }
-        $ownerArr=[];
-        foreach ($owners as $owner){
-            foreach ($packages as $package){
-                if ($owner->id==$package->owner_id){
-                    $ownerArr[$owner->name][$package->logistic_id]=$package->count;
-                }
+
+        $column = ["货主","总计"];
+
+        $columnMap = [];
+        $logistics=app('LogisticService')->getSelection();
+        foreach ($logistics as $index => $logistic){
+            if (!($logisticsTemp[$logistic->id] ?? false))unset($logistics[$index]);
+            else {
+                $columnMap[] = $logistic->id;
+                $column[] = $logistic->name;
             }
         }
-        $list=[];
-        $i=0;
-        foreach ($owners as $owner){
-            if (isset($ownerArr[$owner->name])){
-                $w['owner']=$owner->name;
-                $sum=0;
-                foreach ($logistics as $logistic){
-                    if (isset($ownerArr[$owner->name][$logistic->id])){
-                        $w[$logistic->id]=$ownerArr[$owner->name][$logistic->id];
-                        $sum=$sum+$ownerArr[$owner->name][$logistic->id];
-                    }
-                    if (!isset($ownerArr[$owner->name][$logistic->id])){
-                        $w[$logistic->id]=0;
-                    }
-                }
-                $w['sum']=$sum;
-                $list[$i]=$w;
-                $i++;
+
+        $list = [];
+        foreach ($ps as $p){
+            $row = [$p["owner_name"],$p["sum"]];
+            foreach ($columnMap as $id){
+                $row[] = $p[$id] ?? 0;
             }
+            $list[] = $row;
         }
-        return Excel::download(new Export($row,$list),date('YmdHis', time()).'-称重统计记录单.xlsx');
+        $post = Http::post(config('go.export.url'),['type'=>'base','data'=>json_encode(["row"=>$column,"list"=>$list],JSON_UNESCAPED_UNICODE)]);
+        if ($post->status() == 500){
+            throw new Exception($post->header("Msg"));
+        }
+        return response($post,200, [
+            "Content-type"=>"application/octet-stream",
+            "Content-Disposition"=>"attachment; filename=称重统计信息单-".date('ymdHis').'.xlsx',
+        ]);
     }
 
-
 }

+ 5 - 5
app/Http/Controllers/PaperBoxController.php

@@ -82,7 +82,7 @@ class PaperBoxController extends Controller
         if ($owner_id){
             $paperBox->owners()->sync($owner_id);
         }
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return redirect('maintenance/paperBox/index/model')->with('successTip','新纸箱'.$request->input('model').'录入成功');
     }
 
@@ -134,7 +134,7 @@ class PaperBoxController extends Controller
         if ($owner_id){
             $paperBox->owners()->sync($owner_id);
         }
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return redirect('maintenance/paperBox/index/model')->with('successTip','纸箱'.$request->input('model').'信息更新成功');
     }
 
@@ -146,10 +146,10 @@ class PaperBoxController extends Controller
     {
         if(!Gate::allows('纸箱-删除')){ return redirect(url('/'));  }
         $paperBox=PaperBox::find($id);
-        $this->log(__METHOD__,__FUNCTION__,json_encode($paperBox),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($paperBox),Auth::user()['id']);
         if ($paperBox->delete()){
             $paperBox->owners()->detach();
-            $this->log(__METHOD__,__FUNCTION__,json_encode($paperBox),Auth::user()['id']);
+            app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($paperBox),Auth::user()['id']);
             return ['success'=>true];
         }else{
             return ['success'=>false];
@@ -173,7 +173,7 @@ class PaperBoxController extends Controller
                 $exception=Cache::get('exception');
                 $a='';
                 for ($i=0;$i<count($exception);$i++){$a.=implode(',',$exception[$i]).'&#10'; };
-                $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+                app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
                 return '<h1 class="text-danger">导入Excel成功<br><textarea style="width: 50%;height: 50%">'.$a.'</textarea></h1>';
             }
         }else{

+ 146 - 68
app/Http/Controllers/PersonnelController.php

@@ -2,26 +2,105 @@
 
 namespace App\Http\Controllers;
 
+use App\Events\ExportEvent;
+use App\Events\ImportEvent;
 use App\Events\TeamAuditEvent;
-use App\LaborCompany;
 use App\LaborReport;
 use App\ProcessDailyParticipant;
-use App\User;
+use App\Services\LaborReportService;
 use App\UserDetail;
 use App\UserDutyCheck;
-use App\UserLabor;
 use App\UserWorkgroup;
 use Carbon\Carbon;
 use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Auth;
-use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Gate;
 use Illuminate\Support\Facades\Validator;
-use Ramsey\Uuid\Uuid;
+
 
 class PersonnelController extends Controller
 {
+    function __construct()
+    {
+        app()->bind('LaborReportService',LaborReportService::class);
+    }
+    //录入补卡
+    public function storeReplenishClock(Request $request){
+        if(!Gate::allows('人事管理-录入补卡')){ return redirect(url('/'));  }
+        $errors=$this->validatorUserDutyCheck($request)->errors();
+        if (count($errors)>0)return ['success'=>false,'error'=>$errors];
+        $user_id=$request->input('user_id');
+        $checked_at=$request->input('checked_at');
+        $type=$request->input('type');
+        $remark=$request->input('remark');
+        $userDutyCheck=new UserDutyCheck([
+            'user_id'=>$user_id,
+            'checked_at'=>$checked_at,
+            'type'=>$type,
+            'source'=>'补入',
+        ]);
+        $checkedAtDate=Carbon::parse($checked_at)->format('Y-m-d');
+        $userDutyCheckBefore=UserDutyCheck::where('user_id',$user_id)->where('checked_at','like',$checkedAtDate.'%')->orderBy('id','desc')->first();
+        if ($userDutyCheckBefore['type']=='登入'&&$userDutyCheck->type=='登入')return ['result'=>true,'data'=>'已存在进场记录!'];
+        if ($userDutyCheckBefore['type']=='登出'&&$userDutyCheck->type=='登出')return ['result'=>true,'data'=>'已存在出场记录!'];
+        if ($type=='登出')$userDutyCheck->verify_user_id=Auth::user()['id'];
+        $userDutyCheck->save();
+        app('LogService')->log(__METHOD__,"录入补卡".__FUNCTION__,json_encode($userDutyCheck),Auth::user()['id']);
+        $errorMessage=$this->makeOrUpdateLaborReport($userDutyCheck,$remark);
+        if ($errorMessage)return $errorMessage;
+        return ['success'=>true,'data'=>$userDutyCheck];
+    }
+    //补卡创建或修改临时工报表
+    public function makeOrUpdateLaborReport($userDutyCheck,$remark){
+        $checkedAtDate=Carbon::parse($userDutyCheck->checked_at)->format('Y-m-d');
+        $laborReport=LaborReport::where('user_id',$userDutyCheck->user_id)->where('created_at','like',$checkedAtDate.'%')->orderBy('id','desc')->first();
+        $laborReportService = app('LaborReportService');
+        if (!$laborReport&&$userDutyCheck->type=='登入'){
+            $newReport=$userDutyCheck->makeEnteringRecord();
+            /** @var LaborReportService $laborReportService */
+            $laborReportService=app(LaborReportService::class);
+            $laborReportService->addOrUpdateRemark($remark,$newReport->id);
+            app('LogService')->log(__METHOD__,"进场创建临时工报表记录__".__FUNCTION__,json_encode([$userDutyCheck]));
+            if ($newReport) event(new ImportEvent($newReport));
+        }
+        else if(!$laborReport&&$userDutyCheck->type=='登出'){
+            //退场时间跨天情况
+            $yesterdayDate=Carbon::parse($userDutyCheck->checked_at.':00')->subDays(1)->format('Y-m-d');
+            $laborReportYesterday=LaborReport::where('user_id',$userDutyCheck->user_id)->where('created_at','like',$yesterdayDate.'%')->orderBy('id','desc')->first();
+            if ($laborReportYesterday&&!$laborReportYesterday['check_out_at']){
+                UserDutyCheck::where('user_id',$laborReportYesterday['user_id'])->where('type','登出')->orderBy('id','desc')->delete();
+                return ['result'=>true,'data'=>'该临时工还未退组,暂不可补退场卡!'];
+            }
+            if ($laborReportYesterday){
+                $exportReport=$laborReportService->exportReplenishToCreateLaborReportData($laborReportYesterday,$userDutyCheck);
+                if ($exportReport->remark) $remark=$exportReport->remark.','.$remark;
+                /** @var LaborReportService $laborReportService */
+                $laborReportService=app(LaborReportService::class);
+                $laborReportService->addOrUpdateRemark($remark,$exportReport->id);
+                app('LogService')->log(__METHOD__,"补退场卡修改临时工报表记录__".__FUNCTION__,json_encode([$laborReportYesterday,$userDutyCheck]));
+                if ($exportReport) event(new ExportEvent($exportReport));
+            }
+        }else if($laborReport){
+            if (!$laborReport->check_out_at){
+                UserDutyCheck::where('user_id',$laborReport->user_id)->where('type','登出')->orderBy('id','desc')->delete();
+                return ['result'=>true,'data'=>'该临时工还未退组,暂不可补退场卡!'];
+            }
+            $exportReport=$laborReportService->exportReplenishToCreateLaborReportData($laborReport,$userDutyCheck);
+            if ($exportReport->remark) $remark=$exportReport->remark.','.$remark;
+            /** @var LaborReportService $laborReportService */
+            $laborReportService=app(LaborReportService::class);
+            $laborReportService->addOrUpdateRemark($remark,$exportReport->id);
+            app('LogService')->log(__METHOD__,"补退场卡修改临时工报表记录__".__FUNCTION__,json_encode([$laborReport,$userDutyCheck]));
+            if ($exportReport) event(new ExportEvent($exportReport));
+        }
+    }
+
+
+
+
+
+
     //任务审核
     public function storeMissionAudit(Request $request){
         if(!Gate::allows('人事管理-任务审核')){ return redirect(url('/'));  }
@@ -31,7 +110,7 @@ class PersonnelController extends Controller
         if (!$id)return ['error'=>'未找到对应记录!'];
         $processDailyParticipant->status='已审核';
         $processDailyParticipant->update();
-        $this->log(__METHOD__,"任务审核".__FUNCTION__,json_encode($processDailyParticipant),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,"任务审核".__FUNCTION__,json_encode($processDailyParticipant),Auth::user()['id']);
         return;
     }
 
@@ -64,14 +143,14 @@ class PersonnelController extends Controller
 
     //打卡审核
     public function storeClockAudit(Request $request){
-        if(!Gate::allows('人事管理-打卡审核')){ return ["success"=>false,"data"=>"您无此权限操作!!!"];  }
+        if(!Gate::allows('人事管理-门卫审核')){ return ["success"=>false,"data"=>"您无此权限操作!!!"];  }
         $id=$request->input('id');
         $type=$request->input('type');
         $userDutyCheck=UserDutyCheck::find($id);
         $userDutyCheck->type=$type;
         $userDutyCheck->verify_user_id=Auth::user()['id'];
         $userDutyCheck->update();
-        $this->log(__METHOD__,"打卡审核".__FUNCTION__,json_encode($userDutyCheck),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,"打卡审核".__FUNCTION__,json_encode($userDutyCheck),Auth::user()['id']);
         return ["success"=>true,"data"=>$userDutyCheck->verify_user_id];
     }
 
@@ -87,29 +166,38 @@ class PersonnelController extends Controller
         $type=$request->input('type');
         $userDutyCheck->type=$type;
         $userDutyCheck->group_user_id=Auth::user()['id'];
-        $checkInDate=Carbon::parse($userDutyCheck->checked_at)->format('Y-m-d');
-        $laborReport=LaborReport::where('user_id',$userDutyCheck->user_id)->where('user_workgroup_id',$workgroup->id)->where('created_at','like',$checkInDate."%")->first();
         $userDutyCheck->update();
-        $this->updateLaborReportVerify($laborReport,$userDutyCheck);
-        $this->log(__METHOD__,"打卡组长审核".__FUNCTION__,json_encode($userDutyCheck),Auth::user()['id']);
+//        $checkInDate=Carbon::parse($userDutyCheck->checked_at)->format('Y-m-d');where('created_at','like',$checkInDate."%")
+        $laborReport=LaborReport::where('user_id',$userDutyCheck->user_id)->where('user_workgroup_id',$workgroup->id)->orderBy('id','desc')->first();
+        if (!$laborReport){
+            $laborReportNew=LaborReport::createLaborReportData($userDutyCheck);
+            app('LogService')->log(__METHOD__,"提交临时工报表记录__".__FUNCTION__,json_encode([$userDutyCheck->user_id,$userDutyCheck->workgroup_id,$userDutyCheck]));
+            //验证五分钟之内重新换组情况
+            $checkInDateNow=Carbon::parse($laborReportNew->created_at)->format('Y-m-d H');
+            $laborReports=LaborReport::where('user_id',$userDutyCheck->user_id)->where('created_at','like',$checkInDateNow."%")->orderBy('created_at','DESC')->limit(2)->get();
+            if (count($laborReports)>1){
+                $laborReportLast=LaborReport::where('user_id',$userDutyCheck->user_id)->where('created_at','like',$checkInDateNow."%")->orderBy('created_at','ASC')->limit(2)->first();
+                $lastDate=Carbon::parse($laborReportLast->created_at);
+                $thisDate=Carbon::parse($laborReportNew->created_at);
+                $diffDate=$thisDate->diffInMinutes($lastDate);
+                if ($diffDate<=5){
+                    $laborReportLast->delete();
+                }
+            }
+        }else if ($laborReport){
+            LaborReport::updateLaborReportVerify($laborReport,$userDutyCheck);
+            app('LogService')->log(__METHOD__,"打卡组长审核".__FUNCTION__,json_encode($userDutyCheck),Auth::user()['id']);
+        }
         event(new TeamAuditEvent($userDutyCheck));
         return ["success"=>true,"data"=>$userDutyCheck->group_user_id];
     }
-    //修改临时工报表审核时间
-    public function updateLaborReportVerify($laborReport,$userDutyCheck){
-        $date=date('Y-m-d H:i:s');
-        $laborReport['verify_at']=$date;
-        $laborReport['group_user_id']=$userDutyCheck->group_user_id;
-        $laborReport->update();
-        $this->log(__METHOD__,"打卡组长审核更新临时工报表的审核时间".__FUNCTION__,json_encode($laborReport),Auth::user()['id']);
-        return;
-    }
+
 
     //去往任务审核
     public function missionAudit(Request $request){
         if(!Gate::allows('人事管理-任务审核')){ return redirect(url('/'));  }
         $processDailyParticipants=ProcessDailyParticipant::with(['processDaily','user_detail'=>function($builder){
-            return $builder->with(['user'=>function($builder){return $builder->with(['userWorkgroups']);},'user_labor'=>function($builder){return $builder->with(['laborCompany']);}]);
+            return $builder->with(['user'=>function($builder){return $builder->with(['userWorkgroups']);},'userLabor'=>function($builder){return $builder->with(['laborCompany']);}]);
         }])->orderBy('id','DESC');
         $start_date=$request->input('start_date');
         $end_date=$request->input('end_date');
@@ -144,6 +232,7 @@ class PersonnelController extends Controller
                 $processDailyParticipant=$processController->countParticipantManHour($processDailyParticipant,$processDailyParticipant->processDaily->date);
             }
         }
+        // 前往任务审核
         return view('personnel/checking-in/missionAudit',['processDailyParticipants'=>$processDailyParticipants,'request'=>$request->input()]);
     }
 
@@ -152,53 +241,22 @@ class PersonnelController extends Controller
         if(!Gate::allows('人事管理')){ return redirect(url('/'));  }
         $user=Auth::user();
         if (!$user)return redirect('/');
-        $result=$user->getPermittingWorkgroupIdsAttribute();
-        $userWorkgroupIds=$result['workgroupIds'];
-        $users=User::whereHas("userWorkgroups",function (Builder $query)use(&$userWorkgroupIds){
-            $query->whereIn("id",$userWorkgroupIds);
-        })->get();
-        $user_ids=array_column($users->toArray(),'id');
-        $dateNow=Carbon::now()->format('Y-m-d');
-        $yesterdayDate=Carbon::now()->addDays(-1)->format('Y-m-d');
+        $userWorkgroupIds=$user->getPermittingWorkgroupIds();
+//        $users=User::whereHas("userWorkgroups",function (Builder $query)use(&$userWorkgroupIds){
+//            $query->whereIn("id",$userWorkgroupIds);
+//        })->get();
+        $permittingWorkgroups=UserWorkgroup::whereIn('id',$userWorkgroupIds)->get();
+        if($permittingWorkgroups->isEmpty())$permittingWorkgroups="[]";
+
+//        $user_ids=array_column($users->toArray(),'id');
+        $dateNow=Carbon::now()->addDays(1)->format('Y-m-d');
         $beforeYesterdayDate=Carbon::now()->addDays(-2)->format('Y-m-d');
-        $userDutyCheckNows=UserDutyCheck::with(['userWorkgroup','userLabor.laborCompany','userDetail'])->whereIn("user_id",$user_ids)
-            ->where('checked_at','like',$dateNow."%")->where('type','登入')->get();
-        $userDutyCheckYesterdays=UserDutyCheck::with(['userWorkgroup','userLabor.laborCompany','userDetail'])->whereIn("user_id",$user_ids)
-            ->where('checked_at','like',$yesterdayDate."%")->where('type','登入')->get();
-        $userDutyCheckBefores=UserDutyCheck::with(['userWorkgroup','userLabor.laborCompany','userDetail'])->whereIn("user_id",$user_ids)
-            ->where('checked_at','like',$beforeYesterdayDate."%")->where('type','登入')->get();
-        return view('personnel/checking-in/clockAudit',['userDutyCheckYesterdays'=>$userDutyCheckYesterdays,'userDutyCheckNows'=>$userDutyCheckNows,'userDutyCheckBefores'=>$userDutyCheckBefores,'workgroupSign'=>$result['workgroupSign']]);
+        $userDutyChecks=UserDutyCheck::with(['userWorkgroup','userLabor.laborCompany','userDetail'])->whereIn("workgroup_id",$userWorkgroupIds)
+            ->whereBetween('checked_at',[$beforeYesterdayDate,$dateNow])->orderBy('checked_at','DESC')->get();
+        $laravelEchoPrefix = config('database.redis.options.prefix');
+        return view('personnel/checking-in/clockAudit',['userDutyChecks'=>$userDutyChecks,'laravelEchoPrefix'=>$laravelEchoPrefix,'permittingWorkgroups'=>$permittingWorkgroups]);
     }
 
-    //录入补卡
-    public function storeReplenishClock(Request $request){
-        if(!Gate::allows('人事管理-录入补卡')){ return redirect(url('/'));  }
-        $errors=$this->validatorUserDutyCheck($request)->errors();
-        if (count($errors)>0)return ['success'=>false,'data'=>$errors];
-        $user_id=$request->input('user_id');
-        $checked_at=$request->input('checked_at');
-        $type=$request->input('type');
-        $userWorkgroupID=DB::table('user_workgroup_user')->where('user_id',$user_id)->value('user_workgroup_id');
-        $userDutyCheck=new UserDutyCheck([
-            'user_id'=>$user_id,
-            'checked_at'=>$checked_at,
-            'type'=>$type,
-            'source'=>'补入',
-            'workgroup_id'=>$userWorkgroupID
-        ]);
-        $userDutyCheck->save();
-        $checkInDate=Carbon::parse($checked_at)->format('Y-m-d');
-        $laborReport=LaborReport::where('user_workgroup_id',$userWorkgroupID)->where('check_in_at','like',$checkInDate."%")->where('user_id',$user_id)->first();
-        if(!$laborReport&&$userDutyCheck->type=='登入'){
-            LaborReport::createLaborReportData($user_id,$userWorkgroupID,$userDutyCheck);
-            $this->log(__METHOD__,"提交临时工报表记录__".__FUNCTION__,json_encode([$user_id,$userWorkgroupID,$userDutyCheck]));
-        }else if ($laborReport&&$userDutyCheck->type=='登出'){
-            LaborReport::updateLaborReportData($laborReport,$userDutyCheck);
-            $this->log(__METHOD__,"更新临时工报表记录__".__FUNCTION__,json_encode([$laborReport,$userDutyCheck]));
-        }
-        $this->log(__METHOD__,"录入补卡".__FUNCTION__,json_encode($userDutyCheck),Auth::user()['id']);
-        return ['success'=>true,'data'=>$userDutyCheck];
-    }
     //搜索临时工下打卡信息
     public function checkUserLabors(Request $request){
         if(!Gate::allows('人事管理-录入补卡')){ return redirect(url('/'));  }
@@ -211,7 +269,7 @@ class PersonnelController extends Controller
 
     //考勤
     public function createReplenishClock(){
-        if(!Gate::allows('人事管理-录入补卡')){ return redirect(url('/'));  }
+        if(!Gate::allows('人事管理-录入补卡')){ return view('personnel/checkRelating/index');  }
         return view('personnel/checking-in/createReplenishClock');
     }
 
@@ -222,7 +280,27 @@ class PersonnelController extends Controller
             'type'=>'required',
         ],[
             'date_format'=>':attribute 格式错误',
-        ],['checked_at'=>'日期']);
+        ],['checked_at'=>'日期'
+            ,'type'=>'补卡类型']);
         return $validator;
     }
+    //打卡审核类型
+    public function updateDutyCheckType(Request $request){
+        if(!Gate::allows('人事管理-审核类型')){return ['success'=>'false','fail_info'=>'没有权限'];}
+        $userDutyCheckId=$request->input('id');
+        $userDutyCheckType=$request->input('type');
+        if (is_null($userDutyCheckId) or is_null($userDutyCheckType)){
+            return ['success'=>false,'fail_info'=>'传参错误'];
+        }
+        $userDutyCheck=UserDutyCheck::find($userDutyCheckId);
+        $userDutyCheck->type=$userDutyCheckType;
+        $userDutyCheck->update();
+        $laborReport=LaborReport::where('user_workgroup_id',$userDutyCheck->workgroup_id)->where('user_id',$userDutyCheck->user_id)->orderBy('id','desc')->first();
+        if ($laborReport&&$userDutyCheck->type){
+            LaborReport::updateLaborReportData($laborReport,$userDutyCheck);
+            app('LogService')->log(__METHOD__,"更新临时工报表记录__".__FUNCTION__,json_encode([$laborReport,$userDutyCheck]));
+        }
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        return ['success'=>true,'data'=>$userDutyCheck];
+    }
 }

+ 941 - 0
app/Http/Controllers/PriceModelController.php

@@ -0,0 +1,941 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Imports\ExpressImport;
+use App\Imports\OwnerPriceDirectLogisticDetailImport;
+use App\Imports\OwnerPriceLogisticDetailImport;
+use App\Owner;
+use App\OwnerOutStorageRule;
+use App\OwnerPriceDirectLogistic;
+use App\OwnerPriceExpress;
+use App\OwnerPriceExpressProvince;
+use App\OwnerPriceLogistic;
+use App\OwnerPriceOperation;
+use App\Services\common\ExportService;
+use App\Services\LogService;
+use App\Services\OwnerOutStorageRuleService;
+use App\Services\OwnerPriceOperationService;
+use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Gate;
+use Illuminate\Support\Facades\Validator;
+use Maatwebsite\Excel\Facades\Excel;
+
+class PriceModelController extends Controller
+{
+    public function storageIndex(Request $request)
+    {
+        if(!Gate::allows('计费模型-仓储')){ return redirect('denied');  }
+        $models = app('OwnerStoragePriceModelService')->paginate($request->input("id"),["unit"]);
+        return response()->view('maintenance.priceModel.storage.index',compact("models"));
+    }
+
+    public function storageCreate()
+    {
+        if(!Gate::allows('计费模型-仓储-录入')){ return redirect('denied');  }
+        $units = app('UnitService')->getSelection();
+        return response()->view('maintenance.priceModel.storage.create',compact("units"));
+    }
+
+    public function storageStore(Request $request)
+    {
+        if(!Gate::allows('计费模型-仓储-录入')){ return redirect('denied');  }
+        $this->storageValidator($request->input())->validate();
+        app('OwnerStoragePriceModelService')->create($request->input());
+        LogService::log(__METHOD__,"计费模型-创建仓储计费",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
+        return response()->redirectTo('maintenance/priceModel/storage')->with('successTip',"创建成功!");
+    }
+
+    public function storageEdit($id)
+    {
+        if(!Gate::allows('计费模型-仓储-编辑')){ return redirect('denied');  }
+        $model = app('OwnerStoragePriceModelService')->find($id);
+        $units = app('UnitService')->getSelection();
+        return response()->view('maintenance.priceModel.storage.create',compact("units","model"));
+    }
+
+    public function storageUpdate(Request $request)
+    {
+        if(!Gate::allows('计费模型-仓储-编辑')){ return redirect('denied');  }
+        app('OwnerStoragePriceModelService')->update(["id"=>$request->input("id")],[
+            "counting_type" => $request->input("counting_type"),
+            "using_type"    => $request->input("using_type"),
+            "minimum_area"  => $request->input("minimum_area"),
+            "price"         => $request->input("price"),
+            "discount_type" => $request->input("discount_type"),
+            "discount_value"=> $request->input("discount_value"),
+            "unit_id"       => $request->input("unit_id"),
+        ]);
+        LogService::log(__METHOD__,"计费模型-修改仓储计费",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
+        return response()->redirectTo('maintenance/priceModel/storage')->with('successTip',"更新成功!");
+    }
+
+    public function storageDestroy($id)
+    {
+        app("OwnerStoragePriceModelService")->destroy($id);
+        LogService::log(__METHOD__,"计费模型-删除仓储计费",$id);
+        return ["success"=>true];
+    }
+
+    private function storageValidator(array $params)
+    {
+        return Validator::make($params,[
+            'counting_type'=>['required'],
+            'using_type'=>['required'],
+            'minimum_area'=>['nullable','numeric','min:0'],
+            'discount_value'=>['nullable','numeric','min:0'],
+            'price'=>['required','numeric','min:0'],
+            'discount_type'=>['required'],
+            'unit_id'=>['required','integer'],
+        ],[
+            'required'=>':attribute 为必填项',
+            'min'=>':attribute 不得小于0',
+            'integer'=>':attribute 未选择',
+        ],[
+            'counting_type' =>"计费类型",
+            'using_type'    =>"用仓类型",
+            'minimum_area'  =>"最低起租面积",
+            'price'         =>"单价",
+            'discount_type' =>"减免类型",
+            'discount_value'=>"减免值",
+            'unit_id'       =>"单位",
+        ]);
+    }
+
+    public function operationIndex(Request $request){
+        if(!Gate::allows('计费模型-作业-查询')){ return redirect('denied');  }
+        $features = app("FeatureService")->getMapArray();
+        OwnerPriceOperation::$features = $features;
+        $models = app('OwnerPriceOperationService')->paginate($request->input(),["ownerPriceOperationOwners","ownerInStorageRule"=>function($query){$query->with("unit");}])->append("featureFormat");
+        $owners = app("OwnerService")->getSelection();
+        return response()->view('maintenance.priceModel.operation.index',compact("models","owners"));
+    }
+
+    /* 获取出库模型规则 */
+    public function operationGetOutStorageRule(Request $request)
+    {
+        if(!Gate::allows('计费模型-作业-查询')){ return ["success"=>false,"data"=>"无权操作"];  }
+        /** @var OwnerOutStorageRuleService $service */
+        $service = app('OwnerOutStorageRuleService');
+        $ownerOutStorageRules = $service->get(["owner_price_operation_id"=>$request->input("id")],["unit"],true)->append("featureFormat");
+        return ["success"=>true,"data"=>$ownerOutStorageRules];
+    }
+    /* 修改出库模型规则 */
+    public function updateOutStorageRule(Request $request)
+    {
+        if(!Gate::allows('计费模型-作业-编辑')){ return ["success"=>false,"data"=>"无权操作"];  }
+        /** @var OwnerOutStorageRuleService $service */
+        $service = app('OwnerOutStorageRuleService');
+        $row = $service->update(["id"=>$request->input("id")],[
+            "amount"=>$request->input("amount"),
+            "unit_id"=>$request->input("unit_id"),
+            "priority"=>$request->input("priority"),
+            "unit_price"=>$request->input("unit_price")]);
+        if ($row == 1){
+            LogService::log(__METHOD__,"计费模型-修改出库规则",json_encode($request->input()));
+            return ["success"=>true];
+        }
+        return ["success"=>false,"data"=>"受影响数据数为:".$row];
+    }
+
+    public function createOutStorageRule(Request $request)
+    {
+        if(!Gate::allows('计费模型-作业-编辑')){ return ["success"=>false,"data"=>"无权操作"];  }
+        /** @var OwnerOutStorageRuleService $service */
+        $service = app('OwnerOutStorageRuleService');
+        switch ($request->input("strategy")){
+            case "起步":
+                $c = $service->isExist(["owner_price_operation_id"=>$request->input("owner_price_operation_id"),"strategy"=>"起步"]);
+                if ($c > 0)return ["success"=>false,"data"=>"已存在起步策略"];
+                break;
+            case "默认":
+                $c = $service->isExist(["owner_price_operation_id"=>$request->input("owner_price_operation_id"),"strategy"=>"默认"]);
+                if ($c > 0)return ["success"=>false,"data"=>"已存在默认策略"];
+                break;
+        }
+        $data = $service->create($request->input());
+        LogService::log(__METHOD__,"计费模型-录入出库规则",json_encode($request->input()));
+        $data->load("unit");
+        return ["success"=>true,"data"=>$data];
+    }
+    public function getFeatures(Request $request)
+    {
+        return ["success"=>true,"data"=>app("FeatureService")->translationFeature($request->input("feature"))];
+    }
+
+    public function addFeature(Request $request)
+    {
+        if(!Gate::allows('计费模型-作业-编辑')){ return ["success"=>false,"data"=>"无权操作"];  }
+        $id = $request->input("id");
+        $features = $request->input("features");
+        if (!$id || !$features)return ["success"=>false,"data"=>"非法参数"];
+        $result = app("FeatureService")->analysisFeature($features);
+        $feature = $result["feature"];
+        $stack = [];
+        if ($feature && ($feature[0]=='|' || $feature[0]=='&'))$feature=substr($feature,1);
+        for ($i=0;$i<strlen($feature);$i++){
+            if ($feature[$i] == '(')array_unshift($stack,'(');
+            if ($feature[$i] == ')'){
+                if (count($stack) == 0)return ["success"=>false,"data"=>"组标记错误,起始与结束标记必须对应"];
+                array_shift($stack);
+            }
+        }
+        if (count($stack) > 0)return ["success"=>false,"data"=>"组标记错误,起始与结束标记必须对应"];
+        $row = app('OwnerOutStorageRuleService')->update(["id"=>$id],["feature"=>$feature]);
+        if ($row != 1)return ["success"=>false,"data"=>"影响了“".$row."”行"];
+        LogService::log(__METHOD__,"计费模型-修改出库特征",json_encode($request->input()));
+        OwnerOutStorageRule::$features = $result["map"];
+        $rule = app('OwnerOutStorageRuleService')->find($id)->append("featureFormat");
+        return ["success"=>true,"data"=>["featureFormat"=>$rule->featureFormat,"feature"=>$feature]];
+    }
+
+    public function getFeature(Request $request)
+    {
+        $features = $request->input("features");
+        if (!$features)return ["success"=>false,"data"=>"非法参数"];
+        $result = app("FeatureService")->analysisFeature($features);
+        $feature = $result["feature"];
+        $stack = [];
+        if ($feature && ($feature[0]=='|' || $feature[0]=='&'))$feature=substr($feature,1);
+        for ($i=0;$i<strlen($feature);$i++){
+            if ($feature[$i] == '(')array_unshift($stack,'(');
+            if ($feature[$i] == ')'){
+                if (count($stack) == 0)return ["success"=>false,"data"=>"组标记错误,起始与结束标记必须对应"];
+                array_shift($stack);
+            }
+        }
+        if (count($stack) > 0)return ["success"=>false,"data"=>"组标记错误,起始与结束标记必须对应"];
+        return ["success"=>true,"data"=>$feature];
+    }
+
+    public function operationDestroy($id)
+    {
+        if(!Gate::allows('计费模型-作业-删除')){ return ["success"=>false,"data"=>"无权操作"];  }
+        $row = app("OwnerPriceOperationService")->destroy($id);
+        if ($row == 1){
+            LogService::log(__METHOD__,"计费模型-删除作业计费",$id);
+            return ["success"=>true];
+        }
+        return ["success"=>false,"data"=>"影响了“".$row."”行"];
+    }
+
+    public function operationCreate(){
+        if(!Gate::allows('计费模型-作业-录入')){ return redirect('denied');  }
+        $owners = app("OwnerService")->getSelection();
+        $units = app('UnitService')->getSelection();
+        return response()->view('maintenance.priceModel.operation.create',compact("owners","units"));
+    }
+
+    public function operationStore(Request $request)
+    {
+        if(!Gate::allows('计费模型-作业-录入')){ return redirect('denied');  }
+        $request->offsetSet("rules",json_decode($request->input("rules"),true));
+        $request->offsetSet("owner_id",explode(',',$request->input("owner_id")));
+        $this->operationValidator($request->input())->validate();
+
+        //录入主表
+        /** @var OwnerPriceOperationService $service */
+        $service = app("OwnerPriceOperationService");
+        $ownerPriceOperation = $service->create([
+            "operation_type" => $request->input("operation_type"),
+            "strategy" => $request->input("strategy"),
+            "name" => $request->input("name"),
+            "priority" => $request->input("priority"),
+            "remark" => $request->input("remark"),
+            "feature" => $request->input("feature"),
+        ]);
+        //录入子表
+        if ($request->input("operation_type") == '入库') $service->insertRule([
+            "owner_price_operation_id" => $ownerPriceOperation->id,
+            "amount" => $request->input("rules")[0]["amount"],
+            "unit_id" => $request->input("rules")[0]["unit_id"],
+            "unit_price" => $request->input("rules")[0]["unit_price"],
+        ],"入库");
+        else{
+            $insert = [];
+            foreach ($request->input("rules") as $rule){
+                $insert[] = [
+                    "owner_price_operation_id" => $ownerPriceOperation->id,
+                    "amount" => $rule["amount"],
+                    "unit_id" => $rule["unit_id"],
+                    "unit_price" => $rule["unit_price"],
+                    "strategy" => $rule["strategy"],
+                    "feature" => $rule["feature"],
+                    "priority" => $rule["priority"],
+                ];
+            }
+            $service->insertRule($insert);
+        }
+        //录入中间表
+        /** @var OwnerPriceOperation $model */
+        if ($request->input("owner_id"))$model->ownerPriceOperationOwners()->sync($request->input("owner_id"));
+        LogService::log(__METHOD__,"计费模型-录入作业计费",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
+        return response()->redirectTo("maintenance/priceModel/operation")->with("successTip","创建“".$request->input("name")."”成功");
+    }
+
+    public function operationEdit($id)
+    {
+        if(!Gate::allows('计费模型-作业-编辑')){ return redirect('denied');  }
+        $model = app('OwnerPriceOperationService')->find($id,true,["ownerPriceOperationOwners"]);
+        $owners = app("OwnerService")->getSelection();
+        $units = app('UnitService')->getSelection();
+        return response()->view('maintenance.priceModel.operation.create',compact("owners","units","model"));
+    }
+
+    public function operationUpdate($id,Request $request)
+    {
+        if(!Gate::allows('计费模型-作业-编辑')){ return redirect('denied');  }
+        $request->offsetSet("rules",json_decode($request->input("rules"),true));
+        $request->offsetSet("owner_id",explode(',',$request->input("owner_id")));
+        $this->operationValidator($request->input(),$id)->validate();
+
+        /** @var OwnerPriceOperationService $service */
+        $service = app("OwnerPriceOperationService");
+
+        $model = $service->find($id);
+        $service->findUpdate($model,[
+            "name" => $request->input("name"),
+            "priority" => $request->input("priority"),
+            "remark" => $request->input("remark"),
+            "feature" => $request->input("feature"),
+        ]);
+        $service->destroyRule($id, $model->operation_type);
+        //录入子表
+        if ($request->input("operation_type") == '入库') $service->insertRule([
+            "owner_price_operation_id" => $model->id,
+            "amount" => $request->input("rules")[0]["amount"],
+            "unit_id" => $request->input("rules")[0]["unit_id"],
+            "unit_price" => $request->input("rules")[0]["unit_price"],
+        ],"入库");
+        else{
+            $insert = [];
+            foreach ($request->input("rules") as $rule){
+                $insert[] = [
+                    "owner_price_operation_id" => $model->id,
+                    "amount" => $rule["amount"],
+                    "unit_id" => $rule["unit_id"],
+                    "unit_price" => $rule["unit_price"],
+                    "strategy" => $rule["strategy"],
+                    "feature" => $rule["feature"],
+                    "priority" => $rule["priority"],
+                ];
+            }
+            $service->insertRule($insert);
+        }
+        //录入中间表
+        /** @var OwnerPriceOperation $model */
+        if ($request->input("owner_id"))$model->ownerPriceOperationOwners()->sync($request->input("owner_id"));
+        LogService::log(__METHOD__,"计费模型-修改作业计费",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
+        return response()->redirectTo("maintenance/priceModel/operation")->with("successTip","修改“".$request->input("name")."”成功");
+    }
+
+    private function operationValidator(array $params, $id= null)
+    {
+        return Validator::make($params,[
+            //required_with:id
+            'operation_type'=>['required'],
+            'owner_id'=>[function ($attribute, $value, $fail)use($params,$id) {
+                if ($params["strategy"] == '默认'){
+                    $owners = Owner::query()->whereIn("id",$value)->withCount(["ownerPriceOperations"=>function($query)use($params,$id){
+                        if ($id)$query->where('id',"!=",$id);
+                        $query->where("strategy","默认")->where("operation_type",$params["operation_type"]);
+                    }])->get();
+                    $err = [];
+                    foreach ($owners as $owner){
+                        if ($owner->owner_price_operations_count > 0)$err[] = $owner->name;
+                    }
+                    if (count($err)>0)$fail("(".implode(',',$err).') 已经绑定'.$params["operation_type"].'的默认策略');
+                }
+            }],
+            'strategy'=>['required'],
+            'name'=>['required',$id?"unique:owner_price_operations,name,$id":'unique:owner_price_operations,name'],
+            'priority'=>['required','integer','min:0','max:100'],
+            'rules.*.strategy'=>['required_if:operation_type,出库'],
+            'rules.*.amount'=>['required',"integer"],
+            'rules.*.unit_id'=>['required','integer'],
+            'rules.*.unit_price'=>['required','numeric',"min:0"],
+            'rules.*.priority'=>['required_if:operation_type,出库','integer','min:0','max:100'],
+        ],[
+            'required'=>':attribute 为必填项',
+            'min'=>':attribute 不得小于0',
+            'integer'=>':attribute 必须为整数',
+            'numeric'=>':attribute 必须为数字',
+            'max'=>':attribute 超出最大值',
+            'required_if'=>':attribute 操作类型为出库时不得为空',
+        ],[
+            'operation_type' =>"操作类型",
+            'strategy'    =>"计费策略",
+            'name'  =>"名称",
+            'priority' =>"优先级",
+        ]);
+    }
+
+    public function expressIndex(Request $request){
+        if(!Gate::allows('计费模型-快递-查询')){ return redirect('denied');  }
+        $models = app('OwnerPriceExpressService')->paginate($request->input("id"));
+        return response()->view('maintenance.priceModel.express.index',compact("models"));
+    }
+
+    public function expressGetDetail(Request $request)
+    {
+        if(!Gate::allows('计费模型-快递-查询')){ return ["success"=>false,"data"=>"无权操作"];  }
+        $model = new OwnerPriceExpress();
+        $model->id = $request->input("id");
+        $model->load(["details"=>function($query){$query->with("province");}]);
+        return ["success"=>true,"data"=>$model->details];
+    }
+
+    public function expressUpdateDetail(Request $request)
+    {
+        if(!Gate::allows('计费模型-快递-编辑')){ return ["success"=>false,"data"=>"无权操作"];  }
+        $detail = $request->input("detail");
+        if ($detail["id"]){
+            app('OwnerPriceExpressService')->updateDetail(["id"=>$detail["id"]],[
+                "additional_weight_price" => $detail["additional_weight_price"],
+                "initial_weight_price" => $detail["initial_weight_price"],
+            ]);
+        }else{
+            $row = app('OwnerPriceExpressService')->isExistDetail(["owner_price_express_id"=>$request->input("id"),"province_id"=>$detail["province_id"]]);
+            if ($row>0)return ["success"=>false,"data"=>"已存在该省份计费模型"];
+            /** @var OwnerPriceExpressProvince $detail */
+            $detail = app('OwnerPriceExpressService')->createDetail([
+                "owner_price_express_id" =>  $request->input("id"),
+                "province_id" => $detail["province_id"],
+                "additional_weight_price" => $detail["additional_weight_price"],
+                "initial_weight_price" => $detail["initial_weight_price"],
+            ]);
+            $detail->load("province");
+        }
+        LogService::log(__METHOD__,"计费模型-修改快递计费",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
+        return ["success"=>true,"data"=>$detail];
+    }
+
+    public function expressDestroyDetail(Request $request)
+    {
+        if(!Gate::allows('计费模型-快递-删除')){ return ["success"=>false,"data"=>"无权操作"];  }
+        $id = $request->input("id");
+        if (!$id)return ["success"=>false,"data"=>"非法参数"];
+        app("OwnerPriceExpressService")->destroyDetail($id);
+        LogService::log(__METHOD__,"计费模型-删除快递计费",$id);
+        return ["success"=>true];
+    }
+
+    public function expressImport(Request $request){
+        if(!Gate::allows('计费模型-快递-录入')){ return ["success"=>false,"data"=>"无权操作"];  }
+        $fileSuffix=$request->file('file')->getClientOriginalExtension();
+        if ($fileSuffix != 'xlsx' && $fileSuffix != 'xls' && $fileSuffix != 'csv')
+            return ['success'=>false,'data'=>'不支持该文件类型'];
+        ini_set('max_execution_time',2500);
+        ini_set('memory_limit','1526M');
+        $fileSuffix = ucwords($fileSuffix);
+        /** @var OwnerPriceExpress $model */
+        $model = app('OwnerPriceExpressService')->find($request->input("id"),["details"]);
+        Excel::import(new ExpressImport($model),$request->file('file')->path(),null,$fileSuffix);
+        if (Cache::has('express'))return Cache::pull('express');
+
+        return ["success"=>false,"data"=>"导入发生错误,数据无响应"];
+    }
+
+    public function expressCreate(){
+        if(!Gate::allows('计费模型-快递-录入')){ return redirect('denied');  }
+        $logistics = app("LogisticService")->getSelection();
+        $owners = app("OwnerService")->getSelection();
+        return response()->view('maintenance.priceModel.express.create',compact("logistics","owners"));
+    }
+
+    public function expressStore(Request $request)
+    {
+        if(!Gate::allows('计费模型-快递-录入')){ return redirect('denied');  }
+        $request->offsetSet("owner_id",explode(",",$request->input("owner_id")));
+        $request->offsetSet("logistic_id",explode(",",$request->input("logistic_id")));
+        $this->expressValidator($request->input())->validate();
+        /** @var OwnerPriceExpress $model */
+        $model = app("OwnerPriceExpressService")->create([
+            "name" => $request->input("name"),
+            "initial_weight" => $request->input("initial_weight"),
+            "additional_weight" => $request->input("additional_weight"),
+        ]);
+        $model->owners()->sync($request->input("owner_id"));
+        $model->logistics()->sync($request->input("logistic_id"));
+        LogService::log(__METHOD__,"计费模型-录入快递计费",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
+        return response()->redirectTo("maintenance/priceModel/express")->with("successTip","录入“".$request->input("name")."”成功");
+    }
+
+    public function expressEdit($id)
+    {
+        if(!Gate::allows('计费模型-快递-编辑')){ return redirect('denied');  }
+        /** @var OwnerPriceExpress $model */
+        $model = app('OwnerPriceExpressService')->find($id)->append(["owner_id","logistic_id"]);
+        $owners = app("OwnerService")->getSelection();
+        $logistics = app('LogisticService')->getSelection();
+        return response()->view('maintenance.priceModel.express.create',compact("owners","logistics","model"));
+    }
+
+    public function expressUpdate($id,Request $request)
+    {
+        if(!Gate::allows('计费模型-快递-编辑')){ return redirect('denied');  }
+        $request->offsetSet("owner_id",explode(",",$request->input("owner_id")));
+        $request->offsetSet("logistic_id",explode(",",$request->input("logistic_id")));
+        $this->expressValidator($request->input(),$id)->validate();
+        /** @var OwnerPriceExpress $model */
+        app("OwnerPriceExpressService")->update(["id"=>$id],[
+            "name" => $request->input("name"),
+            "initial_weight" => $request->input("initial_weight"),
+            "additional_weight" => $request->input("additional_weight"),
+        ]);
+        $model = new OwnerPriceExpress();
+        $model->id = $id;
+        $model->owners()->sync($request->input("owner_id"));
+        $model->logistics()->sync($request->input("logistic_id"));
+        LogService::log(__METHOD__,"计费模型-修改快递计费",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
+        return response()->redirectTo("maintenance/priceModel/express")->with("successTip","修改“".$request->input("name")."”成功");
+    }
+
+    private function expressValidator(array $params, $id=null)
+    {
+        return Validator::make($params,[
+            'name'=>['required',$id?"unique:owner_price_expresses,name,$id":'unique:owner_price_expresses,name'],
+            'initial_weight'=>['required','numeric','min:0'],
+            'additional_weight'=>['required','numeric','min:0'],
+            'owner_id'=>[function ($attribute, $value, $fail)use($id) {
+                $owners = app("OwnerPriceExpressService")->getExistOwnerName($value,$id);
+                if ($owners)$fail("(".implode(',',$owners).') 已经绑定计费模型');
+            }],
+            'logistic_id'=>[function ($attribute, $value, $fail)use($id) {
+                $logistics = app("OwnerPriceExpressService")->getExistLogisticName($value,$id);
+                if ($logistics)$fail("(".implode(',',$logistics).') 已经绑定计费模型');
+            }],
+        ],[
+            'required'=>':attribute 为必填项',
+            'unique' => ':attribute 已存在',
+        ],[
+            'name' =>"名称",
+            'initial_weight'  =>"首重",
+            'additional_weight'  =>"续重",
+        ]);
+    }
+
+    public function expressDestroy($id)
+    {
+        if(!Gate::allows('计费模型-快递-删除')){ return ["success"=>false,"data"=>"无权操作"]; };
+        app("OwnerPriceExpressService")->destroy($id);
+        LogService::log(__METHOD__,"计费模型-删除快递计费",$id);
+        return ["success"=>true];
+    }
+
+    public function logisticIndex(Request $request)
+    {
+        if(!Gate::allows('计费模型-物流-查询')){ return redirect('denied');  }
+        $models = app("OwnerPriceLogisticService")->paginate($request->input("id"))->append(["unit_range_json","other_unit_range_json"]);
+        return response()->view('maintenance.priceModel.logistic.index',compact("models"));
+    }
+
+    public function logisticCreate()
+    {
+        if(!Gate::allows('计费模型-物流-录入')){ return redirect('denied');  }
+        $owners = app("OwnerService")->getSelection();
+        $logistics = app('LogisticService')->getSelection();
+        $units = app('UnitService')->getSelection();
+        return response()->view('maintenance.priceModel.logistic.create',compact("owners","logistics","units"));
+    }
+
+    public function logisticStore(Request $request)
+    {
+        if(!Gate::allows('计费模型-物流-录入')){ return redirect('denied');  }
+        $request->offsetSet("owner_id",explode(",",$request->input("owner_id")));
+        $request->offsetSet("logistic_id",explode(",",$request->input("logistic_id")));
+        $this->logisticValidator($request->input())->validate();
+        /** @var OwnerPriceLogistic $model */
+        $model = app("OwnerPriceLogisticService")->create([
+            "name" => $request->input("name"),
+            "pick_up_price" => $request->input("pick_up_price"),
+            "fuel_price" => $request->input("fuel_price"),
+            "service_price" => $request->input("service_price"),
+            "unit_id" => $request->input("unit_id"),
+            "unit_range" => $request->input("unit_range"),
+            "other_unit_id" => $request->input("other_unit_id"),
+            "other_unit_range" => $request->input("other_unit_range"),
+        ]);
+        $model->owners()->sync($request->input("owner_id"));
+        $model->logistics()->sync($request->input("logistic_id"));
+        LogService::log(__METHOD__,"计费模型-录入物流计费",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
+        return response()->redirectTo("maintenance/priceModel/logistic")->with("successTip","创建“".$request->input("name")."”成功");
+    }
+
+    public function logisticEdit($id)
+    {
+        if(!Gate::allows('计费模型-物流-编辑')){ return redirect('denied');  }
+        $owners = app("OwnerService")->getSelection();
+        $logistics = app('LogisticService')->getSelection();
+        $units = app('UnitService')->getSelection();
+        $model = app("OwnerPriceLogisticService")->find($id)->append(["owner_id","logistic_id"]);
+        return response()->view('maintenance.priceModel.logistic.create',compact("owners","logistics","units","model"));
+    }
+
+    public function logisticUpdate($id, Request $request)
+    {
+        if(!Gate::allows('计费模型-物流-编辑')){ return redirect('denied');  }
+        $request->offsetSet("owner_id",explode(",",$request->input("owner_id")));
+        $request->offsetSet("logistic_id",explode(",",$request->input("logistic_id")));
+        $this->logisticValidator($request->input(),$id)->validate();
+        app("OwnerPriceLogisticService")->update(["id"=>$id],[
+            "name" => $request->input("name"),
+            "pick_up_price" => $request->input("pick_up_price"),
+            "fuel_price" => $request->input("fuel_price"),
+            "service_price" => $request->input("service_price"),
+            "unit_id" => $request->input("unit_id"),
+            "unit_range" => $request->input("unit_range"),
+            "other_unit_id" => $request->input("other_unit_id"),
+            "other_unit_range" => $request->input("other_unit_range"),
+        ]);
+        $model = new OwnerPriceLogistic();
+        $model->id = $id;
+        $model->owners()->sync($request->input("owner_id"));
+        $model->logistics()->sync($request->input("logistic_id"));
+        LogService::log(__METHOD__,"计费模型-修改物流计费",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
+        return response()->redirectTo("maintenance/priceModel/logistic")->with("successTip","修改“".$request->input("name")."”成功");
+    }
+
+    public function logisticGetDetail(Request $request)
+    {
+        if(!Gate::allows('计费模型-物流-查询')){ return ["success"=>false,"data"=>"无权操作"];  }
+        $model = new OwnerPriceLogistic();
+        $model->id = $request->input("id");
+        $model->load(["details"=>function($query){
+            /** @var Builder $query */
+            $query->with(["unit","province","city"]);
+        }]);
+        return ["success"=>true,"data"=>$model->details];
+    }
+
+    public function expressExport($id)
+    {
+        if(!Gate::allows('计费模型-快递-查询')){ return ["success"=>false,"data"=>"无权操作"];  }
+        $model = app("OwnerPriceExpressService")->find($id,[
+            "owners","logistics","details"=>function($query){
+                /** @var Builder $query */
+                $query->with("province");
+            }]);
+        $row = ["客户","首重","续重","承运商"];
+        $list = [[
+            implode(",",array_column($model->owners->toArray(),"name")),
+            $model->initial_weight,
+            $model->additional_weight,
+            implode(",",array_column($model->logistics->toArray(),"name")),
+        ],[
+            "价格名称","省","首重价格","续重价格",
+        ]];
+        foreach ($model->details as $detail){
+            $list[] = [
+                $model->name,
+                $detail->province ? $detail->province->name : '',
+                $detail->initial_weight_price,
+                $detail->additional_weight_price,
+            ];
+        }
+        return app(ExportService::class)->json($row,$list,"快递计费模型");
+    }
+
+    public function logisticImport(Request $request)
+    {
+        if(!Gate::allows('计费模型-物流-录入')){ return ["success"=>false,"data"=>"无权操作"];  }
+        $fileSuffix=$request->file('file')->getClientOriginalExtension();
+        if ($fileSuffix != 'xlsx' && $fileSuffix != 'xls' && $fileSuffix != 'csv')
+            return ['success'=>false,'data'=>'不支持该文件类型'];
+        ini_set('max_execution_time',2500);
+        ini_set('memory_limit','1526M');
+        $fileSuffix = ucwords($fileSuffix);
+        /** @var OwnerPriceLogistic $model */
+        $model = app('OwnerPriceLogisticService')->find($request->input("id"),["unit","otherUnit","details"]);
+        Excel::import(new OwnerPriceLogisticDetailImport($model),$request->file('file')->path(),null,$fileSuffix);
+        if (Cache::has('logistic'))return Cache::pull('logistic');
+
+        return ["success"=>false,"data"=>"导入发生错误,数据无响应"];
+    }
+
+    public function logisticExport($id)
+    {
+        if(!Gate::allows('计费模型-物流-查询')){ return ["success"=>false,"data"=>"无权操作"];  }
+        $model = app("OwnerPriceLogisticService")->find($id,[
+            "owners","logistics","unit","otherUnit","details"=>function($query){
+                /** @var Builder $query */
+                $query->with(["province","unit","city"]);
+            }]);
+        $row = ["客户","价格名称",
+            "单位一区间/".($model->unit ? $model->unit->name : ''),
+            "单位二区间/".($model->otherUnit ? $model->otherUnit->name : ''),
+            "提货费","燃油附加费","信息服务费","创建时间","承运商"];
+        $range = "";
+        foreach (explode(",",$model->unit_range) as $str){
+            $range .= $str."\r\n";
+        }
+        $otherRange = "";
+        foreach (explode(",",$model->other_unit_range) as $str){
+            $otherRange .= $str."\r\n";
+        }
+        $list = [[
+            implode(",",array_column($model->owners->toArray(),"name")),
+            $model->name,
+            $range,
+            $otherRange,
+            $model->pick_up_price,
+            $model->fuel_price,
+            $model->service_price,
+            $model->created_at,
+            implode(",",array_column($model->logistics->toArray(),"name")),
+        ],[
+            "单位","区间","省份","市","单价","送货费","起始计费","起始计数","费率"
+        ]];
+        foreach ($model->details as $detail){
+            $list[] = [
+                $detail->unit ? $detail->unit->name : '',
+                $detail->range,
+                $detail->province ? $detail->province->name : '',
+                $detail->city ? $detail->city->name : '',
+                $detail->unit_price,
+                $detail->delivery_fee,
+                $detail->initial_fee,
+                $detail->initial_amount,
+                $detail->rate ? $detail->rate."%" : '',
+            ];
+        }
+        return app(ExportService::class)->json($row,$list,"物流计费模型");
+    }
+
+    public function logisticUpdateDetail(Request $request)
+    {
+        if(!Gate::allows('计费模型-物流-编辑')){ return ["success"=>false,"data"=>"无权操作"];  }
+        $detail = $request->input("detail");
+        if ($detail["id"]){
+            app('OwnerPriceLogisticService')->updateDetail(["id"=>$detail["id"]],[
+                "unit_price" => $detail["unit_price"],
+                "delivery_fee" => $detail["delivery_fee"],
+                "initial_fee" => $detail["initial_fee"],
+                "initial_amount" => $detail["initial_amount"],
+                "rate" => $detail["rate"],
+            ]);
+        }else{
+            $row = app('OwnerPriceLogisticService')->isExistDetail([
+                "owner_price_logistic_id"=>$request->input("id"),
+                "unit_id"=>$detail["unit_id"],
+                "range"=>$detail["range"],
+                "province_id"=>$detail["province_id"],
+                "city_id"=>$detail["city_id"],
+            ]);
+            if ($row>0)return ["success"=>false,"data"=>"已存在该计费模型"];
+            /** @var OwnerPriceExpressProvince $detail */
+            $detail = app('OwnerPriceLogisticService')->createDetail([
+                "owner_price_logistic_id"=>$request->input("id"),
+                "unit_id"=>$detail["unit_id"],
+                "range"=>$detail["range"],
+                "province_id"=>$detail["province_id"],
+                "city_id"=>$detail["city_id"],
+                "unit_price" => $detail["unit_price"],
+                "delivery_fee" => $detail["delivery_fee"],
+                "initial_fee" => $detail["initial_fee"],
+                "initial_amount" => $detail["initial_amount"],
+                "rate" => $detail["rate"],
+            ]);
+            $detail->load("province","unit","city");
+        }
+        LogService::log(__METHOD__,"计费模型-修改物流计费详情",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
+        return ["success"=>true,"data"=>$detail];
+    }
+
+    public function logisticDestroyDetail(Request $request)
+    {
+        if(!Gate::allows('计费模型-物流-删除')){ return ["success"=>false,"data"=>"无权操作"];  }
+        $id = $request->input("id");
+        if (!$id)return ["success"=>false,"data"=>"非法参数"];
+        app("OwnerPriceLogisticService")->destroyDetail($id);
+        LogService::log(__METHOD__,"计费模型-删除物流计费详情",$id);
+        return ["success"=>true];
+    }
+
+    private function logisticValidator(array $params,$id = null)
+    {
+        return Validator::make($params,[
+            'name'=>['required',$id?"unique:owner_price_logistics,name,$id":'unique:owner_price_logistics,name'],
+            'pick_up_price'=>['nullable','numeric','min:0'],
+            'fuel_price'=>['nullable','numeric','min:0'],
+            'service_price'=>['nullable','numeric','min:0'],
+            'unit_id'=>['required'],
+            'unit_range'=>['required',function ($attribute, $value, $fail) {
+                $bool = app("OwnerPriceLogisticService")->checkRange($value);
+                if (!$bool)$fail("格式错误,值必须为连续的且最后一个值不允许封闭");
+            }],
+            'other_unit_id'=>['required'],
+            'other_unit_range'=>['required',function ($attribute, $value, $fail) {
+                $bool = app("OwnerPriceLogisticService")->checkRange($value);
+                if (!$bool)$fail("格式错误,值必须为连续的且最后一个值不允许封闭");
+            }],
+        ],[
+            'required'=>':attribute 为必填项',
+            'unique' => ':attribute 已存在',
+            'numeric' => ':attribute 必须为数字',
+            'min' => ':attribute 不得为负',
+        ],[
+            'name' =>"名称",
+            'pick_up_price'  =>"提货费",
+            'fuel_price'  =>"燃油附加费",
+            'service_price'  =>"信息服务费",
+            'unit_id'  =>"单位一",
+            'unit_range'  =>"区间值",
+            'other_unit_id'  =>"单位二",
+            'other_unit_range'  =>"区间值",
+        ]);
+    }
+
+    public function directLogisticIndex(Request $request){
+        if(!Gate::allows('计费模型-直发-查询')){ return redirect('denied');  }
+        $models = app("OwnerPriceDirectLogisticService")->paginate($request->input("id"));
+        return response()->view('maintenance.priceModel.directLogistic.index',compact("models"));
+    }
+
+    public function directLogisticCreate(){
+        if(!Gate::allows('计费模型-直发-录入')){ return redirect('denied');  }
+        $owners = app("OwnerService")->getSelection();
+        return response()->view('maintenance.priceModel.directLogistic.create',compact("owners"));
+    }
+
+    public function directLogisticStore(Request $request)
+    {
+        if(!Gate::allows('计费模型-直发-录入')){ return redirect('denied');  }
+        $request->offsetSet("owner_id",explode(",",$request->input("owner_id")));
+        $this->directLogisticValidator($request->input())->validate();
+        /** @var OwnerPriceDirectLogistic $model */
+        $model = app("OwnerPriceDirectLogisticService")->create([
+            "name" => $request->input("name"),
+            "base_km" => $request->input("base_km"),
+        ]);
+        $model->owners()->sync($request->input("owner_id"));
+        LogService::log(__METHOD__,"计费模型-录入直发车计费",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
+        return response()->redirectTo("maintenance/priceModel/directLogistic")->with("successTip","创建“".$request->input("name")."”成功");
+    }
+
+    public function directLogisticDestroy($id)
+    {
+        if(!Gate::allows('计费模型-直发-删除')){ return ["success"=>false,"data"=>"无权操作"];  }
+        $row = app("OwnerPriceDirectLogisticService")->destroy($id);
+        if ($row == 1){
+            LogService::log(__METHOD__,"计费模型-删除直发车计费",$id);
+            return ["success"=>true];
+        }
+        return ["success"=>false,"data"=>"影响了“".$row."”行"];
+    }
+
+    public function directLogisticEdit($id)
+    {
+        if(!Gate::allows('计费模型-直发-编辑')){ return redirect('denied');  }
+        $owners = app("OwnerService")->getSelection();
+        $model = app("OwnerPriceDirectLogisticService")->find($id)->append("owner_id");
+        return response()->view('maintenance.priceModel.directLogistic.create',compact("model","owners"));
+    }
+
+    public function directLogisticUpdate($id, Request $request)
+    {
+        if(!Gate::allows('计费模型-直发-编辑')){ return redirect('denied');  }
+        $request->offsetSet("owner_id",explode(",",$request->input("owner_id")));
+        $this->directLogisticValidator($request->input(),$id)->validate();
+        app("OwnerPriceDirectLogisticService")->update(["id"=>$id],[
+            "name" => $request->input("name"),
+            "base_km" => $request->input("base_km"),
+        ]);
+        $model = new OwnerPriceDirectLogistic();
+        $model->id = $id;
+        $model->owners()->sync($request->input("owner_id"));
+        LogService::log(__METHOD__,"计费模型-修改直发车计费",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
+        return response()->redirectTo("maintenance/priceModel/directLogistic")->with("successTip","修改“".$request->input("name")."”成功");
+    }
+
+    public function directLogisticGetDetail(Request $request)
+    {
+        if(!Gate::allows('计费模型-直发-查询')){ return ["success"=>false,"data"=>"无权操作"];  }
+        $model = new OwnerPriceDirectLogistic();
+        $model->id = $request->input("id");
+        $model->load(["details"=>function($query){
+            /** @var Builder $query */
+            $query->with("carType");
+        }]);
+        return ["success"=>true,"data"=>$model->details];
+    }
+
+    public function directLogisticImport(Request $request)
+    {
+        if(!Gate::allows('计费模型-直发-录入')){ return ["success"=>false,"data"=>"无权操作"];  }
+        $fileSuffix=$request->file('file')->getClientOriginalExtension();
+        if ($fileSuffix != 'xlsx' && $fileSuffix != 'xls' && $fileSuffix != 'csv')
+            return ['success'=>false,'data'=>'不支持该文件类型'];
+        ini_set('max_execution_time',2500);
+        ini_set('memory_limit','1526M');
+        $fileSuffix = ucwords($fileSuffix);
+        $model = new OwnerPriceDirectLogistic();
+        $model->id = $request->input("id");
+        $model->load("details");
+        Excel::import(new OwnerPriceDirectLogisticDetailImport($model),$request->file('file')->path(),null,$fileSuffix);
+        if (Cache::has('directLogistic'))return Cache::pull('directLogistic');
+
+        return ["success"=>false,"data"=>"导入发生错误,数据无响应"];
+    }
+
+    public function directLogisticUpdateDetail(Request $request)
+    {
+        if(!Gate::allows('计费模型-直发-编辑')){ return ["success"=>false,"data"=>"无权操作"];  }
+        $detail = $request->input("detail");
+        if ($detail["id"]){
+            app('OwnerPriceDirectLogisticService')->updateDetail(["id"=>$detail["id"]],[
+                "base_fee" => $detail["base_fee"],
+                "additional_fee" => $detail["additional_fee"],
+            ]);
+        }else{
+            $row = app('OwnerPriceDirectLogisticService')->isExistDetail([
+                "owner_price_direct_logistic_id"=>$request->input("id"),
+                "car_type_id"=>$detail["car_type_id"],
+            ]);
+            if ($row>0)return ["success"=>false,"data"=>"已存在该计费模型"];
+            /** @var OwnerPriceExpressProvince $detail */
+            $detail = app('OwnerPriceDirectLogisticService')->createDetail([
+                "owner_price_direct_logistic_id"=>$request->input("id"),
+                "car_type_id"=>$detail["car_type_id"],
+                "base_fee" => $detail["base_fee"],
+                "additional_fee" => $detail["additional_fee"],
+            ]);
+            $detail->load("carType");
+        }
+        LogService::log(__METHOD__,"计费模型-修改直发车计费详情",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
+        return ["success"=>true,"data"=>$detail];
+    }
+
+    public function directLogisticDestroyDetail(Request $request)
+    {
+        if(!Gate::allows('计费模型-直发-删除')){ return ["success"=>false,"data"=>"无权操作"];  }
+        $id = $request->input("id");
+        if (!$id)return ["success"=>false,"data"=>"非法参数"];
+        app("OwnerPriceDirectLogisticService")->destroyDetail($id);
+        LogService::log(__METHOD__,"计费模型-删除直发车计费详情",$id);
+        return ["success"=>true];
+    }
+
+    private function directLogisticValidator(array $params, $id= null)
+    {
+        return Validator::make($params,[
+            'name'=>['required',$id?"unique:owner_price_direct_logistics,name,$id":'unique:owner_price_direct_logistics,name'],
+            'base_km'=>['required','numeric','min:0'],
+            'owner_id'=>[function ($attribute, $value, $fail)use($id) {
+                $owners = app("OwnerPriceDirectLogisticService")->getExistOwnerName($value,$id);
+                if ($owners)$fail("(".implode(',',$owners).') 已经绑定直发计费模型');
+            }],
+        ],[
+            'required'=>':attribute 为必填项',
+            'unique' => ':attribute 已存在',
+            'numeric' => ':attribute 必须为数字',
+            'min' => ':attribute 不得为负',
+        ],[
+            'name' =>"名称",
+            'base_km'  =>"起步公里数",
+        ]);
+    }
+
+}

File diff suppressed because it is too large
+ 657 - 296
app/Http/Controllers/ProcessController.php


+ 122 - 0
app/Http/Controllers/ProcessMethodController.php

@@ -0,0 +1,122 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Illuminate\Http\Request;
+use Illuminate\Http\Response;
+use Illuminate\Support\Facades\Gate;
+use Illuminate\Support\Facades\Validator;
+
+class ProcessMethodController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return Response
+     */
+    public function index()
+    {
+        if(!Gate::allows('作业类型-查询')){ return redirect('denied');  }
+        $methods = app('ProcessMethodService')->paginate();
+        return response()->view("maintenance.processMethod.index",compact("methods"));
+    }
+
+    /**
+     * Show the form for creating a new resource.
+     *
+     * @return Response
+     */
+    public function create()
+    {
+        if(!Gate::allows('作业类型-录入')){ return redirect('denied');  }
+        $units = app('UnitService')->getSelection();
+        return response()->view("maintenance.processMethod.create",compact("units"));
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  Request  $request
+     * @return Response
+     */
+    public function store(Request $request)
+    {
+        if(!Gate::allows('作业类型-录入')){ return redirect('denied');  }
+        $this->validator($request->input())->validate();
+        app('ProcessMethodService')->create([
+            "name"=>$request->input("name"),
+            "unit_id"=>$request->input("unit_id"),
+            "unit_price"=>$request->input("unit_price"),
+        ]);
+        return response()->redirectTo("maintenance/processMethod")->with("successTip","成功创建项目组“".$request->input("name")."”");
+    }
+
+    /**
+     * Show the form for editing the specified resource.
+     *
+     * @param  int  $id
+     * @return Response
+     */
+    public function edit($id)
+    {
+        if(!Gate::allows('作业类型-编辑')){ return redirect('denied');  }
+        $method = app('ProcessMethodService')->find($id);
+        $units = app('UnitService')->getSelection();
+        return response()->view('maintenance.processMethod.create',compact("method","units"));
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  Request  $request
+     * @param  int  $id
+     * @return Response
+     */
+    public function update(Request $request, $id)
+    {
+        if(!Gate::allows('作业类型-编辑')){ return redirect('denied');  }
+        $this->validator($request->input(),$id)->validate();
+        $result = app('ProcessMethodService')->update(["id"=>$id],[
+            "name"=>$request->input("name"),
+            "unit_id"=>$request->input("unit_id"),
+            "unit_price"=>$request->input("unit_price"),
+        ]);
+        if ($result == 1){
+            return response()->redirectTo("maintenance/processMethod")->with("successTip","成功修改项目组“".$request->input("name")."”的信息");
+        }
+        return response()->view("exception.default",["code"=>"509"]);
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  int  $id
+     * @return array
+     */
+    public function destroy($id)
+    {
+        if(!Gate::allows('作业类型-删除')){ return ["success"=>false,"data"=>"无权操作!"];  }
+        $result = app('ProcessMethodService')->destroy($id);
+        if ($result == 1)return ["success"=>true];
+        return ["success"=>false,"data"=>"删除了“".$result."”行"];
+    }
+
+    private function validator(array $params, $id = null)
+    {
+        return Validator::make($params,[
+            'name'=>['required',$id?"unique:process_methods,name,$id":'unique:process_methods,name','max:20'],
+            "unit_id" => ["nullable",'numeric'],
+            "unit_price" => ["nullable",'numeric','min:0'],
+        ],[
+            'required'=>':attribute 为必填项',
+            'max'=>':attribute 字符过多或输入值过大',
+            'unique'=>':attribute 已存在',
+            'numeric'=>':attribute 必须为数字',
+            'min'=>':attribute 数值过小',
+        ],[
+            'name'=>'作业类型名称',
+            'unit_id'=>'作业类型单位',
+            'unit_price'=>'作业类型单价',
+        ]);
+    }
+}

+ 33 - 109
app/Http/Controllers/ProcessStatisticController.php

@@ -2,123 +2,47 @@
 
 namespace App\Http\Controllers;
 
-use App\Exports\Export;
-use App\Owner;
-use App\ProcessMethod;
-use App\ProcessStatistic;
-use Illuminate\Database\Eloquent\Builder;
+use App\Process;
+use App\Services\ProcessStatisticService;
+use Exception;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Gate;
-use Maatwebsite\Excel\Facades\Excel;
+use Illuminate\Support\Facades\Http;
 
 class ProcessStatisticController extends Controller
 {
-    public function conditionQuery(Request $request,$processStatistics){
-        if ($request->input('started_at')){
-            $processStatistics=$processStatistics->where('started_at','>=',$request->input('started_at'));
-        }
-        if ($request->input('owner_id')){
-            $owner_id=$request->input('owner_id');
-            $processStatistics=$processStatistics->whereHas('process',function (Builder $query)use($owner_id){
-                $query->where('owner_id',$owner_id);
-            });
-        }
-        if ($request->input('ended_at')){
-            $processStatistics=$processStatistics->where('ended_at','<=',$request->input('ended_at'));
-        }
-        if ($request->input('code')){
-            $code=$request->input('code');
-            $processStatistics=$processStatistics->whereHas('process',function (Builder $query)use($code){
-                $query->where('code','like',$code."%");
-            });
-        }
-        if ($request->input('status')){
-            $status=$request->input('status');
-            $processStatistics=$processStatistics->whereHas('process',function (Builder $query)use($status){
-                $query->where('status',$status);
-            });
-        }
-        $processStatistics=$processStatistics->paginate($request->input('paginate')?$request->input('paginate'):50);
-        return $processStatistics;
-    }
-
     public function index(Request $request){
-        $processStatistics=ProcessStatistic::with('process')->orderBy('process_id','DESC');
-        if ($request->input('checkSign')){
-            $excel=$this->isExport($request,$processStatistics);
-            return $excel;
-        }
-        $processStatistics=$this->conditionQuery($request,$processStatistics);
-        $owners=Owner::get();
-        $processMethods=ProcessMethod::get();
-        return view('process.statistic',['processStatistics'=>$processStatistics,'owners'=>$owners,'processMethods'=>$processMethods]);
-    }
-
-    //获取导出数据
-    public function isExport(Request $request,$processStatistics){
-        if(!Gate::allows('二次加工管理-查询')){ return redirect(url('/'));  }
-        if ($request->input('checkSign')=="-1"){
-            $processStatistics=$this->conditionQuery($request,$processStatistics);
-            $excel=$this->export($processStatistics);
-            return $excel;
-        }
-        $id = explode( ',',$request->input('checkSign'));
-        $processStatistics=$processStatistics->whereIn('process_id',$id)->get();
-        $excel=$this->export($processStatistics);
-        return $excel;
+        if(!Gate::allows('二次加工管理-查询')){ return redirect('denied');  }
+        /** @var ProcessStatisticService $processStatistics */
+        $processStatistics=app("ProcessStatisticService")->paginate($request->input());
+        $owners=app("OwnerService")->getSelection();
+        $processMethods=app("ProcessMethodService")->getSelection();
+        return view('process.statistic',['processStatistics'=>$processStatistics,'params'=>$request->input(),'owners'=>$owners,'processMethods'=>$processMethods]);
     }
 
-    //执行
-    public function export($processStatistics){
+    public function export(Request $request){
         if(!Gate::allows('二次加工管理-查询')){ return '没有权限';  }
-        $row=[[
-            'process_id'=>'ID',
-            'code'=>'任务号',
-            'owner_name'=>'货主',
-            'started_at'=>'开始日期',
-            'ended_at'=>'完成日期',
-            'unit_price'=>'单价',
-            'amount'=>'预期数量',
-            'completed_amount'=>'完成数量',
-            'revenue'=>'收入合计',
-            'duration_days'=>'完成时间(天)',
-            'duration_man_hours'=>'总工时',
-            'process_method_name'=>'加工类型',
-            'top_capacity'=>'最高日产能',
-            'bottom_capacity'=>'最低日产能',
-            'average_capacity'=>'日均产能',
-            'total_cost'=>'合计成本',
-            'gross_profit'=>'毛利润',
-            'gross_profit_rate'=>'毛利率',
-            'status'=>'状态',
-        ]];
-        $list=[];
-        $i=0;
-        foreach ($processStatistics as $processStatistic){
-            $w=[
-                'process_id'=>$processStatistic->process_id,
-                'code'=>$processStatistic->process?$processStatistic->process->code:'',
-                'owner_name'=>$processStatistic->process?$processStatistic->process->owner_name:'',
-                'started_at'=>$processStatistic->started_at,
-                'ended_at'=>$processStatistic->ended_at,
-                'unit_price'=>$processStatistic->process?$processStatistic->process->unit_price:'',
-                'amount'=>$processStatistic->process?$processStatistic->process->amount:'',
-                'completed_amount'=>$processStatistic->process?$processStatistic->process->completed_amount:'',
-                'revenue'=>$processStatistic->revenue,
-                'duration_days'=>$processStatistic->duration_days,
-                'duration_man_hours'=>$processStatistic->duration_man_hours,
-                'process_method_name'=>$processStatistic->process?$processStatistic->process->process_method_name:'',
-                'top_capacity'=>$processStatistic->top_capacity,
-                'bottom_capacity'=>$processStatistic->bottom_capacity,
-                'average_capacity'=>$processStatistic->average_capacity,
-                'total_cost'=>$processStatistic->total_cost,
-                'gross_profit'=>$processStatistic->gross_profit,
-                'gross_profit_rate'=>round(($processStatistic->gross_profit_rate)*100,2).'%',
-                'status'=>$processStatistic->process?$processStatistic->process->status:'',
-            ];
-            $list[$i]=$w;
-            $i++;
-        }
-        return Excel::download(new Export($row,$list),date('YmdHis', time()).'-二次加工单.xls');
+        if ($request->checkAllSign){
+            $params = $request->input();
+            unset($params['checkAllSign']);
+            $sql = app('ProcessStatisticService')->getSql($params);
+        }else $sql = app('ProcessStatisticService')->getSql(["process_id"=>$request->data]);
+
+        $row = ["任务号", "货主", "开始日期", "完成日期","创建日期", "单价", "预期数量", "完成数量", "收入合计",
+            "完成时间(天)'", "总工时", "加工类型", "最高日产能", "最低日产能", "日均产能", "合计成本", "毛利润",
+            "毛利率", "状态","加工备注","结算备注"];
+        $column = ["process_code", "owner_name", "started_at", "ended_at","process_created_at", "process_unit_price", "process_amount", "process_completed_amount", "revenue",
+		"duration_days", "duration_man_hours", "process_method_name", "top_capacity", "bottom_capacity",
+		"average_capacity", "total_cost", "gross_profit", "gross_profit_rate", "process_status", "process_remark", "process_balance_remark"];
+        $rule = ["gross_profit_rate"=> "percent", "started_at"=>"mysqlDate", "ended_at"=>"mysqlDate", "process_created_at"=>"mysqlDate"];
+        $post = Http::post(config('go.export.url'),['type'=>'unify','sql'=>$sql, 'connection'=>'mysql',
+            'row'=>json_encode($row,JSON_UNESCAPED_UNICODE), 'column'=>json_encode($column), 'rule'=>json_encode($rule)]);
+        if ($post->status() == 500){
+            throw new Exception($post->header("Msg"));
+        }
+        return response($post,200, [
+            "Content-type"=>"application/octet-stream",
+            "Content-Disposition"=>"attachment; filename=二次加工统计记录-".date('ymdHis').'.xlsx',
+        ]);
     }
 }

+ 7 - 3
app/Http/Controllers/ProvincesController.php

@@ -31,7 +31,7 @@ class ProvincesController extends Controller
         $this->validatorProvinces($request,$id)->validate();
         $provinces=$request->input('Province');
         if(Province::create($provinces)){
-            $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+            app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
             return redirect('maintenance/province')->with('successTip','新省份“'.$request->input('Province.name').'”添加成功');
         };
     }
@@ -51,7 +51,7 @@ class ProvincesController extends Controller
         $province=Province::find($id);
         $province->fill($data);
         if ($province->save()){
-            $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+            app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
             return redirect('maintenance/province')->with('successTip','省份“'.$request->input('Province.name').'”修改成功');
         }
     }
@@ -60,7 +60,7 @@ class ProvincesController extends Controller
     {
         if(!Gate::allows('省份-删除')){ return redirect(url('/'));  }
         $province=Province::find($id);
-        $this->log(__METHOD__,__FUNCTION__,json_encode($province),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($province),Auth::user()['id']);
         $result=$province->delete();
         return ['success'=>$result];
     }
@@ -77,4 +77,8 @@ class ProvincesController extends Controller
         ]);
         return $validator;
     }
+
+    public function get(){
+        return Province::query()->select("id","name")->get();
+    }
 }

+ 114 - 64
app/Http/Controllers/QRCodeController.php

@@ -3,105 +3,155 @@
 namespace App\Http\Controllers;
 
 use App\UserDetail;
+use App\UserDutyCheck;
 use App\UserToken;
 use App\UserWorkgroup;
 use App\Warehouse;
 use Endroid\QrCode\QrCode;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Cache;
+use mysql_xdevapi\Collection;
 use Ramsey\Uuid\Uuid;
 
 class QRCodeController extends Controller
 {
+    //进入打卡页面
     public function goGetQRCode(){
-        $warehouses=Warehouse::get();
+        $warehouses=Warehouse::with('userWorkgroups')->get();
         return view("personnel/checking-in/getQRcode",compact('warehouses'));
     }
-    //二维码刷新时间
-    public function qrCode_refresh_time($userWorkgroups,$beforeTime){
+
+    //进入进出场二维码显示页面
+    public function importAndExportQRCode(){
+        $importAndExportQRCodes=[];
+        $userDutyCheckOne=new UserDutyCheck([
+            'source'=>'进场',
+            'type'=>'import',
+        ]);
+        $userDutyCheck=new UserDutyCheck([
+            'source'=>'出场',
+            'type'=>'export',
+        ]);
+        array_push($importAndExportQRCodes,$userDutyCheckOne,$userDutyCheck);
+        $importAndExportQRCodes=$this->qrCode_refresh_time($importAndExportQRCodes);
+        Cache::forget('next_refresh_time');
+        return view('personnel/checking-in/importAndExportQRCode',['importAndExportQRCodes'=>$importAndExportQRCodes,'next_refresh_time'=>Cache::get('next_refresh_time'),]);
+
+    }
+    //进出场二维码刷新时间
+    public function qrCode_refresh_time($importAndExportQRCodes){
         $qrCode_refresh=config('hr.qrCode_refresh');
-        if (!Cache::has('last_refresh_date') || Cache::get('last_refresh_date')<date('Y-m-d H:i:s')){
-            $last_refresh_date=date('Y-m-d H:i:s',strtotime('+'.$qrCode_refresh.'second'));
-            Cache::put('last_refresh_date',$last_refresh_date);
-            return $this->flushQRCode($userWorkgroups);
-        }
-        if ($beforeTime==Cache::get('last_refresh_date')){
-            $time=strtotime($beforeTime);
-            //刷新 更新cache
-            $last_refresh_date=date('Y-m-d H:i:s', strtotime('+'.$qrCode_refresh.'second', $time));
-            Cache::put('last_refresh_date',$last_refresh_date);
-            return $this->flushQRCode($userWorkgroups);
-        }
-        //每次刷新都标记一个cache 新建  每次刷新前判断这个标记时间
-        //直接去本地获取二维码
-        return $this->getQRCode($userWorkgroups);
+        $next_refresh_time=date('Y-m-d H:i:s',strtotime('+'.$qrCode_refresh.'second'));
+        Cache::put('next_refresh_time',$next_refresh_time);
+        return $this->flushQRCode($importAndExportQRCodes);
     }
-    //刷新二维码
-    public function flushQRCode($userWorkgroups){
-        foreach ($userWorkgroups as $userWorkgroup){
-            $time=strtotime(Cache::get('last_refresh_date'));
+    //刷新进出场二维码方法
+    public function flushQRCode($importAndExportQRCodes){
+        foreach ($importAndExportQRCodes as $importAndExportQRCode){
+            $time=strtotime(Cache::get('next_refresh_time'));
             $qrCode_refresh=config('hr.qrCode_refresh');
             if ($qrCode_refresh){
                 $date=date('Y-m-d H:i:s', strtotime('+30second',$time));
-                $url=url("personnel/checking-in/userDutyCheck/clock?key=").$date;
-                $url=$url."&&userWorkgroupID=".$userWorkgroup->id;
+                $url=url("personnel/checking-in/userDutyCheck/importAndExportClock?key=").$date;
+                $url=$url."&&importAndExportQRCodeType=".$importAndExportQRCode->type;
             }else{
-                $url=url("personnel/checking-in/userDutyCheck/clock");
-                $url=$url."?userWorkgroupID=".$userWorkgroup->id;
+                $url=url("personnel/checking-in/userDutyCheck/importAndExportClock");
+                $url=$url."?importAndExportQRCodeType=".$importAndExportQRCode->type;
             }
             $qrCode=new QrCode($url);
-            if ($userWorkgroup->id){
-                $fileURL=base_path('public/images/QRCodeIMG/'.$userWorkgroup->id.'.png');
-                $qrCode->writeFile($fileURL);
-                $userWorkgroup->url=url('images/QRCodeIMG/'.$userWorkgroup->id.'.png').'?da='.Uuid::uuid1();
+            if ($importAndExportQRCode->type){
+//                $fileURL=base_path('public/images/QRCodeIMG/'.$importAndExportQRCode->type.'.png');
+//                $qrCode->writeFile($fileURL);
+                $importAndExportQRCode->src=base64_encode($qrCode->writeString());
+//                $importAndExportQRCode->url=url('images/QRCodeIMG/'.$importAndExportQRCode->type.'.png').'?da='.Uuid::uuid1();
             }
         }
-        return $userWorkgroups;
+        return $importAndExportQRCodes;
     }
-    //获取二维码
-    public function getQRCode($userWorkgroups){
-        foreach ($userWorkgroups as $userWorkgroup){
-            $qrCode_refresh_everyday=config('hr.qrCode_refresh_everyday');
-            if ($qrCode_refresh_everyday){
-                $date=md5(date('Y-m-d'));
-                $url=url("personnel/checking-in/userDutyCheck/clock?key=").$date;
-                $url=$url."&&userWorkgroupID=".$userWorkgroup->id;
-            }else{
+    //刷新进出场二维码页面
+    public function refreshQRCode(Request $request){
+        $importAndExportQRCodes=[];
+        $userDutyCheckOne=new UserDutyCheck([
+            'type'=>'import',
+            'source'=>'进场',
+        ]);
+        $userDutyCheck=new UserDutyCheck([
+            'type'=>'export',
+            'source'=>'出场',
+        ]);
+        array_push($importAndExportQRCodes,$userDutyCheckOne,$userDutyCheck);
+        $importAndExportQRCodes=$this->qrCode_refresh_time($importAndExportQRCodes);
+        $csrfToken=csrf_token();
+        return ['importAndExportQRCodes'=>$importAndExportQRCodes,'next_refresh_time'=>Cache::get('next_refresh_time'),'csrf_Token'=>$csrfToken];
+    }
+
+    //进入工作组二维码显示页面
+    public function QRCode(Request $request){
+        $userWorkgroupId=$request->input('userWorkgroupId');
+        $userWorkgroup=UserWorkgroup::find($userWorkgroupId);
+        $userWorkgroup=$this->getQRCode($userWorkgroup);
+        if (!$userWorkgroup)return view('exception.404',['error'=>'未找到工作组!']);
+        return view('personnel/checking-in/QRcode',['userWorkgroup'=>$userWorkgroup]);
+    }
+
+    //获取工作组二维码
+    public function getQRCode($userWorkgroup){
                 $url=url("personnel/checking-in/userDutyCheck/clock");
                 $url=$url."?userWorkgroupID=".$userWorkgroup->id;
-            }
             $qrCode=new QrCode($url);
             if ($userWorkgroup->id){
                 $fileURL=base_path('public/images/QRCodeIMG/'.$userWorkgroup->id.'.png');
                 if (file_exists($fileURL)){
                     $userWorkgroup->url=url('images/QRCodeIMG/'.$userWorkgroup->id.'.png');
-                    continue;
                 }
                 $qrCode->writeFile($fileURL);
                 $userWorkgroup->url=url('images/QRCodeIMG/'.$userWorkgroup->id.'.png');
             }
-        }
-        return $userWorkgroups;
+        return $userWorkgroup;
+    }
 
 
-    }
-    //进入刷新二维码页面
-    public function refreshQRCode(Request $request){
-        $beforeTime=$request->input('beforeTime');
-        $warehouseId=$request->input('warehouseId');
-        $userWorkgroups=UserWorkgroup::where('warehouse_id',$warehouseId)->get();
-        $userWorkgroups=$this->qrCode_refresh_time($userWorkgroups,$beforeTime);
-        if (!$userWorkgroups)return view('exception.404',['error'=>'未找到工作组!']);
-        return ['userWorkgroups'=>$userWorkgroups,'last_refresh_date'=>Cache::get('last_refresh_date'),];
-    }
-    //第一次进入二维码显示页面
-    public function QRCode(Request $request){
-        $warehouseId=$request->input('warehouseId');
-        $userWorkgroups=UserWorkgroup::where('warehouse_id',$warehouseId)->get();
-        $beforeTime=date('Y-m-d H:i:s');
-        $userWorkgroups=$this->qrCode_refresh_time($userWorkgroups,$beforeTime);
-        Cache::forget('last_refresh_date');
-        if (!$userWorkgroups)return view('exception.404',['error'=>'未找到工作组!']);
-        return view('personnel/checking-in/QRcode',['warehouseId'=>$warehouseId,'userWorkgroups'=>$userWorkgroups,'last_refresh_date'=>Cache::get('last_refresh_date'),]);
-    }
+    //获取进出场二维码
+//    public function getImportAndExportQRCode($importAndExportQRCodes){
+//            foreach ($importAndExportQRCodes as $importAndExportQRCode){
+//                $qrCode_refresh_everyday=config('hr.qrCode_refresh_everyday');
+//                if ($qrCode_refresh_everyday){
+//                    $date=md5(date('Y-m-d'));
+//                    $url=url("personnel/checking-in/userDutyCheck/importAndExportClock?key=").$date;
+//                    $url=$url."&&importAndExportQRCodeType=".$importAndExportQRCode->type;
+//                }else{
+//                    $url=url("personnel/checking-in/userDutyCheck/importAndExportClock");
+//                    $url=$url."?importAndExportQRCodeType=".$importAndExportQRCode->type;
+//                }
+//                $qrCode=new QrCode($url);
+//                if ($importAndExportQRCode->type){
+//                    $fileURL=base_path('public/images/QRCodeIMG/'.$importAndExportQRCode->type.'.png');
+//                    if (file_exists($fileURL)){
+//                        $importAndExportQRCode->url=url('images/QRCodeIMG/'.$importAndExportQRCode->type.'.png');
+//                        continue;
+//                    }
+//                    $qrCode->writeFile($fileURL);
+//                    $importAndExportQRCode->url=url('images/QRCodeIMG/'.$importAndExportQRCode->type.'.png');
+//                }
+//            }
+//        return $importAndExportQRCodes;
+//    }
+
+//    //进出场二维码刷新时间
+//    public function qrCode_refresh_time($importAndExportQRCodes,$beforeTime){
+//        $qrCode_refresh=config('hr.qrCode_refresh');
+//        if (!Cache::has('next_refresh_time') || Cache::get('next_refresh_time')<date('Y-m-d H:i:s')){
+//            $next_refresh_time=date('Y-m-d H:i:s',strtotime('+'.$qrCode_refresh.'second'));
+//            Cache::put('next_refresh_time',$next_refresh_time);
+//            return $this->flushQRCode($importAndExportQRCodes);
+//        }
+//        if ($beforeTime==Cache::get('next_refresh_time')){
+//            $time=strtotime($beforeTime);
+//            //刷新 更新cache
+//            $next_refresh_time=date('Y-m-d H:i:s', strtotime('+'.$qrCode_refresh.'second', $time));
+//            Cache::put('next_refresh_time',$next_refresh_time);
+//            return $this->flushQRCode($importAndExportQRCodes);
+//        }
+//        return $this->getImportAndExportQRCode($importAndExportQRCodes);
+//    }
 }

+ 3 - 3
app/Http/Controllers/QualityLabelController.php

@@ -48,7 +48,7 @@ class QualityLabelController extends Controller
         $qualityLabel=new QualityLabel($request->all());
         $qualityLabel->save();
 
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return redirect('maintenance/qualityLabel/create')->with('successTip',"成功录入品质标签“{$request->input('name')}”");
     }
     protected function validatorCreate(array $data)
@@ -100,7 +100,7 @@ class QualityLabelController extends Controller
         $this->validatorUpdate($request->all())->validate();
         $qualityLabel->fill($request->all());
         $qualityLabel->update();
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return redirect('maintenance/qualityLabel/')->with('successTip',"成功修改品质标签“{$qualityLabel['name']}”!");
     }
 
@@ -114,7 +114,7 @@ class QualityLabelController extends Controller
     public function destroy(QualityLabel $qualityLabel)
     {
         if(!Gate::allows('品质标签-删除')){ return redirect(url('/'));  }
-        $this->log(__METHOD__,__FUNCTION__,$qualityLabel->toJson(),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,$qualityLabel->toJson(),Auth::user()['id']);
         $re=$qualityLabel->delete();
         return ['success'=>$re];
     }

+ 179 - 16
app/Http/Controllers/RejectedBillController.php

@@ -5,11 +5,19 @@ namespace App\Http\Controllers;
 use App\Events\InformWMSReceivedEvent;
 use App\Http\Controllers\Api\thirdPart\flux\ReceiveController;
 use App\Logistic;
+use App\OracleActAllocationDetails;
+use App\OracleBasSKU;
+use App\OracleDOCOrderHeader;
 use App\Owner;
 use App\QualityLabel;
 use App\Rejected;
 use App\RejectedBill;
 use App\RejectedBillItem;
+use App\Services\LogService;
+use App\Services\OrderPackageCommoditiesService;
+use App\Services\OrderService;
+use App\Services\RejectedBillItemService;
+use App\Services\RejectedBillService;
 use Illuminate\Contracts\View\Factory;
 use Illuminate\Http\RedirectResponse;
 use Illuminate\Http\Request;
@@ -24,6 +32,12 @@ use Ramsey\Uuid\Uuid;
 
 class RejectedBillController extends Controller
 {
+    function __construct()
+    {
+
+//        app()->bind('OrderPackageCommoditiesService',OrderPackageCommoditiesService::class);
+    }
+
     /**
      * Display a listing of the resource.
      *
@@ -54,17 +68,17 @@ class RejectedBillController extends Controller
     {
         //
     }
+
     public function apiGetRecent()
     {
         if(!Gate::allows('退货管理-查询')){
             return ['success'=>'false','fail_info'=>'没有权限'];}
         $user=Auth::user();
         $rejectedBills = RejectedBill::query()->orderByDesc('id')->whereIn('id_owner',
-            $user?$user->getPermittingOwnerIdsAttribute():[])->limit(20)->get();
+            $user?app('UserService')->getPermittingOwnerIds($user):[])->limit(20)->get();
         return ['success'=>'true','rejectedBills'=>$rejectedBills->toArray()];
     }
 
-
     public function apiStore(Request $request)
     {
         if(!Gate::allows('退货管理-录入')){
@@ -82,8 +96,10 @@ class RejectedBillController extends Controller
         $rejectedBill=new RejectedBill($request->all());
         $rejectedBill['id_operator'] = Auth::user()['id'];
         $rejectedBill->save();
+        app(RejectedBillService::class)->syncOrderIssue($rejectedBill);
+//        $rejectedBill->同步问题件退件状态();
 
-        $this->log(__METHOD__,__FUNCTION__.'_'.$rejectedBill['id'],json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__.'_'.$rejectedBill['id'],json_encode($request->toArray()),Auth::user()['id']);
         return ['success'=>'true','id'=>$rejectedBill['id']];
     }
 
@@ -92,7 +108,9 @@ class RejectedBillController extends Controller
         if(!Gate::allows('退货管理-编辑')){
             return ['success'=>'false','fail_info'=>'没有权限'];
         }
-        if($request['is_loaded']=='null')$request['is_loaded']=null;
+        if($request['is_loaded']==='null'){
+            $request['is_loaded']=null;
+        }
         $errorFields= $this->validator($request->all(),true)->errors()->getMessages();
         if(!empty($errorFields)){
             return ['success'=>'false','error_fields'=>$errorFields,'fail_info'=>'fileds error'];
@@ -100,14 +118,13 @@ class RejectedBillController extends Controller
         $rejectedBill=RejectedBill::find($request->input('id'));
         $rejectedBill->fill($request->all());
         $rejectedBill->save();
+        app(RejectedBillService::class)->syncOrderIssue($rejectedBill);
+//        $rejectedBill->同步问题件退件状态();
 
-        if($request->input('is_at_edit_page')==true){
-            Session::put('rejected.index.isFromEditPage',true);
-        }
-
-        $this->log(__METHOD__,__FUNCTION__.'_'.$rejectedBill['id'],json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__.'_'.$rejectedBill['id'],json_encode($request->toArray()),Auth::user()['id']);
         return ['success'=>'true'];
     }
+
     public function apiConfirmBeStored(Request $request)
     {
         if(!Gate::allows('退货管理-编辑')){
@@ -118,7 +135,7 @@ class RejectedBillController extends Controller
         if(config('api.jianshang_rejecteds_log_switch'))Controller::logS(__METHOD__,__FUNCTION__,"人工确认入库。退单号:".$rejectedBill['logistic_number_return'],Auth::user()['id']);
         $result_TransferToWMS=ReceiveController::accomplishToWMS($rejectedBill);
 
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         switch ($result_TransferToWMS){
             case 'success':
                 $rejectedBill['is_loaded']=1;
@@ -129,14 +146,18 @@ class RejectedBillController extends Controller
         }
     }
 
-
     protected function validator(array $data,$isUpdate=false)
     {
         $mobileShouldBeRequired = 'required';
         $logistic=Logistic::find($data['id_logistic_return']);
-        if($logistic){if(strstr($logistic['name'],'顺丰')){
+        if($logistic){if(
+            strstr($logistic['name'],'顺丰')
+        ){
             $mobileShouldBeRequired = 'nullable';
         }}
+        if($data['id_owner']=='4'){
+            $mobileShouldBeRequired = 'nullable';
+        }
         $mobileDigits = '';
         if($data['mobile_sender']&&$data['mobile_sender'][0]=='1'){
             $mobileDigits = 'digits:11';
@@ -222,13 +243,14 @@ class RejectedBillController extends Controller
     public function edit(RejectedBill $rejectedBill,Request $request)
     {
         if(!Gate::allows('退货管理-编辑')){ return redirect(url('/'));  }
-        $filterParams=$request->input('filterParams');
-        Session::put('rejected.index.filterParams',$filterParams);
         $user=Auth::user();
         $owners=Owner::all()->whereIn('id',
-            $user?$user->getPermittingOwnerIdsAttribute():[])->sortBy('name');
+            $user?app('UserService')->getPermittingOwnerIds($user):[])->sortBy('name');
         $logistics=Logistic::all()->sortBy('name');
         $qualityLabels=QualityLabel::all()->sortBy('name');
+        $rejectedBill['is_loaded'] = $rejectedBill['is_loaded_null'];
+        $rejectedBill['isEditing'] = false;
+        $rejectedBill['is_at_edit_page'] = true;
         return view('rejected.edit',compact('owners','logistics','qualityLabels','rejectedBill'));
     }
 
@@ -248,7 +270,7 @@ class RejectedBillController extends Controller
     {
         if(!Gate::allows('退货管理-删除')){ return redirect(url('/'));}
         $re=$rejectedBill->delete();
-        $this->log(__METHOD__,__FUNCTION__,$rejectedBill->toJson(),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,$rejectedBill->toJson(),Auth::user()['id']);
         return ['success'=>$re];
     }
 
@@ -260,4 +282,145 @@ class RejectedBillController extends Controller
         if(!$bill)return ['success'=>'true','result'=>'false'];
         return ['success'=>'true','result'=>'true'];
     }
+
+    function seekOrder(Request $request){
+        if (!$request->soreference5)return ['success'=>false];
+        $order=OracleDOCOrderHeader::select('soreference1','customerid','c_contact','c_tel2','c_tel1','carrierid')->where('soreference5',$request->soreference5)->first();
+        if ($order)return ['success'=>true,'data'=>$order];
+    }
+
+    public function disposeImportApi(Request $request)
+    {
+        if(!Gate::allows('退货管理-编辑'))
+            return ['success'=>false,'message'=>'没有对应权限'];
+        /**
+         * @var RejectedBillItemService $rejectedBillItemService
+         * @var RejectedBillService $service
+         */
+        $service = app('RejectedBillService');
+        $rejectedBillItemService = app('RejectedBillItemService');
+        $params = [['logistic_number_return','logistic_number','fee_collected']];
+        $logistic_numbers = [];             // 原单单号
+        $logistic_number_map = [];
+        $logistic_number_return = [];       // 退回单号
+        $logistic_number_return_map = [];
+
+        $errors = [];
+        $array = explode("\n",$request['dataText']); //拆分行
+        foreach ($array as  $i=>$item) {
+            $items = [];
+            preg_match('/^(\w*?)[\s,,;;](\w*?)[\s,,;;](\d.*)$/u',$item,$items);
+            if(count($items) < 1)
+                preg_match('/^(\w*?)[\s,,;;](\w*?)$/u',$item,$items);
+            $head = '第'.($i+1).'行';
+            if(count($items) < 3){
+                $errors[$head] = ['数据不完整'];
+                unset($items);
+                continue;
+            }
+            array_shift($items);
+            isset($items[1]) ? $logistic_numbers[] = $items[1] : null;
+            isset($items[0]) ? $logistic_number_return[] = $items[0] : null;
+            $param = [$items[0] ?? null, $items[1] ?? null, $items[2] ?? null];
+            $params[] = $param;
+            $logistic_number_map[$items[1]] = $param;
+            $logistic_number_return_map[$items[0]] =$param;
+            unset($param);
+        }
+        $rejectedBill_collect = collect();
+
+        // 对已用的进行修改
+        $update_fee_params = [['id','logistic_number','fee_collected']];                //对原有的进行修改 有到付费用
+        $update_params = [['id','logistic_number']];                                    // 无到付费用
+        $exist_picktotraceid = [];                                                      // 已有退回单号
+        $rejectedBills = RejectedBill::query()->whereIn('logistic_number_return',$logistic_number_return)->get();
+        $rejectedBills->each(function($rejectedBill)use(&$update_fee_params,&$update_params,$logistic_number_return_map,&$exist_picktotraceid,&$rejectedBill_collect){
+            $rejectedBill_collect->push($rejectedBill);
+            $logistic_number_return =  $rejectedBill->logistic_number_return; //退回单号
+            $params = $logistic_number_return_map[$logistic_number_return];
+            $rejectedBill->logistic_number ? $exist_picktotraceid[$rejectedBill->logistic_number] = $rejectedBill->logistic_number : null;    // 记录已有原单单号
+            if(isset($params[2])){
+                $update_fee_params[] = ['id'=>$rejectedBill->id,'logistic_number'=>$params[1],'fee_collected'=>$params[2]];
+            }else if(isset($params[1])){
+                $update_params[] = ['id'=>$rejectedBill->id,'logistic_number'=>$params[1]];
+            }
+        });
+        // 对不存在的进行创建
+        $inner_items_params = [];
+        $details = OracleActAllocationDetails::query()->with('oracleDocOrderHeader.oracleBASCustomer')->whereIn('picktotraceid',$logistic_numbers)->get();
+        $bas_sku_map =[];
+        OracleBasSKU::query()->selectRaw('SKU,CustomerID,Alternate_SKU1,Descr_C')->whereIn('SKU',array_diff(data_get($details,'*.sku'),[' ','*']))->whereIn('CustomerID',data_get($details,'*.customerid'))->get()
+            ->each(function($bas_sku)use(&$bas_sku_map){
+                $key = 'Sku = '.$bas_sku->sku.' CustomerID = '.$bas_sku->customerid;
+                $bas_sku_map[$key] = $bas_sku;
+            });
+        $details = $details->groupBy('picktotraceid');
+
+        $details->each(function($items,$key)use(&$inner_params,$bas_sku_map,$exist_picktotraceid,&$inner_items_params,&$rejectedBill_collect,$logistic_number_map){
+            if(!isset($exist_picktotraceid[$key])){
+                $order_header = $items->first()->oracleDocOrderHeader;
+                $owner = app('OwnerService')->firstOrCreate(['name' => $order_header->oracleBASCustomer->descr_c],
+                    ['name' => $order_header->oracleBASCustomer->descr_c, 'code' => $order_header->oracleBASCustomer->descr_c]);
+                $logistic = app('LogisticService')->firstOrCreate(['name' => $order_header->carriername],
+                    ['name' => $order_header->carriername, 'code' => $order_header->carriername]);
+                $rejectedBill = RejectedBill::query()->create([
+                    'id_owner' => $owner->id ?? '',
+                    'sender' => $order_header->c_contact,
+                    'logistic_number_return' => $logistic_number_map[$key][0] ?? '',
+                    'id_logistic_return' =>$logistic->id ?? '',
+                    'fee_collected' => $logistic_number_map[$key][2] ?? '',
+                    'order_number' =>$order_header->soreference1,
+                    'mobile_sender' => empty($order_header->c_tel2)?$order_header->c_tel1:$order_header->c_tel2,
+                    'logistic_number' => $logistic_number_map[$key][1] ?? '',
+                    'remark' => $order_header->notes,
+                    'is_loaded' =>0,
+                    "id_operator" => Auth::id(),
+                ]);
+                $rejectedBill_collect->push($rejectedBill);
+                LogService::log(__METHOD__,"生成退货单",json_encode($rejectedBill),Auth::user()['id']);
+                // 获取创建items
+                $items->each(function($item)use($rejectedBill,$bas_sku_map,&$inner_items_params){
+                    $key = 'Sku = '.$item->sku.' CustomerID = '.$item->customerid;
+                    $bas_sku = $bas_sku_map[$key] ?? '';
+                    $date = date('Y-m-d H:i:s');
+                    $inner_items_params[] = [
+                        'id_rejected_bill' => $rejectedBill->id ?? '',
+                        'barcode_goods' => $bas_sku['alternate_sku1'] ?? '',
+                        'name_goods' => $bas_sku['descr_c'],
+                        'amount' => $item->qty_each,
+                        'id_quality_label' => 1,
+                        'created_at' => $date,
+                        'updated_at' => $date
+                    ];
+                });
+            }
+        });
+        try {
+            if (count($update_fee_params) > 1) {
+                $service->batchUpdate($update_fee_params);
+            }
+            if (count($update_params) > 1) {
+                $service->batchUpdate($update_params);
+            }
+            if(count($inner_items_params) > 0){
+                $rejectedBillItemService->insert($inner_items_params);
+                LogService::log(__METHOD__, "批量生成退货单详情", json_encode($inner_items_params), Auth::user()['id']);
+            }
+            $rejectedBill_collect->each(function ($rejectedBill)use($service){
+                $service->syncOrderIssue($rejectedBill);
+            });
+            return ['success'=>true];
+        } catch (\Exception $e) {
+            LogService::log(__METHOD__, __FUNCTION__.' error', '修改退回单号 失败', json_encode($request->getContent()).' ||'.json_encode($e->getMessage())." || ".json_encode($e->getTraceAsString()));
+            return ['success'=>false,'error'=>['导入处理发生异常'=>$e->getMessage()]];
+        }
+    }
+
+    public function importRejectedNumber(Request $request)
+    {
+        if(!Gate::allows('退货管理-编辑'))
+            return redirect(url('/'));
+        return view('rejected.importRejectedNumber');
+    }
+
 }

+ 58 - 21
app/Http/Controllers/RejectedBillItemController.php

@@ -5,9 +5,10 @@ namespace App\Http\Controllers;
 use App\Commodity;
 use App\Events\InformWMSReceivedEvent;
 use App\Owner;
-use App\Rejected;
 use App\RejectedBill;
 use App\RejectedBillItem;
+use App\Services\CommodityService;
+use App\Services\RejectedBillService;
 use App\WMSReflectReceive;
 use App\WMSReflectReceiveSku;
 use Illuminate\Http\Request;
@@ -72,10 +73,32 @@ class RejectedBillItemController extends Controller
             $rejectedBillItem=new RejectedBillItem($request->all());
             $rejectedBillItem->save();
         }
-        $rejectedBillItem->injectCommodityName();
+
+        if (!$rejectedBillItem->rejectedBill || !$rejectedBillItem->rejectedBill->owner)return ['success'=>'false','failure_info'=>'退货单或货主不存在'];
+
+        /** @var CommodityService $commodityService */
+        $commodityService = app('CommodityService');
+        $commodity = $commodityService->ownerBarcodeSeekCommodityFirst(['name'=>$rejectedBillItem->rejectedBill->owner->name],$rejectedBillItem->barcode_goods);
+        if (!$commodity){
+            $commodity = $commodityService->ownerAndBarcodeFirstOrCreate($rejectedBillItem->rejectedBill->owner,$rejectedBillItem->barcode_goods);
+            if (!$commodity){
+                $commodity = $commodityService->create([
+                    "name" => $rejectedBillItem->name_goods,
+                    "owner_id" => $rejectedBillItem->rejectedBill->owner->id,
+                ]);
+                app('CommodityBarcodeService')->first([
+                    'commodity_id' => $commodity->id,
+                    'code' => $rejectedBillItem->barcode_goods,
+                ]);
+            }
+        }
 
 
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        $rejectedBill = RejectedBill::query()->where('id',$request->input('id_rejected_bill'))->first();
+        app(RejectedBillService::class)->syncOrderIssue($rejectedBill);
+//        $rejectedBIll->同步问题件();
+//        $rejectedBIll->同步问题件退件状态();
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return ['success'=>'true','id'=>$rejectedBillItem['id']];
     }
 
@@ -95,11 +118,12 @@ class RejectedBillItemController extends Controller
             $rejectedBillItem->fill($request->all());
             $rejectedBillItem->update();
             $rejectedBillItem->injectCommodityName();
-            $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+            $rejectedBill = RejectedBill::query()->where('id',$rejectedBillItem->id_rejected_bill)->with('orderIssue')->first();
+//            $rejectedBill->同步问题件退件状态();
+            app(RejectedBillService::class)->syncOrderIssue($rejectedBill);
+            app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
             return ['success'=>'true','id'=>$rejectedBillItem['id']];
         }
-
-
     }
 
 
@@ -118,6 +142,10 @@ class RejectedBillItemController extends Controller
                 $rejectedBill=RejectedBill::find($rejectedBillItem['id_rejected_bill']);
                 $owner = Owner::find($rejectedBill['id_owner']);
                 if(strstr($owner->name??'','笕尚')){
+                    app('LogService')->log(__METHOD__,'找不到表','121行');
+//                    $rejected=new Rejected();
+//                    $rejected->fill($rejectedBill->toArray());
+//                    $rejected->fill($rejectedBillItem->toArray());
                     $rejected=new Rejected();
                     $rejected->fill($rejectedBill->toArray());
                     $rejected->fill($rejectedBillItem->toArray());
@@ -125,7 +153,7 @@ class RejectedBillItemController extends Controller
                     $sended=$rejectedJianshang->sendRejected($rejected);
                     if(!$sended){
                         echo '<h1>数据发送给笕尚失败,请通知IT相关负责人</h1>';
-                        $this->log(__METHOD__,'error','数据发送给笕尚失败');
+                        app('LogService')->log(__METHOD__,'error','数据发送给笕尚失败');
                         $havingFail++;
                         return false;
                     }
@@ -150,7 +178,9 @@ class RejectedBillItemController extends Controller
             return ['success'=>'false','fail_info'=>'没有匹配到相应内容'];
         }
         $item=$rejectedBillItems->first();
-        $rejectedBill = RejectedBill::find($item['id_rejected_bill']);
+        $rejectedBill = RejectedBill::query()->find($item['id_rejected_bill']);
+        app(RejectedBillService::class)->syncOrderIssue($rejectedBill);
+//        $rejectedBill->同步问题件();
         if(config('api.jianshang_rejecteds_log_switch'))Controller::logS(__METHOD__,__FUNCTION__,'请求处理退单:'.$rejectedBill['logistic_number_return'],Auth::user()['id']);
         $downloadedSkus = WMSReflectReceive::downloadedSkus($rejectedBill['logistic_number_return'],true);
         $isGotMoreThenDownloaded=WMSReflectReceiveSku::isItemsOverDownloadedSkus($rejectedBillItems,$downloadedSkus);
@@ -163,12 +193,14 @@ class RejectedBillItemController extends Controller
         })($rejectedBill);
         if(config('api.jianshang_rejecteds_log_switch'))Controller::logS(__METHOD__,__FUNCTION__,"当前,实收件:(".json_encode($rejectedBillItems).")},下载件:("
             .json_encode($downloadedSkus).")},退单号:{$rejectedBill['logistic_number_return']}",null);
+        $shouldStore=!$isGotMoreThenDownloaded    //没有录入超过下载货物数
+            && !($rejectedBill['is_loaded']==1)//并且不是已入库////去掉了或无需入库的判断:||$rejectedBill['is_loaded']===null
+            &&config('api.api_switch_receive_to_wms');//并且配置开
+        if(config('api.jianshang_rejecteds_log_switch'))Controller::logS(__METHOD__,__FUNCTION__,"自动入库:{$shouldStore}||isGotMoreThenDownloaded={$isGotMoreThenDownloaded}/rejectedBill['is_loaded']={$rejectedBill['is_loaded']}/rejectedBill['is_loaded']={$rejectedBill['is_loaded']}",null);
 
 
 
-        if(!$isGotMoreThenDownloaded    //没有录入超过下载货物数
-            && !($rejectedBill['is_loaded']==1||$rejectedBill['is_loaded']===null)//并且不是已入库或无需入库
-            &&config('api.api_switch_receive_to_wms')){ //并且配置开
+        if($shouldStore){
             if(config('api.jianshang_rejecteds_log_switch'))Controller::logS(__METHOD__,__FUNCTION__,'满足条件,准备从网页主动请求富勒入库:'.$rejectedBill['logistic_number_return'],Auth::user()['id']);
             $result_transferToWms=(new InformWMSReceivedEvent($rejectedBill))->directRun();
             if($result_transferToWms=='fail')return ['success'=>'false','fail_info'=>'提交至WMS错误,请手动校验、操作WMS并通知相关人员'];
@@ -195,14 +227,17 @@ class RejectedBillItemController extends Controller
         $havingFail=0;
         if(!config('api.API_FAKING')){
             $items->each(function(RejectedBillItem $rejectedBillItem)use(&$havingFail,$rejectedBill){
-                $rejected=new Rejected();
-                $rejected->fill($rejectedBill->toArray());
-                $rejected->fill($rejectedBillItem->toArray());
+//                $rejected=new Rejected();
+//                app('LogService')->log(__METHOD__,'找不到表','200行');
+//                $rejected->fill($rejectedBill->toArray());
+//                $rejected->fill($rejectedBillItem->toArray());
+                $rejected=$rejectedBill->toArray();
+                $rejected = array_merge($rejected, $rejectedBillItem->toArray());
                 $rejectedJianshang=new api\thirdPart\jianshang\RejectedController();
                 $sended=$rejectedJianshang->sendRejected($rejected);
                 if(!$sended){
                     echo '<h1>数据发送给笕尚失败,请通知IT相关负责人</h1>';
-                    $this->log(__METHOD__,'error_'.__FUNCTION__.'_'.$rejectedBillItem['id'],'数据发送给笕尚失败');
+                    app('LogService')->log(__METHOD__,'error_'.__FUNCTION__.'_'.$rejectedBillItem['id'],'数据发送给笕尚失败');
                     $havingFail++;
                     return false;
                 }
@@ -216,7 +251,7 @@ class RejectedBillItemController extends Controller
         }
 
         if($havingFail>0){
-            $this->log(__METHOD__,'error_'.__FUNCTION__.'_'.$rejectedBill['id'],"$havingFail/{$items->count()} 条记录没有发送成功",Auth::user()['id']);
+            app('LogService')->log(__METHOD__,'error_'.__FUNCTION__.'_'.$rejectedBill['id'],"$havingFail/{$items->count()} 条记录没有发送成功",Auth::user()['id']);
             return false;
         }
         return true;
@@ -228,8 +263,9 @@ class RejectedBillItemController extends Controller
             if(config('api.jianshang_rejecteds_log_switch'))Controller::logS(__METHOD__,__FUNCTION__,"进入发送方法,但退单已入库,跳出!退单号:{$rejectedBill['logistic_number_return']}",Auth::user()['id']);
             return true;
         }
-        $rejected=new Rejected();
-        $rejected->fill($rejectedBill->toArray());
+//        $rejected=new Rejected();
+        $rejected=$rejectedBill->toArray();
+//        $rejected->fill($rejectedBill->toArray());
         $goodses=[];
         $items->each(function(RejectedBillItem $item)use(&$goodses){
             $goodses[]=$item->toArray();
@@ -282,7 +318,7 @@ class RejectedBillItemController extends Controller
             $rejectedBillItem->delete();
         });
 
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return ['success'=>'true'];
     }
 
@@ -291,8 +327,8 @@ class RejectedBillItemController extends Controller
         return Validator::make($data, [
             'id_rejected_bill' => ['required', 'numeric', 'exists:rejected_bills,id'],
             'barcode_goods' => ['required', 'string','max:60'],
-            'name_goods' => ['nullable', 'string','max:50'],
-            'amount' => ['numeric','nullable', 'max:99999'],
+            'name_goods' => ['nullable', 'string','max:219'],
+            'amount' => ['numeric','required', 'max:99999'],
             'id_quality_label' => ['required','numeric',  'max:11'],
             'batch_number' => ['string', 'nullable',],
             'validity_at' => ['nullable','date_format:Y-m-d'],
@@ -327,6 +363,7 @@ class RejectedBillItemController extends Controller
         }
         $rejectedBillItem = RejectedBillItem::find($request->input('id'));
         $rejectedBillItem->forceDelete();
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($rejectedBillItem),Auth::user()['id']);
         return ['success'=>'true','id'=>$request->input('id')];
     }
 

+ 149 - 52
app/Http/Controllers/RejectedController.php

@@ -2,51 +2,61 @@
 
 namespace App\Http\Controllers;
 
-use App\Exports\RejectedExport;
-use App\Imports\CommodityImport;
 use App\Imports\RejectedImport;
 use App\Logistic;
 use App\Owner;
 use App\QualityLabel;
 use App\Rejected;
+use App\RejectedAnalyzeOwner;
 use App\RejectedBill;
-use App\RejectedBillItem;
+use App\Services\LogisticService;
+use App\Services\OwnerService;
+use App\Services\QualityLabelService;
+use App\Services\RejectedService;
 use Carbon\Carbon;
 use Exception;
+use Illuminate\Contracts\Foundation\Application;
 use Illuminate\Contracts\View\Factory;
 use Illuminate\Http\RedirectResponse;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
+use Illuminate\Routing\Redirector;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Gate;
-use Illuminate\Support\Facades\Session;
+use Illuminate\Support\Facades\Http;
 use Illuminate\Support\Facades\Validator;
 use Illuminate\View\View;
 use Maatwebsite\Excel\Facades\Excel;
-use phpDocumentor\Reflection\Types\Array_;
 use function foo\func;
 
 class RejectedController extends Controller
 {
+    public function __construct()
+    {
+        app()->singleton('RejectedService',RejectedService::class);
+    }
+
     /**
      * Display a listing of the resource.
-     *
-     * @return Factory|View|RedirectResponse
+     * @param Request $request
+     * @param OwnerService $ownerService
+     * @param QualityLabelService $qualityLabelService
+     * @param LogisticService $logisticService
+     * @return Application|Factory|View|void
      */
-    public function index(Request $request)
+    public function index(Request $request,OwnerService $ownerService,
+                          QualityLabelService $qualityLabelService,LogisticService $logisticService)
     {
-        if(!Gate::allows('退货管理-查询')){ return redirect(url('/'));  }
-        $user=Auth::user();
-        $paginate = $request->input('paginate')??50;
-        $paginateParams = $this->packFilterParams($request);
-        $page =$paginateParams['page'] ?? $request->input('page') ?? 1;
-        $paginateParams['paginate']=$paginate;
-        $rejectedQuery=$this->buildFilteredQuery($paginateParams)->orderBy('id','desc')->whereIn('id_owner',
-            $user?$user->getPermittingOwnerIdsAttribute():[]);
-        $rejectedBills=$rejectedQuery->paginate($paginate, ['*'], 'page', $page);
-        $owners = Owner::filterAuthorities()->get();
-        $qualityLabels = QualityLabel::all();
-        return view('rejected.index',compact('rejectedBills','owners',
+        if(!Gate::allows('退货管理-查询')){ return redirect(url('/login'));  }
+        $paginateParams = $request->input();
+        /** @var RejectedService $application */
+        $application = app('RejectedService');
+        $rejectedBills= $application->paginate($request);
+//        $issueIds = $application->返回有问题件的ID($request);
+        $owners = $ownerService->getSelection();
+        $qualityLabels = $qualityLabelService->get();
+        $logistics=$logisticService->getSelection();
+        return view('rejected.search.general',compact('rejectedBills','owners','logistics',
             'paginateParams','qualityLabels'));
     }
     public function recycle(Request $request)
@@ -57,7 +67,7 @@ class RejectedController extends Controller
         $paginateParams = $this->packFilterParams($request);
         $paginateParams['paginate']=$paginate;
         $rejectedQuery=$this->buildFilteredQuery($paginateParams)->orderBy('id','desc')->whereIn('id_owner',
-            $user?$user->getPermittingOwnerIdsAttribute():[])->withTrashed()->whereNotNull('deleted_at');
+            $user?app('UserService')->getPermittingOwnerIds($user):[])->withTrashed()->whereNotNull('deleted_at');
         $total = $rejectedQuery->count();
         $rejectedBills=$rejectedQuery->paginate($paginate);
         return view('rejected.recycle',compact('rejectedBills','total','paginateParams'));
@@ -72,7 +82,7 @@ class RejectedController extends Controller
         $rejecteds->each(function(RejectedBill $rejected){
             $rejected->restore();
         });
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return ['success'=>'true','rejecteds'=>$rejecteds];
     }
 
@@ -91,13 +101,8 @@ class RejectedController extends Controller
             'barcode_goods'=> $request->input('barcode_goods'),
             'logistic_number_return'=> $request->input('logistic_number_return'),
             'logistic_number'=> $request->input('logistic_number'),
+            'id_logistic_return'=> $request->id_logistic_return,
         ];
-
-        if(Session::get('rejected.index.isFromEditPage')){
-            $paginateParams=json_decode(Session::get('rejected.index.filterParams'),true);
-            Session::forget('rejected.index.isFromEditPage');
-            Session::forget('rejected.index.filterParams');
-        }
         return $paginateParams;
     }
     private function buildFilteredQuery(Array $params){
@@ -113,7 +118,8 @@ class RejectedController extends Controller
         $barcode_goods = $params['barcode_goods'];
         $logistic_number_return = $params['logistic_number_return'];
         $logistic_number = $params['logistic_number'];
-        $rejectedBillsQuery=RejectedBill::with(['owner','logistic','items',]);
+        $id_logistic_return= $params['id_logistic_return'];
+        $rejectedBillsQuery=RejectedBill::with(['user','owner','logistic','items']);
         if($created_at_start&&!$created_at_end){
             $created_at_end = $created_at_start;
         }
@@ -144,10 +150,6 @@ class RejectedController extends Controller
             }
         }
         if($is_checked!=''){
-//            $orderSign = false;
-//            if($is_checked){
-//                $orderSign = true;
-//            }
             if(!$is_checked)
                 $rejectedBillsQuery=$rejectedBillsQuery->where(function ($query) {
                     $query->where('is_checked', false)
@@ -178,7 +180,7 @@ class RejectedController extends Controller
             $rejectedBillsQueryTem=$rejectedBillsQueryTem->where('created_at','>',$startDay->format('Y-m-d'));
             $rejectedBillsQueryTem=$rejectedBillsQueryTem->where('order_number','like','%'.$order_number.'%');
             if($rejectedBillsQueryTem->count()==0
-                ||$rejectedBillsQueryTem->first()['order_number']==$order_number){
+                ||$rejectedBillsQueryTem->get()[0]['order_number']==$order_number){
                 $rejectedBillsQuery=$rejectedBillsQuery->where('order_number',$order_number);
             }else{
                 $rejectedBillsQuery=$rejectedBillsQueryTem;
@@ -194,7 +196,7 @@ class RejectedController extends Controller
                 $rejectedBillsQueryTem=$rejectedBillsQueryTem->where('created_at','>',$startDay->format('Y-m-d'));
                 $rejectedBillsQueryTem=$rejectedBillsQueryTem->where('logistic_number_return','like','%'.$logistic_number_return.'%');
                 if($rejectedBillsQueryTem->count()==0
-                    ||$rejectedBillsQueryTem->first()['logistic_number_return']==$logistic_number_return){
+                    ||$rejectedBillsQueryTem->get()[0]['logistic_number_return']==$logistic_number_return){
                     $rejectedBillsQuery=$rejectedBillsQuery->where('logistic_number_return',$logistic_number_return);
                 }else{
                     $rejectedBillsQuery=$rejectedBillsQueryTem;
@@ -206,31 +208,40 @@ class RejectedController extends Controller
             $rejectedBillsQueryTem=clone $rejectedBillsQuery;
             $rejectedBillsQueryTem=$rejectedBillsQueryTem->where('created_at','>',$startDay->format('Y-m-d'));
             $rejectedBillsQueryTem=$rejectedBillsQueryTem->where('logistic_number','like','%'.$logistic_number.'%');
+
             if($rejectedBillsQueryTem->count()==0
-                ||$rejectedBillsQueryTem->first()['logistic_number']==$logistic_number){
+                ||$rejectedBillsQueryTem->get()[0]['logistic_number']==$logistic_number){
                 $rejectedBillsQuery=$rejectedBillsQuery->where('logistic_number',$logistic_number);
             }else{
                 $rejectedBillsQuery=$rejectedBillsQueryTem;
             }
         }
+        if ($id_logistic_return){
+            $rejectedBillsQuery=$rejectedBillsQuery->where('id_logistic_return',$id_logistic_return);
+        }
+
         return $rejectedBillsQuery;
     }
 
     /**
      * Show the form for creating a new resource.
      *
-     * @return Response
+     * @return Application|RedirectResponse|Response|Redirector
      */
     public function create()
     {
         if(!Gate::allows('退货管理-录入')){ return redirect(url('/'));}
         $user=Auth::user();
         $owners=Owner::all()->whereIn('id',
-            $user?$user->getPermittingOwnerIdsAttribute():[])->sortBy('name');
+            $user?app('UserService')->getPermittingOwnerIds($user):[])->sortBy('name');
         $logistics=Logistic::all()->sortBy('name');
         $qualityLabels=QualityLabel::all()->sortBy('name');
         $rejectedBills = RejectedBill::query()->orderByDesc('id')->whereIn('id_owner',
-            $user?$user->getPermittingOwnerIdsAttribute():[])->limit(20)->get();
+            $user?app('UserService')->getPermittingOwnerIds($user):[])->limit(20)->get();
+        foreach($rejectedBills as $bill){
+            $bill['is_loaded'] = $bill['is_loaded_null'];
+            $bill['isEditing'] = false;
+        }
         return view('rejected.create',compact('owners','logistics','qualityLabels','rejectedBills'));
     }
 
@@ -238,15 +249,16 @@ class RejectedController extends Controller
      * Store a newly created resource in storage.
      *
      * @param Request $request
-     * @return Response
+     * @return Application|RedirectResponse|Response|Redirector
      */
     public function store(Request $request)
     {
         if(!Gate::allows('退货管理-录入')){ return redirect(url('/'));  }
         $this->validatorCreate($request->all())->validate();
+        app('LogService')->log(__METHOD__,'找不到表','247行');
         $rejected=new Rejected($request->all());
         $rejected->save();
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return redirect('rejected/create')->with('successTip',"成功录入退货信息(退单:{$request->input('logistic_number_return')})");
     }
     public function ajaxCheck(Request $request)
@@ -259,7 +271,7 @@ class RejectedController extends Controller
         if ($re){
             return ['success'=>'true','checked_numbers'=>$rejected['checked_numbers']];
         }
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return ['success'=>'false','fail_info'=>'数据更新失败'];
     }
     public function ajaxCheckAll(Request $request)
@@ -281,7 +293,7 @@ class RejectedController extends Controller
                 return ['success'=>'false','fail_info'=>"数据 {$rejected['id']} 更新失败"];
             }
         });
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return ['success'=>'true','rejecteds'=>$rejecteds];
     }
     public function ajaxFinishAll(Request $request)
@@ -296,7 +308,7 @@ class RejectedController extends Controller
                 return ['success'=>'false','fail_info'=>"数据 {$rejected['id']} 更新失败"];
             }
         });
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return ['success'=>'true'];
     }
     protected function validatorCreate(array $data)
@@ -363,7 +375,7 @@ class RejectedController extends Controller
         $this->validatorUpdate($request->all())->validate();
         $rejected->fill($request->all());
         $rejected->update();
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return redirect('rejected/')->with('successTip',"成功修改退货信息“{$rejected['name']}”!");
     }
 
@@ -377,14 +389,34 @@ class RejectedController extends Controller
     public function destroy(Rejected $rejected)
     {
 //        if(!Gate::allows('退货管理-删除')){ return redirect(url('/'));}
-//        $this->log(__METHOD__,__FUNCTION__,$rejectedBill->toJson(),Auth::user()['id']);
+//        app('LogService')->log(__METHOD__,__FUNCTION__,$rejectedBill->toJson(),Auth::user()['id']);
 //        $items=$rejectedBill->items();
 //        $items->delete();
-//        $this->log(__METHOD__,__FUNCTION__,$items->toJson(),Auth::user()['id']);
+//        app('LogService')->log(__METHOD__,__FUNCTION__,$items->toJson(),Auth::user()['id']);
 //        $re=$rejectedBill->delete();
 //        return ['success'=>$re];
     }
-    public function exportExcel(Request $request)
+    public function export(Request $request){
+        if(!Gate::allows('退货管理-查询')){ return '没有权限';  }
+        if ($request->checkAllSign){
+            $param = $request->input();
+            unset($param["checkAllSign"]);
+        }else{
+            $param = ["id"=>$request->data];
+        }
+        $sql = app('RejectedService')->getSql($param);
+        $post = Http::post(config('go.export.url'),['type'=>'rejected','sql'=>$sql]);
+        if ($post->status() == 500){
+            throw new Exception($post->header("Msg"));
+        }
+        return response($post,200, [
+            "Content-type"=>"application/octet-stream",
+            "Content-Disposition"=>"attachment; filename=退货单列表-".date('ymdHis').'.xlsx',
+        ]);
+    }
+
+
+    /*public function exportExcel(Request $request)
     {
         if(!Gate::allows('退货管理-查询')){ return '没有权限';  }
         ini_set('max_execution_time',2500);
@@ -393,7 +425,7 @@ class RejectedController extends Controller
         $ids=json_decode($ids,true);
         $export=new RejectedExport();
         $export->setIds($ids);
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return Excel::download($export,'退货表'.Carbon::now().'.xlsx');
     }
     public function exportExcelOnFilterParams(Request $request)
@@ -404,17 +436,17 @@ class RejectedController extends Controller
         $filterParams=json_decode($request->input('filterParams'),true);
         $user=Auth::user();
         $rejectedBills=$this->buildFilteredQuery($filterParams)->orderBy('id','desc')->whereIn('id_owner',
-            $user?$user->getPermittingOwnerIdsAttribute():[]);
+            $user?app('UserService')->getPermittingOwnerIds($user):[]);
         if($rejectedBills->count()>RejectedExport::$max){
             $rejectedBills->where('is_finished',false);
         }
         $rejectedBills->get();
         $export=new RejectedExport();
         $export->setRejectedBills($rejectedBills);
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return Excel::download($export,'退货表'.Carbon::now().'.xlsx');
 
-    }
+    }*/
     public function import(Request $request)
     {
         return view('rejected.import');
@@ -435,4 +467,69 @@ class RejectedController extends Controller
             return '<h1 class="text-danger">失败</h1>'.$e->getMessage();
         }
     }
+
+    //analyzeSearch 统计查询 zengjun
+    public function indexAnalyze(Request $request)
+    {
+        if(!Gate::allows('退货管理-查询')){ return redirect(url('/'));  }
+        $paginateParams = $this->getAnalyzeSearchParams($request);
+        $rejectedBills =  RejectedAnalyzeOwner::findBy($paginateParams);
+        $owners = Owner::filterAuthorities()->get();
+        $qualityLabels = QualityLabel::all();
+        return view('rejected.search.analyze',compact('rejectedBills','owners',
+            'paginateParams','qualityLabels'));
+    }
+
+    // 统计查询参数获取 zengjun
+    private function getAnalyzeSearchParams(Request $request)
+    {
+        $searchParams = [
+            'owner_id' => $request->input('owner_id'),
+            'data'=> $request->input('data'),
+            'created_at_start' => $request->input('created_at_start'),
+            'created_at_end' => $request->input('created_at_end')
+        ];
+        return $searchParams;
+    }
+
+    //统计页导出
+    public function exportAnalyze(Request $request){
+        $searchParams = $this->getAnalyzeSearchParams($request);
+        $sql = RejectedAnalyzeOwner::getQuerySQL($searchParams);
+        $post = Http::post(config('go.export.url'),['type'=>'rejectedStatistics','sql'=>$sql]);
+        if ($post->status() == 500){
+            throw new Exception($post->header("Msg"));
+        }
+        return response($post,200, [
+            "Content-type"=>"application/octet-stream",
+            "Content-Disposition"=>"attachment; filename=退货统计记录单-".date('ymdHis').'.xlsx',
+        ]);
+    }
+
+    public function apiGetRejectedByLogisticNumberReturn(Request $request){
+        if(!$request->filled('logisticNumberReturn')){
+            return ['success' => false,'fail_info' => '没有传入对应的参数'];
+        }
+        $rejectedBill =  RejectedBill::with(['items'])->where('logistic_number_return',$request->input('logisticNumberReturn'))->first();
+        if(!$rejectedBill){
+            return ['success' => false,'fail_info' => '没有对应的退回单号,请先录入退件单'];
+        }
+        return ['success'=>true,'rejectedBill' => $rejectedBill];
+    }
+    public function changeRejectedBillRemark(Request $request){
+        if(!Gate::allows('退货管理-编辑备注')){return ['success'=>'false','fail_info'=>'没有权限'];}
+        $id= $request->input('id');
+        $remark = $request->input('remark');
+        if(is_null($id) ){
+            return ['success'=>false,'fail_info'=>'参数异常'];
+        }
+        $rejectedBill=RejectedBill::query()->updateOrCreate([
+            'id'=>$id,
+        ],[
+            'id'=>$id,
+            'remark'=>$remark
+        ]);
+        app('LogService')->log(__METHOD__,'添加或者修改退单备注'.__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        return ['success'=>true,'status'=>$rejectedBill];
+    }
 }

+ 15 - 5
app/Http/Controllers/RoleController.php

@@ -18,10 +18,20 @@ class RoleController extends Controller
      *
      * @return Response
      */
-    public function index()
+    public function index(Request $request)
     {
         if(!Gate::allows('角色-查询')){ return redirect(url('/'));  }
-        $roles=Role::with('authorities')->orderBy('id','desc')->paginate(35);
+        $query = Role::with('authorities');
+/*        if($request->has('user')){
+            $user = $request->input('user');
+            $query->whereHas('users',function($query) use ($user){
+                $query->where('name','like',$user);
+            });
+        }*/
+        if($request->has('role')){
+            $query->where('name','like',$request->input('role'));
+        }
+        $roles= $query->orderBy('id','desc')->paginate(35);
         return view('maintenance.role.index',['roles'=>$roles]);
     }
 
@@ -55,7 +65,7 @@ class RoleController extends Controller
             $role->authorities()->sync($authorityIdArr);
         }
 
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return redirect('maintenance/role/create')->with('successTip',"成功录入角色“{$request->input('name')}”");
     }
     protected function validatorCreate(array $data)
@@ -115,7 +125,7 @@ class RoleController extends Controller
         }else{
             $role->authorities()->sync([]);
         }
-        $this->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,json_encode($request->toArray()),Auth::user()['id']);
         return redirect('maintenance/role/')->with('successTip',"成功修改角色“{$role['name']}”!");
     }
 
@@ -129,7 +139,7 @@ class RoleController extends Controller
     public function destroy(Role $role)
     {
         if(!Gate::allows('角色-删除')){ return redirect(url('/'));  }
-        $this->log(__METHOD__,__FUNCTION__,$role->toJson(),Auth::user()['id']);
+        app('LogService')->log(__METHOD__,__FUNCTION__,$role->toJson(),Auth::user()['id']);
         $re=$role->delete();
         return ['success'=>$re];
     }

+ 85 - 0
app/Http/Controllers/ShopController.php

@@ -0,0 +1,85 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Shop;
+use Illuminate\Http\Request;
+
+class ShopController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function index()
+    {
+        //
+    }
+
+    /**
+     * Show the form for creating a new resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function create()
+    {
+        //
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\Response
+     */
+    public function store(Request $request)
+    {
+        //
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  \App\Shop  $shop
+     * @return \Illuminate\Http\Response
+     */
+    public function show(Shop $shop)
+    {
+        //
+    }
+
+    /**
+     * Show the form for editing the specified resource.
+     *
+     * @param  \App\Shop  $shop
+     * @return \Illuminate\Http\Response
+     */
+    public function edit(Shop $shop)
+    {
+        //
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \App\Shop  $shop
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, Shop $shop)
+    {
+        //
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  \App\Shop  $shop
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(Shop $shop)
+    {
+        //
+    }
+}

+ 85 - 0
app/Http/Controllers/SortingStationController.php

@@ -0,0 +1,85 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\SortingStation;
+use Illuminate\Http\Request;
+
+class SortingStationController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function index()
+    {
+        //
+    }
+
+    /**
+     * Show the form for creating a new resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function create()
+    {
+        //
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\Response
+     */
+    public function store(Request $request)
+    {
+        //
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  \App\SortingStation  $sortingStation
+     * @return \Illuminate\Http\Response
+     */
+    public function show(SortingStation $sortingStation)
+    {
+        //
+    }
+
+    /**
+     * Show the form for editing the specified resource.
+     *
+     * @param  \App\SortingStation  $sortingStation
+     * @return \Illuminate\Http\Response
+     */
+    public function edit(SortingStation $sortingStation)
+    {
+        //
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \App\SortingStation  $sortingStation
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, SortingStation $sortingStation)
+    {
+        //
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  \App\SortingStation  $sortingStation
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(SortingStation $sortingStation)
+    {
+        //
+    }
+}

+ 90 - 0
app/Http/Controllers/StationController.php

@@ -0,0 +1,90 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Station;
+use Illuminate\Http\Request;
+
+class StationController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return void
+     */
+    public function index()
+    {
+
+    }
+    public function monitorIndex()
+    {
+        $stations = Station::query()->with('type:name','parent:name')->whereHas('type',function($query){
+            $query->where('name','料箱监视器');
+        })->paginate(100);
+        return view('station.monitor.index',compact('stations'));
+    }
+
+    /**
+     * Show the form for creating a new resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function create()
+    {
+        //
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\Response
+     */
+    public function store(Request $request)
+    {
+        //
+    }
+
+    public function show(Station $station)
+    {
+        //
+    }
+    public function monitorShow(Station $station)
+    {
+        return view('station.monitor.show',compact('station'));
+    }
+
+    /**
+     * Show the form for editing the specified resource.
+     *
+     * @param  \App\Station  $station
+     * @return \Illuminate\Http\Response
+     */
+    public function edit(Station $station)
+    {
+        //
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \App\Station  $station
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, Station $station)
+    {
+        //
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  \App\Station  $station
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(Station $station)
+    {
+        //
+    }
+}

+ 85 - 0
app/Http/Controllers/StationRuleBatchController.php

@@ -0,0 +1,85 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\StationRuleBatch;
+use Illuminate\Http\Request;
+
+class StationRuleBatchController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function index()
+    {
+        //
+    }
+
+    /**
+     * Show the form for creating a new resource.
+     *
+     * @return \Illuminate\Http\Response
+     */
+    public function create()
+    {
+        //
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return \Illuminate\Http\Response
+     */
+    public function store(Request $request)
+    {
+        //
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param  \App\StationRuleBatch  $stationRuleBatch
+     * @return \Illuminate\Http\Response
+     */
+    public function show(StationRuleBatch $stationRuleBatch)
+    {
+        //
+    }
+
+    /**
+     * Show the form for editing the specified resource.
+     *
+     * @param  \App\StationRuleBatch  $stationRuleBatch
+     * @return \Illuminate\Http\Response
+     */
+    public function edit(StationRuleBatch $stationRuleBatch)
+    {
+        //
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \App\StationRuleBatch  $stationRuleBatch
+     * @return \Illuminate\Http\Response
+     */
+    public function update(Request $request, StationRuleBatch $stationRuleBatch)
+    {
+        //
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param  \App\StationRuleBatch  $stationRuleBatch
+     * @return \Illuminate\Http\Response
+     */
+    public function destroy(StationRuleBatch $stationRuleBatch)
+    {
+        //
+    }
+}

Some files were not shown because too many files changed in this diff