瀏覽代碼

contracts: CRUD

Alexander Musikhin 7 月之前
父節點
當前提交
0813a0fc9b

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

@@ -0,0 +1,75 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Http\Requests\StoreContractRequest;
+use App\Models\Contract;
+use Illuminate\Http\Request;
+
+class ContractController extends Controller
+{
+    protected array $data = [
+        'active'    => 'contracts',
+        'title'     => 'Договоры',
+        'id'        => 'contracts',
+        'header'    => [
+            'id'                        => 'ID',
+            'contract_number'           => 'Номер договора',
+            'contract_date'             => 'Дата договора',
+            'year'                      => 'Год',
+        ],
+        'searchFields' => [
+            'contract_number',
+        ],
+    ];
+
+
+    public function index(Request $request)
+    {
+        $model = new Contract();
+        // fill filters
+        $this->createFilters($model, 'year');
+        $this->data['ranges'] = [];
+        $this->createDateFilters($model, 'contract_date');
+
+        $q = $model::query();
+        $this->acceptSearch($q, $request);
+        $this->acceptFilters($q, $request);
+        $this->setSortAndOrderBy($model, $request);
+
+        $q->orderBy($this->data['sortBy'], $this->data['orderBy']);
+        $this->data['contracts'] = $q->paginate(session('per_page', config('pagination.per_page')))->withQueryString();
+
+        return view('contracts.index', $this->data);
+    }
+
+    public function show(Contract $contract)
+    {
+        $this->data['contract'] = $contract;
+        return view('contracts.edit', $this->data);
+    }
+
+    public function create()
+    {
+        $this->data['contract'] = null;
+        return view('contracts.edit', $this->data);
+    }
+
+    public function store(StoreContractRequest $request)
+    {
+        Contract::query()->create($request->validated());
+        return redirect()->route('contract.index');
+    }
+
+    public function update(StoreContractRequest $request, Contract $contract)
+    {
+        $contract->update($request->validated());
+        return redirect()->route('contract.index');
+    }
+
+    public function delete(Contract $contract)
+    {
+        $contract->delete();
+        return redirect()->route('contract.index');
+    }
+}

+ 30 - 0
app/Http/Requests/StoreContractRequest.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace App\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class StoreContractRequest extends FormRequest
+{
+    /**
+     * Determine if the user is authorized to make this request.
+     */
+    public function authorize(): bool
+    {
+        return hasRole('admin');
+    }
+
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array
+     */
+    public function rules(): array
+    {
+        return [
+            'contract_number'   => 'required|string',
+            'contract_date'     => 'required|date',
+            'year'              => 'required|numeric|min:2000',
+        ];
+    }
+}

+ 11 - 0
app/Models/Contract.php

@@ -0,0 +1,11 @@
+<?php
+
+namespace App\Models;
+
+use Illuminate\Database\Eloquent\Model;
+
+class Contract extends Model
+{
+    const DEFAULT_SORT_BY = 'contract_date';
+    protected $fillable = ['year', 'contract_number', 'contract_date'];
+}

+ 30 - 0
database/migrations/2025_04_23_121432_create_contracts_table.php

@@ -0,0 +1,30 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+    /**
+     * Run the migrations.
+     */
+    public function up(): void
+    {
+        Schema::create('contracts', function (Blueprint $table) {
+            $table->id();
+            $table->unsignedInteger('year');
+            $table->string('contract_number');
+            $table->date('contract_date');
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::dropIfExists('contracts');
+    }
+};

+ 30 - 0
resources/views/contracts/edit.blade.php

@@ -0,0 +1,30 @@
+@extends('layouts.app')
+
+@section('content')
+    <div class="px-3">
+        <div class="col-xxl-6 offset-xxl-2">
+            <form action="{{ ($contract) ? route('contract.update', $contract) : route('contract.store') }}" method="post">
+
+                @csrf
+                @include('partials.input', ['name' => 'year',
+                                            'type' => 'number',
+                                            'title' => 'Год',
+                                            'required' => true,
+                                            'value' => $contract->year ?? date('Y'),
+                                            ])
+                @include('partials.input', ['name' => 'contract_number', 'title' => 'Номер договора', 'required' => true, 'value' => $contract->contract_number ?? ''])
+                @include('partials.input', ['name' => 'contract_date', 'type' => 'date','title' => 'Дата договора', 'value' => $contract->contract_date ?? date('Y-m-d'), 'required' => true])
+
+                @include('partials.submit', ['deleteDisabled' => (!isset($contract)), 'delete' => ['form_id' => 'deleteContract']])
+            </form>
+            @if($contract)
+                <div class="visually-hidden">
+                    <form action="{{ route('contract.delete', $contract) }}" method="POST" id="deleteContract">
+                        @csrf
+                        @method('DELETE')
+                    </form>
+                </div>
+            @endif
+        </div>
+    </div>
+@endsection

+ 32 - 0
resources/views/contracts/index.blade.php

@@ -0,0 +1,32 @@
+@extends('layouts.app')
+
+@section('content')
+    <div class="row mb-3">
+        <div class="col-6">
+            <h3>Пользователи</h3>
+        </div>
+        <div class="col-6 text-end">
+            <a href="{{ route('contract.create') }}" class="btn btn-primary">Добавить</a>
+        </div>
+    </div>
+
+
+    @include('partials.table', [
+        'id'        => $id,
+        'header'    => $header,
+        'strings'   => $contracts,
+        'routeName' => 'contract.show',
+    ])
+
+    <div class="row pt-3 px-3">
+        <div class="col-12 pagination">
+            {{ $contracts->links() }}
+        </div>
+    </div>
+
+
+    @if($errors->any())
+        @dump($errors)
+    @endif
+
+@endsection

+ 2 - 1
resources/views/layouts/menu.blade.php

@@ -5,8 +5,9 @@
 <li class="nav-item"><a class="nav-link" href="{{ route('catalog.index') }}">Каталог</a></li>
 
 @if(hasrole('admin'))
+    <li class="nav-item"><a class="nav-link" href="{{ route('contract.index') }}">Договоры</a></li>
     <li class="nav-item dropdown">
-        <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+    <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
             Администрирование
         </a>
         <ul class="dropdown-menu dropdown-menu-end">

+ 1 - 1
resources/views/partials/submit.blade.php

@@ -2,7 +2,7 @@
     <div class="@if(!($right ?? null)) offset-md-{{ $offset ?? 4 }} col-md-8 @endif buttons">
         <button type="submit" class="btn btn-primary text-white">{{ $name ?? 'Сохранить' }}</button>
         @if(isset($delete) && !($deleteDisabled ?? false))
-            <a href="#" class="btn btn-danger delete">{{ $delete['title'] }}</a>
+            <a href="#" class="btn btn-danger delete">{{ $delete['title'] ?? 'Удалить' }}</a>
         @endif
         <a href="{{ url()->previous() }}" class="btn btn-outline-secondary">Назад</a>
     </div>

+ 9 - 0
routes/web.php

@@ -1,6 +1,7 @@
 <?php
 
 use App\Http\Controllers\AreaController;
+use App\Http\Controllers\ContractController;
 use App\Http\Controllers\MafOrderController;
 use App\Http\Controllers\OrderController;
 use App\Http\Controllers\ProductController;
@@ -59,6 +60,14 @@ Route::middleware('auth:web')->group(function () {
     Route::post('catalog/import', [ProductController::class, 'import'])->name('catalog.import');
     Route::post('catalog/export', [ProductController::class, 'export'])->name('catalog.export');
 
+    // contracts
+    Route::get('contract', [ContractController::class, 'index'])->name('contract.index');
+    Route::get('contract/create', [ContractController::class, 'create'])->name('contract.create');
+    Route::get('contract/{contract}', [ContractController::class, 'show'])->name('contract.show');
+    Route::post('contract', [ContractController::class, 'store'])->name('contract.store');
+    Route::post('contract/{contract}', [ContractController::class, 'update'])->name('contract.update');
+    Route::delete('contract/{contract}', [ContractController::class, 'delete'])->name('contract.delete');
+
     // orders
     Route::get('order', [OrderController::class, 'index'])->name('order.index');
     Route::get('order/create', [OrderController::class, 'create'])->name('order.create');