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

Merge branch 'Haozi' of ssh://was.baoshi56.com:10022/var/git/bswas

 Conflicts:
	app/Http/Controllers/TestController.php
	bootstrap/cache/packages.php
	composer.lock
LD 5 лет назад
Родитель
Сommit
f262a53b74
72 измененных файлов с 4820 добавлено и 116 удалено
  1. 79 0
      app/Console/Commands/CreateProcurementTotalBill.php
  2. 123 0
      app/Filters/ProcurementCheckSheetFilters.php
  3. 158 0
      app/Filters/ProcurementFilters.php
  4. 1 1
      app/Http/Controllers/LaborReportController.php
  5. 3 3
      app/Http/Controllers/OwnerMaterialController.php
  6. 85 0
      app/Http/Controllers/ProcurementCheckSheetController.php
  7. 433 0
      app/Http/Controllers/ProcurementController.php
  8. 85 0
      app/Http/Controllers/ProcurementDeliverieController.php
  9. 85 0
      app/Http/Controllers/ProcurementQuotationController.php
  10. 85 0
      app/Http/Controllers/ProcurementTotalBillController.php
  11. 50 6
      app/Http/Controllers/SupplierController.php
  12. 6 4
      app/Http/Controllers/TestController.php
  13. 98 0
      app/Http/Controllers/api/procurement/wechat/AuthController.php
  14. 1 0
      app/Http/Kernel.php
  15. 56 0
      app/Http/Middleware/ProcurementApiAuth.php
  16. 40 0
      app/Http/Requests/Procurement/EnquiryRequest.php
  17. 40 0
      app/Http/Requests/Procurement/ProcurementAmountRequest.php
  18. 44 0
      app/Http/Requests/Procurement/ProcurementRequest.php
  19. 41 0
      app/Http/Requests/Procurement/ProofRequest.php
  20. 6 1
      app/Material.php
  21. 14 0
      app/MaterialSupplier.php
  22. 4 0
      app/Owner.php
  23. 73 0
      app/Procurement.php
  24. 31 0
      app/ProcurementCheckSheet.php
  25. 27 0
      app/ProcurementDeliverie.php
  26. 22 0
      app/ProcurementQuotation.php
  27. 32 0
      app/ProcurementTotalBill.php
  28. 6 0
      app/Providers/AppServiceProvider.php
  29. 20 0
      app/Services/OwnerMaterialService.php
  30. 37 0
      app/Services/ProcurementService.php
  31. 34 0
      app/Services/ProcurementTotalBillService.php
  32. 1 2
      app/Services/WarehouseService.php
  33. 1 2
      app/Supplier.php
  34. 28 0
      app/Traits/RequestApiFormValidation.php
  35. 13 1
      app/User.php
  36. 12 0
      bootstrap/cache/packages.php
  37. 14 12
      bootstrap/cache/services.php
  38. 1 0
      composer.json
  39. 512 77
      composer.lock
  40. 2 0
      config/app.php
  41. 2 1
      config/auth.php
  42. 304 0
      config/jwt.php
  43. 42 0
      database/migrations/2021_02_03_145200_create_procurements_table.php
  44. 37 0
      database/migrations/2021_02_03_151138_create_procurement_quotations_table.php
  45. 37 0
      database/migrations/2021_02_03_151704_create_procurement_deliveries_table.php
  46. 36 0
      database/migrations/2021_02_03_152845_create_procurement_check_sheets_table.php
  47. 35 0
      database/migrations/2021_02_03_153406_create_procurement_total_bills_table.php
  48. 36 0
      database/migrations/2021_02_03_161934_add_authorrities_to_procurement.php
  49. 32 0
      database/migrations/2021_02_25_092328_change_material_suppliers.php
  50. 31 0
      database/migrations/2021_03_01_140330_create_supplier_user_table.php
  51. 1 1
      laravel-echo-server.lock
  52. 5 0
      resources/views/layouts/menu.blade.php
  53. 8 0
      resources/views/maintenance/supplier/_create.blade.php
  54. 7 0
      resources/views/maintenance/supplier/_edit.blade.php
  55. 16 4
      resources/views/maintenance/supplier/index.blade.php
  56. 24 0
      resources/views/procurement/finance/_changeCostPrice.blade.php
  57. 24 0
      resources/views/procurement/finance/_fillInvoiceNumber.blade.php
  58. 222 0
      resources/views/procurement/finance/checkBill.blade.php
  59. 23 0
      resources/views/procurement/finance/menu.blade.php
  60. 137 0
      resources/views/procurement/finance/monthlyBillReport.blade.php
  61. 212 0
      resources/views/procurement/finance/procurementBill.blade.php
  62. 21 0
      resources/views/procurement/menu.blade.php
  63. 32 0
      resources/views/procurement/menuProcurement.blade.php
  64. 115 0
      resources/views/procurement/procurement/_addEnquiry.blade.php
  65. 106 0
      resources/views/procurement/procurement/_addProcurement.blade.php
  66. 115 0
      resources/views/procurement/procurement/_addProof.blade.php
  67. 54 0
      resources/views/procurement/procurement/_addQuantity.blade.php
  68. 187 0
      resources/views/procurement/procurement/create.blade.php
  69. 460 0
      resources/views/procurement/procurement/index.blade.php
  70. 19 0
      resources/views/procurement/procurement/menu.blade.php
  71. 8 1
      routes/api.php
  72. 29 0
      routes/web.php

+ 79 - 0
app/Console/Commands/CreateProcurementTotalBill.php

@@ -0,0 +1,79 @@
+<?php
+
+namespace App\Console\Commands;
+
+use App\ProcurementCheckSheet;
+use Illuminate\Console\Command;
+use Illuminate\Support\Facades\DB;
+
+class CreateProcurementTotalBill extends Command
+{
+    /**
+     * The name and signature of the console command.
+     *
+     * @var string
+     */
+    protected $signature = 'createProcurementTotalBill';
+
+    /**
+     * The console command description.
+     *
+     * @var string
+     */
+    protected $description = '采购生成总账单';
+
+    /**
+     * Create a new command instance.
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /**
+     * Execute the console command.
+     *
+     * @return int
+     */
+    public function handle()
+    {
+        $date=$this->getDate();
+        $procurementCheckSheets=ProcurementCheckSheet::query()
+            ->selectRaw('procurements.supplier_id supplier_id,procurement_check_sheets.created_at created_at,procurement_check_sheets.status status,SUM(procurement_check_sheets.account_payable) account_payable')
+            ->leftJoin('procurement_deliveries','procurement_check_sheets.procurement_delivery_id','procurement_deliveries.id')
+            ->leftJoin('procurements','procurement_deliveries.procurement_id','procurements.id')
+            ->where('procurement_check_sheets.created_at','like',$date."%")
+            ->groupBy('supplier_id')
+            ->get();
+        $totalBill=[];
+        foreach ($procurementCheckSheets as $procurementCheckSheet){
+            $totalBill[]=[
+                'counting_month'=>$date.'-01',
+                'supplier_id'=>$procurementCheckSheet->supplier_id,
+                'total_payable'=>$procurementCheckSheet->account_payable,
+                'status'=>$procurementCheckSheet->status,
+                'created_at'=>date('Y-m-01 00:00:00'),
+                'updated_at'=>date('Y-m-01 00:00:00'),
+            ];
+        }
+        if (count($totalBill)>0){
+            DB::table("procurement_total_bills")->insert($totalBill);
+            app('LogService')->log(__METHOD__,"采购管理-生成月账单报表",json_encode($totalBill));
+        }
+    }
+
+    private function getDate(){//获取当前日期的上月 月份
+        $month = (int)date('m');
+        $year = (int)date('Y');
+        if ($month == 1){
+            $year--;
+            $lastMonth = '12';
+        }else{
+            $lastMonth = ($month-1) < 10 ? "0".($month-1) : ($month-1);
+        }
+        $date=$year."-".$lastMonth;
+        return $date;
+    }
+}

+ 123 - 0
app/Filters/ProcurementCheckSheetFilters.php

@@ -0,0 +1,123 @@
+<?php
+
+
+namespace App\Filters;
+
+
+
+use App\Procurement;
+use App\ProcurementDeliverie;
+use App\Supplier;
+use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Http\Request;
+
+class ProcurementCheckSheetFilters
+{
+    protected $request;
+    protected $queryBuilder;
+    protected $procurementDeliveryQuery;
+    protected $procurementQuery;
+    protected $supplierQuery;
+    protected $array_filter;
+    protected $filters = [
+        'id','status','signed_at','supplier_id',
+    ];
+    protected $params = [];
+
+    public function __construct(Request $request)
+    {
+        $this->request = $request;
+        $this->params = $request->all();
+    }
+
+    public function apply($builder)
+    {
+        $this->queryBuilder = $builder;
+        $filters = array_filter($this->request->only($this->filters));
+        $this->beforeApply();
+
+        foreach ($filters as $filter => $value) {
+            if (method_exists($this, $filter)) {
+                $this->$filter($value, $this->queryBuilder);
+            }
+        }
+        $this->afterApply();
+        return $this->queryBuilder;
+    }
+
+    private function isSearchLike($str):bool
+    {
+        if (substr($str, 0, 1) == "%" || substr($str, strlen($str) - 1, 1) == "%") {
+            return true;
+        }
+        return false;
+    }
+
+    private function searchWay($query, $param, $column)
+    {
+        if ($this->isSearchLike($param)) {
+            $query->where($column, 'like', $param);
+        } else {
+            $query->whereIn($column, array_filter(preg_split('/[,, ]+/is', $param)));
+        }
+        return $query;
+    }
+    private function getProcurementDeliveryQuery():Builder
+    {
+        if(!$this->procurementDeliveryQuery)
+            $this->procurementDeliveryQuery = ProcurementDeliverie::query()->selectRaw('id');
+        return $this->procurementDeliveryQuery;
+    }
+    private function getProcurementQuery():Builder
+    {
+        if(!$this->procurementQuery)
+            $this->procurementQuery = Procurement::query()->selectRaw('id');
+        return $this->procurementQuery;
+    }
+    private function getSupplierQuery():Builder
+    {
+        if(!$this->supplierQuery)
+            $this->supplierQuery = Supplier::query()->selectRaw('id');
+        return $this->supplierQuery;
+    }
+    public function id($id)
+    {
+        $this->queryBuilder->whereIn('id',$id);
+    }
+    public function status($status)
+    {
+        $this->queryBuilder->where('status',$status);
+    }
+
+    public function supplier_id($supplier_id)
+    {
+        $this->searchWay($this->getSupplierQuery(),$supplier_id,'id');
+    }
+    public function signed_at($signed_at)
+    {
+        $this->getProcurementDeliveryQuery()->where('signed_at','>=',"{$signed_at} 00:00:00")->where('signed_at','<=',"{$signed_at} 23:59:59");
+    }
+
+    public function beforeApply()
+    {
+        if(isset($this->params['data'])){
+            $ids = explode(',',$this->params['data']);
+            $this->id($ids);
+        }
+    }
+
+    public function afterApply()
+    {
+
+        if($this->supplierQuery)
+            $this->getProcurementQuery()->whereIn('supplier_id',$this->supplierQuery);
+
+        if($this->procurementQuery)
+            $this->getProcurementDeliveryQuery()->whereIn('procurement_id',$this->procurementQuery);
+
+        if($this->procurementDeliveryQuery)
+            $this->queryBuilder->whereIn('procurement_delivery_id',$this->procurementDeliveryQuery);
+
+
+    }
+}

+ 158 - 0
app/Filters/ProcurementFilters.php

@@ -0,0 +1,158 @@
+<?php
+
+
+namespace App\Filters;
+
+
+use App\Customer;
+use App\Material;
+use App\Owner;
+use App\OwnerMaterial;
+use App\Supplier;
+use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Http\Request;
+
+class ProcurementFilters
+{
+    protected $request;
+    protected $queryBuilder;
+    protected $ownerMaterialQuery;
+    protected $materialQuery;
+    protected $ownerQuery;
+    protected $supplierQuery;
+    protected $customerQuery;
+    protected $array_filter;
+    protected $filters = [
+        'id','owner_id','material_id','company_name','created_at_start','created_at_end','supplier_id'
+    ];
+    protected $params = [];
+
+    public function __construct(Request $request)
+    {
+        $this->request = $request;
+        $this->params = $request->all();
+    }
+
+    public function apply($builder)
+    {
+        $this->queryBuilder = $builder;
+        $filters = array_filter($this->request->only($this->filters));
+        $this->beforeApply();
+
+        foreach ($filters as $filter => $value) {
+            if (method_exists($this, $filter)) {
+                $this->$filter($value, $this->queryBuilder);
+            }
+        }
+        $this->afterApply();
+        return $this->queryBuilder;
+    }
+
+    private function isSearchLike($str):bool
+    {
+        if (substr($str, 0, 1) == "%" || substr($str, strlen($str) - 1, 1) == "%") {
+            return true;
+        }
+        return false;
+    }
+
+    private function searchWay($query, $param, $column)
+    {
+        if ($this->isSearchLike($param)) {
+            $query->where($column, 'like', $param);
+        } else {
+            $query->whereIn($column, array_filter(preg_split('/[,, ]+/is', $param)));
+        }
+        return $query;
+    }
+
+    private function getMaterialQuery():Builder
+    {
+        if(!$this->materialQuery)
+            $this->materialQuery = Material::query()->selectRaw('id');
+        return $this->materialQuery;
+    }
+    private function getOwnerMaterialQuery():Builder
+    {
+        if(!$this->ownerMaterialQuery)
+            $this->ownerMaterialQuery = OwnerMaterial::query()->selectRaw('id');
+        return $this->ownerMaterialQuery;
+    }
+    private function getOwnerQuery():Builder
+    {
+        if(!$this->ownerQuery)
+            $this->ownerQuery = Owner::query()->selectRaw('id');
+        return $this->ownerQuery;
+    }
+    private function getSupplierQuery():Builder
+    {
+        if(!$this->supplierQuery)
+            $this->supplierQuery = Supplier::query()->selectRaw('id');
+        return $this->supplierQuery;
+    }
+    private function getCustomerQuery():Builder
+    {
+        if(!$this->customerQuery)
+            $this->customerQuery = Customer::query()->selectRaw('id');
+        return $this->customerQuery;
+    }
+
+    public function created_at_start($created_at)
+    {
+        $this->queryBuilder->where('created_at','>=',"{$created_at} 00:00:00");
+    }
+
+    public function created_at_end($created_at)
+    {
+        $this->queryBuilder->where('created_at','<=',"{$created_at} 23:59:59");
+    }
+
+    public function company_name($company_name)
+    {
+        $this->getCustomerQuery()->where('company_name','like',$company_name);
+    }
+    public function id($id)
+    {
+        $this->queryBuilder->whereIn('id',$id);
+    }
+    public function owner_id($owner_id)
+    {
+        $this->searchWay($this->getOwnerQuery(),$owner_id,'owner_id');
+    }
+    public function supplier_id($supplier_id)
+    {
+        $this->searchWay($this->getSupplierQuery(),$supplier_id,'id');
+    }
+
+    public function material_id($material_id)
+    {
+        $this->searchWay($this->getMaterialQuery(),$material_id,'id');
+    }
+
+    public function beforeApply()
+    {
+        if(isset($this->params['data'])){
+            $ids = explode(',',$this->params['data']);
+            $this->id($ids);
+        }
+    }
+
+    public function afterApply()
+    {
+        if($this->customerQuery)
+            $this->getOwnerQuery()->whereIn('customer_id',$this->customerQuery);
+
+        if($this->ownerQuery)
+            $this->getOwnerMaterialQuery()->whereIn('owner_id',$this->ownerQuery);
+
+        if($this->materialQuery)
+            $this->getOwnerMaterialQuery()->whereIn('material_id',$this->materialQuery);
+
+        if($this->ownerMaterialQuery)
+            $this->queryBuilder->whereIn('owner_material_id',$this->ownerMaterialQuery);
+
+        if($this->supplierQuery)
+            $this->queryBuilder->whereIn('supplier_id',$this->supplierQuery);
+
+    }
+}

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

@@ -114,7 +114,7 @@ class LaborReportController extends Controller
 
     //门卫打卡审核
     public function guardClockAudit(Request $request){
-        if(!Gate::allows('人事管理-门卫审核')){ return ["success"=>false,"data"=>"您无此权限操作!!!"];  }
+        if(!Gate::allows('人事管理-门卫审核')){ return ["success"=>false,"data"=>"您无此权限操作!"];  }
         $id=$request->input('id');
         $userDutyCheckId=$request->input('user_duty_check_id');
         $laborReportStatus=new LaborReportStatus([

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

@@ -8,7 +8,7 @@ use App\Filters\OwnerMaterialFilters;
 use App\Material;
 use App\OwnerMaterial;
 use App\Services\OwnerService;
-use App\UploadFile;
+use App\file;
 use Faker\Provider\Uuid;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Auth;
@@ -60,7 +60,7 @@ class OwnerMaterialController extends Controller
         $this->success();
     }
 
-    public function uploadFileApi(Request $request)
+    public function fileApi(Request $request)
     {
         $this->gate('项目耗材-文件上传');
         $ownerMaterial = OwnerMaterial::query()->find($request['id']);
@@ -71,7 +71,7 @@ class OwnerMaterialController extends Controller
             $fileType = $file->getMimeType();// 文件类型
             $fileName = strtolower($file->getClientOriginalExtension());// 文件名
             $path = $file->storeAs("ownerMaterial", Uuid::uuid() . "." . $fileName);
-            $file = UploadFile::query()->create([
+            $file = file::query()->create([
                 'table_name' => 'owner_material',
                 'table_id' => $ownerMaterial['id'],
                 'url' => $path,

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

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

+ 433 - 0
app/Http/Controllers/ProcurementController.php

@@ -0,0 +1,433 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Components\AsyncResponse;
+use App\Configuration;
+use App\Filters\ProcurementCheckSheetFilters;
+use App\Filters\ProcurementFilters;
+use App\Http\Requests\Procurement\EnquiryRequest;
+use App\Http\Requests\Procurement\ProcurementAmountRequest;
+use App\Http\Requests\Procurement\ProcurementRequest;
+use App\Http\Requests\Procurement\ProofRequest;
+use App\Material;
+use App\Procurement;
+use App\ProcurementCheckSheet;
+use App\ProcurementDeliverie;
+use App\ProcurementTotalBill;
+use App\Services\common\ExportService;
+use App\Services\OwnerMaterialService;
+use App\Services\ProcurementService;
+use App\Services\ProcurementTotalBillService;
+use App\Supplier;
+use Carbon\Traits\Date;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Gate;
+
+class ProcurementController extends Controller
+{
+    use AsyncResponse;
+
+    private function newProcurement($param){
+        $procurement=new Procurement([
+            'owner_material_id'=>$param['owner_material_id'],
+            'quantity'=>$param['quantity'],
+            'amount'=>$param['amount'],
+            'unit_price'=>$param['unit_price'],
+            'initiator'=>Auth::user()['id'],
+            'type'=>0,
+        ]);
+        $procurement->save();
+        $number_id=$procurement['id'];
+        $procurement_code='BSHC';
+        $procurement_code .= date ("ymd").str_pad($number_id>99999?$number_id%99999:$number_id,4,"0",STR_PAD_LEFT);
+        $procurement->update(['code'=>$procurement_code]);
+        return $procurement;
+    }
+
+    public function index(Request $request,ProcurementFilters $filters)
+    {
+        if(!Gate::allows('采购管理-采购-查询')){ return ["success"=>false,"data"=>"您无此权限操作!"];  }
+        $paginateParams=$request->input();
+        $owner_ids=app('UserService')->getPermittingOwnerIds(auth()->user());
+        $procurements = Procurement::query()
+            ->filter($filters)
+            ->with(['initiator','ownerMaterial.material','ownerMaterial.owner'=>function($query)use($owner_ids){
+                $query->with('customer')->whereIn('id',$owner_ids);
+            }])->paginate($param['paginate'] ?? 50);
+        /** @var OwnerMaterialService $ownerMaterialService*/
+        $ownerMaterialService=app(OwnerMaterialService::class);
+        $owners=$ownerMaterialService->getOwnerPermittingWithMaterial();
+        $materials=Material::query()->select('id','name')->get();
+        $date=date('Y-m-d');
+        $countReceive=ProcurementDeliverie::query()->where('signed_at',$date)->count();
+        $countProcurement=Procurement::query()->where('type',0)->where('created_at','like',$date.'%')->count();
+        return view('procurement/procurement/index',compact('procurements','owners','materials','paginateParams','countReceive','countProcurement'));
+    }
+
+
+    public function create()
+    {
+        if(!Gate::allows('采购管理-采购-新建')){ return ["success"=>false,"data"=>"您无此权限操作!"];  }
+        /** @var OwnerMaterialService $ownerMaterialService*/
+        $ownerMaterialService=app(OwnerMaterialService::class);
+        $owners=$ownerMaterialService->getOwnerPermittingWithMaterial();
+        return view('procurement/procurement/create',compact('owners'));
+    }
+
+    public function store(Request $request)
+    {
+        $this->gate('采购管理-采购-新建');
+        $param=$request->all(['owner_material_id','quantity','amount','unit_price']);
+        $procurement=$this->newProcurement($param);
+        return redirect('procurement/procurement/index')->with('successTip','新采购单“'.$procurement->code.'”添加成功');
+    }
+    public function createProcurement(ProcurementRequest $request)
+    {
+        $this->gate('采购管理-采购-新建');
+        $request->validated();
+        $param=$request->all(['owner_material_id','quantity','amount','unit_price']);
+        try {
+            $procurement=$this->newProcurement($param);
+            $procurement = $procurement->loadMissing(['initiator','ownerMaterial.material','ownerMaterial.owner.customer']);
+            if ($procurement) return ['success' => true,'data' => $procurement];
+            else return ['success' => false, 'message' => '添加失败'];
+        } catch (\Exception $e) {
+            return ['success' => false,'message' => $e->getMessage()];
+        }
+    }
+    //新增询价
+    public function createEnquiry(EnquiryRequest $request)
+    {
+        $this->gate('采购管理-采购-新建');
+        $request->validated();
+        $param=$request->all(['owner_material_id']);
+        try {
+            $procurement=new Procurement([
+                'owner_material_id'=>$param['owner_material_id'],
+                'quantity'=>0,
+                'amount'=>0,
+                'unit_price'=>0,
+                'initiator'=>Auth::user()['id'],
+                'type'=>1,
+                'status'=>9,
+                //'is_enquiry'=>'是',
+            ]);
+            $procurement->save();
+            $number_id=$procurement['id'];
+            $procurement_code='BSHC';
+            $procurement_code .= date ("ymd").str_pad($number_id>99999?$number_id%99999:$number_id,4,"0",STR_PAD_LEFT);
+            $procurement->update(['code'=>$procurement_code]);
+            $procurement = $procurement->loadMissing(['initiator','ownerMaterial.material','ownerMaterial.owner.customer']);
+            if ($procurement) return ['success' => true,'data' => $procurement];
+            else return ['success' => false, 'message' => '添加失败'];
+        } catch (\Exception $e) {
+            return ['success' => false,'message' => $e->getMessage()];
+        }
+    }
+    //新增打样
+    public function createProof(ProofRequest $request)
+    {
+        $this->gate('采购管理-采购-新建');
+        $request->validated();
+        $param=$request->all(['owner_material_id']);
+        try {
+            $procurement=new Procurement([
+                'owner_material_id'=>$param['owner_material_id'],
+                'quantity'=>1,
+                'amount'=>0,
+                'unit_price'=>0,
+                'initiator'=>Auth::user()['id'],
+                'type'=>2,
+            ]);
+            $procurement->save();
+            $number_id=$procurement['id'];
+            $procurement_code='BSHC';
+            $procurement_code .= date ("ymd").str_pad($number_id>99999?$number_id%99999:$number_id,4,"0",STR_PAD_LEFT);
+            $procurement->update(['code'=>$procurement_code]);
+            $procurement = $procurement->loadMissing(['initiator','ownerMaterial.material','ownerMaterial.owner.customer']);
+            if ($procurement) return ['success' => true,'data' => $procurement];
+            else return ['success' => false, 'message' => '添加失败'];
+        } catch (\Exception $e) {
+            return ['success' => false,'message' => $e->getMessage()];
+        }
+    }
+    public function cancel($id){
+        $this->gate('采购管理-采购-编辑');
+        try {
+            $procurement=Procurement::query()->find($id);
+            $procurement->update(['status'=>3]);
+            $procurement = $procurement->loadMissing(['initiator','ownerMaterial.material','ownerMaterial.owner.customer']);
+            if ($procurement) return ['success' => true,'data' => $procurement];
+            else return ['success' => false, 'message' => '取消失败'];
+        } catch (\Exception $e) {
+            return ['success' => false,'message' => $e->getMessage()];
+        }
+    }
+    //询价单提交采购申请
+    public function submitProcurement(ProcurementAmountRequest $request){
+        $this->gate('采购管理-采购-编辑');
+        $request->validated();
+        $param=$request->all();
+        try {
+            $procurement=Procurement::query()->find($param['id']);
+            $unit_price=$param['unit_price'];
+            if (!$unit_price){
+                $priceCoefficient=Configuration::query()->where('name','priceCoefficient')->value('value');
+                $unit_price=$priceCoefficient*$param['offer'];
+            }
+            $procurement->update([
+                'type'=>0,
+                'status'=>0,
+                'quantity'=>$param['quantity'],
+                'amount'=>$param['amount'],
+                'unit_price'=>$unit_price,
+                'cost_price'=>$param['offer'],
+                'supplier_id'=>$param['supplier_id'],
+            ]);
+            $procurement = $procurement->loadMissing(['initiator','ownerMaterial.material','ownerMaterial.owner.customer']);
+            if ($procurement) return ['success' => true,'data' => $procurement];
+            else return ['success' => false, 'message' => '发起采购失败'];
+        } catch (\Exception $e) {
+            return ['success' => false,'message' => $e->getMessage()];
+        }
+    }
+    public function initiateProcurement(Request $request){
+        $this->gate('采购管理-采购-编辑');
+        $id=$request->input('id');
+        /** @var ProcurementService $procurementService*/
+        $procurementService=app(ProcurementService::class);
+        try {
+            $procurementQuotation=$procurementService->screenLowestQuotation($id);
+            if ($procurementQuotation) return ['success' => true,'data' => $procurementQuotation];
+            else return ['success' => false, 'message' => '暂无供应商报价!'];
+        } catch (\Exception $e) {
+            return ['success' => false,'message' => $e->getMessage()];
+        }
+    }
+    public function costPrice(Request $request){
+        $this->gate('采购管理-财务-采购账单');
+        $id=$request->input('id');
+        $cost_price=$request->input('cost_price');
+        try {
+            $procurement=Procurement::query()->find($id);
+            if ($procurement->cost_price!=$cost_price)$procurement->update(['cost_price'=>$cost_price]);
+            $procurement = $procurement->loadMissing(['initiator','supplier','ownerMaterial.material','ownerMaterial.owner.customer']);
+            if ($procurement) return ['success' => true,'data' => $procurement];
+            else return ['success' => false, 'message' => '修改采购单价失败!'];
+        } catch (\Exception $e) {
+            return ['success' => false,'message' => $e->getMessage()];
+        }
+    }
+
+
+
+    public function show(Procurement $procurement)
+    {
+        //
+    }
+
+
+    public function edit(Procurement $procurement)
+    {
+        //
+    }
+
+
+    public function update(Request $request, Procurement $procurement)
+    {
+        //
+    }
+
+
+    public function destroy(Procurement $procurement)
+    {
+        //
+    }
+
+    public function checkBill(Request $request,ProcurementCheckSheetFilters $filters)
+    {
+        if(!Gate::allows('采购管理-财务-对账单')){ return ["success"=>false,"data"=>"您无此权限操作!"];  }
+        $paginateParams=$request->input();
+        $procurementCheckSheets=ProcurementCheckSheet::query()
+            ->filter($filters)
+            ->with(['procurementDelivery.procurement.supplier','procurementDelivery.procurement.ownerMaterial.material','procurementDelivery.receiver'])
+            ->paginate($param['paginate'] ?? 50);
+        $suppliers=Supplier::query()->select('id','name')->get();
+        $materials=Material::query()->select('id','name')->get();
+        return view('procurement/finance/checkBill',compact('procurementCheckSheets','suppliers','paginateParams','materials'));
+    }
+    public function fillInvoice(Request $request){
+        $this->gate('采购管理-财务-对账单');
+        $id=$request->input('procurementCheckSheetId');
+        $invoice_number=$request->input('invoice_number');
+        try {
+            $procurementCheckSheet=ProcurementCheckSheet::query()->where('id',$id)->update(['invoice_number'=>$invoice_number]);
+            if ($procurementCheckSheet) return ['success' => true,'data' => $invoice_number];
+            else return ['success' => false, 'message' => '添加失败'];
+        } catch (\Exception $e) {
+            return ['success' => false,'message' => $e->getMessage()];
+        }
+    }
+
+    public function procurementBill(Request $request,ProcurementFilters $filters)
+    {
+        if(!Gate::allows('采购管理-财务-采购账单')){ return ["success"=>false,"data"=>"您无此权限操作!"];  }
+        $paginateParams=$request->input();
+        $owner_ids=app('UserService')->getPermittingOwnerIds(auth()->user());
+        $owners=app("OwnerService")->getIntersectPermitting();
+        $materials=Material::query()->select('id','name')->get();
+        $suppliers=Supplier::query()->select('id','name')->get();
+        $procurements = Procurement::query()
+            ->filter($filters)
+            ->with(['initiator','supplier','ownerMaterial.material','ownerMaterial.owner'=>function($query)use($owner_ids){
+                $query->with('customer')->whereIn('id',$owner_ids);
+            }])
+            ->where('type',0) //只取采购单
+            ->paginate($param['paginate'] ?? 50);
+        return view('procurement/finance/procurementBill',compact('suppliers','materials','owners','paginateParams','procurements'));
+    }
+
+    public function monthlyBillReport(Request $request)
+    {
+        if(!Gate::allows('采购管理-财务-月账单报表')){ return ["success"=>false,"data"=>"您无此权限操作!"];  }
+        $paginateParams=$request->input();
+        /** @var ProcurementTotalBillService $procurementTotalBillService*/
+        $procurementTotalBillService=app(ProcurementTotalBillService::class);
+        $procurementTotalBills=$procurementTotalBillService->paginate($paginateParams);
+        $suppliers=Supplier::query()->select('id','name')->get();
+        return view('procurement/finance/monthlyBillReport',compact('suppliers','procurementTotalBills','paginateParams'));
+    }
+    //采购导出
+    public function procurementExport(Request $request,ProcurementFilters $filters){
+        $this->gate('采购管理-采购-查询');
+        $owner_ids=app('UserService')->getPermittingOwnerIds(auth()->user());
+        $procurements = Procurement::query()
+            ->filter($filters)
+            ->with(['initiator','ownerMaterial.material','ownerMaterial.owner'=>function($query)use($owner_ids){
+                $query->with('customer')->whereIn('id',$owner_ids);
+            }])->get();
+
+        $procurementStatus=Procurement::status;
+        $procurementType=Procurement::type;
+        $row = ['采购编号','项目','单据类型','采购公司','耗材编号','耗材','尺寸大小','特殊要求','材质规格','采购数量','销售单价(元)','送货数量','销售总价(元)','采购单状态','联系方式'];
+        $list = [];
+        foreach ($procurements as $procurement){
+            $list[] = [
+                $procurement->code,
+                $procurement->ownerMaterial->owner ? $procurement->ownerMaterial->owner->name :'',
+                is_null($procurement->type) ? '' :$procurementType[$procurement->type],
+                $procurement->ownerMaterial->owner->customer ? $procurement->ownerMaterial->owner->customer->company_name :'',
+                $procurement->ownerMaterial->material ? $procurement->ownerMaterial->material->code :'',
+                $procurement->ownerMaterial->material ? $procurement->ownerMaterial->material->name :'',
+                $procurement->ownerMaterial ? $procurement->ownerMaterial->size :'',
+                $procurement->ownerMaterial ? $procurement->ownerMaterial->special :'',
+                $procurement->ownerMaterial ? $procurement->ownerMaterial->specification :'',
+                $procurement->quantity,
+                $procurement->unit_price,
+                '',//送货数量
+                '',//销售总价
+                is_null($procurement->status) ? '' :$procurementStatus[$procurement->status],
+                $procurement->ownerMaterial->owner->customer ? $procurement->ownerMaterial->owner->customer->phone :'',
+            ];
+        }
+        return app(ExportService::class)->json($row,$list,"采购管理-采购报表记录");
+    }
+    //对账单报表导出
+    public function checkBillExport(Request $request,ProcurementCheckSheetFilters $filters){
+        $this->gate('采购管理-财务-对账单');
+        $procurementCheckSheets=ProcurementCheckSheet::query()
+            ->filter($filters)
+            ->with(['procurementDelivery.procurement.supplier','procurementDelivery.procurement.ownerMaterial.material','procurementDelivery.receiver'])
+            ->get();
+        $procurementCheckSheetStatus=ProcurementCheckSheet::status;
+        $row = ['采购编号','采购日期','送货日期','供应商名称','耗材编号','耗材','采购数量','送货数量','签收人','签收日期','应付金额','发票号','状态'];
+        $list = [];
+        foreach ($procurementCheckSheets as $procurementCheckSheet){
+            $list[] = [
+                $procurementCheckSheet->procurementDelivery->procurement ? $procurementCheckSheet->procurementDelivery->procurement->code : '',
+                $procurementCheckSheet->procurementDelivery->procurement ? $procurementCheckSheet->procurementDelivery->procurement->created_at :'',
+                $procurementCheckSheet->procurementDelivery ? $procurementCheckSheet->procurementDelivery->created_at :'',
+                $procurementCheckSheet->procurementDelivery->procurement->supplier ? $procurementCheckSheet->procurementDelivery->procurement->supplier->name :'',
+                $procurementCheckSheet->procurementDelivery->procurement->ownerMaterial->material ? $procurementCheckSheet->procurementDelivery->procurement->ownerMaterial->material->code :'',
+                $procurementCheckSheet->procurementDelivery->procurement->ownerMaterial->material ? $procurementCheckSheet->procurementDelivery->procurement->ownerMaterial->material->name :'',
+                $procurementCheckSheet->procurementDelivery->procurement ? $procurementCheckSheet->procurementDelivery->procurement->quantity :'',
+                $procurementCheckSheet->procurementDelivery ? $procurementCheckSheet->procurementDelivery->amount :'',
+                $procurementCheckSheet->procurementDelivery->receiver ? $procurementCheckSheet->procurementDelivery->receiver->name :'',
+                $procurementCheckSheet->procurementDelivery ? $procurementCheckSheet->procurementDelivery->signed_at :'',
+                $procurementCheckSheet->account_payable,
+                $procurementCheckSheet->invoice_number,
+                is_null($procurementCheckSheet->status) ? '' :$procurementCheckSheetStatus[$procurementCheckSheet->status],
+            ];
+        }
+        return app(ExportService::class)->json($row,$list,"采购管理-对账单报表记录");
+    }
+    //采购账单导出
+    public function procurementBillExport(Request $request,ProcurementFilters $filters){
+        $this->gate('采购管理-财务-采购账单');
+        $owner_ids=app('UserService')->getPermittingOwnerIds(auth()->user());
+        $procurements = Procurement::query()
+            ->filter($filters)
+            ->with(['initiator','supplier','ownerMaterial.material','ownerMaterial.owner'=>function($query)use($owner_ids){
+                $query->with('customer')->whereIn('id',$owner_ids);
+            }])->get();
+
+        $procurementStatus=Procurement::status;
+        $row = ['采购编号','采购日期','接单日期','签收日期','项目名称','采购公司','供应商','耗材编号','耗材','尺寸大小','特殊要求',
+                '材质规格','采购数量','销售数量','收货数量','采购单价(元)','销售单价(元)','应收金额(元)','应付金额(元)','状态'];
+        $list = [];
+        foreach ($procurements as $procurement){
+            $list[] = [
+                $procurement->code,
+                $procurement->created_at,
+                '',//接单日期
+                '',//签收日期
+                $procurement->ownerMaterial->owner ? $procurement->ownerMaterial->owner->name :'',
+                $procurement->ownerMaterial->owner->customer ? $procurement->ownerMaterial->owner->customer->company_name :'',
+                $procurement->supplier ? $procurement->supplier->name :'',
+                $procurement->ownerMaterial->material ? $procurement->ownerMaterial->material->code :'',
+                $procurement->ownerMaterial->material ? $procurement->ownerMaterial->material->name :'',
+                $procurement->ownerMaterial ? $procurement->ownerMaterial->size :'',
+                $procurement->ownerMaterial ? $procurement->ownerMaterial->special :'',
+                $procurement->ownerMaterial ? $procurement->ownerMaterial->specification :'',
+                $procurement->quantity,
+                $procurement->amount,
+                '',//收货数量
+                $procurement->cost_price,
+                $procurement->unit_price,
+                '',//应收金额
+                '',//应付金额
+                is_null($procurement->status) ? '' :$procurementStatus[$procurement->status],
+            ];
+        }
+        return app(ExportService::class)->json($row,$list,"采购账单报表记录");
+    }
+    //月账单报表导出
+    public function procurementTotalBillExport(Request $request){
+        $this->gate('采购管理-财务-月账单报表');
+        /** @var ProcurementTotalBillService $procurementTotalBillService*/
+        $procurementTotalBillService=app(ProcurementTotalBillService::class);
+        if ($request->input('checkAllSign')){
+            $params = $request->input();
+            unset($params["checkAllSign"]);
+            $procurementTotalBills=$procurementTotalBillService->get($params);
+        }else{
+            $procurementTotalBills=$procurementTotalBillService->get(["id"=>$request->data]);
+        }
+        $procurementTotalBillStatus=ProcurementTotalBill::status;
+        $row = ['对账编号','账单日期','提交日期','供应商','总金额','状态'];
+        $list = [];
+        foreach ($procurementTotalBills as $procurementTotalBill){
+            $list[] = [
+                $procurementTotalBill->id,
+                $procurementTotalBill->counting_month,
+                $procurementTotalBill->created_at,
+                $procurementTotalBill->supplier ? $procurementTotalBill->supplier :'',
+                $procurementTotalBill->total_payable,
+                $procurementTotalBill->status ? $procurementTotalBillStatus[$procurementTotalBill->status] :'',
+            ];
+        }
+        return app(ExportService::class)->json($row,$list,"采购管理-月账单报表记录");
+    }
+}

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

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

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

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

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

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

+ 50 - 6
app/Http/Controllers/SupplierController.php

@@ -4,6 +4,8 @@ namespace App\Http\Controllers;
 
 use App\Components\AsyncResponse;
 use App\Filters\SupplierFilters;
+use App\Material;
+use App\MaterialSupplier;
 use App\Supplier;
 use Illuminate\Http\Request;
 
@@ -13,23 +15,44 @@ class SupplierController extends Controller
     public function index(Request $request,SupplierFilters $filters)
     {
         $this->gate('供应商');
-        $suppliers = Supplier::query()->orderByDesc('id')->filter($filters)->paginate($request['paginate']??50);
-        return view('/maintenance/supplier/index',compact('suppliers'));
+        $suppliers = Supplier::query()->with('material')->orderByDesc('id')->filter($filters)->paginate($request['paginate']??50);
+        $materials=Material::query()->select('id','name')->get();
+        return view('/maintenance/supplier/index',compact('suppliers','materials'));
     }
 
     public function storeApi(Request $request)
     {
         $this->gate('供应商-编辑');
-        $supplier = Supplier::query()->create($request->all());
+        $supplier = Supplier::query()->create($request->addSupplier);
+        $material_supplier=[];
+        foreach ($request->material_id as $item){
+            $material_supplier[]=[
+              'material_id'=>$item,
+              'supplier_id'=>$supplier->id,
+            ];
+        }
+        MaterialSupplier::query()->insert($material_supplier);
         $this->success($supplier);
     }
 
     public function updateApi(Request $request)
     {
         $this->gate('供应商-编辑');
-        $supplier = Supplier::query()->find($request['id']);
-        $bool= $supplier->update($request->only(['name','contact_man','phone','invoice_title','bank','bank_account','opening_bank']));
-        if($bool)$this->success($supplier);
+        $editSupplier=$request->input('editSupplier');
+        $material_ids=$request->input('material_id');
+        $material_suppliers=MaterialSupplier::query()->where('supplier_id',$editSupplier['id'])->get();
+        $this->updateMaterial($material_suppliers,$material_ids,$editSupplier['id']);
+        $supplier = Supplier::query()->find($editSupplier['id']);
+        $bool= $supplier->update([
+            'name'=>$editSupplier['name'],
+            'contact_man'=>$editSupplier['contact_man'],
+            'phone'=>$editSupplier['phone'],
+            'invoice_title'=>$editSupplier['invoice_title'],
+            'bank'=>$editSupplier['bank'],
+            'bank_account'=>$editSupplier['bank_account'],
+            'opening_bank'=>$editSupplier['opening_bank']
+        ]);
+        if($bool)$this->success($supplier->loadMissing('material'));
         $this->error('更新异常');
     }
 
@@ -40,4 +63,25 @@ class SupplierController extends Controller
         $supplier->delete();
         $this->success();
     }
+    private function updateMaterial($material_suppliers,$material_ids,$supplier_id){
+        $exist=[]; $adds=[];$addMaterial=[];
+        foreach ($material_suppliers as $material_supplier){
+            $exist[]=$material_supplier['material_id'];
+        }
+        $deletes=array_diff($exist,$material_ids);
+        foreach ($material_ids as $id){
+            if (empty($material_suppliers->where('material_id',$id)->first()))$adds[]=$id;
+        }
+        foreach ($adds as $add){
+            $addMaterial[]=[
+                'material_id'=>$add,
+                'supplier_id'=>$supplier_id,
+            ];
+        }
+        if (count($addMaterial)>0) MaterialSupplier::query()->insert($addMaterial);
+        foreach ($deletes as $delete){
+            MaterialSupplier::query()->where('material_id',$delete)
+                ->where('supplier_id',$supplier_id)->delete();
+        }
+    }
 }

+ 6 - 4
app/Http/Controllers/TestController.php

@@ -58,6 +58,9 @@ use App\Package;
 use App\Process;
 use App\ProcessDaily;
 use App\ProcessStatistic;
+use App\Procurement;
+use App\ProcurementCheckSheet;
+use App\ProcurementQuotation;
 use App\Province;
 use App\Region;
 use App\RejectedBill;
@@ -77,7 +80,6 @@ use App\Services\OracleDocAsnHerderService;
 use App\Services\OracleDOCOrderHeaderService;
 use App\Services\OracleDocWaveDetailService;
 use App\Services\OrderCommodityService;
-use App\Services\OrderFreezeService;
 use App\Services\OrderPackageReceivedSyncService;
 use App\Services\OrderPackageService;
 use App\Services\OrderService;
@@ -92,11 +94,11 @@ use App\Services\StoreService;
 use App\Services\WarehouseService;
 use App\StationRuleBatch;
 use App\StationTask;
-use App\StationTaskMaterialBox;
 use App\Store;
 use App\StationTaskBatch;
 use App\StoreCheckingReceiveItem;
-use App\StoreItem;
+use App\StoreItems;
+use App\Supplier;
 use App\Unit;
 use App\User;
 use App\ValueStore;
@@ -347,7 +349,7 @@ sql;
 
     function tlog(Request $request)
     {
-         dd((User::class)::query()->first());
+        app('LogService')->log(__METHOD__, 'cczdelme' . __FUNCTION__, json_encode($request->all()), null);
     }
 
     function setCache(Request $request)

+ 98 - 0
app/Http/Controllers/api/procurement/wechat/AuthController.php

@@ -0,0 +1,98 @@
+<?php
+
+namespace App\Http\Controllers\api\procurement\wechat;
+
+use App\UserDetail;
+use Illuminate\Support\Facades\Auth;
+use App\Http\Controllers\Controller;
+
+class AuthController extends Controller
+{
+    /**
+     * Create a new AuthController instance.
+     * 要求附带email和password(数据来源users表)
+     *
+     * @return void
+     */
+    public function __construct()
+    {
+        // 这里额外注意了:官方文档样例中只除外了『login』
+        // 这样的结果是,token 只能在有效期以内进行刷新,过期无法刷新
+        // 如果把 refresh 也放进去,token 即使过期但仍在刷新期以内也可刷新
+        // 不过刷新一次作废
+        $this->middleware('auth:api', ['except' => ['login']]);
+        // 另外关于上面的中间件,官方文档写的是『auth:api』
+        // 但是我推荐用 『jwt.auth』,效果是一样的,但是有更加丰富的报错信息返回
+    }
+
+    /**
+     * Get a JWT via given credentials.
+     *
+     * @return \Illuminate\Http\JsonResponse
+     */
+    public function login()
+    {
+        $phone=request('phone');
+        $user_id=UserDetail::query()->where('mobile_phone',$phone)->value('user_id');
+        $credentials = [
+            'id'=>$user_id,
+            'password'=>request('password')
+        ];
+
+
+        if (! $token = auth('api')->attempt($credentials)) {
+            return response()->json(['error' => '很抱歉,您的手机号和密码不匹配'], 401);
+        }
+
+        return $this->respondWithToken($token);
+    }
+
+    /**
+     * Get the authenticated User.
+     *
+     * @return \Illuminate\Http\JsonResponse
+     */
+    public function me()
+    {
+        return response()->json(auth('api')->user());
+    }
+
+    /**
+     * Log the user out (Invalidate the token).
+     *
+     * @return \Illuminate\Http\JsonResponse
+     */
+    public function logout()
+    {
+        auth('api')->logout();
+
+        return response()->json(['message' => 'Successfully logged out']);
+    }
+
+    /**
+     * Refresh a token.
+     * 刷新token,如果开启黑名单,以前的token便会失效。
+     * 值得注意的是用上面的getToken再获取一次Token并不算做刷新,两次获得的Token是并行的,即两个都可用。
+     * @return \Illuminate\Http\JsonResponse
+     */
+    public function refresh()
+    {
+        return $this->respondWithToken(auth('api')->refresh());
+    }
+
+    /**
+     * Get the token array structure.
+     *
+     * @param  string $token
+     *
+     * @return \Illuminate\Http\JsonResponse
+     */
+    protected function respondWithToken($token)
+    {
+        return response()->json([
+            'access_token' => $token,
+            'token_type' => 'bearer',
+            'expires_in' => auth('api')->factory()->getTTL() * 60
+        ]);
+    }
+}

+ 1 - 0
app/Http/Kernel.php

@@ -74,6 +74,7 @@ class Kernel extends HttpKernel
         'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
         'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
         'auth.api' => \App\Http\Middleware\ApiAuth::class,
+        'procurement.auth.api' => \App\Http\Middleware\ProcurementApiAuth::class,
     ];
 
     /**

+ 56 - 0
app/Http/Middleware/ProcurementApiAuth.php

@@ -0,0 +1,56 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Closure;
+use Tymon\JWTAuth\Exceptions\JWTException;
+use Tymon\JWTAuth\Exceptions\TokenExpiredException;
+use Tymon\JWTAuth\Exceptions\TokenInvalidException;
+use Tymon\JWTAuth\Facades\JWTAuth;
+
+
+class ProcurementApiAuth
+{
+    /**
+     * Handle an incoming request.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @param  \Closure  $next
+     * @return mixed
+     */
+    public function handle($request, Closure $next)
+    {
+        try {
+            if (! $user = JWTAuth::parseToken()->authenticate()) {
+                return response()->json([
+                    'code' => 1004,
+                    'msg' => '用户不存在'
+
+                ], 404);
+            }
+            return $next($request);
+
+        } catch (TokenExpiredException $e) {
+
+            return response()->json([
+                'code' => 1003,
+                'msg' => 'token 过期' ,
+            ]);
+
+        } catch (TokenInvalidException $e) {
+
+            return response()->json([
+                'code' => 1002,
+                'msg' => 'token 无效',
+            ]);
+
+        }catch (JWTException $e) {
+
+            return response()->json([
+                'code' => 1001,
+                'msg' => '缺少token' ,
+            ]);
+
+        }
+    }
+}

+ 40 - 0
app/Http/Requests/Procurement/EnquiryRequest.php

@@ -0,0 +1,40 @@
+<?php
+
+namespace App\Http\Requests\Procurement;
+
+use App\Traits\RequestApiFormValidation;
+use Illuminate\Foundation\Http\FormRequest;
+
+class EnquiryRequest extends FormRequest
+{
+    use RequestApiFormValidation;
+    /**
+     * Determine if the user is authorized to make this request.
+     *
+     * @return bool
+     */
+    public function authorize()
+    {
+        return true;
+    }
+
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array
+     */
+    public function rules()
+    {
+        return [
+            'owner_id'=>'required',
+            'owner_material_id'=>'required',
+        ];
+    }
+    public function messages()
+    {
+        return [
+            'owner_id.required' => '项目必选',
+            'owner_material_id.required' => '项目耗材编码必选',
+        ];
+    }
+}

+ 40 - 0
app/Http/Requests/Procurement/ProcurementAmountRequest.php

@@ -0,0 +1,40 @@
+<?php
+
+namespace App\Http\Requests\Procurement;
+
+use App\Traits\RequestApiFormValidation;
+use Illuminate\Foundation\Http\FormRequest;
+
+class ProcurementAmountRequest extends FormRequest
+{
+    use RequestApiFormValidation;
+    /**
+     * Determine if the user is authorized to make this request.
+     *
+     * @return bool
+     */
+    public function authorize()
+    {
+        return true;
+    }
+
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array
+     */
+    public function rules()
+    {
+        return [
+            'quantity'=>'required',
+            'amount'=>'required',
+        ];
+    }
+    public function messages()
+    {
+        return [
+            'quantity.required' => '采购数量不可为空',
+            'amount.required' => '销售数量不可为空',
+        ];
+    }
+}

+ 44 - 0
app/Http/Requests/Procurement/ProcurementRequest.php

@@ -0,0 +1,44 @@
+<?php
+
+namespace App\Http\Requests\Procurement;
+
+use App\Traits\RequestApiFormValidation;
+use Illuminate\Foundation\Http\FormRequest;
+
+class ProcurementRequest extends FormRequest
+{
+    use RequestApiFormValidation;
+    /**
+     * Determine if the user is authorized to make this request.
+     *
+     * @return bool
+     */
+    public function authorize()
+    {
+        return true;
+    }
+
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array
+     */
+    public function rules()
+    {
+        return [
+            'owner_id'=>'required',
+            'owner_material_id'=>'required',
+            'quantity'=>'required',
+            'amount'=>'required',
+        ];
+    }
+    public function messages()
+    {
+        return [
+            'owner_id.required' => '项目必选',
+            'owner_material_id.required' => '项目耗材编码必选',
+            'quantity.required' => '采购数量不可为空',
+            'amount.required' => '销售数量不可为空',
+        ];
+    }
+}

+ 41 - 0
app/Http/Requests/Procurement/ProofRequest.php

@@ -0,0 +1,41 @@
+<?php
+
+namespace App\Http\Requests\Procurement;
+
+use App\Traits\RequestApiFormValidation;
+use Illuminate\Foundation\Http\FormRequest;
+
+class ProofRequest extends FormRequest
+{
+    use RequestApiFormValidation;
+    /**
+     * Determine if the user is authorized to make this request.
+     *
+     * @return bool
+     */
+    public function authorize()
+    {
+        return true;
+    }
+
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array
+     */
+    public function rules()
+    {
+        return [
+            'owner_id'=>'required',
+            'owner_material_id'=>'required',
+        ];
+    }
+
+    public function messages()
+    {
+        return [
+            'owner_id.required' => '项目必选',
+            'owner_material_id.required' => '项目耗材编码必选',
+        ];
+    }
+}

+ 6 - 1
app/Material.php

@@ -4,8 +4,8 @@ namespace App;
 
 use App\Filters\MaterialFilters;
 use Illuminate\Database\Eloquent\Model;
-
 use App\Traits\ModelLogChanging;
+use Illuminate\Database\Eloquent\Relations\BelongsToMany;
 
 class Material extends Model
 {
@@ -13,6 +13,11 @@ class Material extends Model
 
     protected $fillable = ['name','code'];
 
+    public function supplier():BelongsToMany
+    {
+        return $this->belongsToMany(Supplier::class,'material_suppliers','material_id','supplier_id');
+    }
+
     public function scopeFilter($query, $filters)
     {
         return $filters->apply($query);

+ 14 - 0
app/MaterialSupplier.php

@@ -0,0 +1,14 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+
+class MaterialSupplier extends Model
+{
+    use ModelLogChanging;
+
+    protected $fillable=['material_id','supplier_id'];
+}

+ 4 - 0
app/Owner.php

@@ -112,4 +112,8 @@ class Owner extends Model
     {   //仓库
         return $this->belongsTo(Warehouse::class,"warehouse_id","id");
     }
+    public function ownerMaterials()
+    {   //耗材
+        return $this->hasMany(OwnerMaterial::class,"owner_id","id");
+    }
 }

+ 73 - 0
app/Procurement.php

@@ -0,0 +1,73 @@
+<?php
+
+namespace App;
+
+use App\Traits\ModelTimeFormat;
+use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\DB;
+
+class Procurement extends Model
+{
+    use ModelLogChanging;
+    use ModelTimeFormat;
+
+    const type=[
+        0 => "采购单",
+        1 => "询价单",
+        2 => "打样单",
+    ];
+
+    const status=[
+        0 => "待推单",
+        1 => "已报价",
+        2 => "生产中",
+        3 => "取消订单",
+        4 => "已完成",
+        5 => "完结",
+        6 => "下单失败",
+        7 => "待出账",
+        8 => "待接单(已过期)",
+        9 => "待报价",
+    ];
+
+    protected $fillable=[
+        'code','owner_material_id', 'supplier_id', 'quantity','amount','unit_price','cost_price','status','initiator','type'
+    ];
+
+    protected static function booted()
+    {
+        /** @var User $user */
+        $user = Auth::user();
+        if ($user && !$user->isSuperAdmin()) {
+            /** @var \stdClass $user */
+            $ids = array_column(DB::select(DB::raw("SELECT supplier_id FROM supplier_user WHERE user_id = ?"),[$user->id]),"supplier_id");
+            if (count($ids)>0){
+                static::addGlobalScope('supplier', function (Builder $builder)use ($ids) {
+                    $builder->whereIn('supplier_id',  $ids);
+                });
+            }
+        }
+    }
+
+    public  function ownerMaterial(){
+        return $this->hasOne('App\OwnerMaterial','id','owner_material_id');
+    }
+
+    public  function supplier(){
+        return $this->hasOne('App\Supplier','id','supplier_id');
+    }
+
+    public function initiator()
+    {
+        return $this->belongsTo(User::class,'initiator','id');
+    }
+
+    public function scopeFilter($query, $filters)
+    {
+        return $filters->apply($query);
+    }
+}

+ 31 - 0
app/ProcurementCheckSheet.php

@@ -0,0 +1,31 @@
+<?php
+
+namespace App;
+
+use App\Traits\ModelTimeFormat;
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+
+class ProcurementCheckSheet extends Model
+{
+    use ModelLogChanging;
+    use ModelTimeFormat;
+
+    const status=[
+        0 => "未出账",
+        1 => "已出账",
+        2 => "已完结",
+    ];
+    protected $fillable=[
+        'procurement_delivery_id','invoice_number', 'account_payable', 'auditor','status','created_at'
+    ];
+    public function procurementDelivery(){
+        return $this->belongsTo('App\ProcurementDeliverie','procurement_delivery_id','id');
+    }
+
+    public function scopeFilter($query, $filters)
+    {
+        return $filters->apply($query);
+    }
+}

+ 27 - 0
app/ProcurementDeliverie.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace App;
+
+use App\Traits\ModelTimeFormat;
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+use Illuminate\Support\Facades\App;
+
+class ProcurementDeliverie extends Model
+{
+    use ModelLogChanging;
+    use ModelTimeFormat;
+
+    protected $fillable=[
+        'procurement_id','amount', 'initiator','status','signer','signed_at',
+    ];
+
+    public function procurement(){
+        return $this->belongsTo('App\Procurement','procurement_id','id');
+    }
+
+    public function receiver(){
+        return $this->belongsTo('App\User','signer','id');
+    }
+}

+ 22 - 0
app/ProcurementQuotation.php

@@ -0,0 +1,22 @@
+<?php
+
+namespace App;
+
+use App\Traits\ModelTimeFormat;
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+
+class ProcurementQuotation extends Model
+{
+    use ModelLogChanging;
+    use ModelTimeFormat;
+
+    protected $fillable=[
+        'procurement_id','offer', 'operator', 'quoted_at','status','created_at','supplier_id'
+    ];
+
+    public  function supplier(){
+        return $this->hasOne('App\Supplier','id','supplier_id');
+    }
+}

+ 32 - 0
app/ProcurementTotalBill.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace App;
+
+use App\Traits\ModelTimeFormat;
+use Illuminate\Database\Eloquent\Model;
+
+use App\Traits\ModelLogChanging;
+
+class ProcurementTotalBill extends Model
+{
+    use ModelLogChanging;
+    use ModelTimeFormat;
+
+    const status=[
+        0 => "未出账",
+        1 => "已出账",
+        2 => "已完结",
+    ];
+
+    protected $fillable=[
+        'counting_month','supplier_id','status','total_payable'
+    ];
+    public function supplier(){
+        return $this->belongsTo('App\Supplier','supplier_id','id');
+    }
+    //截取账单日期为月
+    public function getCountingMonthAttribute($value)
+    {
+        return substr($value,0,7);
+    }
+}

+ 6 - 0
app/Providers/AppServiceProvider.php

@@ -45,6 +45,7 @@ use App\Services\OrderTrackingService;
 use App\Services\OwnerAreaReportService;
 use App\Services\OwnerBillReportService;
 use App\Services\OwnerFeeDetailService;
+use App\Services\OwnerMaterialService;
 use App\Services\OwnerPriceDirectLogisticService;
 use App\Services\OwnerPriceExpressService;
 use App\Services\OwnerPriceLogisticService;
@@ -59,6 +60,8 @@ use App\Services\ProcessesContentService;
 use App\Services\ProcessMethodService;
 use App\Services\ProcessService;
 use App\Services\ProcessStatisticService;
+use App\Services\ProcurementService;
+use App\Services\ProcurementTotalBillService;
 use App\Services\ProvinceService;
 use App\Services\RealtimePendingOrdersService;
 use App\Services\RejectedBillItemService;
@@ -194,6 +197,7 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('OwnerReportService',OwnerReportService::class);
         app()->singleton('OwnerService',OwnerService::class);
         app()->singleton('OwnerStoragePriceModelService',OwnerStoragePriceModelService::class);
+        app()->singleton('OwnerMaterialService',OwnerMaterialService::class);
         app()->singleton('PackageService',PackageService::class);
         app()->singleton('PackageStatisticsService',PackageStatisticsService::class);
         app()->singleton('ProcessMethodService',ProcessMethodService::class);
@@ -201,6 +205,8 @@ class AppServiceProvider extends ServiceProvider
         app()->singleton('ProcessStatisticService',ProcessStatisticService::class);
         app()->singleton('ProcessesContentService',ProcessesContentService::class);
         app()->singleton('ProvinceService',ProvinceService::class);
+        app()->singleton('ProcurementService',ProcurementService::class);
+        app()->singleton('ProcurementTotalBillService',ProcurementTotalBillService::class);
         app()->singleton('RealtimePendingOrdersService',RealtimePendingOrdersService::class);
         app()->singleton('RegionService',RegionService::class);
         app()->singleton('RejectedBillItemService',RejectedBillItemService::class);

+ 20 - 0
app/Services/OwnerMaterialService.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace App\Services;
+
+use App\Owner;
+use App\OwnerMaterial;
+use Illuminate\Support\Facades\Auth;
+use App\Traits\ServiceAppAop;
+
+
+class OwnerMaterialService
+{
+    use ServiceAppAop;
+    protected $modelClass=OwnerMaterial::class;
+    public function getOwnerPermittingWithMaterial()
+    {
+        $ownerIds=app('UserService')->getPermittingOwnerIds(Auth::user());
+        return Owner::query()->with(['ownerMaterials.material','customer'])->select(['id','name','customer_id'])->whereIn('id', $ownerIds)->get();
+    }
+}

+ 37 - 0
app/Services/ProcurementService.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace App\Services;
+
+use App\Owner;
+use App\Procurement;
+use App\ProcurementQuotation;
+use App\Services\common\QueryService;
+use Illuminate\Support\Facades\Auth;
+use App\Traits\ServiceAppAop;
+
+
+class ProcurementService
+{
+    use ServiceAppAop;
+
+    public function screenLowestQuotation($procurement_id){
+        if (!$procurement_id) return null;
+        $procurementQuotation=ProcurementQuotation::query()->with('supplier')
+            ->select('supplier_id','offer')->orderBy('offer','asc')->where('procurement_id',$procurement_id)->first();
+        return $procurementQuotation;
+    }
+
+    public function pushEnquiryToSupplier($procurement_id){
+        $procurement=Procurement::query()->find($procurement_id);
+        $procurement->loadMissing(['ownerMaterial.material.supplier']);
+        if (!empty($procurement->ownerMaterial->material->supplier))$suppliers=$procurement->ownerMaterial->material->supplier;
+        foreach ($suppliers as $supplier){
+            $procurementQuotation= new ProcurementQuotation([
+                'procurement_id'=>10,
+                'supplier_id'=>$supplier->id,
+            ]);
+            $procurementQuotation->save();
+            //TODO 添加广播推送给指定供应商
+        }
+    }
+}

+ 34 - 0
app/Services/ProcurementTotalBillService.php

@@ -0,0 +1,34 @@
+<?php
+
+namespace App\Services;
+
+use App\Owner;
+use App\Procurement;
+use App\ProcurementTotalBill;
+use App\Services\common\QueryService;
+use Illuminate\Support\Facades\Auth;
+use App\Traits\ServiceAppAop;
+
+
+class ProcurementTotalBillService
+{
+    use ServiceAppAop;
+
+    private function conditionQuery(array $param){
+        $procurementTotalBills=ProcurementTotalBill::query()->with('supplier');
+        $columnQueryRules=[
+            'supplier_id' => ['multi' => ','],
+            'counting_month' => ['like' => ''],
+        ];
+        $procurementTotalBills = app(QueryService::class)->query($param,$procurementTotalBills,$columnQueryRules,"procurement_total_bills");
+        return $procurementTotalBills;
+    }
+
+    public function paginate(array $param){
+        $procurementTotalBills = $this->conditionQuery($param);
+        return $procurementTotalBills->paginate($param['paginate'] ?? 50);
+    }
+    public function get(array $params){
+        return $this->conditionQuery($params)->get();
+    }
+}

+ 1 - 2
app/Services/WarehouseService.php

@@ -11,10 +11,9 @@ use Illuminate\Support\Facades\Cache;
 use App\Traits\ServiceAppAop;
 
 
-class WarehouseService
+Class WarehouseService
 {
     use ServiceAppAop;
-    protected $modelClass=Warehouse::class;
     /** @var CacheService $cacheService */
     private $cacheService;
     function __construct(){

+ 1 - 2
app/Supplier.php

@@ -4,7 +4,6 @@ namespace App;
 
 use App\Traits\ModelTimeFormat;
 use Illuminate\Database\Eloquent\Model;
-
 use App\Traits\ModelLogChanging;
 use Illuminate\Database\Eloquent\Relations\BelongsToMany;
 use Illuminate\Database\Eloquent\SoftDeletes;
@@ -18,7 +17,7 @@ class Supplier extends Model
 
     public function material():BelongsToMany
     {
-        return $this->belongsToMany(Material::class,'material_supplier','supplier_id','material_id','id','material_id');
+        return $this->belongsToMany(Material::class,'material_suppliers','supplier_id','material_id');
     }
 
     public function scopeFilter($query,$filters)

+ 28 - 0
app/Traits/RequestApiFormValidation.php

@@ -0,0 +1,28 @@
+<?php
+
+
+namespace App\Traits;
+
+
+use Illuminate\Contracts\Validation\Validator;
+use Illuminate\Validation\ValidationException;
+use Symfony\Component\HttpFoundation\Response;
+
+trait RequestApiFormValidation
+{
+    // 重写ajax请求验证错误响应格式(防止验证422报错)
+    protected function failedValidation(Validator $validator)
+    {
+        // 此处自定义表单验证错误信息
+        $data = [
+            'code' => 200,
+            'success' => false,
+            'errors' => $validator->errors()
+        ];
+        $response = new Response(json_encode($data));
+        throw (new ValidationException($validator, $response))
+            ->errorBag($this->errorBag)
+            ->redirectTo($this->getRedirectUrl());
+    }
+
+}

+ 13 - 1
app/User.php

@@ -9,8 +9,9 @@ use Illuminate\Support\Collection;
 use Illuminate\Support\Facades\Cache;
 use Illuminate\Support\Facades\Gate;
 use App\Traits\ModelTimeFormat;
+use Tymon\JWTAuth\Contracts\JWTSubject;
 
-class User extends Authenticatable
+class User extends Authenticatable implements JWTSubject
 {
     use ModelLogChanging;
     use ModelTimeFormat;
@@ -131,4 +132,15 @@ class User extends Authenticatable
         }
         return $workgroupIds;
     }
+
+    //jwt
+    public function getJWTIdentifier()
+    {
+        return $this->getKey();
+    }
+
+    public function getJWTCustomClaims()
+    {
+        return [];
+    }
 }

+ 12 - 0
bootstrap/cache/packages.php

@@ -103,6 +103,18 @@
       0 => 'Te7aHoudini\\LaravelTrix\\LaravelTrixServiceProvider',
     ),
   ),
+  'tymon/jwt-auth' =>
+  array (
+    'aliases' =>
+    array (
+      'JWTAuth' => 'Tymon\\JWTAuth\\Facades\\JWTAuth',
+      'JWTFactory' => 'Tymon\\JWTAuth\\Facades\\JWTFactory',
+    ),
+    'providers' =>
+    array (
+      0 => 'Tymon\\JWTAuth\\Providers\\LaravelServiceProvider',
+    ),
+  ),
   'yajra/laravel-oci8' =>
   array (
     'providers' =>

+ 14 - 12
bootstrap/cache/services.php

@@ -35,12 +35,13 @@
     31 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider',
     32 => 'Overtrue\\LaravelPinyin\\ServiceProvider',
     33 => 'Te7aHoudini\\LaravelTrix\\LaravelTrixServiceProvider',
-    34 => 'Yajra\\Oci8\\Oci8ServiceProvider',
-    35 => 'App\\Providers\\AppServiceProvider',
-    36 => 'App\\Providers\\AuthServiceProvider',
-    37 => 'App\\Providers\\BroadcastServiceProvider',
-    38 => 'App\\Providers\\EventServiceProvider',
-    39 => 'App\\Providers\\RouteServiceProvider',
+    34 => 'Tymon\\JWTAuth\\Providers\\LaravelServiceProvider',
+    35 => 'Yajra\\Oci8\\Oci8ServiceProvider',
+    36 => 'App\\Providers\\AppServiceProvider',
+    37 => 'App\\Providers\\AuthServiceProvider',
+    38 => 'App\\Providers\\BroadcastServiceProvider',
+    39 => 'App\\Providers\\EventServiceProvider',
+    40 => 'App\\Providers\\RouteServiceProvider',
   ),
   'eager' => 
   array (
@@ -65,12 +66,13 @@
     18 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider',
     19 => 'Overtrue\\LaravelPinyin\\ServiceProvider',
     20 => 'Te7aHoudini\\LaravelTrix\\LaravelTrixServiceProvider',
-    21 => 'Yajra\\Oci8\\Oci8ServiceProvider',
-    22 => 'App\\Providers\\AppServiceProvider',
-    23 => 'App\\Providers\\AuthServiceProvider',
-    24 => 'App\\Providers\\BroadcastServiceProvider',
-    25 => 'App\\Providers\\EventServiceProvider',
-    26 => 'App\\Providers\\RouteServiceProvider',
+    21 => 'Tymon\\JWTAuth\\Providers\\LaravelServiceProvider',
+    22 => 'Yajra\\Oci8\\Oci8ServiceProvider',
+    23 => 'App\\Providers\\AppServiceProvider',
+    24 => 'App\\Providers\\AuthServiceProvider',
+    25 => 'App\\Providers\\BroadcastServiceProvider',
+    26 => 'App\\Providers\\EventServiceProvider',
+    27 => 'App\\Providers\\RouteServiceProvider',
   ),
   'deferred' => 
   array (

+ 1 - 0
composer.json

@@ -28,6 +28,7 @@
         "predis/predis": "^1.1",
         "pusher/pusher-php-server": "^4.1",
         "te7a-houdini/laravel-trix": "^2.0",
+        "tymon/jwt-auth": "1.*@rc",
         "yajra/laravel-oci8": "7.0",
         "ext-bcmath": "*"
     },

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


+ 2 - 0
config/app.php

@@ -224,6 +224,8 @@ return [
         'URL' => Illuminate\Support\Facades\URL::class,
         'Validator' => Illuminate\Support\Facades\Validator::class,
         'View' => Illuminate\Support\Facades\View::class,
+        'JWTAuth' => 'Tymon\JWTAuth\Facades\JWTAuth',
+        'JWTFactory' => 'Tymon\JWTAuth\Facades\JWTFactory',
     ],
 
 ];

+ 2 - 1
config/auth.php

@@ -42,7 +42,8 @@ return [
         ],
 
         'api' => [
-            'driver' => 'token',
+//            'driver' => 'token',
+            'driver' => 'jwt',
             'provider' => 'users',
             'hash' => false,
         ],

+ 304 - 0
config/jwt.php

@@ -0,0 +1,304 @@
+<?php
+
+/*
+ * This file is part of jwt-auth.
+ *
+ * (c) Sean Tymon <tymon148@gmail.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+return [
+
+    /*
+    |--------------------------------------------------------------------------
+    | JWT Authentication Secret
+    |--------------------------------------------------------------------------
+    |
+    | Don't forget to set this in your .env file, as it will be used to sign
+    | your tokens. A helper command is provided for this:
+    | `php artisan jwt:secret`
+    |
+    | Note: This will be used for Symmetric algorithms only (HMAC),
+    | since RSA and ECDSA use a private/public key combo (See below).
+    |
+    */
+
+    'secret' => env('JWT_SECRET'),
+
+    /*
+    |--------------------------------------------------------------------------
+    | JWT Authentication Keys
+    |--------------------------------------------------------------------------
+    |
+    | The algorithm you are using, will determine whether your tokens are
+    | signed with a random string (defined in `JWT_SECRET`) or using the
+    | following public & private keys.
+    |
+    | Symmetric Algorithms:
+    | HS256, HS384 & HS512 will use `JWT_SECRET`.
+    |
+    | Asymmetric Algorithms:
+    | RS256, RS384 & RS512 / ES256, ES384 & ES512 will use the keys below.
+    |
+    */
+
+    'keys' => [
+
+        /*
+        |--------------------------------------------------------------------------
+        | Public Key
+        |--------------------------------------------------------------------------
+        |
+        | A path or resource to your public key.
+        |
+        | E.g. 'file://path/to/public/key'
+        |
+        */
+
+        'public' => env('JWT_PUBLIC_KEY'),
+
+        /*
+        |--------------------------------------------------------------------------
+        | Private Key
+        |--------------------------------------------------------------------------
+        |
+        | A path or resource to your private key.
+        |
+        | E.g. 'file://path/to/private/key'
+        |
+        */
+
+        'private' => env('JWT_PRIVATE_KEY'),
+
+        /*
+        |--------------------------------------------------------------------------
+        | Passphrase
+        |--------------------------------------------------------------------------
+        |
+        | The passphrase for your private key. Can be null if none set.
+        |
+        */
+
+        'passphrase' => env('JWT_PASSPHRASE'),
+
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | JWT time to live
+    |--------------------------------------------------------------------------
+    |
+    | Specify the length of time (in minutes) that the token will be valid for.
+    | Defaults to 1 hour.
+    |
+    | You can also set this to null, to yield a never expiring token.
+    | Some people may want this behaviour for e.g. a mobile app.
+    | This is not particularly recommended, so make sure you have appropriate
+    | systems in place to revoke the token if necessary.
+    | Notice: If you set this to null you should remove 'exp' element from 'required_claims' list.
+    |
+    */
+
+    'ttl' => env('JWT_TTL', 60),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Refresh time to live
+    |--------------------------------------------------------------------------
+    |
+    | Specify the length of time (in minutes) that the token can be refreshed
+    | within. I.E. The user can refresh their token within a 2 week window of
+    | the original token being created until they must re-authenticate.
+    | Defaults to 2 weeks.
+    |
+    | You can also set this to null, to yield an infinite refresh time.
+    | Some may want this instead of never expiring tokens for e.g. a mobile app.
+    | This is not particularly recommended, so make sure you have appropriate
+    | systems in place to revoke the token if necessary.
+    |
+    */
+
+    'refresh_ttl' => env('JWT_REFRESH_TTL', 20160),
+
+    /*
+    |--------------------------------------------------------------------------
+    | JWT hashing algorithm
+    |--------------------------------------------------------------------------
+    |
+    | Specify the hashing algorithm that will be used to sign the token.
+    |
+    | See here: https://github.com/namshi/jose/tree/master/src/Namshi/JOSE/Signer/OpenSSL
+    | for possible values.
+    |
+    */
+
+    'algo' => env('JWT_ALGO', 'HS256'),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Required Claims
+    |--------------------------------------------------------------------------
+    |
+    | Specify the required claims that must exist in any token.
+    | A TokenInvalidException will be thrown if any of these claims are not
+    | present in the payload.
+    |
+    */
+
+    'required_claims' => [
+        'iss',
+        'iat',
+        'exp',
+        'nbf',
+        'sub',
+        'jti',
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Persistent Claims
+    |--------------------------------------------------------------------------
+    |
+    | Specify the claim keys to be persisted when refreshing a token.
+    | `sub` and `iat` will automatically be persisted, in
+    | addition to the these claims.
+    |
+    | Note: If a claim does not exist then it will be ignored.
+    |
+    */
+
+    'persistent_claims' => [
+        // 'foo',
+        // 'bar',
+    ],
+
+    /*
+    |--------------------------------------------------------------------------
+    | Lock Subject
+    |--------------------------------------------------------------------------
+    |
+    | This will determine whether a `prv` claim is automatically added to
+    | the token. The purpose of this is to ensure that if you have multiple
+    | authentication models e.g. `App\User` & `App\OtherPerson`, then we
+    | should prevent one authentication request from impersonating another,
+    | if 2 tokens happen to have the same id across the 2 different models.
+    |
+    | Under specific circumstances, you may want to disable this behaviour
+    | e.g. if you only have one authentication model, then you would save
+    | a little on token size.
+    |
+    */
+
+    'lock_subject' => true,
+
+    /*
+    |--------------------------------------------------------------------------
+    | Leeway
+    |--------------------------------------------------------------------------
+    |
+    | This property gives the jwt timestamp claims some "leeway".
+    | Meaning that if you have any unavoidable slight clock skew on
+    | any of your servers then this will afford you some level of cushioning.
+    |
+    | This applies to the claims `iat`, `nbf` and `exp`.
+    |
+    | Specify in seconds - only if you know you need it.
+    |
+    */
+
+    'leeway' => env('JWT_LEEWAY', 0),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Blacklist Enabled
+    |--------------------------------------------------------------------------
+    |
+    | In order to invalidate tokens, you must have the blacklist enabled.
+    | If you do not want or need this functionality, then set this to false.
+    |
+    */
+
+    'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true),
+
+    /*
+    | -------------------------------------------------------------------------
+    | Blacklist Grace Period
+    | -------------------------------------------------------------------------
+    |
+    | When multiple concurrent requests are made with the same JWT,
+    | it is possible that some of them fail, due to token regeneration
+    | on every request.
+    |
+    | Set grace period in seconds to prevent parallel request failure.
+    |
+    */
+
+    'blacklist_grace_period' => env('JWT_BLACKLIST_GRACE_PERIOD', 0),
+
+    /*
+    |--------------------------------------------------------------------------
+    | Cookies encryption
+    |--------------------------------------------------------------------------
+    |
+    | By default Laravel encrypt cookies for security reason.
+    | If you decide to not decrypt cookies, you will have to configure Laravel
+    | to not encrypt your cookie token by adding its name into the $except
+    | array available in the middleware "EncryptCookies" provided by Laravel.
+    | see https://laravel.com/docs/master/responses#cookies-and-encryption
+    | for details.
+    |
+    | Set it to true if you want to decrypt cookies.
+    |
+    */
+
+    'decrypt_cookies' => false,
+
+    /*
+    |--------------------------------------------------------------------------
+    | Providers
+    |--------------------------------------------------------------------------
+    |
+    | Specify the various providers used throughout the package.
+    |
+    */
+
+    'providers' => [
+
+        /*
+        |--------------------------------------------------------------------------
+        | JWT Provider
+        |--------------------------------------------------------------------------
+        |
+        | Specify the provider that is used to create and decode the tokens.
+        |
+        */
+
+        'jwt' => Tymon\JWTAuth\Providers\JWT\Lcobucci::class,
+
+        /*
+        |--------------------------------------------------------------------------
+        | Authentication Provider
+        |--------------------------------------------------------------------------
+        |
+        | Specify the provider that is used to authenticate users.
+        |
+        */
+
+        'auth' => Tymon\JWTAuth\Providers\Auth\Illuminate::class,
+
+        /*
+        |--------------------------------------------------------------------------
+        | Storage Provider
+        |--------------------------------------------------------------------------
+        |
+        | Specify the provider that is used to store tokens in the blacklist.
+        |
+        */
+
+        'storage' => Tymon\JWTAuth\Providers\Storage\Illuminate::class,
+
+    ],
+
+];

+ 42 - 0
database/migrations/2021_02_03_145200_create_procurements_table.php

@@ -0,0 +1,42 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateProcurementsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('procurements', function (Blueprint $table) {
+            $table->id();
+            $table->string('code')->index()->comment('采购编号');
+            $table->tinyInteger('type')->index()->default(0)->comment('采购类型');
+            $table->bigInteger('owner_material_id')->index()->comment('外键项目耗材');
+            $table->bigInteger('supplier_id')->index()->nullable()->comment('外键供应商');
+            $table->decimal('quantity')->comment('采购数量');
+            $table->decimal('amount')->comment('销售数量');
+            $table->decimal('unit_price')->nullable()->comment('销售单价');
+            $table->decimal('cost_price')->nullable()->comment('成本单价(采购)');
+            $table->tinyInteger('status')->default(0)->comment('状态');//待报价 已报价 待接单 生产中 送货中 已完成 已取消
+            $table->enum('is_enquiry',['是','否'])->default('否')->comment('是否询价');
+            $table->bigInteger('initiator')->index()->comment('外键用户(发起者)');
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('procurements');
+    }
+}

+ 37 - 0
database/migrations/2021_02_03_151138_create_procurement_quotations_table.php

@@ -0,0 +1,37 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateProcurementQuotationsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('procurement_quotations', function (Blueprint $table) {
+            $table->id();
+            $table->bigInteger('procurement_id')->index()->comment('外键采购单');
+            $table->bigInteger('supplier_id')->index()->comment('外键供应商');
+            $table->decimal('offer')->nullable()->comment('报价');
+            $table->bigInteger('operator')->index()->comment('操作者');
+            $table->timestamp('quoted_at')->nullable()->comment('报价时间');
+            $table->tinyInteger('status')->default(0)->comment('状态');
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('procurement_quotations');
+    }
+}

+ 37 - 0
database/migrations/2021_02_03_151704_create_procurement_deliveries_table.php

@@ -0,0 +1,37 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateProcurementDeliveriesTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('procurement_deliveries', function (Blueprint $table) {
+            $table->id();
+            $table->bigInteger('procurement_id')->index()->comment('外键采购单');
+            $table->decimal('amount')->comment('送货数量');
+            $table->bigInteger('initiator')->index()->comment('发起人');
+            $table->bigInteger('signer')->index()->comment('签收人');
+            $table->tinyInteger('status')->default(0)->comment('状态');
+            $table->date('signed_at')->comment('签收时间');
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('procurement_deliveries');
+    }
+}

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

@@ -0,0 +1,36 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateProcurementCheckSheetsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('procurement_check_sheets', function (Blueprint $table) {
+            $table->id();
+            $table->bigInteger('procurement_delivery_id')->index()->comment('外键采购送货单');
+            $table->integer('invoice_number')->nullable()->comment('发票号');
+            $table->decimal('account_payable',10,4)->comment('应付款');
+            $table->tinyInteger('status')->default(0)->comment('状态');
+            $table->bigInteger('auditor')->index()->comment('出纳审核人');
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('procurement_check_sheets');
+    }
+}

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

@@ -0,0 +1,35 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateProcurementTotalBillsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('procurement_total_bills', function (Blueprint $table) {
+            $table->id();
+            $table->date('counting_month')->index()->comment('结算月');
+            $table->bigInteger('supplier_id')->index()->comment('外键供应商');
+            $table->tinyInteger('status')->default(0)->comment('状态');
+            $table->decimal('total_payable',10,4)->comment('总金额');
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('procurement_total_bills');
+    }
+}

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

@@ -0,0 +1,36 @@
+<?php
+
+use App\Authority;
+use Illuminate\Database\Migrations\Migration;
+
+class AddAuthorritiesToProcurement extends Migration
+{
+    private $names = [
+        '采购管理',
+        '采购管理-采购','采购管理-财务','采购管理-相关设置',
+        '采购管理-采购-查询','采购管理-采购-新建','采购管理-采购-编辑',
+        '采购管理-财务-对账单','采购管理-财务-采购账单','采购管理-财务-月账单报表',
+    ];
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        foreach ($this->names as $name) {
+            if(!Authority::query()->where('name',$name)->exists())
+                Authority::query()->create(['name'=>$name,'alias_name'=>$name]);
+        }
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Authority::query()->whereIn('name',$this->names)->delete();
+    }
+}

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

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class ChangeMaterialSuppliers extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::dropIfExists('material_supplier');
+        Schema::create('material_suppliers', function (Blueprint $table) {
+            $table->bigInteger('material_id');
+            $table->bigInteger('supplier_id');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('material_suppliers');
+    }
+}

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

@@ -0,0 +1,31 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateSupplierUserTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('supplier_user', function (Blueprint $table) {
+            $table->bigInteger("user_id")->comment("外键用户");
+            $table->bigInteger("supplier_id")->comment("外键供应商");
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('supplier_user');
+    }
+}

+ 1 - 1
laravel-echo-server.lock

@@ -1,3 +1,3 @@
 {
 	"process": 19904
-}
+}

+ 5 - 0
resources/views/layouts/menu.blade.php

@@ -57,6 +57,11 @@
                                     :class="{active:isActive('station',1)}">
                     <span class="fa fa-share-alt-square" style="color: #72441b"></span>
                     站管理</a></li> @endcan
+        @can('采购管理')
+                <li class="nav-item"><a href="{{url("procurement/procurement/index")}}" class="nav-link"
+                                        :class="{active:isActive('station',1)}">
+                        <span class="fa fa-cart-plus" style="color: #1b4b72"></span>
+                        采购管理</a></li>@endcan
         @can('基础设置')
             <li class="nav-item"><a href="{{url("maintenance")}}" class="nav-link" target="maintenance"
                                     :class="{active:isActive('maintenance',1)}">

+ 8 - 0
resources/views/maintenance/supplier/_create.blade.php

@@ -51,6 +51,14 @@
                             <textarea name="specification" id="add-opening-bank " cols="30" rows="5"  class="form-control form-text col-10" v-model="addSupplier.opening_bank "></textarea>
                         </div>
                     </div>
+                    <div class="form-group row">
+                        <label for="add-bank-account " class="col-sm-3 col-form-label text-right">耗材类型</label>
+                        <select id="material_id" class="selectpicker" multiple data-live-search="true" title="耗材类型(多选)"
+                                v-model="material_id">
+                            <option v-for="material in materials" :value="material.id">@{{ material.name }}</option>
+                        </select>
+                        <label hidden><input name="material_id" type="text" :value="material_id"></label>
+                    </div>
                 </form>
             </div>
             <div class="modal-footer">

+ 7 - 0
resources/views/maintenance/supplier/_edit.blade.php

@@ -51,6 +51,13 @@
                             <textarea name="specification" id="edit-opening-bank " cols="30" rows="5"  class="form-control form-text col-10" v-model="editSupplier.opening_bank "></textarea>
                         </div>
                     </div>
+                    <div class="form-group row">
+                        <label for="add-bank-account " class="col-sm-3 col-form-label text-right">耗材类型</label>
+                        <select id="material_id" class="selectpicker" multiple data-live-search="true" title="耗材类型(多选)" v-model="material_id">
+                            <option v-for="material in materials" :value="material.id">@{{ material.name }}</option>
+                        </select>
+                        <label hidden><input name="material_id" type="text" :value="material_id"></label>
+                    </div>
                 </form>
             </div>
             <div class="modal-footer">

+ 16 - 4
resources/views/maintenance/supplier/index.blade.php

@@ -28,6 +28,12 @@
             el:'#supplier',
             data:{
                 suppliers:{!! $suppliers->toJson() !!}['data'],
+                materials : [
+                        @foreach($materials as $material)
+                    {id:"{{$material->id}}",name:"{{$material->name}}"},
+                    @endforeach
+                ],
+                material_id:{!! old('material_id') ? json_encode(old('material_id')) : '[]' !!},
                 editSupplier:{},
                 addSupplier:{},
                 index:''
@@ -53,18 +59,23 @@
                         tempTip.show('删除当前项目耗材失败:'+err);
                     });
                 },
-                edit(suppliers,i){
-                    this.editSupplier = JSON.parse(JSON.stringify(suppliers));
+                edit(supplier,i){
+                    this.editSupplier = JSON.parse(JSON.stringify(supplier));
+                    this.material_id= [];
+                    supplier.material.forEach((item)=>{
+                        this.material_id.push(item.id);
+                    });
                     this.index = i;
                     $('#edit-supplier').modal('show');
                 },
                 update(){
                     let url = '{{url('apiLocal/supplier/update')}}';
-                    let params = this.editSupplier;
+                    let params = {editSupplier:this.editSupplier,material_id:this.material_id};
                     window.tempTip.postBasicRequest(url,params,res=>{
                         this.$set(this.suppliers,this.index,res);
                         this.index = null;
                         this.editSupplier = {};
+                        this.material_id = [];
                         $("#edit-supplier").modal('hide');
                         return "修改完成";
                     },true);
@@ -74,10 +85,11 @@
                 },
                 create(){
                     let url = '{{url('apiLocal/supplier/store')}}';
-                    let params = this.addSupplier;
+                    let params = {addSupplier:this.addSupplier,material_id:this.material_id};
                     window.tempTip.postBasicRequest(url,params,res=>{
                         this.$set(this.suppliers,this.suppliers.length,res);
                         this.addSupplier = {};
+                        this.material_id = [];
                         $("#add-supplier").modal('hide');
                         return "创建成功";
                     },true);

+ 24 - 0
resources/views/procurement/finance/_changeCostPrice.blade.php

@@ -0,0 +1,24 @@
+<div class="modal " id="change-costPrice" tabindex="-1" >
+    <div class="modal-dialog modal-lg modal-dialog-centered">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title text-center">修改采购单价</h5>
+                <button type="button" class="close" data-dismiss="modal">
+                    <span>&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                    <div class="form-group row">
+                        <label for="cost_price" class="col-2 col-form-label text-right">采购单价</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control "  name="cost_price" autocomplete="off"  v-model="cost_price">
+                        </div>
+                    </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary"  data-dismiss="modal" >关闭</button>
+                <button type="button" class="btn btn-primary" @click="costPrice">提交</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 24 - 0
resources/views/procurement/finance/_fillInvoiceNumber.blade.php

@@ -0,0 +1,24 @@
+<div class="modal " id="fill-invoice-number" tabindex="-1" >
+    <div class="modal-dialog modal-lg">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title text-center">填写发票号</h5>
+                <button type="button" class="close" data-dismiss="modal">
+                    <span>&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                    <div class="form-group row">
+                        <label for="invoice_number" class="col-2 col-form-label text-right">发票号</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control "  name="invoice_number" autocomplete="off"  v-model="invoice_number">
+                        </div>
+                    </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary"  data-dismiss="modal" >关闭</button>
+                <button type="button" class="btn btn-primary" @click="fillInvoice">提交</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 222 - 0
resources/views/procurement/finance/checkBill.blade.php

@@ -0,0 +1,222 @@
+@extends('layouts.app')
+@section('title')采购管理-财务-对账单@endsection
+
+@section('content')
+    @component('procurement.finance.menu')@endcomponent
+    <div class="container-fluid" id="list">
+        <div id="form_div" class="mt-1"></div>
+        <div class="row mt-2">
+        <span class="dropdown ml-3">
+        <button class="btn btn-outline-dark btn-sm form-control-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="checkBillExport(false)" href="javascript:">导出勾选内容</a>
+            <a class="dropdown-item" @click="checkBillExport(true)" href="javascript:">导出所有页</a>
+        </div>
+        </span>
+        </div>
+        <label for="all" id="cloneCheckAll" class="d-none">
+            <input id="all" type="checkbox" @click="checkAll($event)">全选
+        </label>
+        <table class="table table-sm table-bordered text-nowrap d-none" id="headerRoll"></table>
+        <table class="table table-sm table-striped table-bordered table-hover text-nowrap card-body mt-2"
+               id="headerParent">
+            <tr id="header"></tr>
+            <tr v-for="(procurementCheckSheet,i) in procurementCheckSheets">
+                <td>
+                    <input class="checkItem" type="checkbox" :value="procurementCheckSheet.id" v-model="checkData">
+                </td>
+                <td class="">@{{ procurementCheckSheet.procurement_code }}</td>
+                <td class="text-muted">@{{ procurementCheckSheet.procurement_at }}</td>
+                <td class="text-muted">@{{ procurementCheckSheet.procurement_delivery_at }}</td>
+                <td class="text-muted">@{{ procurementCheckSheet.supplier_name }}</td>
+                <td class="tooltipTarget" style="max-width: 200px;overflow:hidden">@{{ procurementCheckSheet.material_code }}</td>
+                <td class="text-muted">@{{ procurementCheckSheet.material_name }}</td>
+                <td class="text-muted">@{{ procurementCheckSheet.procurement_quantity }}</td>
+                <td class="text-muted">@{{ procurementCheckSheet.amount }}</td>
+                <td class="text-muted">@{{ procurementCheckSheet.signer_name }}</td>
+                <td class="text-muted">@{{ procurementCheckSheet.signed_at }}</td>
+                <td class="text-muted">@{{ procurementCheckSheet.account_payable }}</td>
+                <td><span>@{{ procurementCheckSheet.invoice_number }}</span></td>
+                <td><span>@{{ procurement_check_sheet_status[procurementCheckSheet.status] }}</span></td>
+                <td><a class="text-primary" @click="fillInvoiceNumber(procurementCheckSheet.id)" v-if="!procurementCheckSheet.invoice_number">填写发票号</a></td>
+            </tr>
+        </table>
+        @can('采购管理-财务-对账单')
+            @include('procurement.finance._fillInvoiceNumber')
+        @endcan
+        <div class="text-info h5 btn btn">{{$procurementCheckSheets->count()}}/@{{ sum }}</div>
+        <div>{{$procurementCheckSheets->appends($paginateParams)->links()}}</div>
+    </div>
+@endsection
+@section('lastScript')
+    <script type="text/javascript" src="{{mix('js/queryForm/export.js')}}"></script>
+    <script type="text/javascript" src="{{mix('js/queryForm/queryForm.js')}}"></script>
+    <script type="text/javascript" src="{{mix('js/queryForm/header.js')}}"></script>
+    <script>
+        let vue = new Vue({
+            el: '#list',
+            data: {
+                procurementCheckSheets: [
+                    @foreach($procurementCheckSheets as $procurementCheckSheet)
+                    {
+                        id:'{{$procurementCheckSheet->id}}',invoice_number:'{{$procurementCheckSheet->invoice_number}}',account_payable:'{{$procurementCheckSheet->account_payable}}',
+                        created_at:'{{$procurementCheckSheet->created_at}}',auditor:'{{$procurementCheckSheet->auditor}}',status:'{{$procurementCheckSheet->status}}',
+
+                        @if($procurementCheckSheet->procurementDelivery)
+                        amount:'{{$procurementCheckSheet->procurementDelivery->amount}}',initiator:'{{$procurementCheckSheet->procurementDelivery->initiator}}',
+                        signer:'{{$procurementCheckSheet->procurementDelivery->signer}}',signed_at:'{{$procurementCheckSheet->procurementDelivery->signed_at}}',
+                        procurement_delivery_at:'{{$procurementCheckSheet->procurementDelivery->created_at}}',@endif
+
+                        @if($procurementCheckSheet->procurementDelivery->procurement)
+                        procurement_quantity:'{{$procurementCheckSheet->procurementDelivery->procurement->quantity}}',
+                        procurement_code:'{{$procurementCheckSheet->procurementDelivery->procurement->code}}',
+                        procurement_at:'{{$procurementCheckSheet->procurementDelivery->procurement->created_at}}',@endif
+
+                        @if($procurementCheckSheet->procurementDelivery->receiver)
+                        signer_name:'{{$procurementCheckSheet->procurementDelivery->receiver->name}}',@endif
+
+                        @if($procurementCheckSheet->procurementDelivery->procurement->supplier)
+                        supplier_id:'{{$procurementCheckSheet->procurementDelivery->procurement->supplier->id}}',supplier_name:'{{$procurementCheckSheet->procurementDelivery->procurement->supplier->name}}',@endif
+
+                        @if($procurementCheckSheet->procurementDelivery->procurement->ownerMaterial->material)
+                        material_id:'{{$procurementCheckSheet->procurementDelivery->procurement->ownerMaterial->material->id}}',
+                        material_name:'{{$procurementCheckSheet->procurementDelivery->procurement->ownerMaterial->material->name}}',
+                        material_code:'{{$procurementCheckSheet->procurementDelivery->procurement->ownerMaterial->material->code}}',@endif
+
+                    },
+                    @endforeach
+                ],
+                suppliers:[
+                        @foreach($suppliers as $supplier)
+                    {name:'{{$supplier->id}}',value:'{{$supplier->name}}'},
+                    @endforeach
+                ],
+                materials: [
+                        @foreach($materials as $material)
+                    {name:'{{$material->id}}',value:'{{$material->name}}'},
+                    @endforeach
+                ],
+                checkData: [],
+                sum:{!! $procurementCheckSheets->total() !!},
+                procurement_check_sheet_status:{!! json_encode(\App\ProcurementCheckSheet::status,JSON_UNESCAPED_UNICODE) !!},
+                invoice_number:'',procurementCheckSheetId:null,
+            },
+            mounted: function () {
+                $(".tooltipTarget").tooltip({'trigger': 'hover'});
+                $('#list').removeClass('d-none');
+                let data = [
+                    [
+                        {name: 'signed_at', type: 'dateTime', tip: '选择显示指定的签收日期'},
+                        {
+                            name: 'supplier_id', type: 'select_multiple_select', tip: ['输入关键词快速定位下拉列表,回车确定', '选择要显示的供应商'],
+                            placeholder: ['供应商', '定位或多选供应商'], data: this.suppliers
+                        },
+                        {
+                            name: 'status', type: 'select',
+                            tip: ['输入关键词快速定位下拉列表,回车确定', '选择要显示的耗材'],
+                            placeholder: '对账单状态',
+                            data: [{name:0,value:'未出账'},{name:1,value:'已出账'},{name:2,value:'已完结'},],
+                        },
+                    ],
+                ];
+                this.form = new query({
+                    el: "#form_div",
+                    condition: data,
+                });
+                this.form.init();
+                let column = [
+                    {
+                        name: 'cloneCheckAll', customization: true, type: 'checkAll',column:'id',
+                        dom: $('#cloneCheckAll').removeClass('d-none'), neglect: true
+                    },
+                    {name: 'code', value: '采购编号', neglect: true},
+                    {name: 'procurement_at', value: '采购日期', class: ''},
+                    {name: '', value: '送货日期', class: 'text-muted'},
+                    {name: 'company_name', value: '供应商名称', class: 'text-muted'},
+                    {name: 'material_code', value: '耗材编号', class: 'text-muted'},
+                    {name: 'material_name', value: '耗材'},
+                    {name: 'quantity', value: '采购数量', class: 'text-muted'},
+                    {name: 'amount', value: '送货数量', class: 'text-muted'},
+                    {name: 'signer', value: '签收人', class: 'text-muted'},
+                    {name: 'signed_at', value: '签收日期', class: 'text-muted'},
+                    {name: '', value: '应付金额', neglect: true},
+                    {name: '', value: '发票号', neglect: true},
+                    {name: '', value: '状态', neglect: true},
+                    {name: '', value: '填写发票号', neglect: true},
+                ];
+
+                let _this = this;
+                setTimeout(function () {
+                    let header = new Header({
+                        el: "#header",
+                        column: column,
+                        data: _this.procurementCheckSheets,
+                        restorationColumn: 'id',
+                        fixedTop: ($('#form_div').height()) + 2,
+                        offset: 0.5,
+                        vue: vue
+                    });
+                    header.init();
+                }, 0);
+            },
+            methods: {
+                //全选事件
+                checkAll(e) {
+                    if (e.target.checked) {
+                        this.procurementCheckSheets.forEach((el, i) => {
+                            if (this.checkData.indexOf(el.id) == '-1') {
+                                this.checkData.push(el.id);
+                            }
+                        });
+                    } else {
+                        this.checkData = [];
+                    }
+                },
+                fillInvoiceNumber(id){
+                    let _this=this;
+                    _this.procurementCheckSheetId=id;
+                    $('#fill-invoice-number').modal('show');
+                },
+                fillInvoice(){
+                    let _this=this;
+                    if (!_this.procurementCheckSheetId)return;
+                    if (!_this.invoice_number){
+                        tempTip.setDuration(3000);
+                        tempTip.show('发票号不可为空!');
+                        return;
+                    }
+                    let url = '{{url('procurement/finance/fillInvoice')}}';
+                    let params = {invoice_number:_this.invoice_number,procurementCheckSheetId:_this.procurementCheckSheetId};
+                    window.axios.post(url,params).then(function (res) {
+                        if (!res.data.success){
+                            tempTip.setDuration(3000);
+                            tempTip.show(res.data.message);
+                        }else {
+                            _this.procurementCheckSheets.forEach(function (procurementCheckSheet) {
+                                if (procurementCheckSheet.id===_this.procurementCheckSheetId){
+                                    procurementCheckSheet.invoice_number=_this.invoice_number;
+                                }
+                            });
+                            $("#fill-invoice-number").modal('hide');
+                            tempTip.setDuration(3000);
+                            tempTip.showSuccess('添加发票号成功!');
+                        }
+                    }).catch(function (err) {
+                        tempTip.setDuration(3000);
+                        tempTip.show('添加发票号失败!网络错误:'+err);
+                    });
+                },
+                checkBillExport(selectAll){
+                    let url = '{{url('procurement/finance/checkBillExport')}}';
+                    let token='{{ csrf_token() }}';
+                    excelExport(selectAll,this.checkData,url,this.sum,token);
+                },
+
+            }
+        });
+    </script>
+@endsection

+ 23 - 0
resources/views/procurement/finance/menu.blade.php

@@ -0,0 +1,23 @@
+<div id="nav2">
+    @component('procurement.menu')
+    @endcomponent
+    <div class="container-fluid nav3">
+        <div class="card menu-third" >
+            <ul class="nav nav-pills">
+                @can('采购管理-财务-对账单')
+                    <li class="nav-item">
+                        <a class="nav-link" href="{{url('procurement/finance/checkBill')}}" :class="{active:isActive('checkBill',3)}">对账单</a>
+                    </li> @endcan
+                @can('采购管理-财务-采购账单')
+                    <li class="nav-item">
+                        <a  class="nav-link" href="{{url('procurement/finance/procurementBill')}}" :class="{active:isActive('procurementBill',3)}">采购账单</a>
+                    </li> @endcan
+                    @can('采购管理-财务-月账单报表')
+                    <li class="nav-item">
+                        <a  class="nav-link" href="{{url('procurement/finance/monthlyBillReport')}}" :class="{active:isActive('monthlyBillReport',3)}">月账单报表</a>
+                    </li> @endcan
+            </ul>
+        </div>
+    </div>
+</div>
+

+ 137 - 0
resources/views/procurement/finance/monthlyBillReport.blade.php

@@ -0,0 +1,137 @@
+@extends('layouts.app')
+@section('title')采购管理-财务-月账单报表@endsection
+
+@section('content')
+    @component('procurement.finance.menu')@endcomponent
+    <div class="container-fluid" id="list">
+        <div id="form_div" class="mt-1"></div>
+        <div class="row mt-2">
+        <span class="dropdown ml-3">
+        <button class="btn btn-outline-dark btn-sm form-control-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="procurementTotalBillExport(false)" href="javascript:">导出勾选内容</a>
+            <a class="dropdown-item" @click="procurementTotalBillExport(true)" href="javascript:">导出所有页</a>
+        </div>
+        </span>
+        </div>
+        <label for="all" id="cloneCheckAll" class="d-none">
+            <input id="all" type="checkbox" @click="checkAll($event)">全选
+        </label>
+        <table class="table table-sm table-bordered text-nowrap d-none" id="headerRoll"></table>
+        <table class="table table-sm table-striped table-bordered table-hover text-nowrap card-body mt-2"
+               id="headerParent">
+            <tr id="header"></tr>
+            <tr v-for="(procurementTotalBill,i) in procurementTotalBills">
+                <td>
+                    <input class="checkItem" type="checkbox" :value="procurementTotalBill.id" v-model="checkData">
+                </td>
+                <td >@{{ procurementTotalBill.id }}</td>
+                <td class="text-muted">@{{ procurementTotalBill.counting_month }}</td>
+                <td class="text-muted">@{{ procurementTotalBill.created_at.substr(0,10) }}</td>
+                <td class="text-muted">@{{ procurementTotalBill.supplier_name }}</td>
+                <td>@{{ procurementTotalBill.total_payable }}</td>
+                <td><span>@{{ procurement_total_bill_status[procurementTotalBill.status] }}</span></td>
+            </tr>
+        </table>
+        <div class="text-info h5 btn btn">{{$procurementTotalBills->count()}}/@{{ sum }}</div>
+        <div>{{$procurementTotalBills->appends($paginateParams)->links()}}</div>
+    </div>
+@endsection
+@section('lastScript')
+    <script type="text/javascript" src="{{mix('js/queryForm/export.js')}}"></script>
+    <script type="text/javascript" src="{{mix('js/queryForm/queryForm.js')}}"></script>
+    <script type="text/javascript" src="{{mix('js/queryForm/header.js')}}"></script>
+    <script>
+        let vue = new Vue({
+            el: '#list',
+            data: {
+                procurementTotalBills: [
+                    @foreach($procurementTotalBills as $procurementTotalBill)
+                    {
+                        id:'{{$procurementTotalBill->id}}',counting_month:'{{$procurementTotalBill->counting_month}}',
+                        created_at:'{{$procurementTotalBill->created_at}}',status:'{{$procurementTotalBill->status}}',total_payable:'{{$procurementTotalBill->total_payable}}',
+                            @if($procurementTotalBill->supplier)
+                            supplier_id:'{{$procurementTotalBill->supplier->id}}',supplier_name:'{{$procurementTotalBill->supplier->name}}',@endif
+                    },
+                    @endforeach
+                ],
+                suppliers:[
+                        @foreach($suppliers as $supplier)
+                    {name:'{{$supplier->id}}',value:'{{$supplier->name}}'},
+                    @endforeach
+                ],
+                checkData: [],
+                sum:{!! $procurementTotalBills->total() !!},
+                procurement_total_bill_status:{!! json_encode(\App\ProcurementTotalBill::status,JSON_UNESCAPED_UNICODE) !!},
+
+            },
+            mounted: function () {
+                $(".tooltipTarget").tooltip({'trigger': 'hover'});
+                $('#list').removeClass('d-none');
+                let data = [
+                    [
+                        {name:'counting_month',type:'dateMonth',tip:'选择账单日期',placeholder: '----年--月'},
+                        {
+                            name: 'supplier_id', type: 'select_multiple_select', tip: ['输入关键词快速定位下拉列表,回车确定', '选择要显示的供应商'],
+                            placeholder: ['供应商', '定位或多选供应商'], data: this.suppliers
+                        },
+                    ],
+                ];
+                this.form = new query({
+                    el: "#form_div",
+                    condition: data,
+                });
+                this.form.init();
+                let column = [
+                    {
+                        name: 'cloneCheckAll', customization: true, type: 'checkAll',column:'id',
+                        dom: $('#cloneCheckAll').removeClass('d-none'), neglect: true
+                    },
+                    {name: 'id', value: '对账编号', neglect: true},
+                    {name: 'counting_month', value: '账单日期', },
+                    {name: 'created_at', value: '提交日期',},
+                    {name: 'supplier', value: '供应商',},
+                    {name: 'total_payable', value: '总金额',},
+                    {name: 'status', value: '状态'},
+                ];
+
+                let _this = this;
+                setTimeout(function () {
+                    let header = new Header({
+                        el: "#header",
+                        column: column,
+                        data: _this.procurementTotalBills,
+                        restorationColumn: 'id',
+                        fixedTop: ($('#form_div').height()) + 2,
+                        offset: 0.5,
+                        vue: vue
+                    });
+                    header.init();
+                }, 0);
+            },
+            methods: {
+                //全选事件
+                checkAll(e) {
+                    if (e.target.checked) {
+                        this.procurementTotalBills.forEach((el, i) => {
+                            if (this.checkData.indexOf(el.id) == '-1') {
+                                this.checkData.push(el.id);
+                            }
+                        });
+                    } else {
+                        this.checkData = [];
+                    }
+                },
+                procurementTotalBillExport(selectAll){
+                    let url = '{{url('procurement/finance/procurementTotalBillExport')}}';
+                    let token='{{ csrf_token() }}';
+                    excelExport(selectAll,this.checkData,url,this.sum,token);
+                },
+            }
+        });
+    </script>
+@endsection

+ 212 - 0
resources/views/procurement/finance/procurementBill.blade.php

@@ -0,0 +1,212 @@
+@extends('layouts.app')
+@section('title')采购管理-财务-采购账单@endsection
+
+@section('content')
+    @component('procurement.finance.menu')@endcomponent
+    <div class="container-fluid" id="list">
+        <div id="form_div" class="mt-1"></div>
+        <div class="row mt-2">
+        <span class="dropdown ml-3">
+        <button class="btn btn-outline-dark btn-sm form-control-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="procurementBillExport(false)" href="javascript:">导出勾选内容</a>
+            <a class="dropdown-item" @click="procurementBillExport(true)" href="javascript:">导出所有页</a>
+        </div>
+        </span>
+        </div>
+        <label for="all" id="cloneCheckAll" class="d-none">
+            <input id="all" type="checkbox" @click="checkAll($event)">全选
+        </label>
+        <table class="table table-sm table-bordered text-nowrap d-none" id="headerRoll"></table>
+        <table class="table table-sm table-striped table-bordered table-hover text-nowrap card-body mt-2"
+               id="headerParent">
+            <tr id="header"></tr>
+            <tr v-for="(procurement,i) in procurements">
+                <td>
+                    <input class="checkItem" type="checkbox" :value="procurement.id" v-model="checkData">
+                </td>
+                <td class="">@{{ procurement.code }}</td>
+                <td class="">@{{ procurement.created_at }}</td>
+                <td class=""></td>
+                <td class=""></td>
+                <td v-if="procurement.owner_material.owner">@{{ procurement.owner_material.owner.name }}</td>
+                <td v-if="procurement.owner_material.owner.customer">@{{ procurement.owner_material.owner.customer.company_name }}</td>
+                <td v-if="procurement.supplier">@{{ procurement.supplier.name }}</td>
+                <td class="tooltipTarget" style="max-width: 200px;overflow:hidden" v-if="procurement.owner_material.material">@{{ procurement.owner_material.material.code }}</td>
+                <td class="text-muted" v-if="procurement.owner_material.material">@{{ procurement.owner_material.material.name }}</td>
+                <td class="text-muted" v-if="procurement.owner_material">@{{ procurement.owner_material.size }}</td>
+                <td class="text-muted" v-if="procurement.owner_material">@{{ procurement.owner_material.special }}</td>
+                <td class="text-muted" v-if="procurement.owner_material">@{{ procurement.owner_material.specification }}</td>
+                <td>@{{ procurement.quantity }}</td>{{--采购数量--}}
+                <td>@{{ procurement.amount }}</td> {{--销售数量--}}
+                <td></td>
+                <td>@{{ procurement.cost_price }}</td> {{--采购单价--}}
+                <td>@{{ procurement.unit_price }}</td>  {{--销售单价--}}
+                <td>@{{ procurement.amount*procurement.cost_price }}</td> {{--应收--}}
+                <td>@{{ procurement.quantity*procurement.unit_price }}</td> {{--应付--}}
+                <td><span>@{{ procurement_status[procurement.status] }}</span></td>
+                <td>
+                    <span class="btn btn-sm btn-outline-danger">锁定</span>
+                    <span class="btn btn-sm btn-outline-success" @click="changeCostPrice(procurement.id,procurement.cost_price)">修改采购单价</span>
+                </td>
+            </tr>
+        </table>
+        @can('采购管理-财务-采购账单')
+            @include('procurement.finance._changeCostPrice')
+        @endcan
+        <div class="text-info h5 btn btn">{{$procurements->count()}}/@{{ sum }}</div>
+        <div>{{$procurements->appends($paginateParams)->links()}}</div>
+    </div>
+@endsection
+@section('lastScript')
+    <script type="text/javascript" src="{{mix('js/queryForm/export.js')}}"></script>
+    <script type="text/javascript" src="{{mix('js/queryForm/queryForm.js')}}"></script>
+    <script type="text/javascript" src="{{mix('js/queryForm/header.js')}}"></script>
+    <script>
+        let vue = new Vue({
+            el: '#list',
+            data: {
+                procurements: {!! $procurements->toJson() !!}['data'],
+                owners:[
+                        @foreach($owners as $owner)
+                    {name:'{{$owner->id}}',value:'{{$owner->name}}'},
+                    @endforeach
+                ],
+                materials: [
+                        @foreach($materials as $material)
+                    {name:'{{$material->id}}',value:'{{$material->name}}'},
+                    @endforeach
+                ],
+                suppliers:[
+                        @foreach($suppliers as $supplier)
+                    {name:'{{$supplier->id}}',value:'{{$supplier->name}}'},
+                    @endforeach
+                ],
+                checkData: [],
+                sum:{!! $procurements->total() !!},
+                procurement_status:{!! json_encode(\App\Procurement::status,JSON_UNESCAPED_UNICODE) !!},
+                procurement_id:'',cost_price:'',
+
+            },
+            mounted: function () {
+                $(".tooltipTarget").tooltip({'trigger': 'hover'});
+                $('#list').removeClass('d-none');
+                let data = [
+                    [
+                        {name: 'created_at_start', type: 'dateTime', tip: '选择显示指定日期的起始时间'},
+                        {name: 'created_at_end', type: 'dateTime', tip: '选择显示指定日期的结束时间'},
+                        {
+                            name: 'owner_id', type: 'select_multiple_select', tip: ['输入关键词快速定位下拉列表,回车确定', '选择要显示的项目'],
+                            placeholder: ['项目', '定位或多选项目'], data: this.owners
+                        },
+                        {
+                            name: 'material_id', type: 'select_multiple_select', tip: ['输入关键词快速定位下拉列表,回车确定', '选择要显示的耗材'],
+                            placeholder: ['耗材', '定位或多选耗材'], data: this.materials
+                        },
+                        {
+                            name: 'supplier_id', type: 'select_multiple_select', tip: ['输入关键词快速定位下拉列表,回车确定', '选择要显示的供应商'],
+                            placeholder: ['供应商', '定位或多选供应商'], data: this.suppliers
+                        },
+                        {name: 'company_name', type: 'input', tip: '采购公司:可在两侧增加百分号(%)进行模糊搜索', placeholder: '采购公司'},
+                    ],
+                ];
+                this.form = new query({
+                    el: "#form_div",
+                    condition: data,
+                });
+                this.form.init();
+                let column = [
+                    {
+                        name: 'cloneCheckAll', customization: true, type: 'checkAll',column:'id',
+                        dom: $('#cloneCheckAll').removeClass('d-none'), neglect: true
+                    },
+                    {name: 'code', value: '采购编号', neglect: true},
+                    {name: 'code', value: '采购日期', neglect: true},
+                    {name: 'code', value: '接单日期', neglect: true},
+                    {name: 'code', value: '签收日期', neglect: true},
+                    {name: 'owner_id', value: '项目名称', class: ''},
+                    {name: 'company_name', value: '采购公司', class: ''},
+                    {name: 'supplier_name', value: '供应商',},
+                    {name: 'material_code', value: '耗材编号', class: 'text-muted'},
+                    {name: 'material_name', value: '耗材'},
+                    {name: 'size', value: '尺寸大小', class: 'text-muted'},
+                    {name: 'special', value: '特殊要求', class: 'text-muted'},
+                    {name: 'specification', value: '材质规格', class: 'text-muted'},
+                    {name: 'quantity', value: '采购数量', neglect: true},
+                    {name: '', value: '销售数量', neglect: true},
+                    {name: '', value: '收货数量', neglect: true},
+                    {name: '', value: '采购单价(元)', neglect: true},
+                    {name: 'unit_price', value: '销售单价(元)', neglect: true},
+                    {name: '', value: '应收金额(元)', neglect: true},
+                    {name: '', value: '应付金额(元)', neglect: true},
+                    {name: '', value: '状态', neglect: true},
+                    {name: '', value: '操作', neglect: true},
+                ];
+
+                let _this = this;
+                setTimeout(function () {
+                    let header = new Header({
+                        el: "#header",
+                        column: column,
+                        data: _this.procurements,
+                        restorationColumn: 'id',
+                        fixedTop: ($('#form_div').height()) + 2,
+                        offset: 0.5,
+                        vue: vue
+                    });
+                    header.init();
+                }, 0);
+            },
+            methods: {
+                //全选事件
+                checkAll(e) {
+                    if (e.target.checked) {
+                        this.procurements.forEach((el, i) => {
+                            if (this.checkData.indexOf(el.id) == '-1') {
+                                this.checkData.push(el.id);
+                            }
+                        });
+                    } else {
+                        this.checkData = [];
+                    }
+                },
+                changeCostPrice(id,cost_price){
+                    this.procurement_id=id;
+                    this.cost_price=cost_price;
+                    $("#change-costPrice").modal('show');
+                },
+                costPrice(){
+                    let _this=this;
+                    let url='{{url('procurement/finance/costPrice')}}';
+                    let param={id:_this.procurement_id,cost_price:_this.cost_price};
+                    window.axios.post(url,param).then(function (res) {
+                        if (res.data.success){
+                            _this.procurements.forEach(function (procurement) {
+                                if (procurement.id===res.data.data.id){
+                                    procurement.cost_price=res.data.data.cost_price;
+                                    $("#change-costPrice").modal('hide');
+                                }
+                            })
+                        }else {
+                            tempTip.setDuration(3000);
+                            tempTip.show(res.data.message);
+                        }
+                    }).catch(function (err) {
+                        window.tempTip.setDuration(3000);
+                        window.tempTip.show("网络错误:" + err);
+                    })
+                },
+                procurementBillExport(selectAll){
+                    let url = '{{url('procurement/finance/procurementBillExport')}}';
+                    let token='{{ csrf_token() }}';
+                    excelExport(selectAll,this.checkData,url,this.sum,token);
+                },
+
+            }
+        });
+    </script>
+@endsection

+ 21 - 0
resources/views/procurement/menu.blade.php

@@ -0,0 +1,21 @@
+<div class="container-fluid nav2" id="nav2">
+    <div class="card">
+        <ul class="nav nav-pills">
+            @can('采购管理-采购')
+                <li class="nav-item">
+                    <a class="nav-link" href="{{url('procurement/procurement/index')}}"
+                       :class="{active:isActive('procurement',2)}">采购</a>
+                </li> @endcan
+            @can('采购管理-财务')
+                <li class="nav-item">
+                    <a class="nav-link" href="{{url('procurement/finance/checkBill')}}"
+                       :class="{active:isActive('finance',2)}">财务</a>
+                </li> @endcan
+            @can('采购管理-相关设置')
+                <li class="nav-item">
+                    <a class="nav-link" href="{{url('procurement/relating')}}"
+                       :class="{active:isActive('relating',2)}">相关设置</a>
+                </li> @endcan
+        </ul>
+    </div>
+</div>

+ 32 - 0
resources/views/procurement/menuProcurement.blade.php

@@ -0,0 +1,32 @@
+@extends('layouts.app')
+@section('title')相关设置@endsection
+
+@section('content')
+    <div id="nav2">
+        @component('procurement.menu')
+        @endcomponent
+            <div class="container-fluid nav3">
+                <div class="card menu-third" >
+                    <ul class="nav nav-pills">
+                    @can('耗材类型')
+                        <li class="nav-item">
+                            <a target="maintenance/userWorkgroup" class="nav-link text-dark" href="{{url('maintenance/material')}}" :class="{active:isActive('material',2)}">耗材</a>
+                        </li> @endcan
+                    @can('项目耗材')
+                        <li class="nav-item">
+                            <a target="maintenance/userLabor" class="nav-link text-dark" href="{{url('maintenance/ownerMaterial')}}" :class="{active:isActive('ownerMaterial',2)}">项目耗材</a>
+                        </li> @endcan
+                    @can('供应商')
+                        <li class="nav-item">
+                            <a target="maintenance/laborCompany" class="nav-link text-dark" href="{{url('maintenance/supplier')}}" :class="{active:isActive('supplier',2)}">供应商</a>
+                        </li> @endcan
+                        @can('系统配置')
+                        <li class="nav-item">
+                            <a target="maintenance/laborCompany" class="nav-link text-dark" href="{{url('maintenance/configuration')}}" :class="{active:isActive('configuration',2)}">系统配置</a>
+                        </li> @endcan
+                </ul>
+            </div>
+        </div>
+    </div>
+@endsection
+

+ 115 - 0
resources/views/procurement/procurement/_addEnquiry.blade.php

@@ -0,0 +1,115 @@
+<div class="modal " id="add-enquiry" tabindex="-1" >
+    <div class="modal-dialog modal-lg modal-dialog-centered">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title text-center">新增询价单</h5>
+                <button type="button" class="close" data-dismiss="modal">
+                    <span>&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <form class="form">
+                    <div class="form-group row">
+                        <label for="owner_id" class="col-2 col-form-label text-right text-primary">项目名称{{old('owner_id')}} *</label>
+                        <div class="col-8 form-inline">
+                            <select id="owner_id" name="owner_id" class="form-control col-4" :class="errors.owner_id ? 'is-invalid' : ''" v-model="owner_id" @change="selectOwner" required>
+                                <option v-for="owner in owners" :value="owner.name">@{{owner.value}}</option>
+                            </select>
+                            <input type="text" class="form-control-sm ml-2" placeholder="输入关键字定位项目" @input="owner_seek">
+                            <span class="invalid-feedback" role="alert" v-if="errors.owner_id">
+                                <strong>@{{ errors.owner_id[0] }}</strong>
+                            </span>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="customer_name" class="col-2 col-form-label text-right">客户名称</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control " name="customer_name" autocomplete="off" value="{{ old('customer_name') }}" v-model="customer_name" readonly>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="owner_material_id" class="col-2 col-form-label text-right text-primary">项目耗材编号{{old('owner_material_id')}} *</label>
+                        <div class="col-8">
+                            <select id="owner_material_id" name="owner_material_id" :class="errors.owner_material_id ? 'is-invalid' : ''" class="form-control" v-model="owner_material_id" @change="ownerMaterial" required>
+                                <option v-for="ownerMaterial in ownerMaterials" :value="ownerMaterial.id">@{{ownerMaterial.material_code}}</option>
+                            </select>
+                            <span class="invalid-feedback" role="alert" v-if="errors.owner_material_id">
+                                <strong>@{{ errors.owner_material_id[0] }}</strong>
+                            </span>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="name" class="col-2 col-form-label text-right">耗材名称</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control " name="material_name" autocomplete="off" value="{{ old('material_name') }}" v-model="material_name" readonly>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="name" class="col-2 col-form-label text-right">尺寸大小</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control " name="size" autocomplete="off" value="{{ old('size') }}" v-model="size" readonly>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="name" class="col-2 col-form-label text-right">特殊要求</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control " name="special" autocomplete="off" value="{{ old('special') }}" v-model="special" readonly>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="name" class="col-2 col-form-label text-right">材质规格</label>
+                        <div class="col-8">
+                            <textarea type="text" class="form-control" name="specification" autocomplete="off" value="{{ old('specification') }}" readonly>@{{ specification }}</textarea>
+                        </div>
+                    </div>
+{{--                    <div class="form-group row">--}}
+{{--                        <label for="quantity" class="col-2 col-form-label text-right">采购数量</label>--}}
+{{--                        <div class="col-8">--}}
+{{--                            <input type="text" class="form-control @error('quantity') is-invalid @enderror"--}}
+{{--                                   v-model="quantity"  name="quantity" autocomplete="off" value="{{ old('quantity') }}" required>--}}
+{{--                            @error('quantity')--}}
+{{--                            <span class="invalid-feedback" role="alert">--}}
+{{--                                <strong>{{ $message }}</strong>--}}
+{{--                            </span>--}}
+{{--                            @enderror--}}
+{{--                        </div>--}}
+{{--                    </div>--}}
+{{--                    <div class="form-group row">--}}
+{{--                        <label for="amount" class="col-2 col-form-label text-right">销售数量</label>--}}
+{{--                        <div class="col-8">--}}
+{{--                            <input type="text" class="form-control @error('amount') is-invalid @enderror"--}}
+{{--                                   name="amount" autocomplete="off" value="{{ old('amount') }}" @input="countTotalPrice" v-model="amount" required>--}}
+{{--                            @error('amount')--}}
+{{--                            <span class="invalid-feedback" role="alert">--}}
+{{--                                <strong>{{ $message }}</strong>--}}
+{{--                            </span>--}}
+{{--                            @enderror--}}
+{{--                        </div>--}}
+{{--                    </div>--}}
+{{--                    <div class="form-group row">--}}
+{{--                        <label for="unit_price" class="col-2 col-form-label text-right">销售单价</label>--}}
+{{--                        <div class="col-8">--}}
+{{--                            <input type="text" class="form-control @error('unit_price') is-invalid @enderror"--}}
+{{--                                   name="unit_price" autocomplete="off" value="{{ old('unit_price') }}" @input="countTotalPrice" v-model="unit_price" required>--}}
+{{--                            @error('unit_price')--}}
+{{--                            <span class="invalid-feedback" role="alert">--}}
+{{--                                <strong>{{ $message }}</strong>--}}
+{{--                            </span>--}}
+{{--                            @enderror--}}
+{{--                        </div>--}}
+{{--                    </div>--}}
+{{--                    <div class="form-group row">--}}
+{{--                        <label for="total_price" class="col-2 col-form-label text-right">销售总价</label>--}}
+{{--                        <div class="col-8">--}}
+{{--                            <input type="text" class="form-control" name="total_price" autocomplete="off" value="{{ old('total_price') }}" v-model="total_price" readonly>--}}
+{{--                        </div>--}}
+{{--                    </div>--}}
+                </form>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary"  data-dismiss="modal" >关闭</button>
+                <button type="button" class="btn btn-primary" @click="createEnquiry">提交</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 106 - 0
resources/views/procurement/procurement/_addProcurement.blade.php

@@ -0,0 +1,106 @@
+<div class="modal " id="add-procurement" tabindex="-1" >
+    <div class="modal-dialog modal-lg modal-dialog-centered">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title text-center">新增采购单</h5>
+                <button type="button" class="close" data-dismiss="modal">
+                    <span>&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <form class="form">
+                    <div class="form-group row">
+                        <label for="owner_id" class="col-2 col-form-label text-right text-primary">项目名称{{old('owner_id')}} *</label>
+                        <div class="col-8 form-inline">
+                            <select id="owner_id" name="owner_id" class="form-control col-4" :class="errors.owner_id ? 'is-invalid' : ''" v-model="owner_id" @change="selectOwner" required>
+                                <option v-for="owner in owners" :value="owner.name">@{{owner.value}}</option>
+                            </select>
+                            <input type="text" class="form-control-sm ml-2" placeholder="输入关键字定位项目" @input="owner_seek">
+                            <span class="invalid-feedback" role="alert" v-if="errors.owner_id">
+                                <strong>@{{ errors.owner_id[0] }}</strong>
+                            </span>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="customer_name" class="col-2 col-form-label text-right">客户名称</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control " name="customer_name" autocomplete="off" value="{{ old('customer_name') }}" v-model="customer_name" readonly>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="owner_material_id" class="col-2 col-form-label text-right text-primary">项目耗材编号{{old('owner_material_id')}} *</label>
+                        <div class="col-8">
+                            <select id="owner_material_id" name="owner_material_id" class="form-control" :class="errors.owner_material_id ? 'is-invalid' : ''" v-model="owner_material_id" @change="ownerMaterial" required>
+                                <option v-for="ownerMaterial in ownerMaterials" :value="ownerMaterial.id">@{{ownerMaterial.material_code}}</option>
+                            </select>
+                            <span class="invalid-feedback" role="alert" v-if="errors.owner_material_id">
+                                <strong>@{{ errors.owner_material_id[0] }}</strong>
+                            </span>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="name" class="col-2 col-form-label text-right">耗材名称</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control " name="material_name" autocomplete="off" value="{{ old('material_name') }}" v-model="material_name" readonly>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="name" class="col-2 col-form-label text-right">尺寸大小</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control " name="size" autocomplete="off" value="{{ old('size') }}" v-model="size" readonly>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="name" class="col-2 col-form-label text-right">特殊要求</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control " name="special" autocomplete="off" value="{{ old('special') }}" v-model="special" readonly>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="name" class="col-2 col-form-label text-right">材质规格</label>
+                        <div class="col-8">
+                            <textarea type="text" class="form-control" name="specification" autocomplete="off" value="{{ old('specification') }}" readonly>@{{ specification }}</textarea>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="quantity" class="col-2 col-form-label text-right">采购数量</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control" v-model="quantity" :class="errors.quantity ? 'is-invalid' : ''"  name="quantity" autocomplete="off" value="{{ old('quantity') }}" required>
+                            <span class="invalid-feedback" role="alert" v-if="errors.quantity">
+                                <strong>@{{ errors.quantity[0] }}</strong>
+                            </span>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="amount" class="col-2 col-form-label text-right">销售数量</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control" name="amount" :class="errors.amount ? 'is-invalid' : ''" autocomplete="off" value="{{ old('amount') }}" @input="countTotalPrice" v-model="amount" required>
+                            <span class="invalid-feedback" role="alert" v-if="errors.amount">
+                                <strong>@{{ errors.amount[0] }}</strong>
+                            </span>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="unit_price" class="col-2 col-form-label text-right">销售单价</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control" name="unit_price" :class="errors.unit_price ? 'is-invalid' : ''" autocomplete="off" value="{{ old('unit_price') }}" @input="countTotalPrice" v-model="unit_price" required>
+                            <span class="invalid-feedback" role="alert" v-if="errors.unit_price">
+                                <strong>@{{ errors.unit_price[0] }}</strong>
+                            </span>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="total_price" class="col-2 col-form-label text-right">销售总价</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control" name="total_price" autocomplete="off" value="{{ old('total_price') }}" v-model="total_price" readonly>
+                        </div>
+                    </div>
+                </form>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary"  data-dismiss="modal" >关闭</button>
+                <button type="button" class="btn btn-primary" @click="createProcurement">提交</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 115 - 0
resources/views/procurement/procurement/_addProof.blade.php

@@ -0,0 +1,115 @@
+<div class="modal " id="add-proof" tabindex="-1" >
+    <div class="modal-dialog modal-lg modal-dialog-centered">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title text-center">新增打样单</h5>
+                <button type="button" class="close" data-dismiss="modal">
+                    <span>&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <form class="form">
+                    <div class="form-group row">
+                        <label for="owner_id" class="col-2 col-form-label text-right text-primary">项目名称{{old('owner_id')}} *</label>
+                        <div class="col-8 form-inline">
+                            <select id="owner_id" name="owner_id" class="form-control col-4" :class="errors.owner_id ? 'is-invalid' : ''" v-model="owner_id" @change="selectOwner" required>
+                                <option v-for="owner in owners" :value="owner.name">@{{owner.value}}</option>
+                            </select>
+                            <input type="text" class="form-control-sm ml-2" placeholder="输入关键字定位项目" @input="owner_seek">
+                            <span class="invalid-feedback" role="alert" v-if="errors.owner_id">
+                                <strong>@{{ errors.owner_id[0] }}</strong>
+                            </span>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="customer_name" class="col-2 col-form-label text-right">客户名称</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control " name="customer_name" autocomplete="off" value="{{ old('customer_name') }}" v-model="customer_name" readonly>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="owner_material_id" class="col-2 col-form-label text-right text-primary">项目耗材编号{{old('owner_material_id')}} *</label>
+                        <div class="col-8">
+                            <select id="owner_material_id" name="owner_material_id" :class="errors.owner_material_id ? 'is-invalid' : ''" class="form-control" v-model="owner_material_id" @change="ownerMaterial" required>
+                                <option v-for="ownerMaterial in ownerMaterials" :value="ownerMaterial.id">@{{ownerMaterial.material_code}}</option>
+                            </select>
+                            <span class="invalid-feedback" role="alert" v-if="errors.owner_material_id">
+                                <strong>@{{ errors.owner_material_id[0] }}</strong>
+                            </span>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="name" class="col-2 col-form-label text-right">耗材名称</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control " name="material_name" autocomplete="off" value="{{ old('material_name') }}" v-model="material_name" readonly>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="name" class="col-2 col-form-label text-right">尺寸大小</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control " name="size" autocomplete="off" value="{{ old('size') }}" v-model="size" readonly>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="name" class="col-2 col-form-label text-right">特殊要求</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control " name="special" autocomplete="off" value="{{ old('special') }}" v-model="special" readonly>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="name" class="col-2 col-form-label text-right">材质规格</label>
+                        <div class="col-8">
+                            <textarea type="text" class="form-control" name="specification" autocomplete="off" value="{{ old('specification') }}" readonly>@{{ specification }}</textarea>
+                        </div>
+                    </div>
+                    {{--                    <div class="form-group row">--}}
+                    {{--                        <label for="quantity" class="col-2 col-form-label text-right">采购数量</label>--}}
+                    {{--                        <div class="col-8">--}}
+                    {{--                            <input type="text" class="form-control @error('quantity') is-invalid @enderror"--}}
+                    {{--                                   v-model="quantity"  name="quantity" autocomplete="off" value="{{ old('quantity') }}" required>--}}
+                    {{--                            @error('quantity')--}}
+                    {{--                            <span class="invalid-feedback" role="alert">--}}
+                    {{--                                <strong>{{ $message }}</strong>--}}
+                    {{--                            </span>--}}
+                    {{--                            @enderror--}}
+                    {{--                        </div>--}}
+                    {{--                    </div>--}}
+                    {{--                    <div class="form-group row">--}}
+                    {{--                        <label for="amount" class="col-2 col-form-label text-right">销售数量</label>--}}
+                    {{--                        <div class="col-8">--}}
+                    {{--                            <input type="text" class="form-control @error('amount') is-invalid @enderror"--}}
+                    {{--                                   name="amount" autocomplete="off" value="{{ old('amount') }}" @input="countTotalPrice" v-model="amount" required>--}}
+                    {{--                            @error('amount')--}}
+                    {{--                            <span class="invalid-feedback" role="alert">--}}
+                    {{--                                <strong>{{ $message }}</strong>--}}
+                    {{--                            </span>--}}
+                    {{--                            @enderror--}}
+                    {{--                        </div>--}}
+                    {{--                    </div>--}}
+                    {{--                    <div class="form-group row">--}}
+                    {{--                        <label for="unit_price" class="col-2 col-form-label text-right">销售单价</label>--}}
+                    {{--                        <div class="col-8">--}}
+                    {{--                            <input type="text" class="form-control @error('unit_price') is-invalid @enderror"--}}
+                    {{--                                   name="unit_price" autocomplete="off" value="{{ old('unit_price') }}" @input="countTotalPrice" v-model="unit_price" required>--}}
+                    {{--                            @error('unit_price')--}}
+                    {{--                            <span class="invalid-feedback" role="alert">--}}
+                    {{--                                <strong>{{ $message }}</strong>--}}
+                    {{--                            </span>--}}
+                    {{--                            @enderror--}}
+                    {{--                        </div>--}}
+                    {{--                    </div>--}}
+                    {{--                    <div class="form-group row">--}}
+                    {{--                        <label for="total_price" class="col-2 col-form-label text-right">销售总价</label>--}}
+                    {{--                        <div class="col-8">--}}
+                    {{--                            <input type="text" class="form-control" name="total_price" autocomplete="off" value="{{ old('total_price') }}" v-model="total_price" readonly>--}}
+                    {{--                        </div>--}}
+                    {{--                    </div>--}}
+                </form>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary"  data-dismiss="modal" >关闭</button>
+                <button type="button" class="btn btn-primary" @click="createProof">提交</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 54 - 0
resources/views/procurement/procurement/_addQuantity.blade.php

@@ -0,0 +1,54 @@
+<div class="modal " id="add-quantity" tabindex="-1" >
+    <div class="modal-dialog modal-lg modal-dialog-centered">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title text-center">添加采购数量和销售数量</h5>
+                <button type="button" class="close" data-dismiss="modal">
+                    <span>&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <div class="form-group row">
+                    <label for="supplier" class="col-2 col-form-label text-right">供应商</label>
+                    <div class="col-8">
+                        <input type="text" class="form-control " name="quantity" autocomplete="off" v-model="supplier" readonly>
+                    </div>
+                </div>
+                <div class="form-group row">
+                    <label for="offer" class="col-2 col-form-label text-right">采购单价(最低报价)</label>
+                    <div class="col-8">
+                        <input type="text" class="form-control " name="offer" autocomplete="off" v-model="offer" readonly>
+                    </div>
+                </div>
+                    <div class="form-group row">
+                        <label for="quantity" class="col-2 col-form-label text-right">采购数量</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control " :class="errors.quantity ? 'is-invalid' : ''" name="quantity" autocomplete="off" v-model="quantity" required>
+                            <span class="invalid-feedback" role="alert" v-if="errors.quantity">
+                                <strong>@{{ errors.quantity[0] }}</strong>
+                            </span>
+                        </div>
+                    </div>
+                     <div class="form-group row">
+                        <label for="amount" class="col-2 col-form-label text-right">销售数量</label>
+                            <div class="col-8">
+                                <input type="text" class="form-control " :class="errors.amount ? 'is-invalid' : ''" name="amount" autocomplete="off" v-model="amount" required>
+                                <span class="invalid-feedback" role="alert" v-if="errors.amount">
+                                <strong>@{{ errors.amount[0] }}</strong>
+                            </span>
+                            </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="unit_price" class="col-2 col-form-label text-right">销售单价</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control " name="unit_price" autocomplete="off" v-model="unit_price">
+                        </div>
+                    </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary"  data-dismiss="modal" >关闭</button>
+                <button type="button" class="btn btn-primary" @click="submitProcurement">提交</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 187 - 0
resources/views/procurement/procurement/create.blade.php

@@ -0,0 +1,187 @@
+@extends('layouts.app')
+@section('title')采购管理-采购-新建@endsection
+
+@section('content')
+    @component('procurement.procurement.menu')@endcomponent
+    <div class="container-fluid" id="list">
+        <div class="card col-md-8 offset-md-2">
+            <div class="card-body">
+                @if(Session::has('successTip'))
+                    <div class="alert alert-success h1">{{Session::get('successTip')}}</div>
+                @endif
+                <form method="POST" action="{{ url('procurement/procurement/store') }}">
+                    @csrf
+                    <div class="form-group row">
+                        <label for="owner_id" class="col-2 col-form-label text-right text-primary">项目名称{{old('owner_id')}} *</label>
+                        <div class="col-8 form-inline">
+                            <select id="owner_id" name="owner_id" class="form-control @error('owner_id') is-invalid @enderror col-4" v-model="owner_id" @change="selectOwner" required>
+                                <option v-for="owner in owners" :value="owner.id">@{{owner.name}}</option>
+                            </select>
+                            <input type="text" class="form-control-sm ml-2" placeholder="输入关键字定位项目" @input="owner_seek">
+                        </div>
+                        <div class="col-sm-5">
+                            <p class="form-control-static text-danger small font-weight-bold" >{{ $errors->first('owner_id') }}</p>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="customer_name" class="col-2 col-form-label text-right">客户名称</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control " name="customer_name" autocomplete="off" value="{{ old('customer_name') }}" v-model="customer_name" readonly>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="owner_material_id" class="col-2 col-form-label text-right text-primary">项目耗材编号{{old('owner_material_id')}} *</label>
+                        <div class="col-8">
+                            <select id="owner_material_id" name="owner_material_id" class="form-control @error('owner_material_id') is-invalid @enderror " v-model="owner_material_id" @change="ownerMaterial" required>
+                                <option v-for="ownerMaterial in ownerMaterials" :value="ownerMaterial.id">@{{ownerMaterial.material_code}}</option>
+                            </select>
+                            @error('owner_material_id')
+                            <span class="invalid-feedback" role="alert">
+                                <strong>{{ $message }}</strong>
+                            </span>
+                            @enderror
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="name" class="col-2 col-form-label text-right">耗材名称</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control " name="material_name" autocomplete="off" value="{{ old('material_name') }}" v-model="material_name" readonly>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="name" class="col-2 col-form-label text-right">尺寸大小</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control " name="size" autocomplete="off" value="{{ old('size') }}" v-model="size" readonly>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="name" class="col-2 col-form-label text-right">特殊要求</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control " name="special" autocomplete="off" value="{{ old('special') }}" v-model="special" readonly>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="name" class="col-2 col-form-label text-right">材质规格</label>
+                        <div class="col-8">
+                            <textarea type="text" class="form-control" name="specification" autocomplete="off" value="{{ old('specification') }}" readonly>@{{ specification }}</textarea>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="quantity" class="col-2 col-form-label text-right">采购数量</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control"
+                                   name="quantity" autocomplete="off" value="{{ old('quantity') }}" v-model="quantity" required>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="amount" class="col-2 col-form-label text-right">销售数量</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control"
+                                   name="amount" autocomplete="off" value="{{ old('amount') }}" @input="countTotalPrice" v-model="amount" required>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="unit_price" class="col-2 col-form-label text-right">销售单价</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control"
+                                   name="unit_price" autocomplete="off" value="{{ old('unit_price') }}" @input="countTotalPrice" v-model="unit_price">
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="total_price" class="col-2 col-form-label text-right">销售总价</label>
+                        <div class="col-8">
+                            <input type="text" class="form-control" name="total_price" autocomplete="off" value="{{ old('total_price') }}" v-model="total_price" readonly>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <div class="col-8 offset-2">
+                            <input type="submit" class="btn btn-success form-control">
+                        </div>
+                    </div>
+                </form>
+            </div>
+        </div>
+    </div>
+@endsection
+
+@section('lastScript')
+    <script>
+        let vueList=new Vue({
+            el:'#list',
+            data:{
+                owners:[
+                        @foreach($owners as $owner)
+                    {
+                        id:'{{$owner->id}}',name:'{{$owner->name}}',
+                        ownerMaterials:[
+                                @foreach($owner->ownerMaterials ? $owner->ownerMaterials :[] as $ownerMaterial)
+                            {
+                                id:'{{$ownerMaterial->id}}',material_code:'{{$ownerMaterial->material_code}}',material_name:'{{$ownerMaterial->material->name}}',
+                                size:'{{$ownerMaterial->size}}',special:'{{$ownerMaterial->special}}',specification:'{{$ownerMaterial->specification}}',
+                            },
+                            @endforeach
+                        ],
+                        @if($owner->customer)customer_name:'{{$owner->customer->name}}',@endif
+                    },
+                    @endforeach
+                ],
+                owner_id:'{{old('owner_id')}}',
+                owner_material_id:'{{old('owner_material_id')}}',
+                material_name:'{{old('material_name')}}',
+                customer_name:'{{old('customer_name')}}',
+                size:'{{old('size')}}',
+                special:'{{old('special')}}',
+                specification:'{{old('specification')}}',
+                quantity:'{{old('quantity')}}',
+                amount:'{{old('amount')}}',
+                unit_price:'{{old('unit_price')}}',
+                total_price:'{{old('total_price')}}',
+                ownerMaterials:[],
+                errors:{},
+            },
+            methods:{
+                owner_seek:function (e) {
+                    let _this=this;
+                    let $val=e.target.value;
+                    if($val===''){
+                        _this.owner_id='';
+                    }else{
+                        _this.owners.forEach(function (owner) {
+                            if (owner.name.includes($val)){
+                                _this.owner_id=owner.id;
+                                _this.ownerMaterials=owner.ownerMaterials;
+                                _this.customer_name=owner.customer_name;
+                            }
+                        });
+                    }
+                },
+                ownerMaterial:function () {
+                    let _this=this;
+                    _this.ownerMaterials.forEach(function (ownerMaterial) {
+                        if (_this.owner_material_id===ownerMaterial.id){
+                            _this.material_name=ownerMaterial.material_name;
+                            _this.size=ownerMaterial.size;
+                            _this.special=ownerMaterial.special;
+                            _this.specification=ownerMaterial.specification;
+                        }
+                    })
+                },
+                selectOwner:function () {
+                    let _this=this;
+                    _this.owners.forEach(function (owner) {
+                        if (_this.owner_id===owner.id){
+                            _this.ownerMaterials=owner.ownerMaterials;
+                            _this.customer_name=owner.customer_name;
+                        }
+                    })
+                },
+                countTotalPrice:function () {
+                    let _this=this;
+                    if (_this.unit_price===''|| _this.amount==='')_this.total_price=null;
+                    _this.total_price=_this.unit_price*_this.amount;
+                }
+            },
+
+        });
+    </script>
+@endsection

+ 460 - 0
resources/views/procurement/procurement/index.blade.php

@@ -0,0 +1,460 @@
+@extends('layouts.app')
+@section('title')采购管理-采购-查询@endsection
+
+@section('content')
+    @component('procurement.procurement.menu')@endcomponent
+    <div class="container-fluid" id="list">
+        <div class="card container-fluid">
+            @if(Session::has('successTip'))
+                <div class="alert alert-success h1">{{Session::get('successTip')}}</div>
+            @endif
+            <div class="row">
+                <div class="col-4">
+                    <div class="card">
+                        <div class="card-body row">
+                            <span class="fa fa-shopping-cart fa-4x offset-md-3" style="color: #4c2584"></span>
+                            <span class="ml-4 mt-2">
+                                <h5 class="font-weight-bold">@{{ countReceive }}</h5>
+                                <p class="text-muted">今日收货次数</p>
+                            </span>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-4">
+                    <div class="card">
+                        <div class="card-body row">
+                            <span class="fa fa-file-o fa-4x offset-md-3" style="color: #9fcdff"></span>
+                            <span class="ml-4 mt-2">
+                                <h5 class="font-weight-bold">@{{ countProcurement }}</h5>
+                                <p class="text-muted">今日发起采购次数</p>
+                            </span>
+                        </div>
+                    </div>
+                </div>
+                <div class="col-4">
+                    <div class="card">
+                        <div class="card-body row">
+                            <span class="fa fa-calendar-o fa-4x offset-md-3" style="color: #2ca02c"></span>
+                            <span class="ml-4 mt-2">
+                        <h5 class="font-weight-bold">数量</h5>
+                        <p class="text-muted">今日对账金额</p>
+                        </span>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div id="form_div" class="mt-1"></div>
+        <div class="row mt-2">
+        <span class="dropdown ml-3">
+        <button class="btn btn-outline-dark btn-sm form-control-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="procurementExport(false)" href="javascript:">导出勾选内容</a>
+            <a class="dropdown-item" @click="procurementExport(true)" href="javascript:">导出所有页</a>
+        </div>
+        </span>
+            <span class="btn btn-sm btn-outline-info ml-2" @click="addProcurement">新增采购</span>
+            @can('采购管理-采购-新建')
+                @include('procurement.procurement._addProcurement')
+            @endcan
+            <span class="btn btn-sm btn-outline-success ml-2" @click="addEnquiry">新增询价</span>
+            @can('采购管理-采购-新建')
+                @include('procurement.procurement._addEnquiry')
+            @endcan
+            <span class="btn btn-sm btn-outline-danger ml-2" @click="addProof">新增打样</span>
+            @can('采购管理-采购-新建')
+                @include('procurement.procurement._addProof')
+            @endcan
+            @can('采购管理-采购-编辑')
+                @include('procurement.procurement._addQuantity')
+            @endcan
+            <span class="btn btn-sm btn-outline-primary ml-2">重新发起</span>
+        </div>
+        <label for="all" id="cloneCheckAll" class="d-none">
+            <input id="all" type="checkbox" @click="checkAll($event)">全选
+        </label>
+        <table class="table table-sm table-bordered text-nowrap d-none" id="headerRoll"></table>
+        <table class="table table-sm table-striped table-bordered table-hover text-nowrap card-body mt-2"
+               id="headerParent">
+            <tr id="header"></tr>
+            <tr v-for="(procurement,i) in procurements">
+                <td>
+                    <input class="checkItem" type="checkbox" :value="procurement.id" v-model="checkData">
+                </td>
+                <td class="">@{{ procurement.code }}</td>
+                <td><span v-if="procurement.owner_material.owner">@{{ procurement.owner_material.owner.name }}</span></td>
+                <td>@{{ procurement_type[procurement.type] }}</td>
+                <td><span v-if="procurement.owner_material.owner.customer">@{{ procurement.owner_material.owner.customer.company_name }}</span></td>
+                <td class="tooltipTarget" style="max-width: 200px;overflow:hidden"><span v-if="procurement.owner_material.material">@{{ procurement.owner_material.material.code }}</span></td>
+                <td class="text-muted"><span v-if="procurement.owner_material.material">@{{ procurement.owner_material.material.name }}</span></td>
+                <td class="text-muted"><span v-if="procurement.owner_material">@{{ procurement.owner_material.size }}</span></td>
+                <td class="text-muted"><span v-if="procurement.owner_material">@{{ procurement.owner_material.special }}</span></td>
+                <td class="text-muted"><span v-if="procurement.owner_material">@{{ procurement.owner_material.specification }}</span></td>
+                <td></td>
+                <td>@{{ procurement.quantity }}</td>
+                <td><span>@{{ procurement.unit_price }}</span></td>
+                <td><span></span></td>
+                <td><span>@{{ procurement.quantity*procurement.unit_price }}</span></td>
+                <td><span>@{{ procurement_status[procurement.status] }}</span></td>
+                <td><span v-if="procurement.owner_material.owner.customer">@{{ procurement.owner_material.owner.customer.phone }}</span></td>
+                <td>
+                    <span v-if="procurement_status[procurement.status]!='取消订单'">
+                        <span class="btn btn-sm btn-outline-danger" v-if="!procurement.supplier_id"
+                              @click="cancel(procurement.id,procurement.type,procurement.code)">取消</span>
+                        <span class="btn btn-sm btn-outline-success" v-if="procurement_type[procurement.type]=='询价单'"
+                              @click="initiateProcurement(procurement.id)">发起采购</span>
+                    </span>
+                </td>
+            </tr>
+        </table>
+        <div class="text-info h5 btn btn">{{$procurements->count()}}/@{{ sum }}</div>
+        <div>{{$procurements->appends($paginateParams)->links()}}</div>
+    </div>
+@endsection
+@section('lastScript')
+    <script type="text/javascript" src="{{mix('js/queryForm/export.js')}}"></script>
+    <script type="text/javascript" src="{{mix('js/queryForm/queryForm.js')}}"></script>
+    <script type="text/javascript" src="{{mix('js/queryForm/header.js')}}"></script>
+    <script>
+        let vue = new Vue({
+            el: '#list',
+            data: {
+                countReceive:{!! $countReceive !!},
+                countProcurement:{!! $countProcurement !!},
+                procurements: {!! $procurements->toJson() !!}['data'],
+                owners: [
+                        @foreach($owners as $owner)
+                    {
+                        name: '{{$owner->id}}', value: '{{$owner->name}}',
+                        ownerMaterials: [
+                                @foreach($owner->ownerMaterials ? $owner->ownerMaterials :[] as $ownerMaterial)
+                            {
+                                id: '{{$ownerMaterial->id}}',
+                                material_code: '{{$ownerMaterial->material_code}}',
+                                material_name: '{{$ownerMaterial->material->name}}',
+                                size: '{{$ownerMaterial->size}}',
+                                special: '{{$ownerMaterial->special}}',
+                                specification: '{{$ownerMaterial->specification}}',
+                            },
+                            @endforeach
+                        ],
+                        @if($owner->customer)customer_name: '{{$owner->customer->name}}',@endif
+                    },
+                    @endforeach
+                ],
+                materials: [
+                        @foreach($materials as $material)
+                    {
+                        name: '{{$material->id}}', value: '{{$material->name}}'
+                    },
+                    @endforeach
+                ],
+                procurement_type:{!! json_encode(\App\Procurement::type,JSON_UNESCAPED_UNICODE) !!},
+                procurement_status:{!! json_encode(\App\Procurement::status,JSON_UNESCAPED_UNICODE) !!},
+                checkData: [],
+                sum:{!! $procurements->total() !!},
+                owner_id: '{{old('owner_id')}}',
+                owner_material_id: '{{old('owner_material_id')}}',
+                material_name: '{{old('material_name')}}',
+                customer_name: '{{old('customer_name')}}',
+                size: '{{old('size')}}',
+                special: '{{old('special')}}',
+                specification: '{{old('specification')}}',
+                quantity: '{{old('quantity')}}',
+                amount: '{{old('amount')}}',
+                unit_price: '{{old('unit_price')}}',
+                total_price: '{{old('total_price')}}',
+                procurement_id:'',supplier:'',offer:'',supplier_id:'',
+                ownerMaterials: [],
+                errors: {},
+
+            },
+            mounted: function () {
+                $(".tooltipTarget").tooltip({'trigger': 'hover'});
+                $('#list').removeClass('d-none');
+                let data = [
+                    [
+                        {name: 'created_at_start', type: 'dateTime', tip: '选择显示指定日期的起始时间'},
+                        {name: 'created_at_end', type: 'dateTime', tip: '选择显示指定日期的结束时间'},
+                        {
+                            name: 'owner_id', type: 'select_multiple_select', tip: ['输入关键词快速定位下拉列表,回车确定', '选择要显示的项目'],
+                            placeholder: ['项目', '定位或多选项目'], data: this.owners
+                        },
+                        {
+                            name: 'material_id',
+                            type: 'select_multiple_select',
+                            tip: ['输入关键词快速定位下拉列表,回车确定', '选择要显示的耗材'],
+                            placeholder: ['耗材', '定位或多选耗材'],
+                            data: this.materials
+                        },
+                        {name: 'company_name', type: 'input', tip: '采购公司:可在两侧增加百分号(%)进行模糊搜索', placeholder: '采购公司'},
+                    ],
+                ];
+                this.form = new query({
+                    el: "#form_div",
+                    condition: data,
+                });
+                this.form.init();
+                let column = [
+                    {
+                        name: 'cloneCheckAll', customization: true, type: 'checkAll', column: 'id',
+                        dom: $('#cloneCheckAll').removeClass('d-none'), neglect: true
+                    },
+                    {name: 'code', value: '采购编号', neglect: true},
+                    {name: 'owner_id', value: '项目', class: ''},
+                    {name: 'type', value: '单据类型', class: 'text-muted'},
+                    {name: 'company_name', value: '采购公司', class: 'text-muted'},
+                    {name: 'material_code', value: '耗材编号', class: 'text-muted'},
+                    {name: 'material_name', value: '耗材'},
+                    {name: 'size', value: '尺寸大小', class: 'text-muted'},
+                    {name: 'special', value: '特殊要求', class: 'text-muted'},
+                    {name: 'specification', value: '材质规格', class: 'text-muted'},
+                    {name: '附件', value: '附件', class: 'text-muted'},
+                    {name: 'quantity', value: '采购数量', neglect: true},
+                    {name: 'unit_price', value: '销售单价(元)', neglect: true},
+                    {name: '', value: '送货数量', neglect: true},
+                    {name: '', value: '销售总价(元)', neglect: true},
+                    {name: '', value: '采购单状态', neglect: true},
+                    {name: '', value: '联系方式', neglect: true},
+                    {name: '', value: '操作', neglect: true},
+                ];
+
+                let _this = this;
+                setTimeout(function () {
+                    let header = new Header({
+                        el: "#header",
+                        column: column,
+                        data: _this.procurements,
+                        restorationColumn: 'id',
+                        fixedTop: ($('#form_div').height()) + 2,
+                        offset: 0.5,
+                        vue: vue
+                    });
+                    header.init();
+                }, 0);
+            },
+            methods: {
+                //全选事件
+                checkAll(e) {
+                    if (e.target.checked) {
+                        this.procurements.forEach((el, i) => {
+                            if (this.checkData.indexOf(el.id) == '-1') {
+                                this.checkData.push(el.id);
+                            }
+                        });
+                    } else {
+                        this.checkData = [];
+                    }
+                },
+                addProcurement() {
+                    this.errors = {};
+                    $('#add-procurement').modal('show');
+                },
+                addEnquiry() {
+                    this.errors = {};
+                    $('#add-enquiry').modal('show');
+                },
+                addProof() {
+                    this.errors = {};
+                    $('#add-proof').modal('show');
+                },
+                initiateProcurement(id) {
+                    let _this=this;
+                    this.procurement_id=id;
+                    let url="{{url('procurement/procurement/initiateProcurement')}}";
+                    let params={id:id};
+                    window.axios.post(url,params).then(res => {
+                            if (res.data.success) {
+                              _this.supplier=res.data.data.supplier.name;
+                              _this.supplier_id=res.data.data.supplier_id;
+                              _this.offer=res.data.data.offer;
+                              $('#add-quantity').modal('show');
+                            } else {
+                                tempTip.setDuration(3000);
+                                tempTip.show(res.data.message);
+                            }
+                        }).catch(err => {
+                        window.tempTip.setDuration(3000);
+                        window.tempTip.show("网络错误:" + err);
+                    });
+                },
+                owner_seek: function (e) {
+                    let _this = this;
+                    let $val = e.target.value;
+                    if ($val === '') {
+                        _this.owner_id = '';
+                    } else {
+                        _this.owners.forEach(function (owner) {
+                            if (owner.value.includes($val)) {
+                                _this.owner_id = owner.name;
+                                _this.ownerMaterials = owner.ownerMaterials;
+                                _this.customer_name = owner.customer_name;
+                            }
+                        });
+                    }
+                },
+                ownerMaterial: function () {
+                    let _this = this;
+                    _this.ownerMaterials.forEach(function (ownerMaterial) {
+                        if (_this.owner_material_id === ownerMaterial.id) {
+                            _this.material_name = ownerMaterial.material_name;
+                            _this.size = ownerMaterial.size;
+                            _this.special = ownerMaterial.special;
+                            _this.specification = ownerMaterial.specification;
+                        }
+                    })
+                },
+                selectOwner: function () {
+                    let _this = this;
+                    _this.owners.forEach(function (owner) {
+                        if (_this.owner_id === owner.name) {
+                            _this.ownerMaterials = owner.ownerMaterials;
+                            _this.customer_name = owner.customer_name;
+                        }
+                    })
+                },
+                countTotalPrice: function () {
+                    let _this = this;
+                    if (_this.unit_price === '' || _this.amount === '') _this.total_price = null;
+                    _this.total_price = _this.unit_price * _this.amount;
+                },
+                createProcurement() {
+                    let _this = this;
+                    let url = '{{url('procurement/procurement/createProcurement')}}';
+                    let params = {
+                        owner_id: _this.owner_id,
+                        owner_material_id: _this.owner_material_id,
+                        quantity: _this.quantity,
+                        amount: _this.amount,
+                        unit_price: _this.unit_price
+                    };
+                    window.axios.post(url, params).then(function (res) {
+                        if (!res.data.success) {
+                            _this.errors = res.data.errors;
+                        } else {
+                            _this.procurements.push(res.data.data);
+                            $("#add-procurement").modal('hide');
+                            _this.clearData();
+                            tempTip.setDuration(3000);
+                            tempTip.showSuccess('新增采购单成功!');
+
+                        }
+                    }).catch(function (err) {
+                        tempTip.setDuration(3000);
+                        tempTip.show('新增采购单失败!网络错误:' + err);
+                    });
+                },
+                createEnquiry() {
+                    let _this = this;
+                    let url = '{{url('procurement/procurement/createEnquiry')}}';
+                    let params = {owner_id: _this.owner_id, owner_material_id: _this.owner_material_id};
+                    window.axios.post(url, params).then(function (res) {
+                        if (!res.data.success) {
+                            _this.errors = res.data.errors;
+                        } else {
+                            _this.procurements.push(res.data.data);
+                            $("#add-enquiry").modal('hide');
+                            _this.clearData();
+                            tempTip.setDuration(3000);
+                            tempTip.showSuccess('新增询价单成功!');
+
+                        }
+                    }).catch(function (err) {
+                        tempTip.setDuration(3000);
+                        tempTip.show('新增询价单失败!网络错误:' + err);
+                    });
+                },
+                createProof() {
+                    let _this = this;
+                    let url = '{{url('procurement/procurement/createProof')}}';
+                    let params = {owner_id: _this.owner_id, owner_material_id: _this.owner_material_id};
+                    window.axios.post(url, params).then(function (res) {
+                        if (!res.data.success) {
+                            _this.errors = res.data.errors;
+                        } else {
+                            _this.procurements.push(res.data.data);
+                            $("#add-proof").modal('hide');
+                            _this.clearData();
+                            tempTip.setDuration(3000);
+                            tempTip.showSuccess('新增打样单成功!');
+
+                        }
+                    }).catch(function (err) {
+                        tempTip.setDuration(3000);
+                        tempTip.show('新增打样单失败!网络错误:' + err);
+                    });
+                },
+                clearData() {
+                    this.owner_id = '';this.owner_material_id = '';
+                    this.material_name = '';this.customer_name = '';
+                    this.size = '';this.special = '';
+                    this.specification = '';this.quantity = '';
+                    this.amount = '';this.unit_price = '';
+                    this.total_price = '';this.procurement_id='';
+                    this.supplier_id='',this.offer='';
+                },
+                procurementExport(selectAll) {
+                    let url = '{{url('procurement/procurement/procurementExport')}}';
+                    let token = '{{ csrf_token() }}';
+                    excelExport(selectAll, this.checkData, url, this.sum, token);
+                },
+                cancel(id, type, code) {
+                    window.tempTip.confirm('确定取消' + this.procurement_type[type] + ' ' + code, () => {
+                        window.axios.get("{{url('procurement/procurement/cancel')}}/" + id)
+                            .then(res => {
+                                if (res.data.success) {
+                                    this.procurements.forEach(function (procurement) {
+                                        if (procurement.id === res.data.data.id) {
+                                            procurement.status = res.data.data.status;
+                                            window.tempTip.setDuration(2000);
+                                            window.tempTip.showSuccess("已成功取消该条采购申请");
+                                        }
+                                    })
+                                } else {
+                                    tempTip.setDuration(3000);
+                                    tempTip.show(res.data.message);
+                                }
+                            }).catch(err => {
+                            window.tempTip.setDuration(3000);
+                            window.tempTip.show("网络错误:" + err);
+                        });
+                    });
+                },
+                submitProcurement() {
+                    let _this=this;
+                    let id=this.procurement_id;
+                    if (!id)return;
+                    let url="{{url('procurement/procurement/submitProcurement')}}";
+                    let params={id:id,quantity:this.quantity,amount:this.amount,unit_price:this.unit_price,offer:this.offer,supplier_id:this.supplier_id};
+                    window.axios.post(url,params).then(res => {
+                            if (!res.data.success) {
+                                _this.errors = res.data.errors;
+                            } else {
+                                this.procurements.forEach(function (procurement) {
+                                    if (procurement.id === res.data.data.id) {
+                                        procurement.status = res.data.data.status;
+                                        procurement.amount = res.data.data.amount;
+                                        procurement.type = res.data.data.type;
+                                        procurement.quantity = res.data.data.quantity;
+                                        procurement.unit_price = res.data.data.unit_price;
+                                        $("#add-quantity").modal('hide');
+                                        _this.clearData();
+                                        window.tempTip.setDuration(2000);
+                                        window.tempTip.showSuccess("已成功发起采购申请");
+                                    }
+                                })
+                            }
+                        }).catch(err => {
+                        window.tempTip.setDuration(3000);
+                        window.tempTip.show("网络错误:" + err);
+                    });
+                },
+
+            }
+        });
+    </script>
+@endsection

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

@@ -0,0 +1,19 @@
+<div id="nav2">
+    @component('procurement.menu')
+    @endcomponent
+    <div class="container-fluid nav3">
+        <div class="card menu-third" >
+            <ul class="nav nav-pills">
+                @can('采购管理-采购-查询')
+                    <li class="nav-item">
+                        <a class="nav-link" href="{{url('procurement/procurement/index')}}" :class="{active:isActive('index',3)}">查询</a>
+                    </li> @endcan
+                @can('采购管理-采购-新建')
+                    <li class="nav-item">
+                        <a  class="nav-link" href="{{url('procurement/procurement/create')}}" :class="{active:isActive('create',3)}">新建</a>
+                    </li> @endcan
+            </ul>
+        </div>
+    </div>
+</div>
+

+ 8 - 1
routes/api.php

@@ -13,5 +13,12 @@ use Illuminate\Support\Facades\Route;
 | is assigned the "api" middleware group. Enjoy building your API!
 |
 */
-
+Route::group(['prefix' => 'procurement','middleware'=>'procurement.auth.api'], function ($router) {
+    Route::post('logout', 'api\procurement\wechat\AuthController@logout');
+    Route::post('refresh', 'api\procurement\wechat\AuthController@refresh');
+    Route::post('me', 'api\procurement\wechat\AuthController@me');
+});
+Route::group(['prefix' => 'procurement'], function ($router) {
+    Route::post('login', 'api\procurement\wechat\AuthController@login');
+});
 

+ 29 - 0
routes/web.php

@@ -728,4 +728,33 @@ Route::group(['prefix'=>'station'],function(){
 Route::group(['prefix'=>'control'],function () {
    Route::get('panel/menu','ControlPanelController@index') ;
 });
+/** 采购管理 */
+Route::group(['prefix'=>'procurement'],function () {
+    /** 采购 */
+    Route::group(['prefix'=>'procurement'],function(){
+        Route::get('index','ProcurementController@index');
+        Route::get('create','ProcurementController@create');
+        Route::post('store','ProcurementController@store');
+        Route::post('getOwnerMaterial','ProcurementController@getOwnerMaterial');
+        Route::post('createProcurement','ProcurementController@createProcurement');
+        Route::post('createEnquiry','ProcurementController@createEnquiry');
+        Route::post('createProof','ProcurementController@createProof');
+        Route::any('procurementExport','ProcurementController@procurementExport');
+        Route::get('cancel/{id}','ProcurementController@cancel');
+        Route::post('initiateProcurement','ProcurementController@initiateProcurement');
+        Route::post('submitProcurement','ProcurementController@submitProcurement');
+    });
+    /** 财务 */
+    Route::group(['prefix'=>'finance'],function(){
+        Route::get('checkBill','ProcurementController@checkBill');
+        Route::get('procurementBill','ProcurementController@procurementBill');
+        Route::get('monthlyBillReport','ProcurementController@monthlyBillReport');
+        Route::post('fillInvoice','ProcurementController@fillInvoice');
+        Route::any('procurementTotalBillExport','ProcurementController@procurementTotalBillExport');
+        Route::any('procurementBillExport','ProcurementController@procurementBillExport');
+        Route::any('checkBillExport','ProcurementController@checkBillExport');
+        Route::post('costPrice','ProcurementController@costPrice');
+    });
+    Route::get('relating',function (){return view('procurement.menuProcurement');});
+});
 

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