Browse Source

Merge branch 'master' into Haozi

haozi 5 years ago
parent
commit
10fd71dd75
59 changed files with 1970 additions and 619 deletions
  1. 53 0
      app/Console/Commands/BeforeCreateOwnerReport.php
  2. 7 8
      app/Console/Commands/CreateOwnerReport.php
  3. 31 0
      app/Console/Commands/InventoryDailyLoggingOwner.php
  4. 1 0
      app/Console/Commands/LogExpireDelete.php
  5. 4 1
      app/Console/Kernel.php
  6. 16 0
      app/DeliveryAppointment.php
  7. 5 0
      app/DeliveryAppointmentCar.php
  8. 18 1
      app/Http/Controllers/CarTypesController.php
  9. 50 33
      app/Http/Controllers/CustomerController.php
  10. 171 1
      app/Http/Controllers/DeliveryAppointmentController.php
  11. 1 1
      app/Http/Controllers/OrderIssueController.php
  12. 31 9
      app/Http/Controllers/PriceModelController.php
  13. 37 0
      app/Http/Controllers/TaxRateController.php
  14. 156 130
      app/Http/Controllers/TestController.php
  15. 1 1
      app/Http/Controllers/api/thirdPart/flux/WaybillController.php
  16. 1 2
      app/Imports/AppointmentDetail.php
  17. 11 2
      app/Owner.php
  18. 9 1
      app/OwnerReport.php
  19. 4 0
      app/Providers/AppServiceProvider.php
  20. 3 3
      app/Providers/AuthServiceProvider.php
  21. 78 0
      app/Services/DeliveryAppointmentService.php
  22. 16 35
      app/Services/NewOrderCountingRecordService.php
  23. 32 4
      app/Services/OrderIssueService.php
  24. 78 4
      app/Services/OrderService.php
  25. 31 13
      app/Services/OwnerPriceExpressService.php
  26. 80 41
      app/Services/OwnerPriceOperationService.php
  27. 37 0
      app/Services/OwnerService.php
  28. 14 10
      app/Services/OwnerStoragePriceModelService.php
  29. 18 0
      app/TaxRate.php
  30. 2 0
      app/User.php
  31. 1 1
      app/Warehouse.php
  32. 9 0
      config/appointment.php
  33. 31 0
      database/migrations/2021_03_05_105547_add_authority_to_area_report.php
  34. 66 0
      database/migrations/2021_03_06_090856_create_tax_rates_table.php
  35. 36 0
      database/migrations/2021_03_08_170734_change_owner_reports_table.php
  36. 4 4
      package.json
  37. 220 158
      resources/js/queryForm/queryForm.js
  38. 13 1
      resources/sass/text.scss
  39. 35 0
      resources/views/customer/project/_editArea.blade.php
  40. 162 89
      resources/views/customer/project/area.blade.php
  41. 12 3
      resources/views/customer/project/create.blade.php
  42. 12 8
      resources/views/customer/project/index.blade.php
  43. 13 7
      resources/views/customer/project/part/_storage.blade.php
  44. 10 10
      resources/views/customer/project/part/_three.blade.php
  45. 7 5
      resources/views/customer/project/part/_two.blade.php
  46. 4 0
      resources/views/maintenance/menu.blade.php
  47. 23 0
      resources/views/maintenance/taxRate/_edit.blade.php
  48. 88 0
      resources/views/maintenance/taxRate/index.blade.php
  49. 28 0
      resources/views/maintenance/warehouse/create.blade.php
  50. 28 0
      resources/views/maintenance/warehouse/edit.blade.php
  51. 8 1
      resources/views/maintenance/warehouse/index.blade.php
  52. 1 1
      resources/views/package/measureMonitor/index.blade.php
  53. 0 12
      resources/views/store/checkingReceive/_selectDate.blade.php
  54. 1 5
      resources/views/store/checkingReceive/menu.blade.php
  55. 27 0
      resources/views/store/deliveryAppointment/_selectDate.blade.php
  56. 103 12
      resources/views/store/deliveryAppointment/appointment.blade.php
  57. 12 0
      resources/views/store/deliveryAppointment/menu.blade.php
  58. 6 2
      resources/views/store/menu.blade.php
  59. 14 0
      routes/web.php

+ 53 - 0
app/Console/Commands/BeforeCreateOwnerReport.php

@@ -0,0 +1,53 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\OwnerReport;
+use App\Services\OwnerService;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Cache;
+
+class BeforeCreateOwnerReport extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'beforeCreateOwnerReport';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = 'Create owner report in advance and build cache';
+
+
+    /**
+     * Execute the console command.
+     *
+     */
+    public function handle()
+    {
+        /** @var OwnerService $ownerService */
+        $ownerService = app('OwnerService');
+        $chunks = ($ownerService->get([],["ownerStoragePriceModels"],false,true))->chunk(50);
+        foreach ($chunks as $owners){
+            $insert = [];
+            $date = date("Y-m-d");
+            foreach ($owners as $owner){
+                $insert[] = [
+                    "owner_id"       => $owner->id,
+                    "counting_month" => date("Y-m-d"),
+                    "created_at"     => $date
+                ];
+                //B:business C:customer D:date
+                Cache::put(date("Y-m")."|B|".$owner->id,0,2764800);
+                Cache::put(date("Y-m")."|C|".$owner->id,0,2764800);
+                Cache::put(date("Y-m")."|D|".$owner->id,time(),2764800);
+            }
+            OwnerReport::query()->insert($insert);
+        }
+    }
+}

+ 7 - 8
app/Console/Commands/CreateOwnerReport.php

@@ -8,6 +8,7 @@ use App\OwnerReport;
 use App\Services\common\BatchUpdateService;
 use App\Services\LogService;
 use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Cache;
 use Illuminate\Support\Facades\DB;
 
 class CreateOwnerReport extends Command
@@ -82,7 +83,7 @@ class CreateOwnerReport extends Command
                 $historyReportMap[$report->owner_id."_".$report->counting_month] = $report->current_month_counting_area;
                 continue;
             }
-            $reportMap[$report->owner_id."_".$report->counting_month] = $report->id;
+            $reportMap[$report->owner_id."_".$report->counting_month] = $report;
         }
 
         //组装账单记录
@@ -97,20 +98,18 @@ class CreateOwnerReport extends Command
         ]];
         $createReports = [];
         foreach ($areas as $area){
-            $total = $area->owner ? ($map[$area->owner->code] ?? 0) : 0;
-            if ($reportMap[$area->owner_id."_".$area->counting_month] ?? false){
+            $report = $reportMap[$area->owner_id."_".$area->counting_month] ?? false;
+            if ($report){
                 $updateReports[] = [
-                    "id"=>$reportMap[$area->owner_id."_".$area->counting_month],
-                    "total" =>$total,
-                    "daily_average_order_amount"=>round($total / $lastDay,2),
+                    "id"=>$report->id,
+                    "daily_average_order_amount"=>round(($report->to_business_quantity+$report->to_customer_quantity) / $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),
+                "daily_average_order_amount"=>0,
                 "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,

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

@@ -3,7 +3,9 @@
 namespace App\Console\Commands;
 
 use App\CommodityBarcode;
+use App\OwnerAreaReport;
 use App\Services\CommodityService;
+use App\Services\common\BatchUpdateService;
 use App\Services\LogService;
 use Illuminate\Console\Command;
 use App\InventoryDailyLoggingOwner as LoggingOwner;
@@ -96,6 +98,8 @@ class InventoryDailyLoggingOwner extends Command
         }
         //第二个数组作为批量插入使用
         $data = [];
+        //盘点货主记录
+        $inventories = [];
         //遍历第一个数组,此时已经去重完成,直接取对应参数push进data中
         foreach ($inventoryDailyLogs as $inventoryDailyLog){
             //寻找己方库中是否存在对应商品,存在更新其长宽高体积,不存在录入
@@ -141,9 +145,36 @@ class InventoryDailyLoggingOwner extends Command
                 "gross_weight"=>$gross_weight,
                 "depository_id"=>$depository ? $depository->id : null,
             ];
+            if (array_key_exists($commodity['owner_id'],$inventories)){
+                $inventories[$commodity['owner_id']]["volume"] += $volumn_occupied;
+                $inventories[$commodity['owner_id']]["amount"] += $inventoryDailyLog['amount'];
+            }else{
+                $inventories[$commodity['owner_id']] = [
+                    "volume" => $volumn_occupied,
+                    "amount" => $inventoryDailyLog['amount'],
+                ];
+            }
         }
         DB::table('inventory_daily_logs')->insert($data);
         app('LogService')->log(__METHOD__,"同步库存每日记录",json_encode($data));
+        if (count($inventories)>0){
+            $update = [["id","accounting_area"]];
+            $areas = OwnerAreaReport::query()->with("ownerStoragePriceModel.unit")
+                ->whereIn("owner_id",array_keys($inventories))
+                ->where("counting_month",'like',date("Y-m")."%")->get();
+            foreach ($areas as $area){
+                $unit = $area->ownerStoragePriceModel->unit->name ?? null;
+                if ($unit!='m³' || $unit!='件')continue;
+                $update[] = [
+                    "id"              => $area->id,
+                    "accounting_area" => $unit=='m³' ? $inventories[$area->owner_id]["volume"] : $inventories[$area->owner_id]["amount"],
+                ];
+            }
+            if (count($update)>1){
+                app(BatchUpdateService::class)->batchUpdate("owner_area_reports",$update);
+                LogService::log(__CLASS__,"监听货主记录时修改面积报信息",json_encode($inventories));
+            }
+        }
     }
 
     public function getLoggingOwners(){

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

@@ -47,5 +47,6 @@ class LogExpireDelete extends Command
         $expire_duration=config('logging.expire_duration');//保留的日志天数
         $date=Carbon::now()->subDays($expire_duration)->format('Y-m-d');
         DB::table('logs')->where('created_at','<',$date)->delete();
+        DB::statement('OPTIMIZE TABLE logs');
     }
 }

+ 4 - 1
app/Console/Kernel.php

@@ -2,6 +2,7 @@
 
 namespace App\Console;
 
+use App\Console\Commands\BeforeCreateOwnerReport;
 use App\Console\Commands\ClearCancelledOrderTask;
 use App\Console\Commands\CreateWeightStatistic;
 use App\Console\Commands\FluxOrderFix;
@@ -21,7 +22,7 @@ use Illuminate\Console\Scheduling\Schedule;
 use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
 use Illuminate\Foundation\Console\ModelMakeCommand;
 
-class Kernel extends ConsoleKernel
+class  Kernel extends ConsoleKernel
 {
     /**
      * The Artisan commands provided by your application.
@@ -44,6 +45,7 @@ class Kernel extends ConsoleKernel
         ClearCancelledOrderTask::class,
         WasSyncWmsAsnInformation::class,
         CreateWeightStatistic::class,
+        BeforeCreateOwnerReport::class,
     ];
 
     /**
@@ -62,6 +64,7 @@ class Kernel extends ConsoleKernel
         $schedule->command('createOwnerReport')->monthlyOn(1);
         $schedule->command('createOwnerBillReport')->monthlyOn(1);
         $schedule->command('createOwnerAreaReport')->monthlyOn(1);
+        $schedule->command('beforeCreateOwnerReport')->monthlyOn(1);
         $schedule->command('sync:batch')->everyMinute();
         $schedule->command('sync:order')->everyMinute();
         $schedule->command('syncOrderPackageLogisticRouteTask')->dailyAt('1:20');//同步快递信息到orderPackage

+ 16 - 0
app/DeliveryAppointment.php

@@ -24,6 +24,22 @@ class DeliveryAppointment extends Model
         "date_period",
         "status",
     ];
+    //时段 映射date_period字段
+    const PERIOD=[
+        0 => "9-11",
+        1 => "13-17",
+    ];
+    //时长 映射PERIOD常量
+    const HOUR=[
+        0 => 3,
+        1 => 5
+    ];
+    //状态
+    const STATUS=[
+        0 => "待收",
+        1 => "取消",
+        2 => "完成",
+    ];
 
     public function cars()
     {   //车辆

+ 5 - 0
app/DeliveryAppointmentCar.php

@@ -21,6 +21,11 @@ class DeliveryAppointmentCar extends Model
     ];
     public $timestamps=false;
 
+    const STATUS=[
+        0 => "待送",
+        1 => "已送"
+    ];
+
     public function deliveryAppointment()
     {   //预约信息
         return $this->belongsTo(DeliveryAppointment::class);

+ 18 - 1
app/Http/Controllers/CarTypesController.php

@@ -3,14 +3,16 @@
 namespace App\Http\Controllers;
 
 use App\CarType;
+use App\Components\AsyncResponse;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\DB;
 use Illuminate\Support\Facades\Gate;
 use Illuminate\Support\Facades\Validator;
 
 class CarTypesController extends Controller
 {
-
+    use AsyncResponse;
     public function index()
     {
         if(!Gate::allows('车型-查询')){ return redirect(url('/'));  }
@@ -93,4 +95,19 @@ class CarTypesController extends Controller
         ]);
         return $validator;
     }
+
+    public function batchInsert()
+    {
+        $arr = request("arr");
+        if (!$arr)$this->error("非法参数");
+        DB::transaction(function()use($arr){
+            $cars = CarType::query()->whereIn("name",$arr)->lockForUpdate()->get()->toArray();
+            $result = array_diff($arr,array_column($cars,"name"));
+            if ($result){
+                foreach ($result as &$r)$r = ["name"=>$r];
+                CarType::query()->insert($result);
+            }
+        });
+        $this->success(CarType::query()->select("id","name")->whereIn("name",$arr)->get());
+    }
 }

+ 50 - 33
app/Http/Controllers/CustomerController.php

@@ -114,7 +114,7 @@ class CustomerController extends Controller
         if(!Gate::allows('客户管理-项目-查询')){ return redirect('denied');  }
         /** @var OwnerService $service */
         $service = app('OwnerService');
-        $withs = ['customer',"userOwnerGroup","contracts","ownerStoragePriceModels","ownerAreaReport"=>function($query){
+        $withs = ['customer',"userOwnerGroup","contracts","taxRate","ownerStoragePriceModels","ownerAreaReport"=>function($query){
             $month = date('Y-m');
             /** @var Builder $query */
             $query->where("counting_month","like",$month."%");
@@ -129,7 +129,7 @@ class CustomerController extends Controller
         foreach ($owners as $owner){
             $list[] = [
                 $owner->customer ? $owner->customer->name : '',
-                $owner->tax_rate,
+                $owner->taxRate->name ?? '',
                 $owner->name,
                 $owner->code,
                 $owner->created_at,
@@ -180,7 +180,7 @@ class CustomerController extends Controller
         $owner = app('OwnerService')->update($owner,[
             "customer_id"           => request("customer_id"),
             "warehouse_id"          => request("warehouse_id"),
-            "tax_rate"              => request("tax_rate"),
+            "tax_rate_id"           => request("tax_rate_id"),
             "linkman"               => request("linkman"),
             "phone_number"          => request("phone_number"),
             "user_owner_group_id"   => request("owner_group_id"),
@@ -228,7 +228,7 @@ class CustomerController extends Controller
     public function projectArea(Request $request)
     {
         if(!Gate::allows('客户管理-项目-面积')){ return redirect('denied');  }
-        $areas = app('OwnerAreaReportService')->paginate($request->input(),["owner"=>function($query){$query->with(["customer","ownerStoragePriceModels.unit"]);}]);
+        $areas = app('OwnerAreaReportService')->paginate($request->input(),["owner"=>function($query){$query->with(["customer","ownerStoragePriceModels.unit"]);},"userOwnerGroup"]);
         $ownerGroups = app('UserOwnerGroupService')->getSelection();
         $customers = app('CustomerService')->getSelection();
         $owners = app('OwnerService')->getIntersectPermitting();
@@ -236,27 +236,35 @@ class CustomerController extends Controller
         return response()->view('customer.project.area',compact("areas","ownerGroups","customers","owners","params"));
     }
 
-    public function updateArea(Request $request)
+    public function updateArea()
     {
-        if(!Gate::allows('客户管理-项目-面积-编辑')){ return ["success"=>false,'data'=>"无权操作!"];  }
-        if (!($request->id ?? false) || !($request->area ?? false)) return ["success"=>false,'data'=>"传递错误!"];
-
-        if (!request("accounting_area")){
-            $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"]*2.5) + ((int)$values["area_on_half_tray"]*1.8) + ((int)$values["area_on_flat"]*1.3);
-            $values["accounting_area"] = $accounting_area;
-        }else $values = ["accounting_area"=>request("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."条数据!"];
+        $this->gate("客户管理-项目-面积-编辑");
+        if (!request("id")) $this->error("非法参数");
+
+        $total = ((int)request("areaOnTray")*2.5) +
+            ((int)request("areaOnHalfTray")*1.8) + ((int)request("areaOnFlat")*1.3);
+        $obj = [
+            "user_owner_group_id" => request("ownerGroupId"),
+            "area_on_tray" => request("areaOnTray"),
+            "area_on_half_tray" => request("areaOnHalfTray"),
+            "area_on_flat" => request("areaOnFlat"),
+            "accounting_area" => intval($total*1000)/1000,
+        ];
+        app('OwnerAreaReportService')->update(["id"=>request("id")],$obj);
+        $this->success($obj);
+    }
+
+    //面积报表审核
+    public function areaReportAudit()
+    {
+        $this->gate("客户管理-项目-用仓盘点-审核");
+        $id = request("id");
+        if(!$id)$this->error("非法参数");
+        $area = OwnerAreaReport::query()->find($id);
+        /** @var \stdClass $area */
+        if (!$area || $area->status!='编辑中')$this->error("记录已被操作");
+        $area->update(["status"=>"已审核"]);
+        $this->success();
     }
 
     public function projectAreaExport(Request $request)
@@ -396,16 +404,25 @@ class CustomerController extends Controller
         return ["success"=>true,"data"=>$date];
     }
 
-    public function billConfirm(Request $request)
+    public function billConfirm()
     {
-        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"=>"是"]);
+        $this->gate("结算管理-账单确认-完结");
+        if (!request("id"))$this->error("非法参数");
+
+        /** @var OwnerBillReport $bill */
+        $bill =  app('OwnerBillReportService')->first(["id"=>request("id"),"confirmed"=>"否"]);
+
+        if (!$bill)$this->error("账单状态变更,禁止操作");
+        /** @var \stdClass $bill */
+        $area = OwnerAreaReport::query()->where("owner_id",$bill->owner_id)
+            ->where("counting_month","like",$bill->counting_month."%")->first();
+        if (!$area || $area->status!='编辑中')$this->error("对应面积报表状态异常");
+        $bill->update(["confirmed"=>"是"]);
+
+        LogService::log(__METHOD__,"客户管理-确认账单",json_encode(request()->input()));
         app('OwnerAreaReportService')->lockArea(null, $bill->owner_id, $bill->counting_month);
         LogService::log(__METHOD__,"客户管理-锁定账单的所有面积",json_encode($bill,JSON_UNESCAPED_UNICODE));
-        return ["success"=>true];
+        $this->success();
     }
 
     private function validator(array $params){
@@ -414,7 +431,7 @@ class CustomerController extends Controller
             'customer_id'=>['required'],
             'owner_group_id'=>['required'],
             'warehouse_id'=>['required'],
-            'tax_rate' => ["nullable",'numeric'],
+            'tax_rate_id' => ["required",'integer'],
             'waring_line_on' => ["nullable",'integer'],
         ],[
             'required'=>':attribute 为必填项',
@@ -426,7 +443,7 @@ class CustomerController extends Controller
             'warehouse_id'=>'仓库',
             'customer_id'=>'客户',
             'owner_group_id'=>'工作组',
-            'tax_rate' => '税率',
+            'tax_rate_id' => '税率',
             'waring_line_on' => '月单量预警'
         ]);
         return $validator;

+ 171 - 1
app/Http/Controllers/DeliveryAppointmentController.php

@@ -2,8 +2,20 @@
 
 namespace App\Http\Controllers;
 
+use App\CarType;
+use App\CommodityBarcode;
 use App\Components\AsyncResponse;
+use App\DeliveryAppointment;
+use App\DeliveryAppointmentCar;
+use App\DeliveryAppointmentDetail;
 use App\Imports\AppointmentDetail;
+use App\Warehouse;
+use Carbon\Carbon;
+use Carbon\CarbonPeriod;
+use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Validator;
 
 class DeliveryAppointmentController extends Controller
 {
@@ -11,11 +23,169 @@ class DeliveryAppointmentController extends Controller
     public function appointment()
     {
         $owners = app("OwnerService")->getIntersectPermitting();
-        return view("store.checkingReceive.appointment",compact("owners"));
+        $cars = CarType::query()->get();
+        $warehouses = Warehouse::query()->select("id","name")->get();
+        return view("store.deliveryAppointment.appointment",compact("owners","cars","warehouses"));
     }
 
     public function import()
     {
         $this->importExcel(new AppointmentDetail());
     }
+
+    /**
+     * 获取产能
+     *
+     */
+    public function getCapacity()
+    {
+        /** @var \stdClass $warehouse */
+        $warehouse = Warehouse::query()->find(request("warehouse_id"));
+        $tonne = request("tonne");
+        $cubicMeter = request("cubic_meter");
+        $amount = request("detail_amount");
+        if (!$warehouse || (!$tonne && !$cubicMeter))$this->error("非法参数");
+        $need = app("DeliveryAppointmentService")->calculateCapacity($tonne,$cubicMeter,$amount,$warehouse->reduced_production_capacity_coefficient);//所需产能
+        $start = Carbon::tomorrow();
+        $end = Carbon::today()->addDays(7);
+        $map = [];
+        DeliveryAppointment::query()->selectRaw("appointment_date,date_period,SUM(capacity) AS capacity")
+            ->whereBetween("appointment_date",[$start->toDateString(),$end->toDateString()])
+            ->where("status",0)
+            ->where("warehouse_id",$warehouse->id)
+            ->groupBy(["appointment_date","date_period"])->get()
+            ->each(function ($appointment)use(&$map){
+                $map[$appointment->appointment_date."-".$appointment->date_period] = $appointment->capacity;
+            });
+        $list = [];
+        $capacity = $warehouse->production_capacity;
+        foreach (CarbonPeriod::create($start,$end) as $date){
+            /** @var $date Carbon */
+            $date = $date->format("Y-m-d");
+            $periods = [];
+            foreach (DeliveryAppointment::PERIOD as $key=>$period){
+                $total = $capacity*DeliveryAppointment::HOUR[$key];//仓库该时段产能总量
+                $used = $map[$date."-".$key] ?? 0; //已使用产能
+                $available = $total-$used; //可用产能
+                if ($available < $need)$periods[] = ["time"=>$period,"index"=>$key,"isAvailable"=>false];
+                else $periods[] = ["time"=>$period,"index"=>$key,"isAvailable"=>true];
+            }
+            $list[] = ["date"=>$date,"period"=>$periods];
+        }
+        $this->success($list);
+    }
+
+    /**
+     * 确定预约
+     */
+    public function submitAppointment()
+    {
+        $model = request("model");
+        $selectDate = request("selectDate");
+        $details = request("details");
+        $errors = Validator::make($model,[
+            "owner_id" => ["required","integer"],
+            "warehouse_id" => ["required","integer"],
+            "tonne" => ["required_without:cubic_meter","numeric"],
+            "cubic_meter" => ["required_without:tonne","numeric"],
+            "box_amount" => ["nullable","integer"],
+            "cars.*.license_plate_number" => ["required","size:7"],
+            "cars.*.car_id" => ["nullable","integer"],
+            "cars.*.driver_phone" => ["nullable"],
+            "cars.*.driver_name" => ["nullable"],
+        ],[
+            'required'=>':attribute 不应为空',
+            'integer'=>':attribute 应为数值',
+            'required_without'=>':attribute 不应为空',
+            'numeric'=>':attribute 必须为数字',
+            'size'=>':attribute 非法',
+        ],[
+            'owner_id'=>'货主',
+            'warehouse_id'=>'仓库',
+            'tonne'=>'吨',
+            'cubic_meter'=>'立方',
+            'cars.*.license_plate_number'=>'车牌号',
+            'cars.*.car_id'=>'车型',
+            'cars.*.driver_phone'=>'司机电话',
+            'cars.*.driver_name'=>'司机姓名',
+        ])->errors();
+        if (count($errors)>0)$this->success(["errors"=>$errors]);
+        $errors = Validator::make($selectDate,[
+            "date" => ["required","date","after:today"],
+            "time" => ["required","integer"],
+        ])->errors();
+        if (count($errors)>0)$this->error("未选定预约日期");
+
+        DB::transaction(function ()use($model,$selectDate,$details){
+            $result = DeliveryAppointment::query()->selectRaw("appointment_date,date_period,SUM(capacity) AS capacity")
+                ->where("appointment_date",$selectDate["date"])
+                ->where("date_period",$selectDate["time"])
+                ->where("warehouse_id",$model["warehouse_id"])
+                ->where("status",0)
+                ->groupBy(["appointment_date","date_period"])
+                ->lockForUpdate()->first();
+            /** @var \stdClass $warehouse */
+            $warehouse = Warehouse::query()->find($model["warehouse_id"]);
+            $need = app("DeliveryAppointmentService")->
+            calculateCapacity($model["tonne"],$model["cubic_meter"],count($details),
+                $warehouse->reduced_production_capacity_coefficient);
+            if ($result){
+                $total = $warehouse->production_capacity*DeliveryAppointment::HOUR[$selectDate["time"]];
+                $available = $total-$result->capacity;
+                if ($available < $need)$this->success(["isFail"=>false]);
+            }
+            /** @var \stdClass $appointment */
+            $appointment = DeliveryAppointment::query()->create([
+                "user_id"               => Auth::id(),
+                "owner_id"              => $model["owner_id"],
+                "procurement_number"    => $model["procurement_number"],
+                "asn_number"            => $model["asn_number"],
+                "warehouse_id"          => $model["warehouse_id"],
+                "tonne"                 => $model["tonne"],
+                "cubic_meter"           => $model["cubic_meter"],
+                "box_amount"            => $model["box_amount"],
+                "capacity"              => $need,
+                "appointment_date"      => $selectDate["date"],
+                "date_period"           => $selectDate["time"],
+            ]);
+            if ($details)app("DeliveryAppointmentService")->insertDetails($appointment,$details);
+            $insert = [];
+            foreach ($model["cars"] as $index=>$car){
+                $rand = mt_rand(0,9);
+                $len = strlen($appointment->id);
+                $ten = $len < 2 ? "0" : substr($appointment->id,$len-2,1);
+                $one = substr($appointment->id,$len-1,1);
+                //唯一码 随机数+十位+当前下标+个位+日期
+                $number = $rand.$ten.$index.$one.date("d");
+                $insert[] = [
+                    "delivery_appointment_id" => $appointment->id,
+                    "license_plate_number"    => $car["license_plate_number"],
+                    "car_id"                  => $car["car_id"],
+                    "driver_name"             => $car["driver_name"],
+                    "driver_phone"            => $car["driver_phone"],
+                    "appointment_number"      => $number,
+                ];
+            }
+            DeliveryAppointmentCar::query()->insert($insert);
+            //md5加密在密文第五位后插入
+            $md5 = substr_replace(md5(date("m-d")),$appointment->id,5,0);
+            $this->success(["key"=>$md5]);
+        });
+    }
+
+    /**
+     * 根据key取id 鉴权数据
+     */
+    public function showAppointmentInfo()
+    {
+        $key = request("k");
+        $len = strlen($key);
+        $id = substr($key,5,$len-32);
+        $md5 = substr($id,0,5).substr($id,5+$len-32);
+        if ($md5!==md5(date("m-d")))return "错误";
+        /** @var \stdClass $appointment */
+        $appointment = DeliveryAppointment::query()->with("cars")->find($id);
+        if (!$appointment || $appointment->user_id != Auth::id())return "错误";
+        return $appointment->cars;
+    }
 }

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

@@ -616,7 +616,7 @@ class OrderIssueController extends Controller
             $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";
+                isset($log->user->name) ? $log_user.=$log->user->name.",\r\n" : null;
             });
             $send_order = $order_issue->secondOrder ??  new Order();
             $send_order_numbers = '';$send_order_sku ='';$send_order_name ='';$send_order_amount = '';

+ 31 - 9
app/Http/Controllers/PriceModelController.php

@@ -83,7 +83,9 @@ class PriceModelController extends Controller
         ]);
         $model = new OwnerStoragePriceModel();
         $model->id = $request->input("id");
-        $model->owners()->sync(explode(",",$request->input("owner_id")));
+        $result = $model->owners()->sync(explode(",",$request->input("owner_id")));
+        app("OwnerService")->refreshRelevance($result["attached"],0);
+        app("OwnerService")->refreshRelevance($result["detached"],0,true);
         LogService::log(__METHOD__,"计费模型-修改仓储计费",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
         return response()->redirectTo('maintenance/priceModel/storage')->with('successTip',"更新成功!");
     }
@@ -293,7 +295,11 @@ class PriceModelController extends Controller
         }
         //录入中间表
         /** @var OwnerPriceOperation $ownerPriceOperation */
-        if ($request->input("owner_id"))$ownerPriceOperation->ownerPriceOperationOwners()->sync($request->input("owner_id"));
+        if ($request->input("owner_id")){
+            $result = $ownerPriceOperation->ownerPriceOperationOwners()->sync($request->input("owner_id"));
+            app("OwnerService")->refreshRelevance($result["attached"],1);
+            app("OwnerService")->refreshRelevance($result["detached"],1,true);
+        }
         LogService::log(__METHOD__,"计费模型-录入作业计费",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
         return response()->redirectTo("maintenance/priceModel/operation")->with("successTip","创建“".$request->input("name")."”成功");
     }
@@ -347,7 +353,11 @@ class PriceModelController extends Controller
         }
         //录入中间表
         /** @var OwnerPriceOperation $model */
-        if ($request->input("owner_id"))$model->ownerPriceOperationOwners()->sync($request->input("owner_id"));
+        if ($request->input("owner_id")){
+            $result = $model->ownerPriceOperationOwners()->sync($request->input("owner_id"));
+            app("OwnerService")->refreshRelevance($result["attached"],1);
+            app("OwnerService")->refreshRelevance($result["detached"],1,true);
+        }
         LogService::log(__METHOD__,"计费模型-修改作业计费",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
         return response()->redirectTo("maintenance/priceModel/operation")->with("successTip","修改“".$request->input("name")."”成功");
     }
@@ -480,7 +490,9 @@ class PriceModelController extends Controller
             "initial_weight" => $request->input("initial_weight"),
             "additional_weight" => $request->input("additional_weight"),
         ]);
-        $model->owners()->sync($request->input("owner_id"));
+        $result = $model->owners()->sync($request->input("owner_id"));
+        app("OwnerService")->refreshRelevance($result["attached"],2);
+        app("OwnerService")->refreshRelevance($result["detached"],2,true);
         $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")."”成功");
@@ -510,7 +522,9 @@ class PriceModelController extends Controller
         ]);
         $model = new OwnerPriceExpress();
         $model->id = $id;
-        $model->owners()->sync($request->input("owner_id"));
+        $result = $model->owners()->sync($request->input("owner_id"));
+        app("OwnerService")->refreshRelevance($result["attached"],2);
+        app("OwnerService")->refreshRelevance($result["detached"],2,true);
         $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")."”成功");
@@ -588,7 +602,9 @@ class PriceModelController extends Controller
             "other_unit_id" => $request->input("other_unit_id"),
             "other_unit_range" => $request->input("other_unit_range"),
         ]);
-        $model->owners()->sync($request->input("owner_id"));
+        $result = $model->owners()->sync($request->input("owner_id"));
+        app("OwnerService")->refreshRelevance($result["attached"],3);
+        app("OwnerService")->refreshRelevance($result["detached"],3,true);
         $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")."”成功");
@@ -622,7 +638,9 @@ class PriceModelController extends Controller
         ]);
         $model = new OwnerPriceLogistic();
         $model->id = $id;
-        $model->owners()->sync($request->input("owner_id"));
+        $result = $model->owners()->sync($request->input("owner_id"));
+        app("OwnerService")->refreshRelevance($result["attached"],3);
+        app("OwnerService")->refreshRelevance($result["detached"],3,true);
         $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")."”成功");
@@ -876,7 +894,9 @@ class PriceModelController extends Controller
             "name" => $request->input("name"),
             "base_km" => $request->input("base_km"),
         ]);
-        $model->owners()->sync($request->input("owner_id"));
+        $result = $model->owners()->sync($request->input("owner_id"));
+        app("OwnerService")->refreshRelevance($result["attached"],4);
+        app("OwnerService")->refreshRelevance($result["detached"],4,true);
         LogService::log(__METHOD__,"计费模型-录入直发车计费",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
         return response()->redirectTo("maintenance/priceModel/directLogistic")->with("successTip","创建“".$request->input("name")."”成功");
     }
@@ -911,7 +931,9 @@ class PriceModelController extends Controller
         ]);
         $model = new OwnerPriceDirectLogistic();
         $model->id = $id;
-        $model->owners()->sync($request->input("owner_id"));
+        $result = $model->owners()->sync($request->input("owner_id"));
+        app("OwnerService")->refreshRelevance($result["attached"],4);
+        app("OwnerService")->refreshRelevance($result["detached"],4,true);
         LogService::log(__METHOD__,"计费模型-修改直发车计费",json_encode($request->input(),JSON_UNESCAPED_UNICODE));
         return response()->redirectTo("maintenance/priceModel/directLogistic")->with("successTip","修改“".$request->input("name")."”成功");
     }

+ 37 - 0
app/Http/Controllers/TaxRateController.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Components\AsyncResponse;
+use App\TaxRate;
+
+class TaxRateController extends Controller
+{
+    use AsyncResponse;
+    public function get()
+    {
+        return TaxRate::query()->get();
+    }
+
+    public function index()
+    {
+        $taxRates = TaxRate::query()->orderByDesc("id")->paginate(50);
+        return view("maintenance.taxRate.index",compact("taxRates"));
+    }
+
+    public function save()
+    {
+        $this->gate("税率-编辑");
+        $value = request("value");
+        if (!is_numeric($value) || $value>=100)$this->error("非法值");
+        if (request("id"))$taxRate = TaxRate::query()->where("id",request("id"))->update(["value"=>$value]);
+        else $taxRate = TaxRate::query()->create(["value"=>$value]);
+        $this->success($taxRate);
+    }
+
+    public function destroy()
+    {
+        $this->gate("税率-删除");
+        $this->success(TaxRate::destroy(request("id")));
+    }
+}

+ 156 - 130
app/Http/Controllers/TestController.php

@@ -6,6 +6,7 @@ namespace App\Http\Controllers;
 use App\Authority;
 use App\Batch;
 use App\Carrier;
+use App\CarType;
 use App\City;
 use App\Commodity;
 use App\CommodityBarcode;
@@ -16,6 +17,7 @@ use App\Console\Commands\SyncBatchTask;
 use App\Console\Commands\SyncWmsCommoditiesInformation;
 use App\Console\Commands\SyncWMSOrderTask;
 use App\Console\Commands\WasSyncWmsAsnInformation;
+use App\DeliveryAppointment;
 use App\Exceptions\ErrorException;
 use App\Events\CancelOrder;
 use App\Events\SendEmailEvent;
@@ -55,6 +57,8 @@ use App\OwnerFeeDetail;
 use App\OwnerFeeDetailLogistic;
 use App\OwnerPriceOperation;
 use App\OwnerPriceOperationItem;
+use App\OwnerReport;
+use App\OwnerStoragePriceModel;
 use App\Package;
 use App\Process;
 use App\ProcessDaily;
@@ -147,32 +151,39 @@ class TestController extends Controller
 
     public function bindOrder()
     {
-        ini_set('max_execution_time',2500);
-        ini_set('memory_limit','1526M');
-        $models = Waybill::query()->whereNotNull("wms_bill_number")->whereNotIn("status",['已完结','无模型'])->get();
-        foreach ($models as $model){
-            $order = Order::query()->where("code",$model->wms_bill_number)->first();
-            if ($order)$model->update(["order_id"=>$order->id]);
+        ini_set('max_execution_time', 2500);
+        ini_set('memory_limit', '1526M');
+        $models = Waybill::query()->whereNotNull("wms_bill_number")->whereNotIn("status", ['已完结', '无模型'])->get();
+        foreach ($models as $model) {
+            $order = Order::query()->where("code", $model->wms_bill_number)->first();
+            if ($order) $model->update(["order_id" => $order->id]);
         }
     }
+
     public function delRegion()
     {
-        dd(Region::query()->where("id",">=",404)->where("id","<=",432)->delete());
+        dd(Region::query()->where("id", ">=", 404)->where("id", "<=", 432)->delete());
     }
     public function tt1(){
-        $order = Order::query()->find(2301382);
-        app("OrderService")->createInstantBill($order);
+        $logistics = [1,2,3];
+        $logisticSql = "(''";
+        foreach ($logistics as $logistic)$logisticSql.=",".$logistic;
+        $logisticSql .= ")";
+        $sql = "SELECT COUNT(1) c FROM orders WHERE logistic_id IN {$logisticSql} AND wms_status = ? AND wms_edittime BETWEEN ? AND ?";
+        dd($sql);
     }
-    public function zzd(){
-        ini_set('max_execution_time',2500);
-        ini_set('memory_limit','1526M');
+
+    public function zzd()
+    {
+        ini_set('max_execution_time', 2500);
+        ini_set('memory_limit', '1526M');
         $menus = [
-            "A管理"=>[
-                "A二级"=>[
+            "A管理" => [
+                "A二级" => [
                     "A三级"
                 ]
             ],
-            "B管理"=>[]
+            "B管理" => []
         ];
         /*$authorities = [
             "A管理"=>[
@@ -188,10 +199,10 @@ class TestController extends Controller
     public function syncWeight()
     {
         $pack = OrderPackageCountingRecord::query()->get();
-        foreach ($pack as $p){
+        foreach ($pack as $p) {
             $yesterday = $p->targeted_at;
-            Cache::pull("weight.".$yesterday);
-            OrderPackageCountingRecord::query()->where("targeted_at",$yesterday)->delete();
+            Cache::pull("weight." . $yesterday);
+            OrderPackageCountingRecord::query()->where("targeted_at", $yesterday)->delete();
             $sql = <<<sql
 SELECT DATE_FORMAT(order_packages.created_at,'%Y-%m-%d') date,
 SUM(CASE WHEN order_packages.weighed_at IS NOT NULL THEN 1 ELSE 0 END) AS count,
@@ -199,47 +210,47 @@ COUNT(1) total FROM order_packages LEFT JOIN orders ON order_packages.order_id=o
 AND order_packages.created_at BETWEEN '{$yesterday} 00:00:00' AND '{$yesterday} 23:59:59' GROUP BY date
 sql;
             $result = DB::selectOne(DB::raw($sql));
-            if (!$result)$obj = [
-                "targeted_at"    => $yesterday,
+            if (!$result) $obj = [
+                "targeted_at" => $yesterday,
                 "un_weigh_count" => 0,
-                "total_count"    => 0
+                "total_count" => 0
             ]; else $obj = [
-                "targeted_at"    => $result->date,
+                "targeted_at" => $result->date,
                 "un_weigh_count" => $result->count,
-                "total_count"    => $result->total,
+                "total_count" => $result->total,
             ];
             /** @var \stdClass $model */
             $model = OrderPackageCountingRecord::query()->create($obj);
-            Cache::put("weight.".$yesterday,[
-                "date"=>$yesterday,
-                "total"=>$model->total_count,
-                "count"=>$model->un_weigh_count,
-                "value"=>$model->total_count ? intval(($model->un_weigh_count/$model->total_count)*100) : 0
+            Cache::put("weight." . $yesterday, [
+                "date" => $yesterday,
+                "total" => $model->total_count,
+                "count" => $model->un_weigh_count,
+                "value" => $model->total_count ? intval(($model->un_weigh_count / $model->total_count) * 100) : 0
             ]);
         }
     }
 
     public function sync()
     {
-        ini_set('max_execution_time',2500);
-        ini_set('memory_limit','1526M');
-        foreach (Batch::query()->with("orders")->where("created_at",">","2021-01-20 15:00:00")->get() as $batch){
+        ini_set('max_execution_time', 2500);
+        ini_set('memory_limit', '1526M');
+        foreach (Batch::query()->with("orders")->where("created_at", ">", "2021-01-20 15:00:00")->get() as $batch) {
             $order = [];
             $map = [];
-            foreach ($batch->orders as $o){
+            foreach ($batch->orders as $o) {
                 $order[] = $o->code;
                 $map[$o->code] = $o->id;
             }
             $sql = <<<sql
 SELECT ORDERNO,WAVENO,SEQNO,EDITTIME FROM DOC_WAVE_DETAILS WHERE WAVENO = ? AND ORDERNO IN (''
 sql;
-            foreach($order as $o){
-                $sql .= ",'".$o."'";
+            foreach ($order as $o) {
+                $sql .= ",'" . $o . "'";
             }
             $sql .= ")";
-            $re = DB::connection("oracle")->select(DB::raw($sql),[$batch->code]);
-            foreach ($re as $r){
-               OrderBin::query()->firstOrCreate([
+            $re = DB::connection("oracle")->select(DB::raw($sql), [$batch->code]);
+            foreach ($re as $r) {
+                OrderBin::query()->firstOrCreate([
                     'order_id' => $map[$r->orderno],
                     'number' => $r->seqno,
                 ]);
@@ -360,7 +371,7 @@ sql;
     function t1(Request $request)
     {
 
-        $re=OracleDOCWaveDetails::query()->where('orderno', 'SO201230003574')->get('seqno')->first()['seqno'];
+        $re = OracleDOCWaveDetails::query()->where('orderno', 'SO201230003574')->get('seqno')->first()['seqno'];
         dd($re);
     }
 
@@ -1084,7 +1095,7 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
 
     public function reNewBatches3()
     {
-        $batches = Batch::query()->where('id','>', 84301)->get('code');
+        $batches = Batch::query()->where('id', '>', 84301)->get('code');
         $batchCodes = $batches->map(function ($batch) {
             return $batch['code'];
         })->toArray();
@@ -1129,7 +1140,6 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
     }
 
 
-
     public function testSyncOrderTask()
     {
         Cache::flush();
@@ -1165,8 +1175,6 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
     }
 
 
-
-
     public function testUpdateSkuNameBarcodeToCommodity_id()
     {
         $amount = 1000;
@@ -1234,7 +1242,7 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
 //        dump('hendle...');
         dump((string)Carbon::now());
 //        dump(memory_get_usage() / 1024 / 1024);
-        $task=new WasSyncWmsAsnInformation();
+        $task = new WasSyncWmsAsnInformation();
         $task->handle();
         dump((string)Carbon::now());
 //        dump('hendle...end');
@@ -1245,8 +1253,8 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
 
     public function editOrderSyncAt()
     {
-        ValueStore::query()->where('name','order_last_created_sync_at')->update(['value'=>'2020-12-22 09:00:00']);
-        ValueStore::query()->where('name','order_last_updated_sync_at')->update(['value'=>'2020-12-22 09:00:00']);
+        ValueStore::query()->where('name', 'order_last_created_sync_at')->update(['value' => '2020-12-22 09:00:00']);
+        ValueStore::query()->where('name', 'order_last_updated_sync_at')->update(['value' => '2020-12-22 09:00:00']);
     }
 
     public function syncOrderTrackingTask()
@@ -1257,7 +1265,7 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
         $orderNos = OracleDOCOrderHeader::query()->selectRaw('orderno')
             ->where('addTime', '>=', $start_data)
             ->where('addTime', '<=', $end_data)
-            ->get()->map(function($orderHeader){
+            ->get()->map(function ($orderHeader) {
                 return $orderHeader->orderno;
             });
         $order_no_list = $orderNos->chunk(3000);
@@ -1293,7 +1301,7 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
         $orderNos = OracleDOCOrderHeader::query()->selectRaw('orderno')
             ->where('addTime', '>=', $start_data)
             ->where('addTime', '<=', $end_data)
-            ->get()->map(function($orderHeader){
+            ->get()->map(function ($orderHeader) {
                 return $orderHeader->orderno;
             });
         $order_no_list = $orderNos->chunk(3000);
@@ -1337,18 +1345,18 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
             foreach ($orderIssue_delete as $key => $order_issue) {
                 if ($order_issue->id == $order_issue_unique->id) continue;
                 $ids[] = $order_issue->id;
-                if($order_issue['logistic_number_return'])$order_issue_unique['logistic_number_return'] =$order_issue['logistic_number_return'];
-                if($order_issue['rejecting_status']!='未退回')$order_issue_unique['rejecting_status'] =$order_issue['rejecting_status'];
-                if($order_issue['is_new_rejecting']!='无')$order_issue_unique['is_new_rejecting'] =$order_issue['is_new_rejecting'];
-                if($order_issue['user_workgroup_id'])$order_issue_unique['user_workgroup_id'] =$order_issue['user_workgroup_id'];
-                if($order_issue['imported_status']!='正常')$order_issue_unique['imported_status'] =$order_issue['imported_status'];
-                if($order_issue['custom_code'])$order_issue_unique['custom_code'] =$order_issue['custom_code'];
+                if ($order_issue['logistic_number_return']) $order_issue_unique['logistic_number_return'] = $order_issue['logistic_number_return'];
+                if ($order_issue['rejecting_status'] != '未退回') $order_issue_unique['rejecting_status'] = $order_issue['rejecting_status'];
+                if ($order_issue['is_new_rejecting'] != '无') $order_issue_unique['is_new_rejecting'] = $order_issue['is_new_rejecting'];
+                if ($order_issue['user_workgroup_id']) $order_issue_unique['user_workgroup_id'] = $order_issue['user_workgroup_id'];
+                if ($order_issue['imported_status'] != '正常') $order_issue_unique['imported_status'] = $order_issue['imported_status'];
+                if ($order_issue['custom_code']) $order_issue_unique['custom_code'] = $order_issue['custom_code'];
             }
             $order_issue_unique->save();
             app('LogService')->log(__METHOD__, __FUNCTION__, '修改OrderIssue:' . json_encode($order_issue_unique));
-            $orderIssues = OrderIssue::query()->whereIn('id',$ids)->get();
-            $bool = OrderIssue::query()->whereIn('id',$ids)->forceDelete();
-            if($bool)app('LogService')->log(__METHOD__, __FUNCTION__, '删除OrderIssue:' . json_encode($orderIssues));
+            $orderIssues = OrderIssue::query()->whereIn('id', $ids)->get();
+            $bool = OrderIssue::query()->whereIn('id', $ids)->forceDelete();
+            if ($bool) app('LogService')->log(__METHOD__, __FUNCTION__, '删除OrderIssue:' . json_encode($orderIssues));
         }
     }
 
@@ -1356,49 +1364,50 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
     {
         /** @var OrderTrackingService $service */
         $service = app(OrderTrackingService::class);
-        $maxId= \App\OrderTracking::query()->orderByDesc('id')->first();
-        $orderTracking_min = \App\OrderTracking::query()->where('logistic_id',0)->orderBy('id')->first();
-         if(!$maxId)return;
+        $maxId = \App\OrderTracking::query()->orderByDesc('id')->first();
+        $orderTracking_min = \App\OrderTracking::query()->where('logistic_id', 0)->orderBy('id')->first();
+        if (!$maxId) return;
         $maxId = $maxId->id;
-        $minId= $orderTracking_min->id;
-        $logistic = \App\Logistic::query()->where('name','新杰物流')->first();
-        $logistic_zt = \App\Logistic::query()->where('name','自提')->first();
-        for ($i=$minId;$i<= $maxId;$i+=100){
+        $minId = $orderTracking_min->id;
+        $logistic = \App\Logistic::query()->where('name', '新杰物流')->first();
+        $logistic_zt = \App\Logistic::query()->where('name', '自提')->first();
+        for ($i = $minId; $i <= $maxId; $i += 100) {
             $orderTrackings = \App\OrderTracking::query()
-                ->where('id','>=',$i)
-                ->where('id','<=',$i+100)
-                ->where('logistic_id','=',0)
-                ->where('created_at','!=','0000-00-00 00:00:00')
+                ->where('id', '>=', $i)
+                ->where('id', '<=', $i + 100)
+                ->where('logistic_id', '=', 0)
+                ->where('created_at', '!=', '0000-00-00 00:00:00')
                 ->get();
-            if($orderTrackings->count() ==0) continue;
-            $update_params = [['id','logistic_id']];
-            $orderTrackings->each(function($orderTracking)use($logistic_zt,$logistic,&$update_params){
-                $order =$orderTracking->commodities->package->order;
+            if ($orderTrackings->count() == 0) continue;
+            $update_params = [['id', 'logistic_id']];
+            $orderTrackings->each(function ($orderTracking) use ($logistic_zt, $logistic, &$update_params) {
+                $order = $orderTracking->commodities->package->order;
                 $logistic_id = $order->logistic_id;
-                if($logistic_id!=null){
-                    if($order->logistic_id == $logistic_zt->id)$logistic_id = $logistic->id;
-                    if($logistic_id==0)dd($order,$logistic_id);
+                if ($logistic_id != null) {
+                    if ($order->logistic_id == $logistic_zt->id) $logistic_id = $logistic->id;
+                    if ($logistic_id == 0) dd($order, $logistic_id);
                     $update_params[] = [
                         'id' => $orderTracking->id,
                         'logistic_id' => $logistic_id,
                     ];
                 }
             });
-            if(count($update_params) > 1){
+            if (count($update_params) > 1) {
                 $service->batchUpdate($update_params);
             }
         }
     }
 
-    public function testHz(){
-        dump('start'.Carbon::now()->toDateTimeString());
-        $ownerAreaReportTask=new CreateOwnerAreaReport();
+    public function testHz()
+    {
+        dump('start' . Carbon::now()->toDateTimeString());
+        $ownerAreaReportTask = new CreateOwnerAreaReport();
         $ownerAreaReportTask->handle();
-        $ownerBillReportTask= new CreateOwnerBillReport();
+        $ownerBillReportTask = new CreateOwnerBillReport();
         $ownerBillReportTask->handle();
-        $ownerReportTask= new CreateOwnerReport();
+        $ownerReportTask = new CreateOwnerReport();
         $ownerReportTask->handle();
-        dump('end'.Carbon::now()->toDateTimeString());
+        dump('end' . Carbon::now()->toDateTimeString());
     }
 
     public function testGetLogisticNumbers(): array
@@ -1430,8 +1439,8 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
     public function logistic_route_sync_ZT()
     {
         $service = new LogisticZopService();
-       $result = $service->get([]);
-       dd($result);
+        $result = $service->get([]);
+        dd($result);
     }
 
     public function testCancelOrder()
@@ -1453,9 +1462,9 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
 
     public function processOrderIssueRejectedBill()
     {
-        OrderIssue::query()->withTrashed()->whereNotNull('logistic_number_return')->chunkById(200,function($orderIssues){
-            $orderIssues->each(function($orderIssue){
-                if($orderIssue->logistic_number_return)
+        OrderIssue::query()->withTrashed()->whereNotNull('logistic_number_return')->chunkById(200, function ($orderIssues) {
+            $orderIssues->each(function ($orderIssue) {
+                if ($orderIssue->logistic_number_return)
                     $orderIssue->rejectedBills()->syncWithoutDetaching([trim($orderIssue->logistic_number_return)]);
             });
         });
@@ -1483,40 +1492,40 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
         $orderHeaderService = new OracleDOCOrderHeaderService();
         $orderTrackingService = new OrderTrackingService();
         $query = $orderHeaderService->getQuery();
-        $orderHeaders = $query->whereIn('Doc_Order_Header.customerid',['ONKYO','RUIHUO'])
-            ->where('Doc_Order_Header.AddTime','>=',$start_at)
-            ->where('Doc_Order_Header.AddTime','<=',$end_at)
+        $orderHeaders = $query->whereIn('Doc_Order_Header.customerid', ['ONKYO', 'RUIHUO'])
+            ->where('Doc_Order_Header.AddTime', '>=', $start_at)
+            ->where('Doc_Order_Header.AddTime', '<=', $end_at)
             ->get();
         $orderTrackingService->updateByWmsOrderHeaders($orderHeaders);
     }
 
     public function updateOrderTracking()
     {
-        OrderTracking::query()->with(['commodities'=>function($query){
-            $query->with(['commodity','package.order']);
+        OrderTracking::query()->with(['commodities' => function ($query) {
+            $query->with(['commodity', 'package.order']);
         }])->whereNotNull('client')
-            ->where('created_at','>=','2021-01-01')
-            ->where('created_at','<=','2021-01-07')
-            ->where('created_at','!=','0000-00-00 00:00:00')
-            ->chunkById('200',function($orderTrackings){
+            ->where('created_at', '>=', '2021-01-01')
+            ->where('created_at', '<=', '2021-01-07')
+            ->where('created_at', '!=', '0000-00-00 00:00:00')
+            ->chunkById('200', function ($orderTrackings) {
                 /**
                  * @var DataHandlerService $dataService
                  */
                 $service = new OrderTrackingService();
                 $update = [];
-                $update[]  = ['id','order_client_code_wms'];
+                $update[] = ['id', 'order_client_code_wms'];
                 foreach ($orderTrackings as $orderTracking) {
-                    if($orderTracking->commodities->order ?? false){
+                    if ($orderTracking->commodities->order ?? false) {
                         $update = [
                             'id' => $orderTracking->id,
                             'order_client_code_wms' => $orderTracking->commodities->order->client_code
                         ];
                     }
                 }
-                if(count($update) > 1){
+                if (count($update) > 1) {
                     $service->batchUpdate($update);
                 }
-        });
+            });
     }
 
     public function deleteOrderTracking()
@@ -1524,23 +1533,23 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
         $deleteId_arr = [];
         $deleteCommoditiesId_arr = [];
         OrderTracking::query()->with(['commodities.package'])
-            ->where('created_at','!=','0000-00-00 00:00:00')
-            ->chunkById('200',function($orderTrackings)use(&$deleteId_arr,&$deleteCommoditiesId_arr){
+            ->where('created_at', '!=', '0000-00-00 00:00:00')
+            ->chunkById('200', function ($orderTrackings) use (&$deleteId_arr, &$deleteCommoditiesId_arr) {
                 $deleteIds = [];
                 $deleteCommoditiesId = [];
                 foreach ($orderTrackings as $orderTracking) {
-                    if(!($orderTracking->commodities->package ?? false)){
-                        $deleteIds[]  = $orderTracking->id;
-                        if($orderTracking->commodities){
+                    if (!($orderTracking->commodities->package ?? false)) {
+                        $deleteIds[] = $orderTracking->id;
+                        if ($orderTracking->commodities) {
                             $deleteCommoditiesId[] = $orderTracking->commodities->id;
                         }
                     }
                 }
-                if($deleteIds){
+                if ($deleteIds) {
                     $deleteId_arr[] = $deleteIds;
                     $deleteCommoditiesId_arr[] = $deleteCommoditiesId;
-                    OrderTracking::query()->whereIn('id',$deleteIds)->delete();
-                    OrderPackageCommodities::query()->whereIn('id',$deleteCommoditiesId)->delete();
+                    OrderTracking::query()->whereIn('id', $deleteIds)->delete();
+                    OrderPackageCommodities::query()->whereIn('id', $deleteCommoditiesId)->delete();
                 }
             });
     }
@@ -1561,38 +1570,38 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
 
     public function updateRejectBillCheckedStatus()
     {
-        $time=Carbon::parse("2021-01-22 00:00:00")->subDays(15)->toDateTimeString();
-        $asnHeaders=OracleDOCASNHeader::query()
-            ->where('addtime','>=',$time)
-            ->select('asnno','addtime','edittime','customerid','notes','asnreference3')
+        $time = Carbon::parse("2021-01-22 00:00:00")->subDays(15)->toDateTimeString();
+        $asnHeaders = OracleDOCASNHeader::query()
+            ->where('addtime', '>=', $time)
+            ->select('asnno', 'addtime', 'edittime', 'customerid', 'notes', 'asnreference3')
             ->get();
-        $chunks=$asnHeaders->chunk(1000);
+        $chunks = $asnHeaders->chunk(1000);
         foreach ($chunks as $chunk) {
-         /** @var RejectedBillService $rejectedBillService */
-        $rejectedBillService=app(RejectedBillService::class);
-        $updates = $rejectedBillService->getNeedUpdateCheckedStatusByWms($chunk);
-        app(BatchUpdateService::class)->batchUpdate('rejected_bills', $updates);
+            /** @var RejectedBillService $rejectedBillService */
+            $rejectedBillService = app(RejectedBillService::class);
+            $updates = $rejectedBillService->getNeedUpdateCheckedStatusByWms($chunk);
+            app(BatchUpdateService::class)->batchUpdate('rejected_bills', $updates);
         }
     }
 
     public function clearCancelledOrder()
     {
-        $wave_nos = ['W210129000248','W210202000216','W210202000251','W210202000216','W210202000282'];
-        $order_nos = ['SO210129004112' , 'SO210202003333','SO210202003333','SO210202003236','SO210202003247','SO210202003719'];
+        $wave_nos = ['W210129000248', 'W210202000216', 'W210202000251', 'W210202000216', 'W210202000282'];
+        $order_nos = ['SO210129004112', 'SO210202003333', 'SO210202003333', 'SO210202003236', 'SO210202003247', 'SO210202003719'];
         try {
-            OracleDOCWaveDetails::query()->whereIn('WaveNo',$wave_nos)->whereIn('OrderNo', $order_nos)->delete();
-            app('LogService')->log(__CLASS__, __METHOD__, 'Delete OracleDOCWaveDetails' . '  ' . json_encode($order_nos).json_encode($wave_nos));
+            OracleDOCWaveDetails::query()->whereIn('WaveNo', $wave_nos)->whereIn('OrderNo', $order_nos)->delete();
+            app('LogService')->log(__CLASS__, __METHOD__, 'Delete OracleDOCWaveDetails' . '  ' . json_encode($order_nos) . json_encode($wave_nos));
         } catch (Exception $e) {
-            app('LogService')->log(__CLASS__, __METHOD__,'Error clearCancelledOrder'.json_encode($order_nos).json_encode($wave_nos));
+            app('LogService')->log(__CLASS__, __METHOD__, 'Error clearCancelledOrder' . json_encode($order_nos) . json_encode($wave_nos));
         }
     }
 
     public function syncOrderByWaveNo(Request $request)
     {
         $input = $request->input('wave');
-        if(!$input){
-            echo 'no wave code!';}
-        else {
+        if (!$input) {
+            echo 'no wave code!';
+        } else {
             echo 'syncing ' . $input;
             return;
         }
@@ -1600,27 +1609,28 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
         $orderService = new OrderService();
         $waveNos = [$input];
         $orderHeaders = OracleDOCOrderHeader::query()
-            ->selectRaw(implode(',',OracleDOCOrderHeaderService::$columns))
-            ->whereIn('WaveNo',$waveNos)
+            ->selectRaw(implode(',', OracleDOCOrderHeaderService::$columns))
+            ->whereIn('WaveNo', $waveNos)
             ->get();
         $orderHeaderList = $orderHeaders->chunk(2000);
         foreach ($orderHeaderList as $item) {
             $item = $oracleDOCOrderHeaderService->loadMissing($item);
 //            $last_order = $item->first();                                                               // 时间点靠后的
 //            $newest_orders = $item->where('addtime',$last_order->addtime);
-            if( count($orderHeaders) >0){
+            if (count($orderHeaders) > 0) {
                 $orderService->syncOrder($item);                                             //  同步订单
             }
         }
     }
+
     public function syncOrderByWaveNo2(Request $request)
     {
         $oracleDOCOrderHeaderService = new OracleDOCOrderHeaderService();
         $orderService = new OrderService();
-        $waveNos = ['W210220000010','W210220000009'];
+        $waveNos = ['W210220000010', 'W210220000009'];
         $orderHeaders = OracleDOCOrderHeader::query()
-            ->selectRaw(implode(',',OracleDOCOrderHeaderService::$columns))
-            ->whereIn('WaveNo',$waveNos)
+            ->selectRaw(implode(',', OracleDOCOrderHeaderService::$columns))
+            ->whereIn('WaveNo', $waveNos)
             ->get();
         $orderHeaderList = $orderHeaders->chunk(2000);
         foreach ($orderHeaderList as $item) {
@@ -1634,4 +1644,20 @@ where (commodities.owner_id,commodity_barcodes.code) in (select commodities.owne
         UserDutyCheck::query()->find(13565)->update(['user_id'=>1004]);
         LaborReportStatus::query()->find(26614)->update(['labor_report_id'=>6835]);
     }
+
+    public function cleanLaborsCache()
+    {
+        $beginDate = now()->subYears(1)->startOfDay();
+        $now = now()->startOfDay();
+        $dateList = $beginDate->daysUntil($now, 1);
+        $count = 0;
+        foreach ($dateList as $date) {
+            $key = 'laborReportsCountingRecords_' . $date->toDateString() . '_' . '日';
+            $bool = Cache::forget($key);
+            if ($bool) {
+                $count++;
+            }
+        }
+        return $count;
+    }
 }

+ 1 - 1
app/Http/Controllers/api/thirdPart/flux/WaybillController.php

@@ -100,12 +100,12 @@ class WaybillController extends Controller
                 $order = app("OrderService")->first(["code"=>$waybill->wms_bill_number]);
                 if ($order)$waybill->order_id = $order->id;
             }
+            $waybill->save();
             WaybillAuditLog::query()->create([
                 'waybill_id'=>$waybill->id,
                 'audit_stage'=>'创建',
                 'user_id'=>Auth::id() ?? 0,
             ]);
-            $waybill->save();
             if ($waybill->type=='直发车'){
                 $waybill_number='BSZF'.date ("ymd").str_pad($waybill->id>99999?$waybill->id%99999:$waybill->id,4,"0",STR_PAD_LEFT);
                 $waybill->waybill_number=$waybill_number;

+ 1 - 2
app/Imports/AppointmentDetail.php

@@ -30,11 +30,10 @@ class AppointmentDetail implements ToCollection,WithMultipleSheets,WithHeadingRo
         $header = $collection->first();
         foreach ($this->row as $row)if (!isset($header[$row]))$this->error("表头不存在“".$row."”");
         $errors = Validator::make($collection->toArray(),[
-            "*.条码" => ["required_without_all:*.商品名称,*.数量"],
+            "*.条码" => ["required_without:*.商品名称"],
             "*.商品名称" => ["required_without:*.条码"],
             "*.数量" => ["required_without:*.条码","integer","min:1"],
         ],[
-            'required_without_all'=>':attribute 条码与商品名称,数量至少存在一组',
             'required_without'=>':attribute 条码与商品名称,数量至少存在一组',
             'integer'=>':attribute 必须为数字',
             'min'=>':attribute 非法',

+ 11 - 2
app/Owner.php

@@ -24,16 +24,21 @@ class Owner extends Model
         'checking_count',       //审核数量
         'deleted_at',           //删除时间
         "customer_id",          //客户ID
-        "tax_rate",             //税率
+        "tax_rate_id",          //税率
         "linkman",              //联系人
         "phone_number",         //联系电话
         "user_owner_group_id",  //项目组ID
         "waring_line_on",       //月单量预警
         "description",          //描述
         "warehouse_id",         //仓库ID
-        "user_workgroup_id",     //仓库小组(工作组)
+        "user_workgroup_id",    //仓库小组(工作组)
+        "relevance",             //关联模型的JSON数组
         'subjection'             //主体公司
     ];
+    //relevance说明 0:仓储 1:作业 2:快递 3:物流 4:直发 存储示例:["0","1"]存在仓储与作业计费
+    protected $casts = [
+        "relevance" => "array"
+    ];
     const subjection=[
         0=>'',
         1 => "宝时物流",
@@ -122,4 +127,8 @@ class Owner extends Model
     {   //耗材
         return $this->hasMany(OwnerMaterial::class,"owner_id","id");
     }
+    public function taxRate()
+    {   //税率
+        return $this->belongsTo(TaxRate::class);
+    }
 }

+ 9 - 1
app/OwnerReport.php

@@ -17,12 +17,16 @@ class OwnerReport extends Model
         "owner_id",                     //货主ID
         "counting_month",               //结算月
         "daily_average_order_amount",   //日均单量
-        "total",                        //总单量
+        "to_business_quantity",         //ToB单量
+        "to_customer_quantity",         //ToC单量
         "current_month_counting_area",  //结算月盘点面积
         "last_month_counting_area",     //结算月上月盘点面积
         "owner_bill_report_id"          //账单ID
     ];
     public $timestamps = false;
+    protected $appends=[
+        "total"
+    ];
 
     public function owner()
     {   //货主
@@ -40,4 +44,8 @@ class OwnerReport extends Model
     {
         return substr($value,0,7);
     }
+    public function getTotalAttribute()
+    {   //总单量
+        return $this->to_business_quantity + $this->to_customer_quantity;
+    }
 }

+ 4 - 0
app/Providers/AppServiceProvider.php

@@ -93,6 +93,8 @@ use App\Services\WeighExceptedService;
 use App\Services\OrderFreezeService;
 use App\Services\RegionService;
 use App\Services\UserWorkgroupService;
+use App\Services\DeliveryAppointment;
+use App\Services\DeliveryAppointmentService;
 use Illuminate\Queue\Events\JobFailed;
 use Illuminate\Support\Facades\Queue;
 use Illuminate\Support\Facades\Schema;
@@ -157,6 +159,8 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('CustomerLogStatusService',CustomerLogStatusService::class);
         app()->singleton('CustomerService',CustomerService::class);
         app()->singleton('DataHandlerService',DataHandlerService::class);
+        app()->singleton('DeliveryAppointment',DeliveryAppointment::class);
+        app()->singleton('DeliveryAppointmentService',DeliveryAppointmentService::class);
         app()->singleton('DepositoryService',DepositoryService::class);
         app()->singleton('FeatureService',FeatureService::class);
         app()->singleton('ForeignHaiRoboticsService',ForeignHaiRoboticsService::class);

+ 3 - 3
app/Providers/AuthServiceProvider.php

@@ -50,9 +50,9 @@ class AuthServiceProvider extends ServiceProvider
                 $isSuperAdmin=$user->isSuperAdmin();
             }
             if ($isSuperAdmin) {
-                Cache::put('isSuperAdmin', true);
+                Cache::put('isSuperAdmin'.$user['id'], true);
             }else{
-                Cache::put('isSuperAdmin', false);
+                Cache::put('isSuperAdmin'.$user['id'], false);
             }
         });
         if(!Schema::hasTable('authorities')){return;}
@@ -61,7 +61,7 @@ class AuthServiceProvider extends ServiceProvider
         });
         foreach($authorities as $authority) {
             Gate::define($authority->name, function($user) use ($authority,$cacheService) {
-                if(Cache::get('isSuperAdmin')){
+                if(Cache::get('isSuperAdmin'.$user['id'])){
                     if($authority['permission']=='允许'){
                         return true;
                     }

+ 78 - 0
app/Services/DeliveryAppointmentService.php

@@ -0,0 +1,78 @@
+<?php 
+
+namespace App\Services;
+
+use App\CommodityBarcode;
+use App\DeliveryAppointmentDetail;
+use App\Traits\ServiceAppAop;
+use App\DeliveryAppointment;
+use Illuminate\Database\Eloquent\Builder;
+
+class DeliveryAppointmentService
+{
+    use ServiceAppAop;
+    protected $modelClass=DeliveryAppointment::class;
+
+    /**
+     * 根据吨,立方,SKU减产系数计算产能
+     *
+     * @param double $tonne
+     * @param double $cubicMeter
+     * @param int $amount
+     * @param int $rpcc reduced_production_capacity_coefficient
+     *
+     * @return double
+     */
+    public function calculateCapacity($tonne, $cubicMeter, $amount, $rpcc)
+    {
+        $need = max(($tonne*config("appointment.production_capacity.tonne")),
+            ($cubicMeter*config("appointment.production_capacity.cubic_meter")));
+        $coefficient = config("appointment.production_capacity.coefficient");
+        if ($amount && ($need/$amount < $coefficient)){
+            $need *= 1-(($coefficient-($need/$amount))*($rpcc/100));
+        }
+        return $need;
+    }
+
+    /**
+     * 根据提供的详情数组插入详情
+     *
+     * @param DeliveryAppointment|object $parent
+     * @param array $details
+     * @param string $name
+     * @param string $amount
+     * @param string $barCode
+     */
+    public function insertDetails($parent, array $details, $name="name", $amount="amount", $barCode="bar_code")
+    {
+        $codes = [];
+        $names = [];
+        foreach ($details as $detail){
+            if ($detail[$barCode])$codes[] = $detail[$barCode];
+            else $names[] = $detail[$name];
+        }
+        $map = [];//存储条码与ID的映射
+        CommodityBarcode::query()->with("commodity")->whereHas("commodity",function ($query)use($parent){
+            /** @var Builder $query */
+            $query->where("owner_id",$parent->owner_id);
+        })->whereIn("code",$codes)->orWhereHas("commodity",function ($query)use($names){
+            /** @var Builder $query */
+            $query->whereIn("name",$names);
+        })->get()->each(function ($commodity)use(&$map){
+            $map[$commodity->code] = $commodity->commodity_id;
+            $map[$commodity->commodity->name] = $commodity->commodity_id;
+        });
+        $insert = [];//插入的元素
+        foreach ($details as $detail){
+            $code = $detail[$barCode];
+            $insert[] = [
+                "delivery_appointment_id" => $parent->id,
+                "commodity_id"            => $code ? ($map[$code] ?? null) : ($map[$detail[$name]] ?? null),
+                "bar_code"                => $code,
+                "name"                    => $detail[$name],
+                "amount"                  => $detail[$amount],
+            ];
+        }
+        if ($insert)DeliveryAppointmentDetail::query()->insert($insert);
+    }
+}

+ 16 - 35
app/Services/NewOrderCountingRecordService.php

@@ -86,41 +86,22 @@ class NewOrderCountingRecordService
     {
         $key = 'warehouseCountingRecords_' . $start . '_' . $end . '_' . json_encode($ownerIds);
         return Cache::remember($key, config('cache.expirations.warehouseCountingRecords'), function () use ($start, $end, $ownerIds) {
-            $dataList = collect();
-            $resultOrders = $this->get($start, $end, '日', $ownerIds);
-            $resultOrders->groupBy('warehouse_id')->each(function ($item) use (&$dataList) {
-                $counter = $item->reduce(function ($sum, $item) {
-                    return $sum + $item->amount;
-                }, 0);
-                $dataList->push([
-                    'value' => $counter,
-                    'warehouse_id' => $item[0]->warehouse_id,
-                ]);
-            });
-            $map = [];
-            $logistics = Warehouse::query()->whereIn('id', data_get($dataList, '*.warehouse_id'))->get();
-            $logistics->each(function ($warehouse) use (&$map) {
-                $map[$warehouse->id] = $warehouse;
-            });
-            return $dataList->map(function (&$item) use ($map) {
-                $warehouse = $map[$item['warehouse_id']] ?? '';
-                $item['code'] = $warehouse->name ?? '';
-                switch ($item['code']) {
-                    case 'WH01':
-                        $item['name'] = '松江一仓';
-                        break;
-                    case 'WH02':
-                        $item['name'] = '松江二仓';
-                        break;
-                    case 'WH03':
-                        $item['name'] = '嘉定一仓';
-                        break;
-                    default:
-                        $item['name'] = '仓库为空';
-                        break;
-                }
-                return $item;
-            });
+        $dataList = collect();
+        $resultOrders = $this->get($start, $end, '日', $ownerIds);
+        $resultOrders->groupBy('warehouse_id')->each(function ($item) use (&$dataList) {
+            $counter = $item->reduce(function ($sum, $item) {
+                return $sum + $item->amount;
+            }, 0);
+            $warehouse = Warehouse::query()->find($item[0]->warehouse_id);
+
+            $dataList->push([
+                'value' => $counter,
+                'warehouse_id' => $item[0]->warehouse_id,
+                'name' => $warehouse ? $warehouse->name : '仓库为空',
+                'code' => $warehouse ? $warehouse->code : 'NULL',
+            ]);
+        });
+        return $dataList;
         });
     }
 

+ 32 - 4
app/Services/OrderIssueService.php

@@ -2,6 +2,7 @@
 
 namespace App\Services;
 
+use App\OracleActAllocationDetails;
 use App\OracleDOCASNHeader;
 use App\OracleDOCOrderHeader;
 use App\OrderIssue;
@@ -254,11 +255,38 @@ class OrderIssueService
 //            return ['success' => true, 'second_logistic_number' => $logisticNumber];
 //        }
 //        $orderIssue->update(['second_client_no' => $order->client_code]);
-        $orderIssue->update(['second_logistic_number' => $logisticNumber]);
+
+        $orderIssue->second_logistic_number = $logisticNumber;
         $order_package = OrderPackage::query()->selectRaw('order_id')->where('logistic_number',$logisticNumber);
-        $order = Order::query()->with(['packages.commodities.commodity', 'logistic'])
-            ->whereIn('id', $order_package)->first();
-        return ['success' => true, 'order' => $order];
+        if($order_package){
+            $order = Order::query()->with(['packages.commodities.commodity', 'logistic'])
+                ->whereIn('id', $order_package)->first();
+            if($order)$orderIssue->second_client_no = $order->code;
+            $orderIssue->save();
+            return ['success' => true, 'order' => $order];
+        }
+        /**
+         * @var OracleDOCOrderHeaderService $orderHeaderService
+         * @var OrderService $orderService
+         */
+        $orderHeaderService = app(OracleDOCOrderHeaderService::class);
+        $orderService = app(OrderService::class);
+        $orderHeader = $orderHeaderService->getQuery()->where("DOC_Order_Header.SOReference5",$logisticNumber)->get();
+        if(count($orderHeader) == 0){
+            $actAllocationQuery = OracleActAllocationDetails::query()->selectRaw("OrderNo")->where("PickToTraceId",$logisticNumber);
+            $orderHeader = $orderHeaderService->getQuery()->whereIn("DOC_Order_Header.OrderNo",$actAllocationQuery)->get();
+        }
+        if(count($orderHeader)>0){
+            $orderService->syncOrderByWMSOrderHeaders($orderHeader);
+            $order = Order::query()->with(['packages.commodities.commodity', 'logistic'])->where("code",$orderHeader->first()->orderno)->first();
+            if($order){
+                $orderIssue->update(['second_client_no'=>$order->client_code]);
+                return ['success' => true, 'order' => $order];
+            }
+        }
+        $orderIssue->update(['second_logistic_number'=>$logisticNumber]);
+        return ['success' => true, 'order' => null];
+
     }
 
     public function createOrderIssue($logisticNumber, $type, $result_explain, $importedStatus = '正常', $custom_code = null,$hiddenTag = null): bool

+ 78 - 4
app/Services/OrderService.php

@@ -14,6 +14,8 @@ use App\OrderIssue;
 use App\Owner;
 use App\OwnerFeeDetail;
 use App\OwnerFeeDetailLogistic;
+use App\OwnerPriceExpress;
+use App\OwnerReport;
 use App\Province;
 use App\RejectedBill;
 use App\Services\common\BatchUpdateService;
@@ -995,6 +997,76 @@ class OrderService
         return Order::query()->create($values);
     }
 
+    /**
+     * 订单量丢失补偿逻辑
+     *
+     * @param int $owner
+     * @param array|null $logistics
+     */
+    private function orderQuantityCompensationLogic($owner, $logistics = null)
+    {
+        if (!$logistics)$logistics = app("OwnerPriceExpressService")->getBuildLogistic($owner);
+        $query = DB::raw(<<<sql
+SELECT COUNT(1) count,logistic_id FROM orders WHERE wms_status = '订单完成' 
+AND owner_id = ?
+AND wms_edittime like ? GROUP BY logistic_id
+sql
+        );
+        $statistics = DB::select($query,[$owner,date("Y-m")."%"]);
+        $toB = 0;
+        $toC = 0;
+        foreach ($statistics as $statistic){
+            if (array_search($statistic->logistic_id,$logistics)===false)$toB += $statistic->count;
+            else $toC += $statistic->count;
+        }
+        Cache::put(date("Y-m")."|B|".$owner,$toB,2764800);
+        Cache::put(date("Y-m")."|C|".$owner,$toC,2764800);
+    }
+
+    /**
+     * 设置订单量
+     *
+     * @param int $owner
+     * @param int $logistic
+     */
+    public function setOrderQuantity($owner, $logistic)
+    {
+        $logistics = app("OwnerPriceExpressService")->getBuildLogistic($owner);
+        $date = date("Y-m");
+        if (array_search($logistic,$logistics)===false)$type = "|B|";
+        else $type = "|C|";
+        if (!Cache::has($date.$type.$owner)){
+            //补偿逻辑
+            $this->orderQuantityCompensationLogic($owner,$logistics);
+        }
+        Cache::increment($date.$type.$owner);
+        $key = $date."|D|".$owner;
+        if (!Cache::has($key) || time()-Cache::get($key)>60){
+            //向数据库持久化
+            OwnerReport::query()->where("owner_id",$owner)
+                ->where("counting_month","like",$date."%")
+                ->update(["to_business_quantity"=>Cache::get($date."|B|".$owner),"to_customer_quantity"=>Cache::get($date."|C|".$owner)]);
+        }
+        Cache::put($key,time());
+    }
+
+    /**
+     * 获取货主下有效订单量 对C端
+     *
+     * @param int $owner
+     * @param bool $isToB
+     *
+     * @return int
+     */
+    public function getOrderQuantity($owner, $isToB)
+    {
+        $date = date("Y-m");
+        if ($isToB)$type = "|B|";
+        else $type = "|C|";
+        if (!Cache::has($date.$type.$owner))$this->orderQuantityCompensationLogic($owner);
+        return Cache::get($date.$type.$owner);
+    }
+
     /**
      * 生成即时账单
      *
@@ -1008,9 +1080,7 @@ class OrderService
         if (!$order || $order->wms_status != "订单完成")return true;
         if (OwnerFeeDetail::query()->where("outer_table_name","orders")->where("outer_id",$order->id)->first())return true;
 
-        $key = date("Y-m")."_".$order->owner_id;
-        if (Cache::has($key))Cache::increment($key);
-        else Cache::put($key,1,2678400);
+        $this->setOrderQuantity($order->owner_id,$order->logistic_id);
 
         $order->loadMissing(["logistic","shop","packages.commodities.commodity","batch"]);
 
@@ -1023,7 +1093,9 @@ class OrderService
         $weight = 0;
         $logistic_bill = "";
 
-        if (!$order->logistic || $order->logistic->type != "快递")$logistic_fee = null;
+        if (!$order->logistic || $order->logistic->type == "物流")$logistic_fee = null;
+
+
 
         $items = [];
         foreach ($order->packages as &$package){
@@ -1249,4 +1321,6 @@ sql;
         return $result;
     }
 
+
+
 }

+ 31 - 13
app/Services/OwnerPriceExpressService.php

@@ -117,6 +117,27 @@ class OwnerPriceExpressService
         return $query->update($values);
     }
 
+    /**
+     * 获取绑定承运商
+     *
+     * @param $owner
+     * @return array
+     */
+    public function getBuildLogistic($owner)
+    {
+        return app(CacheService::class)->getOrExecute("logistics_owner_".$owner,function ()use($owner){
+            $query = DB::raw(<<<sql
+    SELECT logistic_id FROM `owner_price_express_owner` e 
+    LEFT JOIN owner_price_express_logistic l 
+    ON e.owner_price_express_id = l.owner_price_express_id 
+    WHERE e.owner_id = ?
+sql
+            );
+            $logistics = DB::select($query,[$owner]);
+            return array_column($logistics,"logistic_id");
+        },null);
+    }
+
     /**
      * CODE: -1:未找到计费模型 -2:重量无效
      *
@@ -130,19 +151,16 @@ class OwnerPriceExpressService
     {
         if (!$weight)return -2;
 
-        $key = "price_express_".$province_id."_".$logistic_id."_".$owner_id;
-        $model = app(CacheService::class)->getOrExecute($key,function ()use($owner_id, $logistic_id, $province_id){
-            return OwnerPriceExpress::query()->with(["details"=>function($query)use($province_id){
-                /** @var Builder $query */
-                $query->where("province_id",$province_id);
-            }])->whereHas("owners",function ($query)use($owner_id){
-                /** @var Builder $query */
-                $query->where("id",$owner_id);
-            })->whereHas("logistics",function ($query)use($logistic_id){
-                /** @var Builder $query */
-                $query->where("id",$logistic_id);
-            })->first();
-        });
+        $model = OwnerPriceExpress::query()->with(["details"=>function($query)use($province_id){
+            /** @var Builder $query */
+            $query->where("province_id",$province_id);
+        }])->whereHas("owners",function ($query)use($owner_id){
+            /** @var Builder $query */
+            $query->where("id",$owner_id);
+        })->whereHas("logistics",function ($query)use($logistic_id){
+            /** @var Builder $query */
+            $query->where("id",$logistic_id);
+        })->first();
         if (!$model || !$model->details)return -1;
         if ($weight <= $model->initial_weight)return $model->details[0]->initial_weight_price;
         $weight -= $model->initial_weight;

+ 80 - 41
app/Services/OwnerPriceOperationService.php

@@ -124,7 +124,7 @@ class OwnerPriceOperationService
 
         if (!$rules)return -2;  //规则不存在跳出
 
-        $total = Cache::get(date("Y-m")."_".$matchObject["owner_id"]); //获取该货主本月单量
+        $total = app("OrderService")->getOrderQuantity($owner_id);//获取该货主本月C端单量
         foreach ($rules as $rule){
             if (!$rule->items)continue; //不存在子规则跳出
             $isDiscount = false;    //是否存在满减
@@ -142,51 +142,35 @@ class OwnerPriceOperationService
             }
             //满减存在
             if ($isDiscount){
-                //未被标记过处理时间或处理时间不为本月,或上次处理值过期,处理历史即时账单
-                $pivot = DB::selectOne(DB::raw("SELECT * FROM owner_price_operation_owner WHERE owner_price_operation_id = ? AND owner_id = ?"),[$rule->id,$owner_id]);
-                if ($pivot && (!$pivot->discount_date || substr($pivot->discount_date,0,7)!=date("Y-m") || $pivot->target_value < $targetValue)){
+                $sign = false;
+                //入口仅在此处存在 缓存1000s
+                $key = "pivot_".$rule->id."_".$owner_id;
+                $pivot = app(CacheService::class)->getOrExecute($key,function ()use($key,$targetValue,&$sign,$rule,$owner_id){
                     try{
                         DB::beginTransaction();
-                        $month = date("Y-m");
-                        $day = date("t",strtotime($month));
-                        foreach (OwnerFeeDetail::query()->with(["order.logistic","order.shop","order.packages.commodities.commodity","order.batch"])
-                                     ->where("owner_id",$owner_id)
-                                     ->whereBetween("worked_at",[$month."-01",$month."-".$day])->get() as $detail){
-                            $order = $detail->order;
-
-                            $logistic_fee = 0;
-                            $commodities = [];
-                            foreach ($order->packages as &$package){
-                                // 四维转二维
-                                foreach($package->commodities as &$commodity){
-                                    $commodity["commodity_name"] = $commodity->commodity ? $commodity->commodity->name : '';
-                                    $commodity["sku"] = $commodity->commodity ? $commodity->commodity->sku : '';
-                                }
-                                $commodities = array_merge($commodities,$package->commodities->toArray());
-                            }
-                            if ($logistic_fee!==null && $logistic_fee<0)$logistic_fee = null;
-
-                            $object = ["commodities"=>$commodities,
-                                "logistic_name"=>($order->logistic ? $order->logistic->name : ''),
-                                "shop_name"=>($order->shop ? $order->shop->name : ''),
-                                "order_type"=>$order->order_type,
-                                "batch_type" => $order->batch ? $order->batch->wms_type : '',
-                                "owner_id"=>$order->owner_id];
-                            $mapping = ["packages"=>"commodities","商品名称"=>"commodity_name",
-                                "承运商"=>"logistic_name", "店铺类型"=>"shop_name",
-                                "订单类型"=>"order_type","波次类型"=>"batch_type"];
-                            $money = $this->matchItem($rule->items,$mapping,$object,$units,$owner_id,false,$isDiscount,$discountIndex);
-                            if ($money>0)$detail->update(["work_fee"=>$money]);
-                            else LogService::log(__CLASS__,"处理历史即时账单时发生匹配错误","账单主键:".$detail->id."; 错误代码".$money);
-                        };
-                        DB::update(DB::raw("UPDATE owner_price_operation_owner SET discount_date = ?,target_value = ? WHERE  owner_price_operation_id = ? AND owner_id = ?"),
-                            [date("Y-m-d"),$targetValue,$rule->id,$owner_id]);
+                        //此处暂时未使用cache的互斥锁 使用sql行锁代替下 防止缓存击穿
+                        $pivot = DB::selectOne(DB::raw("SELECT * FROM owner_price_operation_owner WHERE owner_price_operation_id = ? AND owner_id = ? for update"),[$rule->id,$owner_id]);
+                        if ($pivot && (!$pivot->discount_date || substr($pivot->discount_date,0,7)!=date("Y-m") || $pivot->target_value < $targetValue)){
+                            //未被标记过处理时间或处理时间不为本月,或上次处理值过期,处理历史即时账单
+                            $sign = true;
+                        }
+                        if ($sign){
+                            //先标记成功 这将在后续推进历史单处理流程,防止程序在此堵塞
+                            DB::update(DB::raw("UPDATE owner_price_operation_owner SET discount_date = ?,target_value = ? WHERE  owner_price_operation_id = ? AND owner_id = ?"),
+                                [date("Y-m-d"),$targetValue,$rule->id,$owner_id]);
+                            $pivot->discount_date = date("Y-m-d");
+                            $pivot->target_value = $targetValue;
+                            Cache::put($key,$pivot,1000);
+                        }
                         DB::commit();
-                    }catch (\Exception $e){
+                    }catch (\Exception $exception){
                         DB::rollBack();
-                        LogService::log(__CLASS__,"处理历史即时账单时发生系统错误","计费模型主键:".$rule->id."; 错误信息".$e->getMessage());
+                        LogService::log(__CLASS__,"即时账单满减处理失败",$exception->getMessage());
                     }
-                }
+                    return $pivot ?? null;
+                },1000);
+                //进入历史单处理
+                if ($pivot && $sign)$this->handlePastBill($rule,$owner_id,$units,$discountIndex,$pivot);
             }
             if ($rule->strategy == '特征'){//特征策略匹配
                 $bool = app("FeatureService")->matchFeature($rule->feature,$columnMapping,$matchObject);
@@ -355,4 +339,59 @@ class OwnerPriceOperationService
             $this->settingCount($packages,$amountColumn,$startNumber);
         }
     }
+
+    /**
+     * 处理历史账单
+     *
+     * @param object $rule
+     * @param int $owner_id
+     * @param array $units
+     * @param int $discountIndex
+     * @param object $pivot
+     */
+    public function handlePastBill($rule, $owner_id, $units, $discountIndex, $pivot)
+    {
+        try{
+            DB::beginTransaction();
+            $month = date("Y-m");
+            $day = date("t",strtotime($month));
+            foreach (OwnerFeeDetail::query()->with(["order.logistic","order.shop","order.packages.commodities.commodity","order.batch"])
+                         ->where("owner_id",$owner_id)
+                         ->whereBetween("worked_at",[$month."-01",$month."-".$day])->get() as $detail){
+                $order = $detail->order;
+
+                $logistic_fee = 0;
+                $commodities = [];
+                foreach ($order->packages as &$package){
+                    // 四维转二维
+                    foreach($package->commodities as &$commodity){
+                        $commodity["commodity_name"] = $commodity->commodity ? $commodity->commodity->name : '';
+                        $commodity["sku"] = $commodity->commodity ? $commodity->commodity->sku : '';
+                    }
+                    $commodities = array_merge($commodities,$package->commodities->toArray());
+                }
+                if ($logistic_fee!==null && $logistic_fee<0)$logistic_fee = null;
+
+                $object = ["commodities"=>$commodities,
+                    "logistic_name"=>($order->logistic ? $order->logistic->name : ''),
+                    "shop_name"=>($order->shop ? $order->shop->name : ''),
+                    "order_type"=>$order->order_type,
+                    "batch_type" => $order->batch ? $order->batch->wms_type : '',
+                    "owner_id"=>$order->owner_id];
+                $mapping = ["packages"=>"commodities","商品名称"=>"commodity_name",
+                    "承运商"=>"logistic_name", "店铺类型"=>"shop_name",
+                    "订单类型"=>"order_type","波次类型"=>"batch_type"];
+                $money = $this->matchItem($rule->items,$mapping,$object,$units,$owner_id,false,true,$discountIndex);
+                if ($money>0)$detail->update(["work_fee"=>$money]);
+                else LogService::log(__CLASS__,"处理历史即时账单时发生匹配错误","账单主键:".$detail->id."; 错误代码".$money);
+            };
+            DB::commit();
+        }catch (\Exception $e){
+            DB::rollBack();
+            //处理失败回退标记
+            DB::update(DB::raw("UPDATE owner_price_operation_owner SET discount_date = ?,target_value = ? WHERE  owner_price_operation_id = ? AND owner_id = ?"),
+                [$pivot->discount_date,$pivot->target_value,$rule->id,$owner_id]);
+            LogService::log(__CLASS__,"处理历史即时账单时发生系统错误","计费模型主键:".$rule->id."; 错误信息".$e->getMessage());
+        }
+    }
 }

+ 37 - 0
app/Services/OwnerService.php

@@ -5,6 +5,7 @@ namespace App\Services;
 use App\Authority;
 use App\OracleBasCustomer;
 use App\Owner;
+use App\Services\common\BatchUpdateService;
 use App\User;
 use Carbon\Carbon;
 use Illuminate\Database\Eloquent\Builder;
@@ -364,4 +365,40 @@ sql
         DB::table("authority_role")->whereIn("id_authority",$ids)->delete();
         Authority::destroy($ids);
     }
+
+    /**
+     * 计费模型变动时更新货主中关联属性
+     *
+     * @param integer|array $owner
+     * @param integer $type
+     * @param bool $isDestroy
+     *
+     */
+    public function refreshRelevance($owner, $type, $isDestroy)
+    {
+        if (!$owner)return;
+        if (!is_array($owner))$owner = [$owner];
+        $owners = Owner::query()->select("id","relevance")->find($owner);
+        $update = [["id","relevance"]];
+        foreach ($owners as $ow){
+            $relevance = $ow->relevance ?? [];
+            $index = array_search($type,$ow->relevance);
+            $exist = $index===false ? false : true;
+            if ($exist && $isDestroy){
+                $arr = array_splice($relevance,$index,1);
+                $update[] = [
+                    "id"=>$ow->id,
+                    "relevance"=>json_encode($arr),
+                ];
+            }
+            if (!$exist && !$isDestroy){
+                $arr = array_push($relevance,$type);
+                $update[] = [
+                    "id"=>$ow->id,
+                    "relevance"=>json_encode($arr),
+                ];
+            }
+        }
+        if (count($update)>1)app(BatchUpdateService::class)->batchUpdate("owners",$update);
+    }
 }

+ 14 - 10
app/Services/OwnerStoragePriceModelService.php

@@ -52,39 +52,43 @@ class OwnerStoragePriceModelService
     //暂时不考虑单位换算问题:后期可能存在多单位换算,此处仅视为单位为 m²,m³
     public function calculationAmount(OwnerStoragePriceModel $model, $area, $owner_id = null, $month = null)
     {
+        /** @var \stdClass $model */
         if (!$model || !$area) return 0;
         if ($area < $model->minimum_area) $area = $model->minimum_area;
-        $money = $area*$model->price;
         switch ($model->discount_type){
             case "按单减免":
                 if ($owner_id && $month){
                     if ($model->timeUnit->name == '月'){
-                        $report = OwnerReport::query()->select("id","total")
+                        $report = OwnerReport::query()->select("id",DB::raw("(to_business_quantity+to_customer_quantity) AS total"))
                             ->where("owner_id",$owner_id)
                             ->where("counting_month","like",$month."%")->first();
-                        $money -= $report ? ($report->total)*($model->discount_value) : 0;
+                        if ($report && $report->total>=0)$area -= floor($report->total/$model->discount_value);
                     }else{
                         $days = date('t', strtotime($month."-01"));
-                        $money *= $days;
+                        $area *= $days;
+                        $logistics = app("OwnerPriceExpressService")->getBuildLogistic($owner_id);
+                        $logisticSql = "(''";
+                        foreach ($logistics as $logistic)$logisticSql.=",".$logistic;
+                        $logisticSql .= ")";
                         for($i=1;$i<=$days;$i++){
                             $d = $i<10 ? "0".$i : $i;
-                            $query = DB::raw("SELECT COUNT(1) c FROM orders WHERE wms_status = ? and updated_at between ? and ?");
+                            $query = DB::raw("SELECT COUNT(1) c FROM orders WHERE logistic_id IN {$logisticSql} AND wms_status = ? AND wms_edittime BETWEEN ? AND ?");
                             $count = DB::selectOne($query,['订单完成',$month."-".$d." 00:00:00",$month."-".$d." 23:59:59"]);
-                            $money -= $count ? ($count->c)*($model->discount_value) : 0;
+                            if ($count && $count->c>=0)$area -= floor($count->c/$model->discount_value);
                         }
                     }
                 }
                 break;
             case "固定减免":
                 if ($model->timeUnit->name == '月'){
-                    $money -= $model->discount_value;
+                    $area -= $model->discount_value;
                 }else{
                     $days = date('t', strtotime($month."-01"));
-                    $money *= $days;
-                    $money -= $days*$model->discount_value;
+                    $area *= $days;
+                    $area -= $days*$model->discount_value;
                 }
                 break;
         }
-        return $money;
+        return $area*$model->price;
     }
 }

+ 18 - 0
app/TaxRate.php

@@ -0,0 +1,18 @@
+<?php
+
+namespace App;
+
+use App\Traits\ModelTimeFormat;
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+
+class TaxRate extends Model
+{
+    use ModelLogChanging;
+    use ModelTimeFormat;
+
+    protected $fillable=[
+        "value"
+    ];
+}

+ 2 - 0
app/User.php

@@ -3,6 +3,7 @@
 namespace App;
 
 use App\Traits\ModelLogChanging;
+use Illuminate\Database\Eloquent\SoftDeletes;
 use Illuminate\Notifications\Notifiable;
 use Illuminate\Foundation\Auth\User as Authenticatable;
 use Illuminate\Support\Collection;
@@ -15,6 +16,7 @@ class User extends Authenticatable
     use ModelLogChanging;
     use ModelTimeFormat;
     use Notifiable;
+    use SoftDeletes;
 
     /**
      * The attributes that are mass assignable.

+ 1 - 1
app/Warehouse.php

@@ -12,7 +12,7 @@ class Warehouse extends Model
     use ModelLogChanging;
 
     use ModelTimeFormat;
-    protected $fillable=['name','code'];
+    protected $fillable=['name','code',"production_capacity","reduced_production_capacity_coefficient"];
 
     public function userWorkgroups(){
         return $this->hasMany('App\UserWorkgroup');

+ 9 - 0
config/appointment.php

@@ -0,0 +1,9 @@
+<?php
+
+return [
+    "production_capacity" => [
+        "tonne"       => 1,
+        "cubic_meter" => 1,
+        "coefficient" => 5,
+    ],
+];

+ 31 - 0
database/migrations/2021_03_05_105547_add_authority_to_area_report.php

@@ -0,0 +1,31 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddAuthorityToAreaReport extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        \App\Authority::query()->firstOrCreate(["name"=>"客户管理-项目-用仓盘点-审核"],[
+            "name"=>"客户管理-项目-用仓盘点-审核",
+            "alias_name"=>"客户管理-项目-用仓盘点-审核",
+        ]);
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        \App\Authority::query()->where("name","客户管理-项目-用仓盘点-审核")->delete();
+    }
+}

+ 66 - 0
database/migrations/2021_03_06_090856_create_tax_rates_table.php

@@ -0,0 +1,66 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateTaxRatesTable extends Migration
+{
+    protected $values = [
+        0,3,6,11
+    ];
+    protected $authorities = [
+        "税率",
+        "税率-查询",
+        "税率-编辑",
+        "税率-删除",
+        "入库管理-客户预约-预约",
+        "入库管理-客户预约"
+    ];
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('tax_rates', function (Blueprint $table) {
+            $table->id();
+            $table->decimal("value",5,2)->unique()->comment("值");
+            $table->timestamps();
+        });
+        Schema::table('owners', function (Blueprint $table) {
+            $table->dropColumn("tax_rate");
+            $table->bigInteger("tax_rate_id")->nullable()->comment("外键税率");
+            $table->string("relevance")->nullable()->comment("关联模型的JSON数组");
+        });
+        foreach ($this->values as $value) \App\TaxRate::query()->firstOrCreate(["value"=>$value]);
+        foreach ($this->authorities as $authority)\App\Authority::query()->firstOrCreate(["name"=>$authority],["name"=>$authority,"alias_name"=>$authority]);
+        \App\Authority::query()->where("name","入库管理-盘收一体-客户预约")->delete();
+        Schema::table('warehouses', function (Blueprint $table) {
+            $table->decimal("production_capacity")->default(0)->comment("产能");
+            $table->integer("reduced_production_capacity_coefficient")->default(0)->comment("SKU减产系数");
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('tax_rates');
+        Schema::table('owners', function (Blueprint $table) {
+            $table->dropColumn("tax_rate_id");
+            $table->decimal("tax_rate")->nullable()->comment("税率");
+            $table->dropColumn("relevance");
+        });
+        foreach ($this->authorities as $authority)\App\Authority::query()->where("name",$authority)->delete();
+        \App\Authority::query()->firstOrCreate(["name"=>"入库管理-盘收一体-客户预约"],["name"=>"入库管理-盘收一体-客户预约","alias_name"=>"入库管理-盘收一体-客户预约"]);
+        Schema::table('warehouses', function (Blueprint $table) {
+            $table->dropColumn("production_capacity");
+            $table->dropColumn("reduced_production_capacity_coefficient");
+        });
+    }
+}

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

@@ -0,0 +1,36 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class ChangeOwnerReportsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('owner_reports', function (Blueprint $table) {
+            $table->dropColumn("total");
+            $table->integer('to_business_quantity')->default(0)->comment("to b 单量");
+            $table->integer('to_customer_quantity')->default(0)->comment("to c 单量");
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('owner_reports', function (Blueprint $table) {
+            $table->integer('total')->nullable()->comment("结算月总单量");
+            $table->dropColumn("to_business_quantity");
+            $table->dropColumn("to_customer_quantity");
+        });
+    }
+}

+ 4 - 4
package.json

@@ -1,12 +1,12 @@
 {
   "private": true,
   "scripts": {
-    "dev": "npm run development",
+    "dev": "yarn run development",
     "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
-    "watch": "npm run development -- --watch",
-    "watch-poll": "npm run watch -- --watch-poll",
+    "watch": "yarn run development -- --watch",
+    "watch-poll": "yarn run watch -- --watch-poll",
     "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
-    "prod": "npm run production",
+    "prod": "yarn run production",
     "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
   },
   "devDependencies": {

+ 220 - 158
resources/js/queryForm/queryForm.js

@@ -5,7 +5,7 @@ const query = function getQueryForm(data) {
         this.method = data.method || 'get';
         this.url = data.url || getPathname();
         this.condition = data.condition;
-        this.paginations =data.paginations ? data.paginations : [50, 100, 200, 500,1000] ;
+        this.paginations = data.paginations ? data.paginations : [50, 100, 200, 500, 1000];
         this.isPaginations = data.isPaginations !== false;
         this.keydownfun = data.keydownfun || undefined;
         this.selectChange = data.selectChange || undefined;
@@ -19,20 +19,20 @@ const query = function getQueryForm(data) {
         this.pervPage = pervPage;
         this.goPage = goPage;
         this.getSearchData = getSearchData;
-        this.autoSubmit = (data.autoSubmit !== false) ;
+        this.autoSubmit = (data.autoSubmit !== false);
         this.param = data.param || [];
         this.appendDom = data.appendDom || undefined;
 
         // 提交表单
         this.onsubmit = function () {
-            if(!this.autoSubmit){
+            if (!this.autoSubmit) {
                 return;
             }
             saveSearchOnCookie();
-            let form = $("<form method='" + _this.method +"'></form>");
+            let form = $("<form method='" + _this.method + "'></form>");
             for (const key in _data) {
                 let map = _data[key];
-                if(map['required'] == true && (map.value === '' || map.value===null || map.value === undefined))return;
+                if (map['required'] == true && (map.value === '' || map.value === null || map.value === undefined)) return;
                 if (["string", "number"].includes(fetchJsType(map.value)) && map.value !== '') {
                     // if(map.value){
                     //     let string = new String(map.value);
@@ -42,14 +42,14 @@ const query = function getQueryForm(data) {
                     //     }
                     // }
                     //form.append("<input name='" + key + "' value='" + map.value.replace(" ","%20") + "'>");
-                      form.append("<input name='" + key + "' value='" + encodeURIComponent(map.value) + "'>")
+                    form.append("<input name='" + key + "' value='" + encodeURIComponent(map.value) + "'>")
                 } else if ('array' === fetchJsType(map.value)) {
                     let string = map.value.join(',');
                     //form.append("<input  name='" + key + "' value='" + string.replace(" ","%20") + "'>");
                     form.append("<input  name='" + key + "' value='" + encodeURIComponent(string) + "'>")
                 }
             }
-            for (let key in this.param){
+            for (let key in this.param) {
                 form.append("<input type='text' name='" + key + "' value='" + this.param[key] + "'>");
             }
             if (_this.method !== 'get') {
@@ -75,7 +75,7 @@ const query = function getQueryForm(data) {
     let _hidden_div = null;
     let _parentNode_top = null;
     let _page = '';
-
+    let _toggle_btn = null;
     this.init = function () {
         _parentNode = $(_this.el);
         _form = $("<div ></div>");
@@ -92,26 +92,48 @@ const query = function getQueryForm(data) {
         $('[data-toggle="tooltip"]').tooltip({'trigger': 'hover'})
     }
 
+    function isSmallScreen() {
+        return $(window).width() <= 640;
+    }
+
+    function getToggleBtn(){
+        _toggle_btn = $("<button  type='button' class='btn btn-sm btn-success position-fixed' style='left:-5px;top:290px;z-index:10;width: 25px;'>展开</button>")
+        _toggle_btn.click(function(){
+            if(_toggle_btn.text() === "展开"){
+                _toggle_btn.text("收缩");
+                _table.removeClass("d-none")
+                _table.css("z-index",9);
+            }else if(_toggle_btn.text() === "收缩"){
+                _toggle_btn.text("展开");
+                _table.addClass("d-none")
+            }
+        });
+        return _toggle_btn;
+     }
+
     // form fixed
     function parentNodeFloat() {
         _parentNode_top = _parentNode.offset().top;
         let height = _parentNode.height();
-        let dom = _this.appendDom ? $("#"+_this.appendDom+"") : null;
-        $(window).scroll(function(){
+        let dom = _this.appendDom ? $("#" + _this.appendDom + "") : null;
+        $(window).scroll(function () {
             let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
+            if(isSmallScreen()){
+                return;
+            }
             if (scrollTop > _parentNode_top) {
                 _form.addClass('fixed-top');
                 _parentNode.height(height);
-                if (dom){
-                    dom.css('position','fixed');
-                    dom.css('background','rgb(255, 255, 255)');
-                    dom.css('top',height);
-                    dom.css('z-index',1000);
+                if (dom) {
+                    dom.css('position', 'fixed');
+                    dom.css('background', 'rgb(255, 255, 255)');
+                    dom.css('top', height);
+                    dom.css('z-index', 1000);
                 }
             } else {
                 _form.removeClass('fixed-top');
-                if (dom){
-                    dom.attr('style','');
+                if (dom) {
+                    dom.attr('style', '');
                 }
             }
         });
@@ -130,14 +152,16 @@ const query = function getQueryForm(data) {
         _table.html('');
         _table.append(crateClearBtn());
         _table.append(createPagination());
+        let isSmall = isSmallScreen();
         _baseData.condition.forEach(function (conditions, index, arrays) {
             let tr = $("<tr></tr>");
             conditions.forEach(function (condition, index, array) {
+                if (isSmall) tr = $("<tr></tr>");
                 let td = $("<td style='width: 260px'></td>");
                 if ([null, '', undefined].includes(condition.type) && ![null, undefined].includes(condition.name)) {
                     condition.type = 'input';
                 }
-                if (['dateTime_dateTime','dateTimeLocal', 'input_input'].includes(condition.type)) {
+                if (['dateTime_dateTime', 'dateTimeLocal', 'input_input'].includes(condition.type)) {
                     td = $("<td  style='width: 330px'</td>")
                 } else if (['select_multiple_select', 'time', 'dateTime_select'].includes(condition.type)) {
                     td = $("<td  style='width: 280px'</td>");
@@ -146,14 +170,25 @@ const query = function getQueryForm(data) {
                 }
                 td.append(createModule(condition));
                 tr.append(td);
+                if (isSmall) {
+                    _table.append(tr);
+                }
             })
-            _table.append(tr);
-            if (arrays.length === index + 1) {
-                let td = $("<td ></td>");
-                tr.append(td.append(createSearchBt()));
+            if (!isSmall) {
+                _table.append(tr);
+                if (arrays.length === index + 1) {
+                    let td = $("<td ></td>");
+                    tr.append(td.append(createSearchBt()));
+                }
             }
-
         })
+        if (isSmall) {
+            let tr = $("<tr></tr>");
+            let td = $("<td style='width: 260px'></td>");
+            _table.append(tr.append(td.append(createSearchBt())));
+            _table.addClass("d-none").addClass("position-fixed").css({"z-index":"9","top":0});
+            _form.append(getToggleBtn());
+        }
         $.cookie.raw = true;
         $.cookie.json = true;
         setTableWidth();
@@ -164,11 +199,11 @@ const query = function getQueryForm(data) {
         _baseData.condition.forEach(function (conditions, xindex, xarrays) {
             let _width = 0;
             conditions.forEach(function (condition, index, array) {
-                if (['input','dateMonth', 'select', 'dateTime', 'input_select'].includes(condition.type)) {
+                if (['input', 'dateMonth', 'select', 'dateTime', 'input_select'].includes(condition.type)) {
                     _width += 260;
-                } else if (['dateTime_dateTime','dateTimeLocal', 'input_input'].includes(condition.type)) {
+                } else if (['dateTime_dateTime', 'dateTimeLocal', 'input_input'].includes(condition.type)) {
                     _width += 330;
-                } else if (['select_multiple_select','search_select'].includes(condition.type)) {
+                } else if (['select_multiple_select', 'search_select'].includes(condition.type)) {
                     _width += 280;
                 } else if (['checkbox'].includes(condition.type)) {
                     _width += 260;
@@ -186,9 +221,14 @@ const query = function getQueryForm(data) {
                 }
             })
         })
-        _parentNode.css('min-width', 1920 - 30)
-        _parentNode.css('max-width', (max_width || window.screen.availWidth) - 30);
-        _table.css('width', max_width + 'px');
+        if (isSmallScreen()) {
+            _parentNode.css("width", 340 + "px");
+            _table.css("width", 340 + "px").addClass("m-0");
+        } else {
+            _parentNode.css('min-width', 1920 - 30)
+            _parentNode.css('max-width', (max_width || window.screen.availWidth) - 30);
+            _table.css('width', max_width + 'px');
+        }
     }
 
     // 清空筛选按钮
@@ -200,7 +240,7 @@ const query = function getQueryForm(data) {
         })
         let tr = $("<tr ><td colspan='10'></td></tr>");
         tr.find('td').append(clearbtn);
-        _clearTr  = tr;
+        _clearTr = tr;
         return tr;
     }
 
@@ -215,7 +255,7 @@ const query = function getQueryForm(data) {
             }
             if (controlJsType(_this._onsubmit, 'fun')) {
                 _this._onsubmit();
-            }else{
+            } else {
                 _this.onsubmit();
             }
         })
@@ -225,7 +265,7 @@ const query = function getQueryForm(data) {
     // create _pagination
     function createPagination() {
         let isPaginations = _this.isPaginations ? '' : 'hidden';
-        _pagination = $("<select id='paginate' "+isPaginations+" name='paginate' class='form-control form-control-sm' style='vertical-align: middle; max-width: 150px;'></select>");
+        _pagination = $("<select id='paginate' " + isPaginations + " name='paginate' class='form-control form-control-sm' style='vertical-align: middle; max-width: 150px;'></select>");
         let tr = $("<tr ><td colspan='10'><div class='col p-0' style='height: 100%'></div></td></tr>");
         tr.find('div').append(_pagination);
         _this.paginations.forEach(function (map) {
@@ -273,13 +313,13 @@ const query = function getQueryForm(data) {
     // 数据清空
     function clearData() {
         saveCookie({});
-        let url=_this.url;
-        if (_this.param !== []){
+        let url = _this.url;
+        if (_this.param !== []) {
             url += "?";
-            let i=0;
-            for (let key in _this.param){
-                if (i!==0) url += "&";
-                url += key+"="+_this.param[key];
+            let i = 0;
+            for (let key in _this.param) {
+                if (i !== 0) url += "&";
+                url += key + "=" + _this.param[key];
                 i++;
             }
         }
@@ -346,13 +386,13 @@ const query = function getQueryForm(data) {
 
     // dateMonth
     function getDateMonth(condition) {
-        let dateMonth = $("<input name = '"+ condition.name +"' type='month' class='form-control form-control-sm' style='vertical-align: middle; max-width: 200px;' placeholder='" + condition.placeholder + "' autocomplete='off' data-toggle='tooltip' >");
+        let dateMonth = $("<input name = '" + condition.name + "' type='month' class='form-control form-control-sm' style='vertical-align: middle; max-width: 200px;' placeholder='" + condition.placeholder + "' autocomplete='off' data-toggle='tooltip' >");
         dateMonth.attr('title', condition.tip === undefined ? '' : condition.tip);
-        dateMonth.blur(function(){
+        dateMonth.blur(function () {
             modifyData({name: condition.name, type: 'dateMonth', value: this.value, mold: 'dateMonth'});
         });
-        dateMonth.keypress(function(event){
-            if(event.which  === 13){
+        dateMonth.keypress(function (event) {
+            if (event.which === 13) {
                 modifyData({name: condition.name, type: 'input', value: this.value, mold: 'input'});
             }
         });
@@ -363,11 +403,11 @@ const query = function getQueryForm(data) {
     function getInput(condition) {
         let input = $("<input name='" + condition.name + "' class='form-control form-control-sm' style='vertical-align: middle; max-width: 200px;' placeholder='" + condition.placeholder + "' autocomplete='off' data-toggle='tooltip' data-placement='top' >");
         input.attr('title', condition.tip === undefined ? '' : condition.tip);
-        input.blur(function(){
+        input.blur(function () {
             modifyData({name: condition.name, type: 'input', value: this.value, mold: 'input'});
         });
-        input.keypress(function(event){
-            if(event.which  === 13)modifyData({name: condition.name, type: 'input', value: this.value, mold: 'input'});
+        input.keypress(function (event) {
+            if (event.which === 13) modifyData({name: condition.name, type: 'input', value: this.value, mold: 'input'});
         });
         return input;
     }
@@ -403,7 +443,7 @@ const query = function getQueryForm(data) {
             placeholder = condition.placeholder[1];
         }
         fillSelectOption(select, condition.data, placeholder);
-        input.blur(function(){
+        input.blur(function () {
             let value = this.value;
             let data = condition.data.filter(function (map) {
                 return map.value.includes(value);
@@ -411,8 +451,8 @@ const query = function getQueryForm(data) {
             fillSelectOption(select, data || condition.data);
             select.val(_data[condition.name].select);
         });
-        input.keypress(function(event){
-            if(event.which  === 13){
+        input.keypress(function (event) {
+            if (event.which === 13) {
                 let value = this.value;
                 let data = condition.data.filter(function (map) {
                     return map.value.includes(value);
@@ -434,11 +474,16 @@ const query = function getQueryForm(data) {
         input.attr('title', controlJsType(condition.tip[0], 'undefined') ? '' : condition.tip[0]);
         let select = $("<select class='form-control form-control-sm ml-2' name='" + condition.name[1] + "'  style='max-width: 200px;' title='" + condition.tip[1] + "''>");
         fillSelectOption(select, condition.data);
-        input.blur(function(){
+        input.blur(function () {
             modifyData({name: this.name, type: 'input_select_longtext', value: this.value, mold: 'input'});
         });
-        input.keypress(function(event){
-            if(event.which === 13)modifyData({name: this.name, type: 'input_select_longtext', value: this.value, mold: 'input'});
+        input.keypress(function (event) {
+            if (event.which === 13) modifyData({
+                name: this.name,
+                type: 'input_select_longtext',
+                value: this.value,
+                mold: 'input'
+            });
         });
         select.change(function () {
             modifyData({name: this.name, type: 'input_select_longtext', value: this.value, mold: 'select'});
@@ -458,7 +503,7 @@ const query = function getQueryForm(data) {
 
     //dateTimeLocal
     function getDateTimeLocal(condition) {
-        let dateTimeLocal = $("<input name = '"+ condition.name +"' type='datetime-local' step='01' class='form-control form-control-sm' style='vertical-align: middle; max-width: 280px;' placeholder='" + condition.placeholder + "' autocomplete='off' data-toggle='tooltip' data-placement='top' >");
+        let dateTimeLocal = $("<input name = '" + condition.name + "' type='datetime-local' step='01' class='form-control form-control-sm' style='vertical-align: middle; max-width: 280px;' placeholder='" + condition.placeholder + "' autocomplete='off' data-toggle='tooltip' data-placement='top' >");
         dateTimeLocal.attr('title', condition.tip === undefined ? '' : condition.tip);
         dateTimeLocal.bind('input propertychange', function () {
             modifyData({name: condition.name, type: 'dateTimeLocal', value: this.value, mold: 'dateTimeLocal'});
@@ -474,12 +519,12 @@ const query = function getQueryForm(data) {
         let min = $("<input id='" + condition.name + "_min' class='form-control form-control-sm ml-2' style='max-width: 100px;' placeholder='00:00' data-toggle='tooltip' data-placement='top' >");
         min.attr('title', controlJsType(condition.tip[1], 'undefined') ? '' : condition.tip[1]);
         dateTime.bind('input propertychange', function () {
-            let value = this.value !== '' ? this.value + ' ' +(!!min.val() ?  min.val() :'23:59' ) : '';
-            modifyData( {name: condition.name, type: 'time', value: value, mold: 'time'});
+            let value = this.value !== '' ? this.value + ' ' + (!!min.val() ? min.val() : '23:59') : '';
+            modifyData({name: condition.name, type: 'time', value: value, mold: 'time'});
             // modifyData({name: condition.name, type: 'dateTime', value: this.value, mold: 'dateTime'});
         });
         min.bind('input propertychange', function () {
-            if (['null', 'undefined', ''].includes(dateTime.val()))return;
+            if (['null', 'undefined', ''].includes(dateTime.val())) return;
             let value = ['null', 'undefined', ''].includes(dateTime.val()) ? '' : dateTime.val() + ' ' + min.val();
             modifyData({name: condition.name, type: 'time', value: value, mold: 'time'});
         })
@@ -494,17 +539,27 @@ const query = function getQueryForm(data) {
         let input2 = $("<input name='" + condition.name[1] + "' class='form-control form-control-sm ml-2' style='vertical-align: middle; max-width: 150px;' placeholder='" + condition.placeholder[1] + "' data-toggle='tooltip' data-placement='top' title='" + condition.tip[1] + "'>");
         input2.attr('title', controlJsType(condition.tip[1], 'undefined') ? '' : condition.tip[1]);
 
-        input1.blur(function(){
+        input1.blur(function () {
             modifyData({name: this.name, type: 'input_input', value: this.value, mold: 'input'});
         });
-        input1.keypress(function(event){
-            if(event.which === 13)modifyData({name: this.name, type: 'input_input', value: this.value, mold: 'input'});
+        input1.keypress(function (event) {
+            if (event.which === 13) modifyData({
+                name: this.name,
+                type: 'input_input',
+                value: this.value,
+                mold: 'input'
+            });
         });
-        input2.blur(function(){
+        input2.blur(function () {
             modifyData({name: this.name, type: 'input_input', value: this.value, mold: 'input'});
         });
-        input2.keypress(function(event){
-            if(event.which === 13)modifyData({name: this.name, type: 'input_input', value: this.value, mold: 'input'});
+        input2.keypress(function (event) {
+            if (event.which === 13) modifyData({
+                name: this.name,
+                type: 'input_input',
+                value: this.value,
+                mold: 'input'
+            });
         });
         return div.append(input1).append(input2);
     }
@@ -540,7 +595,7 @@ const query = function getQueryForm(data) {
 
         fillSelectOption(select, condition.data)
         dateTime.bind('input propertychange', function () {
-            modifyData( {name: this.name, type: 'dateTime_select', value: this.value, mold: 'dateTime'});
+            modifyData({name: this.name, type: 'dateTime_select', value: this.value, mold: 'dateTime'});
         })
         select.change(function () {
             modifyData({name: this.name, type: 'dateTime_select', value: this.value, mold: 'select'});
@@ -576,27 +631,27 @@ const query = function getQueryForm(data) {
         check.click(function () {
             _data[condition.name].value = [];
             _data[condition.name].select = [];
-            if (check[0].checked === true){
+            if (check[0].checked === true) {
                 condition.data.forEach(function (data) {
                     _data[condition.name].value.push(data.name);
                     if (_data[condition.name].select) _data[condition.name].select.push(data.name);
                     else _data[condition.name].select = [data.name];
                 });
-            }else{
+            } else {
                 let dom = {
                     name: condition.name,
                     mold: 'select_multiple_select',
                     value: [],
-                    select:[],
+                    select: [],
                 };
                 modifyData(dom);
             }
             redenerUl(ul);
         });
-        check.mouseleave(()=>{
+        check.mouseleave(() => {
             isMouseenterCheckBox = false;
         });
-        check.mouseenter(()=>{
+        check.mouseenter(() => {
             isMouseenterCheckBox = true;
         });
 
@@ -651,12 +706,12 @@ const query = function getQueryForm(data) {
         })*/
         ul_div.hide();
         ul_div.mouseleave(function () {
-            if(_data[condition.name].value.length>0){
+            if (_data[condition.name].value.length > 0) {
                 // _this.onsubmit();
                 ul_div.hide();
                 return;
             }
-            if (!isMouseenterCheckBox){
+            if (!isMouseenterCheckBox) {
                 ul_div.hide();
             }
         });
@@ -725,10 +780,10 @@ const query = function getQueryForm(data) {
             li.click(function () {
                 let value = li.attr('value');
                 let dom_data = _data[name].value;
-                if(!dom_data){
+                if (!dom_data) {
                     dom_data = [];
                 }
-                if (controlJsType(dom_data,'string')){
+                if (controlJsType(dom_data, 'string')) {
                     dom_data = [dom_data];
                 }
                 if (dom_data.includes(value)) {
@@ -755,11 +810,11 @@ const query = function getQueryForm(data) {
         let label = $('#' + name + '_lab');
         let select = $('#' + name + '_sel');
         let dom_data = _data[name].value;
-        if (dom_data && dom_data.length === 1 ) {
+        if (dom_data && dom_data.length === 1) {
             select.show();
             select.val(dom_data[0]);
             label.hide();
-        }else if(controlJsType(dom_data,'string')){
+        } else if (controlJsType(dom_data, 'string')) {
             select.show();
             select.val(dom_data);
             label.hide();
@@ -775,10 +830,10 @@ const query = function getQueryForm(data) {
         _data[dom.name].value = dom.value;
         _data[dom.name].select = dom.value;
         redenerSearchFormOnData(dom.name, dom.value, dom.mold);
-        let killings=_data[dom.name].killings;
-        if(killings){
-            killings.forEach(function(targetName){
-                _data[targetName].value= '';
+        let killings = _data[dom.name].killings;
+        if (killings) {
+            killings.forEach(function (targetName) {
+                _data[targetName].value = '';
                 redenerSearchFormOnData(_data[targetName].name, '', _data[targetName].mold);
             })
         }
@@ -791,18 +846,21 @@ const query = function getQueryForm(data) {
         *   {date_relevance:{date:['',''],relevance:'',killing:'',default:[]}}
         * */
         let rules = _data[dom.name].rules;
-        if (rules && JSON.stringify(rules) !== '{}'){
-            if (rules['son']){
-                for (let key in rules['son']){
-                    if (!dom.value){
+        if (rules && JSON.stringify(rules) !== '{}') {
+            if (rules['son']) {
+                for (let key in rules['son']) {
+                    if (!dom.value) {
                         redenerSearchFormOnData(_data[key].name, '', _data[key].mold);
                         continue;
                     }
-                    if (!_data[key].value){
-                        if (rules['son'][key].required_without_all_if && Array.isArray(rules['son'][key].required_without_all_if)){
+                    if (!_data[key].value) {
+                        if (rules['son'][key].required_without_all_if && Array.isArray(rules['son'][key].required_without_all_if)) {
                             let sign = true;
                             rules['son'][key].required_without_all_if.some(function (name) {
-                                if (_data[name].value){ sign=false; return true;}
+                                if (_data[name].value) {
+                                    sign = false;
+                                    return true;
+                                }
                             });
                             if (sign) {
                                 _data[_data[key].name].mold = _data[key].mold;
@@ -814,7 +872,7 @@ const query = function getQueryForm(data) {
                     }
                 }
             }
-            if (rules['date_relevance']){
+            if (rules['date_relevance']) {
                 if (!rules['date_relevance']['date']
                     || !Array.isArray(rules['date_relevance']['date'])
                     || rules['date_relevance']['date'].length !== 2
@@ -822,36 +880,36 @@ const query = function getQueryForm(data) {
                 let start = _data[rules['date_relevance']['date'][0]];
                 let end = _data[rules['date_relevance']['date'][1]];
                 let relevance = _data[rules['date_relevance']['relevance']];
-                if (dom.name === rules['date_relevance']['relevance']){
-                    if (relevance.value){
+                if (dom.name === rules['date_relevance']['relevance']) {
+                    if (relevance.value) {
                         let today = getToday();
-                        let tarDate = getSubDate(getToday(),relevance.value);
-                        _data[end.name].value = today+" 23:59";
-                        _data[start.name].value = tarDate+" 00:00";
+                        let tarDate = getSubDate(getToday(), relevance.value);
+                        _data[end.name].value = today + " 23:59";
+                        _data[start.name].value = tarDate + " 00:00";
                         /*redenerSearchFormOnData(end.name, tarDate+" 23:59", end.mold);
                         redenerSearchFormOnData(start.name, tarDate+" 00:00", start.mold);*/
                     }
                     return;
                 }
-                if (!start.value || !end.value){
-                    if (rules['date_relevance']['killing'] === 'date'){
+                if (!start.value || !end.value) {
+                    if (rules['date_relevance']['killing'] === 'date') {
                         _data[start.name].value = '';
                         redenerSearchFormOnData(start.name, '', start.mold);
                         _data[start.name].value = '';
                         redenerSearchFormOnData(end.name, '', end.mold);
-                    }else{
+                    } else {
                         _data[relevance.name].value = '';
                         redenerSearchFormOnData(relevance.name, '', relevance.mold);
                     }
                 }
-                if (start.value && end.value){
-                    start.value = start.value.replace('+',' ');
-                    end.value = end.value.replace('+',' ');
-                    let diff = getDiffDay(start.value,end.value);
-                    if (rules['date_relevance']['default'] && rules['date_relevance']['default'].includes(diff)){
+                if (start.value && end.value) {
+                    start.value = start.value.replace('+', ' ');
+                    end.value = end.value.replace('+', ' ');
+                    let diff = getDiffDay(start.value, end.value);
+                    if (rules['date_relevance']['default'] && rules['date_relevance']['default'].includes(diff)) {
                         _data[relevance.name].value = diff;
-                        redenerSearchFormOnData(relevance.name, diff, relevance.mold);}
-                    else {
+                        redenerSearchFormOnData(relevance.name, diff, relevance.mold);
+                    } else {
                         _data[relevance.name].value = '';
                         redenerSearchFormOnData(relevance.name, '', relevance.mold);
                     }
@@ -859,13 +917,14 @@ const query = function getQueryForm(data) {
             }
         }
     }
-    function getDiffDay(startDate,endDate) {
+
+    function getDiffDay(startDate, endDate) {
         startDate = new Date(startDate);
         endDate = new Date(endDate);
-        return Math.floor((endDate.getTime() - startDate.getTime())/(24*3600*1000));
+        return Math.floor((endDate.getTime() - startDate.getTime()) / (24 * 3600 * 1000));
     }
 
-    function getSubDate(date,value) {
+    function getSubDate(date, value) {
         date = new Date(date);
         date.setDate(date.getDate() - value);
         return dateFormat(date);
@@ -877,10 +936,10 @@ const query = function getQueryForm(data) {
     }
 
     function dateFormat(date) {
-        let year=date.getFullYear();
-        let month=(date.getMonth()+1)<10 ? '0'+(date.getMonth()+1) : date.getMonth()+1;
-        let day=date.getDate()<10 ? '0'+date.getDate() : date.getDate();
-        return  year+"-"+month+"-"+day;
+        let year = date.getFullYear();
+        let month = (date.getMonth() + 1) < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;
+        let day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
+        return year + "-" + month + "-" + day;
     }
 
     // save search on cookie
@@ -1061,12 +1120,12 @@ const query = function getQueryForm(data) {
 
     function rendererSearchFormOnTime(key, value, mold) {
         if (![undefined, null, ''].includes(value)) {
-            $(_form).find("input[name="+key+"]").val(value.substring(0, 10)).addClass('bg-warning');
+            $(_form).find("input[name=" + key + "]").val(value.substring(0, 10)).addClass('bg-warning');
             if (value.length > 11 + 5) {
                 $(_form).find("input[name='" + key + "_tim']").val(value.substring(11, 5));
             }
         } else {
-            $(_form).find("input[name="+key+"]").val("").removeClass('bg-warning');
+            $(_form).find("input[name=" + key + "]").val("").removeClass('bg-warning');
             $(_form).find("input[name='" + key + "_tim']").val("");
         }
     }
@@ -1080,7 +1139,7 @@ const query = function getQueryForm(data) {
                 }
             } else {
                 if (![undefined, null, ''].includes(_data[key].value)) {
-                    if(controlJsType(_data[key].value,'array') && _data[key].value.length === 0 ){
+                    if (controlJsType(_data[key].value, 'array') && _data[key].value.length === 0) {
                         continue;
                     }
                     bool = true;
@@ -1101,14 +1160,14 @@ const query = function getQueryForm(data) {
                 setTimeout(function () {
                     if (_this.keydownSearch) _this.onsubmit();
                     if (controlJsType(_this.keydownfun, 'fun')) _this.keydownfun();
-                },100);
+                }, 100);
             }
         });
         $(_form).find("input[type='date']").change(function (e) {
             setTimeout(function () {
                 // if (_this.keydownSearch)_this.onsubmit();
                 if (controlJsType(_this.keydownfun, 'fun')) _this.keydownfun();
-            },100);
+            }, 100);
         });
     }
 
@@ -1119,7 +1178,7 @@ const query = function getQueryForm(data) {
     }
 
     function redenerSearchFormOnData(key, value, mold) {
-        if (mold === 'input' ||mold === 'dateTime' || mold === 'dateTimeLocal' || mold === 'dateMonth') {
+        if (mold === 'input' || mold === 'dateTime' || mold === 'dateTimeLocal' || mold === 'dateMonth') {
             rendererSearchFormOnInput(key, value, mold);
         } else if (mold === 'select') {
             rendererSearchFormOnSelect(key, value, mold);
@@ -1136,7 +1195,7 @@ const query = function getQueryForm(data) {
     function switchData() {
         _this.condition.forEach(function (conditions) {
             conditions.forEach(function (condition) {
-                if (['input', 'select', 'dateTime','dateTimeLocal', 'dateMonth', 'search_select', 'time', 'select_multiple_select','checkbox'].includes(condition.type)) {
+                if (['input', 'select', 'dateTime', 'dateTimeLocal', 'dateMonth', 'search_select', 'time', 'select_multiple_select', 'checkbox'].includes(condition.type)) {
                     if (!condition.select) {
                         condition.select = '';
                     }
@@ -1146,15 +1205,15 @@ const query = function getQueryForm(data) {
                         value: condition.value,
                         select: condition.select,
                         mold: ['input', 'dateTime'].includes(condition.type) ? 'input' : condition.type,
-                        data:condition.data,
-                        killings:condition.killings,
-                        rules:condition.rules,
-                        required:condition.required,
+                        data: condition.data,
+                        killings: condition.killings,
+                        rules: condition.rules,
+                        required: condition.required,
                     }
                     if (condition.type === 'search_select') {
                         data.mold = 'select';
                     }
-                    if(condition.type === 'select_multiple_select'){
+                    if (condition.type === 'select_multiple_select') {
                         data.value = [];
                     }
                     _data[condition.name] = data;
@@ -1173,15 +1232,15 @@ const query = function getQueryForm(data) {
                             value: condition.value[index],
                             select: condition.select[index],
                             mold: ['input', 'dateTime'].includes(types[index]) ? 'input' : types[index],
-                            killings:condition.killings,
-                            rules:condition.rules,
-                            required:condition.required,
+                            killings: condition.killings,
+                            rules: condition.rules,
+                            required: condition.required,
                         }
-                        if(condition.killings&&Array.isArray(condition.killings)){
-                            data.killings=condition.killings[index];
+                        if (condition.killings && Array.isArray(condition.killings)) {
+                            data.killings = condition.killings[index];
                         }
-                        if(condition.rules&&Array.isArray(condition.rules)){
-                            data.rules=condition.rules[index];
+                        if (condition.rules && Array.isArray(condition.rules)) {
+                            data.rules = condition.rules[index];
                         }
                         _data[_name] = data;
                     })
@@ -1271,7 +1330,7 @@ const query = function getQueryForm(data) {
             data = (data.substr(1)).split('&');
             data = convertArrayToObj(data);
             for (const key in data) {
-                if(!data[key] || _this.param[key]){
+                if (!data[key] || _this.param[key]) {
                     continue;
                 }
                 if (key === 'paginate') {
@@ -1283,13 +1342,13 @@ const query = function getQueryForm(data) {
                     }
                 } else if (key === 'page') {
                     _page = data[key];
-                }  else if(_data[key].type === 'select_multiple_select' ){
-                    if(!_data[key]){
+                } else if (_data[key].type === 'select_multiple_select') {
+                    if (!_data[key]) {
                         _data[key].value = [];
-                    }else{
+                    } else {
                         _data[key].value = data[key].split(',');
                     }
-                }else {
+                } else {
                     _data[key].value = data[key];
                 }
             }
@@ -1335,20 +1394,20 @@ const query = function getQueryForm(data) {
     //  paginate
     function pervPage() {
         let obj = getSearchData();
-        if(!!obj['page'] && obj['page']>1){
-            obj['page'] = obj['page']-1;
+        if (!!obj['page'] && obj['page'] > 1) {
+            obj['page'] = obj['page'] - 1;
         }
         return getSearchUri(obj);
     }
 
     function nextPage() {
         let obj = getSearchData();
-        if(!!obj['page'] ){
-            obj['page'] = obj['page']+1;
-        }else{
+        if (!!obj['page']) {
+            obj['page'] = obj['page'] + 1;
+        } else {
             obj['page'] = 2;
         }
-        if(!obj['paginate']){
+        if (!obj['paginate']) {
             obj['paginate'] = 50;
         }
         return getSearchUri(obj);
@@ -1357,19 +1416,19 @@ const query = function getQueryForm(data) {
     function getSearchObj() {
         let data = window.location.search;
         data = decodeURIComponent(data);
-        if(!data){
+        if (!data) {
             return {};
         }
         let saveData = {};
         data = data.substr(1).split('&');
         data.forEach(function (map) {
-            let arr = map.split('&'),key = arr[0],value = arr[1];
-            if(!!value){
+            let arr = map.split('&'), key = arr[0], value = arr[1];
+            if (!!value) {
                 if (!saveData[key]) {
                     saveData[key] = value;
                 } else {
                     if (controlJsType(data[key], 'string')) {
-                        saveData[key] = [saveData[key] , value];
+                        saveData[key] = [saveData[key], value];
                     } else if (controlJsType(data[key], 'array')) {
                         saveData[key].push(value);
                     }
@@ -1379,19 +1438,20 @@ const query = function getQueryForm(data) {
         return saveData;
     }
 
-    function getPage(){
-        return  getSearchObj()['page'];
+    function getPage() {
+        return getSearchObj()['page'];
     }
+
     //  paginate
     function pervPage() {
         let obj = getSearchData();
         _page = getPage();
-        if(!obj['paginate']){
+        if (!obj['paginate']) {
             obj['paginate'] = 50;
         }
-        if(Number(_page)>1){
-            _page= Number(_page)-1;
-        }else{
+        if (Number(_page) > 1) {
+            _page = Number(_page) - 1;
+        } else {
             _page = 1;
         }
         return getSearchUri(obj);
@@ -1400,30 +1460,32 @@ const query = function getQueryForm(data) {
     function nextPage() {
         let obj = getSearchData();
         _page = getPage();
-        if(!_page){_page=1;}
-        if(_page){
-            _page = Number(_page)+ 1;
+        if (!_page) {
+            _page = 1;
+        }
+        if (_page) {
+            _page = Number(_page) + 1;
         }
-        if(!obj['paginate']){
+        if (!obj['paginate']) {
             obj['paginate'] = 50;
         }
         return getSearchUri(obj);
     }
 
-    function goPage(page){
+    function goPage(page) {
         let obj = getSearchData();
         _page = page;
         return getSearchUri(obj);
     }
 
-    function getSearchUri(obj){
+    function getSearchUri(obj) {
         let string = "?";
         for (const key in obj) {
-            if(controlJsType(obj[key],['string','number'])){
-                string+= key + "=" + obj[key]+'&';
-            }else if( controlJsType(obj[key],'array')&&obj[key].length > 0){
-                obj[key].forEach(function(value){
-                    string+=key + "=" + value+'&';
+            if (controlJsType(obj[key], ['string', 'number'])) {
+                string += key + "=" + obj[key] + '&';
+            } else if (controlJsType(obj[key], 'array') && obj[key].length > 0) {
+                obj[key].forEach(function (value) {
+                    string += key + "=" + value + '&';
                 })
             }
         }

+ 13 - 1
resources/sass/text.scss

@@ -193,4 +193,16 @@
     position: absolute;
     left: 55%;
     top: 2px;
-}
+}
+
+//浅色
+.opacity{
+    opacity: 0.6;
+}
+
+//选中的黑色阴影效果
+.box-shadow-dark{
+    box-shadow: 0 0 10px 5px rgba(0,0,0,0.9);
+    z-index:100;
+    position:relative;
+}

+ 35 - 0
resources/views/customer/project/_editArea.blade.php

@@ -0,0 +1,35 @@
+<div class="modal fade" tabindex="-1" role="dialog" id="editArea">
+    <div class="modal-dialog modal-lg modal-dialog-centered">
+        <div class="modal-content">
+            <div class="modal-header">
+                <button type="button" class="close" data-dismiss="modal">&times;</button>
+            </div>
+            <div class="modal-body">
+                <div class="row">
+                    <label class="col-2 offset-1" for="ownerGroup">项目小组</label>
+                    <select id="ownerGroup" class="form-control col-6" v-model="area.ownerGroupId">
+                        <option v-for="group in ownerGroups" :value="group.name">@{{ group.value }}</option>
+                    </select>
+                </div>
+                <div class="row mt-3">
+                    <label class="col-2 offset-1" for="areaOnTray">货物整托</label>
+                    <input id="areaOnTray" :readonly="area.unitName=='m²' ? false : true"
+                           type="number" min="0" class="form-control col-6" v-model="area.areaOnTray">
+                </div>
+                <div class="row mt-3">
+                    <label class="col-2 offset-1" for="areaOnHalfTray">货物半托</label>
+                    <input id="areaOnHalfTray" :readonly="area.unitName=='m²' ? false : true"
+                           type="number" min="0" class="form-control col-6" v-model="area.areaOnHalfTray">
+                </div>
+                <div class="row mt-3">
+                    <label class="col-2 offset-1" for="areaOnFlat">平面区</label>
+                    <input id="areaOnFlat" :readonly="area.unitName=='m²' ? false : true"
+                           type="number" min="0" class="form-control col-6" v-model="area.areaOnFlat">
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-success" @click="submitArea()">提交</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 162 - 89
resources/views/customer/project/area.blade.php

@@ -1,26 +1,27 @@
 @extends('layouts.app')
 @section('title')
-    面积报表-客户管理
+    用仓盘点-客户管理
 @endsection
 @section('content')
     @component('customer.project.menu')@endcomponent
     <div class="container-fluid d-none" id="container">
 
         @include("customer._selectedOwner")
-
-        <div id="form_div"></div>
-        <div>
-            <button type="button" class="btn btn-outline-dark btn-sm dropdown-toggle tooltipTarget" :class="[checkData.length>0?'btn-dark text-light':'']"
-                    data-toggle="dropdown" title="导出所有页将会以搜索条件得到的筛选结果,将其全部记录(每一页)导出">
-                导出Excel
-            </button>
-            <div class="dropdown-menu">
-                <a class="dropdown-item" @click="areaExport(false)" href="javascript:">导出勾选内容</a>
-                <a class="dropdown-item" @click="areaExport(true)" href="javascript:">导出所有页</a>
+        @include("customer.project._editArea")
+        <!-- pc >544 -->
+        <div class="d-none d-sm-block">
+            <div id="form_div"></div>
+            <div>
+                <button type="button" class="btn btn-outline-dark btn-sm dropdown-toggle tooltipTarget" :class="[checkData.length>0?'btn-dark text-light':'']"
+                        data-toggle="dropdown" title="导出所有页将会以搜索条件得到的筛选结果,将其全部记录(每一页)导出">
+                    导出Excel
+                </button>
+                <div class="dropdown-menu">
+                    <a class="dropdown-item" @click="areaExport(false)" href="javascript:">导出勾选内容</a>
+                    <a class="dropdown-item" @click="areaExport(true)" href="javascript:">导出所有页</a>
+                </div>
+                <button class="ml-1 btn btn-sm btn-outline-primary" data-toggle="modal" data-target="#selectedOwner">新 增</button>
             </div>
-            <button class="ml-1 btn btn-sm btn-outline-primary" data-toggle="modal" data-target="#selectedOwner">新 增</button>
-        </div>
-        <div>
             <label for="all" id="cloneCheckAll" class="d-none">
                 <input id="all" type="checkbox" @click="checkAll($event)">全选
             </label>
@@ -33,47 +34,115 @@
                     </td>
                     <td>@{{ i+1 }}</td>
                     <td>
-                        <span v-if="area.status=='已完成'" class="text-success">@{{ area.status }}</span>
-                        <span v-if="area.status!='已完成' && editIndex!=i"><button class="btn btn-sm btn-outline-info" @click="edit(area,i)">编辑</button></span>
-                        <span v-if="editIndex==i">
-                            <button class="btn btn-sm btn-success" @click="submitArea()">确定</button>
-                            <button class="btn btn-sm btn-danger" @click="editIndex='-1'">取消</button>
+                        <span v-if="area.status=='编辑中'">
+                            <button class="btn btn-sm btn-outline-info" @click="edit(area,i)">编辑</button>
+                            @can("客户管理-项目-用仓盘点-审核")<button class="btn btn-sm btn-outline-success" v-if="area.accountingArea" @click="audit(i)">审核</button>@endcan
                         </span>
+                        <span v-if="area.status=='已完成'" class="text-success font-weight-bold">@{{ area.status }}</span>
+                        <span v-if="area.status=='已审核'" class="text-primary font-weight-bold">@{{ area.status }}</span>
                     </td>
-                    <td>
-                        <label><select @change="thisArea.user_owner_group_id = $event.target.value" :disabled="editIndex==i ? false : true"
-                                       :value="area.ownerGroupId" class="form-control form-control-sm">
-                            <option v-for="ownerGroup in ownerGroups" :value="ownerGroup.name">@{{ ownerGroup.value }}</option>
-                        </select></label>
-                    </td>
+                    <td>@{{ area.userOwnerGroupName }}</td>
                     <td>@{{ area.customerName }}</td>
                     <td>@{{ area.ownerName }}</td>
                     <td>@{{ area.countingMonth }}</td>
                     <td>@{{ area.updatedAt }}</td>
                     <td>@{{ area.ownerStoragePriceModel }}</td>
                     <td>@{{ area.unitName }}</td>
-                    <td>
-                        <label><input :readonly="editIndex==i && (area.unitName=='m²' || area.unitName=='㎡') ? false : true" @change="thisArea.area_on_tray = $event.target.value"
-                                      type="number" min="0" class="form-control form-control-sm" :value="area.areaOnTray"></label>
-                    </td>
-                    <td>
-                        <label><input :readonly="editIndex==i && (area.unitName=='m²' || area.unitName=='㎡') ? false : true" @change="thisArea.area_on_half_tray = $event.target.value"
-                                      type="number" min="0" class="form-control form-control-sm" :value=area.areaOnHalfTray></label>
-                    </td>
-                    <td>
-                        <label><input :readonly="editIndex==i && (area.unitName=='m²' || area.unitName=='㎡') ? false : true" @change="thisArea.area_on_flat = $event.target.value"
-                                      type="number" min="0" class="form-control form-control-sm" :value="area.areaOnFlat"></label>
-                    </td>
-                    <td>
-                        <label class="form-inline"><input :readonly="editIndex==i && (area.unitName!='m²' || area.unitName!='㎡') ? false : true" @change="thisArea.accounting_area = $event.target.value"
-                                      type="number" min="0" class="form-control form-control-sm" :value="area.accountingArea">
-                            <label> / @{{ area.unitName }}</label>
-                        </label>
-                    </td>
+                    <td>@{{ area.areaOnTray }}</td>
+                    <td>@{{ area.areaOnHalfTray }}</td>
+                    <td>@{{ area.areaOnFlat }}</td>
+                    <td>@{{ area.accountingArea }}</td>
                 </tr>
             </table>
-            {{$areas->appends($params)->links()}}
         </div>
+        <!-- phone <544 -->
+        <div class="d-xl-none">
+            <div v-for="(area,i) in areas" class="mt-1 border border-1 rounded"
+                 @click="openAll(i)">
+                <div class="row">
+                    <div class="col-4">
+                        <label class="text-muted">序号:</label>@{{ i+1 }}
+                    </div>
+                    <div class="col-4 text-center">
+                        <b :class="area.status=='编辑中' ? 'text-secondary' : (area.status=='已完成' ? 'text-success' : 'text-primary')">@{{ area.status }}</b>
+                    </div>
+                    <div class="col-4">
+                        <span class="pull-right mr-1 text-primary font-weight-bold small" v-if="area.unitName=='m²' && area.status=='编辑中'">点击展开编辑</span>
+                    </div>
+                </div>
+                <div class="row">
+                    <div class="col-6">
+                        <label class="text-muted">项目:</label>@{{ area.ownerName }}
+                    </div>
+                    <div class="col-6">
+                        <label class="text-muted">客户:</label>@{{ area.customerName }}
+                    </div>
+                </div>
+                <div class="row">
+                    <div class="col-6">
+                        <label class="text-muted">用仓:</label>@{{ area.ownerStoragePriceModel }}
+                    </div>
+                    <div class="col-6">
+                        <label class="text-muted">单位:</label>@{{ area.unitName }}
+                    </div>
+                </div>
+                <div class="row">
+                    <div class="col-6">
+                        <label class="text-muted">项目组:</label>@{{ area.userOwnerGroupName }}
+                    </div>
+                    <div class="col-6">
+                        <label class="text-muted">结算月:</label>@{{ area.countingMonth }}
+                    </div>
+                </div>
+                <div class="row font-weight-bold">
+                    <div class="col-6">
+                        <label class="text-dark">结算值:</label>@{{ area.accountingArea }}
+                    </div>
+                    <div class="col-6">
+                        <label class="text-dark">平面区:</label>@{{ area.areaOnFlat }}
+                    </div>
+                </div>
+                <div class="row font-weight-bold">
+                    <div class="col-6">
+                        <label class="text-dark">货物整托:</label>@{{ area.areaOnTray }}
+                    </div>
+                    <div class="col-6">
+                        <label class="text-dark">货物半托:</label>@{{ area.areaOnHalfTray }}
+                    </div>
+                </div>
+                <div :id="'area_'+i" class="up" v-if="area.unitName=='m²' && area.status=='编辑中'">
+                    <div class="row">
+                        <label class="text-dark col-4">平面区:</label>
+                        <label class="col-8">
+                            <input :id="'item-'+i+'-areaOnFlat'" class="form-control form-control-sm" type="number" step="0.01" min="0" :value="area.areaOnFlat" @click="$event.stopPropagation();">
+                        </label>
+                    </div>
+                    <div class="row">
+                        <label class="text-dark col-4">货物整托:</label>
+                        <label class="col-8">
+                            <input :id="'item-'+i+'-areaOnTray'" class="form-control form-control-sm" type="number" step="0.01" min="0" :value="area.areaOnTray" @click="$event.stopPropagation();">
+                        </label>
+                    </div>
+                    <div class="row">
+                        <label class="text-dark col-4">货物半托:</label>
+                        <label class="col-8">
+                            <input :id="'item-'+i+'-areaOnHalfTray'" class="form-control form-control-sm" type="number" step="0.01" min="0" :value="area.areaOnHalfTray" @click="$event.stopPropagation();">
+                        </label>
+                    </div>
+                    <div class="row">
+                        <div class="col-10 offset-1">
+                            @can('客户管理-项目-用仓盘点-审核')<button type="button" @click.stop="submitArea(i)" class="btn btn-sm btn-outline-primary w-100">提交编辑</button>@endcan
+                        </div>
+                    </div>
+                </div>
+                <div class="row mt-2" v-if="area.status=='编辑中'">
+                    <div class="col-10 offset-1">
+                        @can('客户管理-项目-用仓盘点-审核')<button type="button" @click.stop="audit(i)" class="btn btn-sm btn-outline-success w-100">审核</button>@endcan
+                    </div>
+                </div>
+            </div>
+        </div>
+        {{$areas->appends($params)->links()}}
     </div>
 @stop
 
@@ -90,6 +159,7 @@
                     {
                         id : "{{$area->id}}",
                         ownerGroupId : "{{$area->user_owner_group_id}}",
+                        userOwnerGroupName : "{{$area->userOwnerGroup->name ?? ''}}",
                         ownerName : "{{$area->owner ? $area->owner->name : ''}}",
                         customerName : "{{$area->owner ? ($area->owner->customer ? $area->owner->customer->name : '') : ''}}",
                         countingMonth : "{{$area->counting_month}}",
@@ -100,16 +170,10 @@
                         status : "{{$area->status}}",
                         updatedAt : "{{$area->updated_at}}",
                         ownerStoragePriceModel:"{{ $area->ownerStoragePriceModel ? $area->ownerStoragePriceModel->using_type : '' }}",
-                        unitName:"{{ $area->ownerStoragePriceModel ? ($area->ownerStoragePriceModel->unit ? $area->ownerStoragePriceModel->unit->name : '') : '' }}",
+                        unitName:"{{ $area->ownerStoragePriceModel->unit->name ?? '' }}",
                     },
                     @endforeach
                 ],
-                thisArea : {
-                    user_owner_group_id : "",
-                    area_on_tray : "",
-                    area_on_half_tray : "",
-                    area_on_flat : "",
-                },
                 ownerGroups : [
                     @foreach($ownerGroups as $ownerGroup)
                     {name:"{{$ownerGroup->id}}",value:"{{$ownerGroup->name}}"},
@@ -125,11 +189,12 @@
                     {name:"{{$owner->id}}",value:"{{$owner->name}}"},
                     @endforeach
                 ],
-                status : [{name:"编辑中",value:"编辑中"},{name:"已完成",value:"已完成"}],
+                status : [{name:"编辑中",value:"编辑中"},{name:"已审核",value:"已审核"},{name:"已完成",value:"已完成"}],
                 checkData : [],
-                editIndex : "-1",
                 sum : Number("{{ $areas->total() }}"),
                 errors:[],
+                area:{},
+                index:"",
             },
             watch:{
                 checkData:{
@@ -146,6 +211,7 @@
                 }
             },
             mounted(){
+                $(".up").slideUp();
                 $('#container').removeClass('d-none');
                 let data=[
                     [
@@ -169,7 +235,7 @@
                         dom:$('#cloneCheckAll').removeClass('d-none'), neglect: true},
                     {name:'index',value: '序号', neglect: true},
                     {name:'status',value: '状态'},
-                    {name:'ownerGroupId',value: '项目组', neglect : true},
+                    {name:'userOwnerGroupName',value: '项目组'},
                     {name:'customerName',value: '客户'},
                     {name:'ownerName',value: '子项目'},
                     {name:'countingMonth',value: '结算月'},
@@ -196,6 +262,9 @@
                 },0);
             },
             methods:{
+                openAll(index){
+                    $("#area_"+index).slideToggle();
+                },
                 areaExport(isAll){
                     let url = '{{url('customer/project/area/export')}}';
                     let token='{{ csrf_token() }}';
@@ -215,42 +284,36 @@
                     }
                 },
                 edit(area,index){
-                    this.editIndex = index;
-                    this.thisArea.user_owner_group_id = area.ownerGroupId;
-                    this.thisArea.area_on_tray = area.areaOnTray;
-                    this.thisArea.area_on_half_tray = area.areaOnHalfTray;
-                    this.thisArea.area_on_flat = area.areaOnFlat;
-                    this.thisArea.accounting_area = area.accountingArea;
+                    $("#editArea").modal("show");
+                    this.area = Object.assign({},area);
+                    this.index = index;
                 },
-                submitArea(){
-                    window.tempTip.confirm("确认要提交该面积的更新吗?",()=>{
-                        axios.post("{{url('customer/project/updateArea')}}",{
-                            id:this.areas[this.editIndex].id,area:this.thisArea
-                        }).then(res=>{
-                            if (res.data.success){
-                                this.areas[this.editIndex].ownerGroupId = res.data.data["user_owner_group_id"];
-                                this.areas[this.editIndex].areaOnTray = res.data.data["area_on_tray"];
-                                this.areas[this.editIndex].areaOnHalfTray = res.data.data["area_on_half_tray"];
-                                this.areas[this.editIndex].areaOnFlat = res.data.data["area_on_flat"];
-                                this.areas[this.editIndex].accountingArea = res.data.data["accounting_area"];
-                                this.editIndex = '-1';
-                                this.thisArea = {
-                                    user_owner_group_id : "",
-                                    area_on_tray : "",
-                                    area_on_half_tray : "",
-                                    area_on_flat : "",
-                                };
-                                window.tempTip.setDuration(2000);
-                                window.tempTip.showSuccess("修改成功");
-                                return;
-                            }
-                            window.tempTip.setDuration(3000);
-                            window.tempTip.show(res.data.data);
-                        }).catch(err=>{
-                            window.tempTip.setDuration(3000);
-                            window.tempTip.show("网络错误:"+err);
-                        })
-                    });
+                submitArea(i = null){
+                    let url = "{{url('customer/project/updateArea')}}";
+                    let param = this.area;
+                    let index = this.index;
+                    if (i!==null){
+                        index = i;
+                        param = {id:this.areas[i].id,areaOnTray:document.getElementById("item-"+i+"-areaOnTray").value,
+                            areaOnHalfTray:document.getElementById("item-"+i+"-areaOnHalfTray").value,areaOnFlat:document.getElementById("item-"+i+"-areaOnFlat").value};
+                    }
+                    window.tempTip.postBasicRequest(url,param,res=>{
+                        if (this.areas[index].ownerGroupId !== res.user_owner_group_id){
+                            this.areas[index].ownerGroupId = res.user_owner_group_id;
+                            this.ownerGroups.some(group=>{
+                                if(group.name === res.user_owner_group_id){
+                                    this.areas[index].userOwnerGroupName = group.value;
+                                    return true;
+                                }
+                            });
+                        }
+                        this.areas[index].areaOnTray = res.area_on_tray;
+                        this.areas[index].areaOnHalfTray = res.area_on_half_tray;
+                        this.areas[index].areaOnFlat = res.area_on_flat;
+                        this.areas[index].accountingArea = res.accounting_area;
+                        $("#editArea").modal("hide");
+                        return "修改成功";
+                    },true);
                 },
                 createReport(isAll = false){
                     let dom = $("#owners");
@@ -280,6 +343,16 @@
                         return "已生成报表";
                     },true)
                 },
+                audit(index){
+                    window.tempTip.confirm("确定要通过该盘点记录的审核吗?",()=>{
+                        let area = this.areas[index];
+                        let url = '{{url('customer/project/areaReportAudit')}}';
+                        window.tempTip.postBasicRequest(url,{id:area.id},()=>{
+                            this.areas[index].status = "已审核";
+                            return "审核通过";
+                        });
+                    })
+                },
             },
         });
     </script>

+ 12 - 3
resources/views/customer/project/create.blade.php

@@ -96,7 +96,7 @@
                     owner_group_id : "{{$owner->user_owner_group_id ?? ''}}",
                     user_workgroup_id : "{{$owner->user_workgroup_id ?? ''}}",
                     warehouse_id : "{{ $owner->warehouse_id ?? ''}}",
-                    tax_rate : "{{$owner->tax_rate ?? ''}}",
+                    tax_rate_id : "{{$owner->tax_rate_id ?? ''}}",
                     linkman : "{{$owner->linkman ?? ''}}",
                     phone_number : "{{$owner->phone_number ?? ''}}",
                     description : "{{$owner->description ?? ''}}",
@@ -212,6 +212,7 @@
                 let type = "{{$type ?? ''}}";
                 if (type){
                     this.base = "three";
+                    this.type = "";
                     setTimeout(()=>{
                         this.switchType(type);
                         if (!this.isLoad && this.ownerTemp.id)this._loadPriceModel();//计费模型未被加载且项目ID存在时
@@ -265,6 +266,7 @@
                     if (!this.owner.id)return;
                     if (base === this.base)return;
                     if (base === 'three') this._loadStorage();
+                    if (base === 'two')this._getTaxRates()
                     this.base = base;
                 },
                 //切换类型
@@ -380,6 +382,8 @@
                     if (!this.owner.customer_id) error["customer_id"] = ["必须选择客户"];
                     if (!this.owner.owner_group_id) error["owner_group_id"] = ["必须选择项目小组"];
                     if (!this.owner.warehouse_id) error["warehouse_id"] = ["必须选择仓库"];
+                    if (!this.owner.user_workgroup_id) error["user_workgroup_id"] = ["必须选择仓库小组"];
+                    if (!this.owner.tax_rate_id) error["tax_rate_id"] = ["必须选择税率"];
                     if (JSON.stringify(error) !== "{}"){
                         this.errors = error;
                         return;
@@ -391,7 +395,7 @@
                     params.owner_group_id !== old.owner_group_id ||
                     params.user_workgroup_id !== old.user_workgroup_id ||
                     params.warehouse_id !== old.warehouse_id ||
-                    params.tax_rate !== old.tax_rate ||
+                    params.tax_rate_id !== old.tax_rate_id ||
                     params.waring_line_on !== old.waring_line_on ||
                     params.phone_number !== old.phone_number ||
                     params.subjection !== old.subjection ||
@@ -408,7 +412,7 @@
                             this.ownerTemp.owner_group_id = res.owner_group_id;
                             this.ownerTemp.user_workgroup_id = res.user_workgroup_id;
                             this.ownerTemp.warehouse_id = res.warehouse_id;
-                            this.ownerTemp.tax_rate = res.tax_rate;
+                            this.ownerTemp.tax_rate_id = res.tax_rate_id;
                             this.ownerTemp.waring_line_on = res.waring_line_on;
                             this.ownerTemp.phone_number = res.phone_number;
                             this.ownerTemp.description = res.description;
@@ -566,6 +570,11 @@
                     let url = "{{url('maintenance/carType/get')}}";
                     window.axios.post(url).then(res=>{this._setModelData("cars",res.data);});
                 },
+                //获取税率
+                _getTaxRates(){
+                    let url = "{{url('maintenance/taxRate/get')}}";
+                    window.axios.post(url).then(res=>{this._setModelData("taxRates",res.data);});
+                },
                 //保存模型
                 saveModel(){
                     this._clearRefuse();

+ 12 - 8
resources/views/customer/project/index.blade.php

@@ -1,5 +1,5 @@
 @extends('layouts.app')
-@section('title')项目查询-客户管理@endsection
+@section('title')项目列表-客户管理@endsection
 
 @section('content')
     @component('customer.project.menu')@endcomponent
@@ -12,27 +12,27 @@
                         <div class="container-fluid" v-if="priceModel[thisClickIndex]">
                             <div class="row" v-for="(model,i) in priceModel[thisClickIndex]['ownerStoragePriceModels']">
                                 <label class="text-dark font-weight-bold col-3"><span v-if="i==0">仓储:</span></label>
-                                <a target="_blank" :href="'{{url('customer/project')}}/'+thisClickIndex+'/edit?type=storage'" class="text-decoration-none">@{{ model.counting_type }}-@{{ model.using_type }}</a>
+                                <a target="_blank" @can("计费模型-仓储-录入"):href="'{{url('customer/project')}}/'+thisClickIndex+'/edit?type=storage'" @endcan class="text-decoration-none">@{{ model.counting_type }}-@{{ model.using_type }}</a>
                             </div>
                             <hr class="m-1" v-if="priceModel[thisClickIndex]['ownerPriceOperations'].length>0">
                             <div class="row" v-for="(model,i) in priceModel[thisClickIndex]['ownerPriceOperations']">
                                 <label class="text-dark font-weight-bold col-3"><span v-if="i==0">作业:</span></label>
-                                <a target="_blank" :href="'{{url('customer/project')}}/'+thisClickIndex+'/edit?type=operation'" class="text-decoration-none">@{{ model.name }}</a>
+                                <a target="_blank" @can("计费模型-作业-录入"):href="'{{url('customer/project')}}/'+thisClickIndex+'/edit?type=operation'" @endcan class="text-decoration-none">@{{ model.name }}</a>
                             </div>
                             <hr class="m-1" v-if="priceModel[thisClickIndex]['ownerPriceExpresses'].length>0">
                             <div class="row" v-for="(model,i) in priceModel[thisClickIndex]['ownerPriceExpresses']">
                                 <label class="text-dark font-weight-bold col-3"><span v-if="i==0">快递:</span></label>
-                                <a target="_blank" :href="'{{url('customer/project')}}/'+thisClickIndex+'/edit?type=express'" class="text-decoration-none">@{{ model.name }}</a>
+                                <a target="_blank" @can("计费模型-快递-录入"):href="'{{url('customer/project')}}/'+thisClickIndex+'/edit?type=express'" @endcan class="text-decoration-none">@{{ model.name }}</a>
                             </div>
                             <hr class="m-1" v-if="priceModel[thisClickIndex]['ownerPriceLogistics'].length>0">
                             <div class="row" v-for="(model,i) in priceModel[thisClickIndex]['ownerPriceLogistics']">
                                 <label class="text-dark font-weight-bold col-3"><span v-if="i==0">物流:</span></label>
-                                <a target="_blank" :href="'{{url('customer/project')}}/'+thisClickIndex+'/edit?type=logistic'" class="text-decoration-none">@{{ model.name }}</a>
+                                <a target="_blank" @can("计费模型-物流-录入"):href="'{{url('customer/project')}}/'+thisClickIndex+'/edit?type=logistic'" @endcan class="text-decoration-none">@{{ model.name }}</a>
                             </div>
                             <hr class="m-1" v-if="priceModel[thisClickIndex]['ownerPriceDirectLogistics'].length>0">
                             <div class="row" v-for="(model,i) in priceModel[thisClickIndex]['ownerPriceDirectLogistics']">
                                 <label class="text-dark font-weight-bold col-3"><span v-if="i==0">直发车:</span></label>
-                                <a target="_blank" :href="'{{url('customer/project')}}/'+thisClickIndex+'/edit?type=directLogistic'" class="text-decoration-none">@{{ model.name }}</a>
+                                <a target="_blank" @can("计费模型-直发-录入"):href="'{{url('customer/project')}}/'+thisClickIndex+'/edit?type=directLogistic'" @endcan class="text-decoration-none">@{{ model.name }}</a>
                             </div>
                         </div>
                     </div>
@@ -62,7 +62,7 @@
             <table class="d-none" id="headerRoll"></table>
             <table class="table table-sm text-nowrap table-striped table-hover" id="headerParent">
                 <tr id="header"></tr>
-                <tr v-for="(owner,i) in owners" @click="selectTableRow(owner.id,$event)">
+                <tr v-for="(owner,i) in owners" :class="owner.id==id ? 'focusing' : ''"  @click="(selectTableRow(owner.id,$event)) && (id=owner.id)">
                     <td>
                         <label><input type="checkbox" :value="owner.id" v-model="checkData"></label>
                     </td>
@@ -71,6 +71,7 @@
                     <td>@{{ owner.customer_name }}</td>
                     <td>@{{ owner.user_owner_group_name }}</td>
                     <td>@{{ owner.user_work_group_name }}</td>
+                    <td><b>@{{ owner.relevance.length }}</b>/5</td>
                     <td>@{{ owner.created_at }}</td>
                     <td>@{{ owner.customer_company_name }}</td>
                     <td>@{{ ownerSubjection[owner.subjection] }}</td>
@@ -102,6 +103,7 @@
                 owners : [
                     @foreach($owners as $owner)
                     {   id : "{{$owner->id}}",
+                        relevance:{!! $owner->relevance ?? [] !!},
                         customer_name:"{{$owner->customer ? $owner->customer->name : ''}}",
                         //tax_rate  : "{{--{{$owner->tax_rate}}--}}",
                         name : "{{$owner->name}}",
@@ -147,7 +149,8 @@
                     @endforeach
                 ],
                 ownerSubjection:{!! json_encode(\App\Owner::subjection,JSON_UNESCAPED_UNICODE) !!},
-                selectTr:''
+                selectTr:'',
+                id:"",
             },
             mounted(){
                 $('#container').removeClass('d-none');
@@ -177,6 +180,7 @@
                     {name:'customer',value: '客户'},
                     {name:'user_owner_group_name',value: '项目小组'},
                     {name:'user_work_group_name',value: '仓库小组'},
+                    {name:'relevance', neglect: true,value: '计费模型填写情况'},
                     {name:'created_at',value: '创建日期'},
                     {name:'customer_full_name',value: '公司全称'},
                     {name:'subjection',value: '主体公司'},

+ 13 - 7
resources/views/customer/project/part/_storage.blade.php

@@ -38,7 +38,7 @@
         <label for="price" class="col-4 text-info">单价</label>
         <input id="price" type="number" min="0" step="0.001" class="offset-3 col-5 form-control"
                :class="errors.price ? 'is-invalid' : ''" v-model="model.storage.price">
-        <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors.price">
+        <span class="invalid-feedback mt-0 offset-6" role="alert" v-if="errors.price">
             <strong>@{{ errors.price[0] }}</strong>
         </span>
     </div>
@@ -46,10 +46,10 @@
         <label for="unit_id" class="col-5 offset-1 text-info">单位</label>
         <select id="unit_id" class="col-6 form-control"
                 :class="errors.unit_id ? 'is-invalid' : ''" v-model="model.storage.unit_id">
-            <option v-for="unit in pool.units" :value="unit.id" v-if="unit.name == 'm²' || unit.name=='㎡' || unit.name == 'm³' || unit.name == '件' || unit.name == '托'">
+            <option v-for="unit in pool.units" :value="unit.id" v-if="unit.name == 'm²' || unit.name=='㎡' || unit.name == 'm³' || unit.name == '件'">
                 @{{ unit.name }}</option>
         </select>
-        <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors.unit_id">
+        <span class="invalid-feedback mt-0 offset-6" role="alert" v-if="errors.unit_id">
             <strong>@{{ errors.unit_id[0] }}</strong>
         </span>
     </div>
@@ -59,7 +59,7 @@
                 :class="errors.time_unit_id ? 'is-invalid' : ''" v-model="model.storage.time_unit_id">
             <option v-for="unit in pool.units" :value="unit.id" v-if="unit.name == '日' || unit.name == '月'">@{{ unit.name }}</option>
         </select>
-        <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors.time_unit_id">
+        <span class="invalid-feedback mt-0 offset-6" role="alert" v-if="errors.time_unit_id">
             <strong>@{{ errors.time_unit_id[0] }}</strong>
         </span>
     </div>
@@ -74,10 +74,16 @@
         <strong>@{{ errors.discount_type[0] }}</strong>
     </span>
 </div>
-<div class="row mt-3">
+<div class="row mt-3" v-if="model.storage.discount_type != '无减免'">
     <label for="discount_value" class="col-2">减免值</label>
-    <input id="discount_value" type="number" min="0" step="0.001" class="col-6 form-control"
-           :class="errors.discount_value ? 'is-invalid' : ''" v-model="model.storage.discount_value">
+    <label class="col-6 mb-0 input-group ml-0">
+        <input id="discount_value" type="number" min="0" step="0.01" class="col-6 form-control" style="margin-left: -4%"
+               :class="errors.discount_value ? 'is-invalid' : ''" v-model="model.storage.discount_value">
+        <span class="d-block input-group-append">
+            <span class="input-group-text font-weight-bold" v-if="model.storage.discount_type == '按单减免'">单减 1@{{ poolMapping.units[model.storage.unit_id] }}</span>
+            <span class="input-group-text font-weight-bold" v-else>@{{ poolMapping.units[model.storage.unit_id] }}</span>
+        </span>
+    </label>
     <span class="invalid-feedback mt-0 offset-2" role="alert" v-if="errors.discount_value">
         <strong>@{{ errors.discount_value[0] }}</strong>
     </span>

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

@@ -332,23 +332,23 @@
                 <button type="button" class="btn mr-1" :class="type == 'directLogistic' ? 'btn-primary text-white' : 'btn-outline-primary'" @click="switchType('directLogistic')">直发</button>
             </div>
             <div class="card-body">
-                <div v-if="type == 'storage'">
+                @can("计费模型-仓储-录入")<div v-if="type == 'storage'">
                     @include("customer.project.part._storage")
-                </div>
-                <div v-show="type == 'operation'">
+                </div>@endcan
+                @can("计费模型-作业-录入")<div v-show="type == 'operation'">
                     @include("customer.project.part._operation")
                     @include("customer.project.part._addFeature")
-                </div>
-                <div v-show="type == 'express'">
+                </div>@endcan
+                @can("计费模型-快递-录入")<div v-show="type == 'express'">
                     @include("customer.project.part._express")
-                </div>
-                <div v-show="type == 'logistic'">
+                </div>@endcan
+                @can("计费模型-物流-录入")<div v-show="type == 'logistic'">
                     @include("customer.project.part._logistic")
                     @include("customer.project.part._logisticDetail")
-                </div>
-                <div v-show="type == 'directLogistic'">
+                </div>@endcan
+                @can("计费模型-直发-录入")<div v-show="type == 'directLogistic'">
                     @include("customer.project.part._directLogistic")
-                </div>
+                </div>@endcan
                 @include("customer.project.part._introducePriceModel")
                 <div class="row mt-3" v-if="base=='three'">
                     <div class="col-2"></div>

+ 7 - 5
resources/views/customer/project/part/_two.blade.php

@@ -28,7 +28,7 @@
     </span>
 </div>
 <div class="row mt-3">
-    <label for="user_workgroup_id" class="col-2">仓库小组</label>
+    <label for="user_workgroup_id" class="col-2 text-info">仓库小组</label>
     <select id="user_workgroup_id" v-model="owner.user_workgroup_id" @change="selectGroup()" class="form-control form-control-sm col-4 mb-0" :class="errors.user_workgroup_id ? 'is-invalid' : ''" >
         <option v-for="userGroup in filterUserGroups" :value="userGroup.id" v-if="userGroup.warehouse_id == owner.warehouse_id">@{{ userGroup.name }}</option>
     </select>
@@ -44,10 +44,12 @@
     </select>
 </div>
 <div class="row mt-3">
-    <label for="tax_rate" class="col-2">税率<span class="badge badge-secondary">%</span></label>
-    <input type="number" v-model="owner.tax_rate" step="0.01" id="tax_rate" class="form-control form-control-sm col-3 mb-0" :class="errors.tax_rate ? 'is-invalid' : ''">
-    <span class="invalid-feedback offset-2 mt-0" role="alert" v-if="errors.tax_rate">
-        <strong>@{{ errors.tax_rate[0] }}</strong>
+    <label for="tax_rate_id" class="col-2 text-info">税率</label>
+    <select id="tax_rate_id" v-model="owner.tax_rate_id" class="form-control form-control-sm col-4 mb-0" :class="errors.tax_rate_id ? 'is-invalid' : ''" >
+        <option v-for="taxRate in pool.taxRates" :value="taxRate.id">@{{ taxRate.value }}%</option>
+    </select>
+    <span class="invalid-feedback offset-2 mt-0" role="alert" v-if="errors.tax_rate_id">
+        <strong>@{{ errors.tax_rate_id[0] }}</strong>
     </span>
 </div>
 <div class="row mt-3">

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

@@ -115,6 +115,10 @@
                 <li class="nav-item">
                     <a class="nav-link text-muted" href="{{url('maintenance/supplier')}}" :class="{active:isActive('supplier',2)}">供应商</a>
                 </li>@endcan
+            @can('税率')
+                <li class="nav-item">
+                    <a class="nav-link text-muted" href="{{url('maintenance/taxRate')}}" :class="{active:isActive('taxRate',2)}">税率</a>
+                </li>@endcan
             @can('系统配置')
                 <li class="nav-item">
                     <a class="nav-link text-muted" href="{{url('maintenance/configuration')}}" :class="{active:isActive('configuration',2)}">系统配置</a>

+ 23 - 0
resources/views/maintenance/taxRate/_edit.blade.php

@@ -0,0 +1,23 @@
+<div class="modal fade" tabindex="-1" role="dialog" id="modal">
+    <div class="modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable">
+        <div class="modal-content">
+            <div class="modal-header">
+                <button type="button" class="close" data-dismiss="modal">&times;</button>
+            </div>
+            <div class="modal-body">
+                <div class="row">
+                    <label class="col-2 offset-1" for="value">税率</label>
+                    <label class="col-6 mb-0 input-group">
+                        <input type="number" min="0" step="0.01"  class="form-control" v-model="taxRate.value">
+                        <span class="d-block input-group-append">
+                            <span class="input-group-text font-weight-bold">%</span>
+                        </span>
+                    </label>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-success" @click="submit()">提交</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 88 - 0
resources/views/maintenance/taxRate/index.blade.php

@@ -0,0 +1,88 @@
+@extends('layouts.app')
+@section('title')设置@endsection
+@section('content')
+    <span id="nav2">
+       @component('maintenance.menu')@endcomponent
+    </span>
+    <div class="container-fluid" id="container">
+        <div class="card">
+            <div class="card-body">
+                @include("maintenance.taxRate._edit")
+                <div class="row pull-left ml-1">
+                    @can("税率-编辑")<button class="btn btn-outline-info mb-1 mr-3" @click="openModal()"><span class="fa fa-plus"></span>&nbsp;新&nbsp;&nbsp;增</button>@endcan
+                </div>
+                <table class="table table-hover table-striped text-nowrap">
+                    <tr>
+                        <th>序号</th>
+                        <th>税率</th>
+                        <th>创建时间</th>
+                        <th>最后操作时间</th>
+                        <th></th>
+                    </tr>
+                    <tr v-for="(taxRate,i) in taxRates">
+                        <td>@{{ i+1 }}</td>
+                        <td>@{{ taxRate.value }}%</td>
+                        <td class="text-muted">@{{ taxRate.created_at }}</td>
+                        <td class="text-muted">@{{ taxRate.updated_at }}</td>
+                        <td>
+                            @can("税率-编辑")<button class="btn btn-sm btn-outline-info" @click="openModal(taxRate)">改</button>@endcan
+                            @can("税率-删除")<button class="btn btn-sm btn-outline-danger" @click="deleteModel(taxRate,i)">删</button>@endcan
+                        </td>
+                    </tr>
+                </table>
+            </div>
+        </div>
+    </div>
+@stop
+@section("lastScript")
+    <script>
+        new Vue({
+            el:"#container",
+            data:{
+                taxRates:[
+                    @foreach($taxRates as $taxRate)@json($taxRate),@endforeach
+                ],
+                taxRate:{},
+            },
+            methods:{
+                openModal(model){
+                    if (model) this.taxRate={id:model.id,value:model.value};
+                    else this.taxRate={};
+                    $("#modal").modal("show");
+                },
+                submit(){
+                    let url="{{url('maintenance/taxRate/save')}}";
+                    let msg=this.taxRate.id ? "成功修改税率"  : "成功新增税率";
+                    window.tempTip.postBasicRequest(url,this.taxRate,(res)=>{
+                        if (this.taxRate.id){
+                            this.taxRates.some((model)=> {
+                                if (model.id === this.taxRate.id){
+                                    model.value = this.taxRate.value;
+                                    return true;
+                                }
+                            });
+                        }else this.taxRates.unshift({
+                            id:res.id,
+                            value:res.value,
+                            created_at:res.created_at,
+                            updated_at:res.updated_at,
+                        });
+                        $("#modal").modal("hide");
+                        return msg;
+                    },true);
+                },
+                deleteModel(model,index){
+                    let url="{{url('maintenance/taxRate/destroy')}}";
+                    let params = {id:model.id};
+                    let msg="成功删除税率“"+model.value+"%”";
+                    window.tempTip.confirm("您确定要删除税率“"+model.value+"%”吗?",()=>{
+                        window.tempTip.postBasicRequest(url,params,res=>{
+                            this.$delete(this.taxRates,index);
+                            return msg;
+                        });
+                    });
+                },
+            },
+        });
+    </script>
+@stop

+ 28 - 0
resources/views/maintenance/warehouse/create.blade.php

@@ -38,6 +38,34 @@
                             @enderror
                         </div>
                     </div>
+                    <div class="form-group row">
+                        <label for="production_capacity" class="col-2 col-form-label text-right">产能</label>
+                        <div class="col-8">
+                            <input id="production_capacity" type="number" step="0.01" min="0" class="form-control @error('production_capacity') is-invalid @enderror"
+                                   name="production_capacity" autocomplete="off" value="{{ old('production_capacity') }}" required>
+                            @error('production_capacity')
+                            <span class="invalid-feedback" role="alert">
+                                <strong>{{ $message }}</strong>
+                            </span>
+                            @enderror
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="reduced_production_capacity_coefficient" class="col-2 col-form-label text-right">SKU减产系数</label>
+                        <div class="col-8 input-group">
+                            <input id="reduced_production_capacity_coefficient" type="number" class="form-control @error('reduced_production_capacity_coefficient') is-invalid @enderror"
+                                   step="1" min="0" max="100" autocomplete="off"
+                                   name="reduced_production_capacity_coefficient"  value="{{ old('reduced_production_capacity_coefficient') }}" required>
+                            <span class="d-block input-group-append">
+                                <span class="input-group-text font-weight-bold">%</span>
+                            </span>
+                            @error('reduced_production_capacity_coefficient')
+                            <span class="invalid-feedback" role="alert">
+                                <strong>{{ $message }}</strong>
+                            </span>
+                            @enderror
+                        </div>
+                    </div>
                     <div class="form-group row">
                         <div class="col-8 offset-2">
                             <input type="submit" class="btn btn-success form-control">

+ 28 - 0
resources/views/maintenance/warehouse/edit.blade.php

@@ -44,6 +44,34 @@
                             @enderror
                         </div>
                     </div>
+                    <div class="form-group row">
+                        <label for="production_capacity" class="col-2 col-form-label text-right">产能</label>
+                        <div class="col-8">
+                            <input id="production_capacity" type="number" step="0.01" min="0" class="form-control @error('production_capacity') is-invalid @enderror"
+                                   name="production_capacity" autocomplete="off" value="{{ old('production_capacity') ?? $warehouse->production_capacity }}" required>
+                            @error('production_capacity')
+                            <span class="invalid-feedback" role="alert">
+                                <strong>{{ $message }}</strong>
+                            </span>
+                            @enderror
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="reduced_production_capacity_coefficient" class="col-2 col-form-label text-right">SKU减产系数</label>
+                        <div class="col-8 input-group">
+                            <input id="reduced_production_capacity_coefficient" type="number" class="form-control @error('reduced_production_capacity_coefficient') is-invalid @enderror"
+                                   step="1" min="0" max="100" autocomplete="off"
+                                   name="reduced_production_capacity_coefficient"  value="{{ old('reduced_production_capacity_coefficient') ?? $warehouse->reduced_production_capacity_coefficient }}" required>
+                            <span class="d-block input-group-append">
+                                <span class="input-group-text font-weight-bold">%</span>
+                            </span>
+                            @error('reduced_production_capacity_coefficient')
+                            <span class="invalid-feedback" role="alert">
+                                <strong>{{ $message }}</strong>
+                            </span>
+                            @enderror
+                        </div>
+                    </div>
                     <div class="form-group row">
                         <div class="col-8 offset-2">
                             <input type="submit" class="btn btn-outline-dark form-control">

+ 8 - 1
resources/views/maintenance/warehouse/index.blade.php

@@ -17,6 +17,8 @@
                         <th>ID</th>
                         <th>仓库名</th>
                         <th>仓库代码</th>
+                        <th>产能</th>
+                        <th>SKU减产系数</th>
                         <th>创建时间</th>
                         <th>操作</th>
                     </tr>
@@ -24,6 +26,8 @@
                         <td class="text-muted">@{{warehouse.id}}</td>
                         <td>@{{warehouse.name}}</td>
                         <td>@{{warehouse.code}}</td>
+                        <td>@{{warehouse.production_capacity}}</td>
+                        <td>@{{warehouse.reduced_production_capacity_coefficient}}%</td>
                         <td class="text-muted">@{{warehouse.created_at}}</td>
                         <td>
                             @can('仓库-编辑')
@@ -46,7 +50,10 @@
             data:{
                 warehouses:[
                     @foreach( $warehouses as $warehouse )
-                    {id:'{{$warehouse->id}}',name:'{{$warehouse->name}}',code:'{{$warehouse->code}}',created_at:'{{$warehouse->created_at}}'},
+                    {id:'{{$warehouse->id}}',name:'{{$warehouse->name}}',
+                        production_capacity:"{{$warehouse->production_capacity}}",
+                        reduced_production_capacity_coefficient:"{{$warehouse->reduced_production_capacity_coefficient}}",
+                        code:'{{$warehouse->code}}',created_at:'{{$warehouse->created_at}}'},
                     @endforeach
                 ],
             },

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

@@ -139,7 +139,7 @@
                             axios.post('/package/measureMonitor/speech',{logistic:logistic_name})
                                 .then(function (response) {
                                     if (response.data){
-                                        _this.logisticAudioURL[_this.package.logistic_name]=response.data;
+                                        _this.logisticAudioURL[logistic_name]=response.data;
                                         audio.src=response.data;
                                         audio.play();
                                     }else {

+ 0 - 12
resources/views/store/checkingReceive/_selectDate.blade.php

@@ -1,12 +0,0 @@
-<div class="modal fade" tabindex="-1" role="dialog" id="selectDate">
-    <div class="modal-dialog modal-lg modal-dialog-centered">
-        <div class="modal-content">
-            <div class="modal-body">
-
-            </div>
-            <div class="modal-footer">
-                <button type="button" class="btn btn-success pull-right" @click="createReport()">生成</button>
-            </div>
-        </div>
-    </div>
-</div>

+ 1 - 5
resources/views/store/checkingReceive/menu.blade.php

@@ -4,13 +4,9 @@
             <ul class="nav nav-pills">
                 @can('入库管理-盘收一体-任务')
                     <li class="nav-item">
-                        <a target="store/checkingReceive/mission" class="nav-link" href="{{url('store/checkingReceive/mission')}}" :class="{active:isActive('mission',3)}">任务</a>
+                        <a target="store/checkingReceive/mission" class="nav-link" href="{{url('store/checkingReceive/mission')}}" :class="{active:isActive('',4)}">任务</a>
                     </li> @endcan
                 {{$slot}}
-                @can('入库管理-盘收一体-客户预约')
-                <li class="nav-item">
-                    <a target="store/checkingReceive/mission" class="nav-link" href="{{url('store/checkingReceive/appointment')}}" :class="{active:isActive('appointment',3)}">客户预约</a>
-                </li> @endcan
             </ul>
         </div>
     </div>

+ 27 - 0
resources/views/store/deliveryAppointment/_selectDate.blade.php

@@ -0,0 +1,27 @@
+<div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-hidden="true">
+    <div class="modal-dialog modal-dialog-centered modal-lg" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <div class="text-center font-weight-bold">预约时间</div>
+                <button type="button" class="close" data-dismiss="modal">&times;</button>
+            </div>
+            <div class="modal-body">
+                <div class="row">
+                    <div v-for="capacity in capacities" :style="{width:(100/capacities.length)+'%'}" class="container">
+                        <div class="row">
+                            <div class="col-12 text-center">@{{ capacity.date }}</div>
+                        </div>
+                        <div class="row border border-2 rounded" v-for="period in capacity.period" style="min-height: 50px;"
+                             :class="[period.isAvailable ? 'cursor-pointer text-dark bg-info' : 'opacity bg-secondary',
+                             selectDate.date==capacity.date && selectDate.time==period.index ? 'box-shadow-dark' : '']" @click="selectPeriod(capacity.date,period.index,period.isAvailable)">
+                            <div class="col-12 m-auto text-center">@{{ period.time }}</div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button class="col-12 btn btn-success" @click="submitAppointment()">确定预约</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 103 - 12
resources/views/store/checkingReceive/appointment.blade.php → resources/views/store/deliveryAppointment/appointment.blade.php

@@ -4,7 +4,7 @@
 @section('content')
     <span id="nav2">
     @component('store.menu')@endcomponent
-    @component('store.checkingReceive.menu')@endcomponent
+    @component('store.deliveryAppointment.menu')@endcomponent
     </span>
     <div class="container-fluid" id="container">
         <div class="card">
@@ -30,9 +30,10 @@
                                 </label>
                                 <label class="col-2">
                                     <div class="dropdown">
-                                        <input type="text" class="form-control" v-model="car.car_id" :id="'car-'+i" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
-                                        <div class="dropdown-menu" :aria-labelledby="'car-'+i">
-
+                                        <input type="text" class="form-control" v-model="car.car_name" :id="'car-'+i" @input="searchCar(car.car_name)"
+                                               data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                                        <div class="dropdown-menu" :aria-labelledby="'car-'+i" v-show="car.car_name && haystack.length>0">
+                                            <span class="row offset-1 text-secondary" v-for="c in haystack" @click="selectCar(c,i)">@{{ c.name }}<br></span>
                                         </div>
                                     </div>
                                 </label>
@@ -71,7 +72,9 @@
                     </div>
                     <div class="row mt-2 ml-1">
                         <label class="col-2" for="warehouse">仓库</label>
-                        <input class="col-6 form-control" type="text" id="warehouse" v-model="model.warehouse_id" :class="errors.warehouse_id ? 'is-invalid' : ''">
+                        <select id="warehouse" v-model="model.warehouse_id" class="col-4 form-control" :class="errors.warehouse_id ? 'is-invalid' : ''">
+                            <option v-for="warehouse in warehouses" :value="warehouse.id">@{{ warehouse.name }}</option>
+                        </select>
                     </div>
                     <label class="row mt-0 mb-0 ml-1" v-if="errors.warehouse_id">
                         <label class="offset-2 text-danger font-weight-bold small">@{{ errors.warehouse_id[0] }}</label>
@@ -108,6 +111,7 @@
                         <button type="button" class="btn btn-success col-8 offset-2" @click="submit()">提 交 预 约</button>
                     </div>
                 </div>
+                @include("store.deliveryAppointment._selectDate")
             </div>
         </div>
     </div>
@@ -118,25 +122,41 @@
         new Vue({
             el:"#container",
             data:{
-                cars:[],
+                cars:[@foreach($cars as $car)@json($car),@endforeach],
                 model:{
                     cars:[{license_plate_number:"",car_id:"",driver_name:"",driver_phone:""}],
                 },
-                owners:@json($owners),
+                owners:[@foreach($owners as $owner)@json($owner),@endforeach],
+                warehouses:[@foreach($warehouses as $warehouse)@json($warehouse),@endforeach],
                 fileName:"",
                 details:[],
                 errors : {
                     details:"",
                 },
-                datePeriod : {
-                    0:"9-11",1:"13-17",
-                },
+                haystack:[],
+                capacities:[],
+                selectDate:{},
             },
             mounted(){
                 if (this.owners.length === 1)this.$set(this.model,"owner_id",this.owners[0].id);
                 $('#openFile').tooltip();
             },
             methods:{
+                selectCar(car,index){
+                    this.model.cars[index].car_id = car.id;
+                    this.model.cars[index].car_name = car.name;
+                },
+                searchCar(name){
+                    if (!name){
+                        this.haystack = [];
+                        return;
+                    }
+                    let stack = [];
+                    this.cars.forEach(car=>{
+                        if (car.name.indexOf(name)!==-1)stack.push(car);
+                    });
+                    this.haystack = stack;
+                },
                 seekOwner(e){
                     let val = e.target.value;
                     this.owners.some(owner=>{
@@ -156,7 +176,7 @@
                     this.fileName = file.name;
                     let formData = new FormData();
                     formData.append("file",file);
-                    window.axios.post('{{url('store/checkingReceive/appointment/import')}}',formData,{
+                    window.axios.post('{{url('store/deliveryAppointment/appointment/import')}}',formData,{
                         'Content-Type':'multipart/form-data'
                     }).then(res=>{
                         if (!res.data.success){
@@ -207,15 +227,86 @@
                         errors.tonne = ["吨与立方值至少填写一个"];
                         errors.cubic_meter = ["立方值与吨至少填写一个"];
                     }
+                    let change = [];
+                    let insert = [];
                     this.model.cars.forEach((car,i)=>{
                         if (!car.license_plate_number) errors[i+".license_plate_number"] = ["不得为空"];
+                        if (!car.car_id && car.car_name){
+                            if (this.cars.every(c=>{
+                               if (c.name === car.car_name){
+                                   car.car_id = c.id;
+                                   return false;
+                               }
+                               return true;
+                            })){
+                                change.push({index:i,name:car.car_name});
+                                if (insert.indexOf(car.car_name)===-1)insert.push(car.car_name);
+                            }
+                        }
                     });
                     if (JSON.stringify(errors) !== "{}"){
                         errors.details=this.errors.details;
                         this.errors = errors;
                         return
                     }
-                    window.tempTip.postBasicRequest();
+                    if (change.length>0)this._addCars(insert,change);
+                    let param = {
+                        warehouse_id:this.model.warehouse_id,
+                        tonne:this.model.tonne,
+                        cubic_meter:this.model.cubic_meter,
+                        detail_amount:this.details.length,
+                    };
+                    window.tempTip.postBasicRequest("{{url('store/deliveryAppointment/getCapacity')}}",param,res=>{
+                        this.capacities = res;
+                        $("#modal").modal("show");
+                    });
+                },
+                _addCars(arr,change){
+                    window.tempTip.postBasicRequest("{{url('maintenance/carType/batchInsert')}}",{arr:arr},res=>{
+                        res.forEach(data=>{
+                            change.forEach(car=>{
+                                if (data.name === car.name)this.model.cars[car.index].car_id = data.id;
+                            });
+                        });
+                    });
+                },
+                selectPeriod(date,time,isSelect){
+                    if (isSelect) this.selectDate = {date:date,time:time};
+                },
+                submitAppointment(){
+                    window.tempTip.setDuration(3000);
+                    window.tempTip.setIndex(1099);
+                    if (!this.selectDate.date){
+                        window.tempTip.show("尚未选择预约时间");
+                        return;
+                    }
+                    let url = "{{url('store/deliveryAppointment/submitAppointment')}}";
+                    let param = {
+                        model:this.model,
+                        details:this.details,
+                        date:this.selectDate,
+                    };
+                    window.tempTip.postBasicRequest(url,param,res=>{
+                        if (res.errors){
+                            this.errors = errors;
+                            return;
+                        }
+                        if (res.isFail){
+                            this.capacities.some(capacity=>{
+                                if (capacity.date === this.selectDate.date){
+                                    capacity.period.some(p=>{
+                                        if (p.index === this.selectDate.time){
+                                            p.isAvailable = false;
+                                            return true;
+                                        }
+                                    });
+                                    return true;
+                                }
+                            });
+                            window.tempTip.show("该预约时段已经被抢占了,请选择其他时段");
+                            return;
+                        }
+                    },true);
                 },
             },
         });

+ 12 - 0
resources/views/store/deliveryAppointment/menu.blade.php

@@ -0,0 +1,12 @@
+<div id="nav2">
+    <div class="container-fluid nav3">
+        <div class="card menu-third" >
+            <ul class="nav nav-pills">
+                @can('入库管理-客户预约-预约')
+                <li class="nav-item">
+                    <a target="store/checkingReceive/mission" class="nav-link" href="{{url('store/deliveryAppointment/appointment')}}" :class="{active:isActive('appointment',3)}">客户预约</a>
+                </li> @endcan
+            </ul>
+        </div>
+    </div>
+</div>

+ 6 - 2
resources/views/store/menu.blade.php

@@ -6,9 +6,13 @@
                 <li class="nav-item">
                     <a target="store/inStorage/index" class="nav-link"  href="{{url('store/inStorage/index')}}" :class="{active:isActive('inStorage',2)}">入库</a>
                 </li> @endcan
-                @can('入库管理-盘收一体')
+            @can('入库管理-盘收一体')
+            <li class="nav-item">
+                <a target="store/checkingReceive/mission" class="nav-link"  href="{{url('store/checkingReceive/mission')}}" :class="{active:isActive('checkingReceive',2)}">盘收一体</a>
+            </li> @endcan
+            @can('入库管理-客户预约')
                 <li class="nav-item">
-                    <a target="store/checkingReceive/mission" class="nav-link"  href="{{url('store/checkingReceive/mission')}}" :class="{active:isActive('checkingReceive',2)}">盘收一体</a>
+                    <a target="store/deliveryAppointment/appointment" class="nav-link"  href="{{url('store/deliveryAppointment/appointment')}}" :class="{active:isActive('deliveryAppointment',2)}">客户预约</a>
                 </li> @endcan
             @can('入库管理-快速入库')
                 <li class="nav-item">

+ 14 - 0
routes/web.php

@@ -188,6 +188,12 @@ Route::group(['prefix'=>'maintenance'],function(){
     });
     Route::group(['prefix'=>'carType'],function (){
         Route::post('get','CarTypesController@get');
+        Route::post('batchInsert','CarTypesController@batchInsert');
+    });
+    Route::group(['prefix'=>'taxRate'],function (){
+        Route::post('get','TaxRateController@get');
+        Route::post('save','TaxRateController@save');
+        Route::post('destroy','TaxRateController@destroy');
     });
     Route::group(['prefix'=>"log"],function (){
         Route::get("exception",'LogController@exception');
@@ -214,6 +220,7 @@ Route::group(['prefix'=>'maintenance'],function(){
 
     Route::get('syncRedisLogs','LogController@syncRedisLogs');
     Route::get('region', 'RegionController@index');
+    Route::get('taxRate', 'TaxRateController@index');
     Route::resource('log', 'LogController');
     Route::resource('user', 'UserController');
     Route::resource('role', 'RoleController');
@@ -406,7 +413,13 @@ Route::group(['prefix'=>'store'],function(){
         Route::post('insertItem','StoreCheckingReceiveController@insertItem');
         Route::get('mission','StoreCheckingReceiveController@mission');
         Route::post('destroyItem','StoreCheckingReceiveController@destroyItem');
+    });
+
+    /** 客户预约 */
+    Route::group(['prefix'=>'deliveryAppointment'],function(){
         Route::get('appointment','DeliveryAppointmentController@appointment');
+        Route::post('getCapacity','DeliveryAppointmentController@getCapacity');
+        Route::post('submitAppointment','DeliveryAppointmentController@submitAppointment');
         Route::group(['prefix'=>'appointment'],function(){
             Route::post('import','DeliveryAppointmentController@import');
         });
@@ -681,6 +694,7 @@ Route::group(['prefix'=>'customer'],function(){
         Route::post('getOwnerPriceModel','CustomerController@getOwnerPriceModel');
         Route::post('updateArea','CustomerController@updateArea');
         Route::post('verify','CustomerController@verifyProject');
+        Route::post('areaReportAudit','CustomerController@areaReportAudit');
 
         //获取现有计费模型
         Route::post('getPriceModel','PriceModelController@getPriceModel');