浏览代码

schedules model, migration, copy from order

Alexander Musikhin 2 月之前
父节点
当前提交
8cdce256b8

+ 49 - 25
app/Http/Controllers/ScheduleController.php

@@ -3,16 +3,17 @@
 namespace App\Http\Controllers;
 
 use App\Helpers\DateHelper;
+use App\Http\Requests\CreateScheduleFromOrderRequest;
 use App\Models\Order;
-use App\Models\OrderStatus;
+use App\Models\Schedule;
 use Illuminate\Http\Request;
 
 class ScheduleController extends Controller
 {
     protected array $data = [
-        'active'    => 'reports',
-        'title'     => 'Отчёты',
-        'id'        => 'reports',
+        'active'    => 'schedule',
+        'title'     => 'График монтажей',
+        'id'        => 'schedule',
     ];
 
     public function index(Request $request)
@@ -29,32 +30,55 @@ class ScheduleController extends Controller
         ];
         $this->data['weekDates'] = $weekDates;
 
-        $maxInstallDays = Order::query()->max('install_days');
 
-        $from = date('Y-m-d', strtotime($weekDates['mon']) - $maxInstallDays * 86400);
-
-        $orders = Order::query()
-            ->whereNotNull('installation_date')
-            ->whereNotNull('brigadier_id')
-            ->whereBetween('installation_date', [$from , $weekDates['sun'] ])
-            ->where('order_status_id', 5)
-            ->orderBy('installation_date')
-            ->orderBy('brigadier_id')
-            ->get();
         $schedules = [];
-        foreach ($weekDates as $wd)
-            $schedules[$wd] = null;
-        foreach ($orders as $order) {
-            for ($iDays = 1; $iDays < $order->install_days + 1; $iDays++) {
-                $instDate = date('Y-m-d', strtotime('+' . $iDays - 1 . ' days', strtotime($order->installation_date)));
-                if(in_array($instDate, $weekDates)) {
-                    $schedules[$instDate][] = $order;
-                }
-            }
+        foreach ($weekDates as $date) {
+            $schedules[$date] = null;
+        }
+        $result = Schedule::query()
+            ->whereBetween('installation_date', [$weekDates['mon'], $weekDates['sun']])
+            ->get();
+        foreach ($result as $schedule) {
+            $schedules[$schedule->installation_date][] = $schedule;
         }
-
 
         $this->data['schedules'] = $schedules;
         return view('schedule.index', $this->data);
     }
+
+    public function createFromOrder(CreateScheduleFromOrderRequest $request)
+    {
+        $validated = $request->validated();
+        // delete all auto schedules for this order
+        Schedule::query()
+            ->where('order_id', $validated['order_id'])
+            ->where('manual', false)
+            ->delete();
+
+        // create all records in schedule
+        $order = Order::query()
+            ->where('id', $validated['order_id'])
+            ->first();
+
+        for ($iDays = 1; $iDays < $order->install_days + 1; $iDays++) {
+            $instDate = date('Y-m-d', strtotime('+' . $iDays - 1 . ' days', strtotime($order->installation_date)));
+            Schedule::query()
+                ->create([
+                    'order_id' => $validated['order_id'],
+                    'installation_date' => $instDate,
+                    'manual' => false,
+                    'district_id' => $order->district_id,
+                    'area_id' => $order->area_id,
+                    'object_address' => $order->object_address,
+                    'object_type_id' => $order->object_type_id,
+                    'mafs' => $order->productsWithCount,
+                    'mafs_count' => $order->products_sku()->count(),
+                    'brigadier_id' => $order->brigadier_id,
+                    'comment'   => $validated['comment'],
+                ]);
+        }
+        return redirect()->route('schedule.index');
+
+    }
+
 }

+ 29 - 0
app/Http/Requests/CreateScheduleFromOrderRequest.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace App\Http\Requests;
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class CreateScheduleFromOrderRequest extends FormRequest
+{
+    /**
+     * Determine if the user is authorized to make this request.
+     */
+    public function authorize(): bool
+    {
+        return auth()->check();
+    }
+
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
+     */
+    public function rules(): array
+    {
+        return [
+            'order_id'  => 'required|exists:orders,id',
+            'comment'   => 'nullable|string',
+        ];
+    }
+}

+ 45 - 0
app/Models/Schedule.php

@@ -0,0 +1,45 @@
+<?php
+
+namespace App\Models;
+
+use App\Models\Dictionary\Area;
+use App\Models\Dictionary\District;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
+
+class Schedule extends Model
+{
+    protected $fillable = [
+        'installation_date',
+        'manual',
+        'order_id',
+        'district_id',
+        'area_id',
+        'object_address',
+        'object_type_id',
+        'mafs',
+        'mafs_count',
+        'brigadier_id',
+        'comment',
+    ];
+
+    public function district(): BelongsTo
+    {
+        return $this->belongsTo(District::class);
+    }
+
+    public function area(): BelongsTo
+    {
+        return $this->belongsTo(Area::class);
+    }
+
+    public function objectType(): BelongsTo
+    {
+        return $this->belongsTo(ObjectType::class);
+    }
+
+    public function brigadier(): BelongsTo
+    {
+        return $this->belongsTo(User::class, 'brigadier_id', 'id');
+    }
+}

+ 38 - 0
database/migrations/2025_09_22_162208_create_schedules_table.php

@@ -0,0 +1,38 @@
+<?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('schedules', function (Blueprint $table) {
+            $table->id();
+            $table->date('installation_date');
+            $table->boolean('manual')->default(false);
+            $table->foreignId('order_id')->constrained('orders')->cascadeOnDelete();
+            $table->foreignId('district_id')->constrained('districts')->cascadeOnDelete();
+            $table->foreignId('area_id')->constrained('areas')->cascadeOnDelete();
+            $table->text('object_address');
+            $table->foreignId('object_type_id')->constrained('object_types')->cascadeOnDelete();
+            $table->text('mafs');
+            $table->integer('mafs_count');
+            $table->foreignId('brigadier_id')->constrained('users')->cascadeOnDelete();
+            $table->text('comment')->nullable();
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::dropIfExists('schedules');
+    }
+};

+ 36 - 2
resources/views/orders/show.blade.php

@@ -28,11 +28,17 @@
                 @if(in_array($order->order_status_id, [Order::STATUS_READY_TO_MOUNT, Order::STATUS_IN_MOUNT]) && $order->isAllMafConnected())
                     <a href="{{ route('order.generate-installation-pack', $order) }}"
                        class="btn btn-sm mb-1 btn-primary">Документы для монтажа</a>
+
+                    <button class="btn btn-primary btn-sm mb-1" data-bs-toggle="modal"
+                            data-bs-target="#copySchedule">Перенести в график
+                    </button>
+
                 @endif
                 @if($order->canCreateHandover())
                     <a href="{{ route('order.generate-handover-pack', $order) }}" class="btn btn-sm mb-1 btn-primary">Документы
                         для сдачи</a>
                 @endif
+
                 <a href="{{ $previous_url ?? route('order.index', session('gp_orders')) }}"
                    class="btn btn-sm mb-1 btn-outline-secondary">Назад</a>
 
@@ -286,6 +292,28 @@
         </div>
     </div>
 
+    <!-- Модальное окно графика -->
+    <div class="modal fade" id="copySchedule" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
+        <div class="modal-dialog modal-fullscreen-sm-down modal-lg">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h1 class="modal-title fs-5" id="addModalLabel">Перенести в график монтажей</h1>
+                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Закрыть"></button>
+                </div>
+                <div class="modal-body">
+                    <form action="{{ route('schedule.create-from-order') }}" method="post">
+                        @csrf
+                        <div>
+                            <input type="hidden" name="order_id" value="{{ $order->id }}">
+                            <textarea name="comment" placeholder="Комментарий для графика" class="form-control mb-3"></textarea>
+                            <button type="submit" class="btn btn-primary">Обновить график</button>
+                        </div>
+                    </form>
+                </div>
+            </div>
+        </div>
+    </div>
+
     <!-- Модальное окно ТТН -->
     <div class="modal fade" id="createTtnModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
         <div class="modal-dialog modal-fullscreen-sm-down modal-lg">
@@ -301,7 +329,7 @@
                             <input type="text" class="form-control mb-2" name="order_number" placeholder="Номер заказа">
                             <input type="date" class="form-control mb-2" name="order_date" placeholder="Дата заказа" value="{{ date('Y-m-d') }}">
                             <input type="number" class="form-control mb-2" name="order_sum" placeholder="Сумма заказа" value="0">
-                            <a href="#" class="btn btn-primary" id="createTtn">Создать ТТН</a>
+                            <button href="#" class="btn btn-primary" id="createTtn">Создать ТТН</button>
                         </div>
                     </form>
                 </div>
@@ -322,7 +350,7 @@
                         @csrf
                         <div id="select_maf_form">
                             <input type="text" class="form-control mb-2" placeholder="Поиск площадки" id="search_order">
-                            <select id="select_order" name="new_order_id" class="form-select mb-3" size="30" multiple
+                            <select id="select_order" name="new_order_id" class="form-select mb-3" size="20" multiple
                                     required></select>
                             <a href="#" class="btn btn-primary" id="moveMaf">Перенести</a>
                         </div>
@@ -332,6 +360,10 @@
         </div>
     </div>
 
+    @if($errors->any())
+        @dump($errors)
+    @endif
+
 @endsection
 
 
@@ -387,6 +419,8 @@
 
             if (ids.length) {
                 $('#create-reclamation-form').submit();
+            } else {
+                alert('Нужно выбрать МАФ для рекламации!');
             }
         });
 

+ 15 - 16
resources/views/schedule/index.blade.php

@@ -58,27 +58,26 @@
                 </tr>
             </thead>
             <tbody>
-            @foreach($schedules as $dow => $orders)
+            @foreach($schedules as $dow => $schs)
                 <tr>
-                    <td rowspan="{{ ($orders) ? count($orders) : '1' }}" class="vertical">{{ \App\Helpers\DateHelper::getHumanDayOfWeek($dow) }}</td>
-                    <td rowspan="{{ ($orders) ? count($orders) : '1' }}" class="vertical">{{ \App\Helpers\DateHelper::getHumanDate($dow) }}</td>
-                    @if($orders)
-                        @foreach($orders as $order)
+                    <td rowspan="{{ ($schs) ? count($schs) : '1' }}" class="vertical">{{ \App\Helpers\DateHelper::getHumanDayOfWeek($dow) }}</td>
+                    <td rowspan="{{ ($schs) ? count($schs) : '1' }}" class="vertical">{{ \App\Helpers\DateHelper::getHumanDate($dow) }}</td>
+                    @if($schs)
+                        @foreach($schs as $schedule)
                             {!! (!$loop->first) ? '<tr>':'' !!}
-                            <td style="background: {{ $order->brigadier->color }}" class="align-middle">{{ $order->id }}</td>
-                            <td style="background: {{ $order->brigadier->color }}" class="align-middle">{{ $order->district->shortname }}</td>
-                            <td style="background: {{ $order->brigadier->color }}" class="align-middle">{{ $order->area->name }}</td>
-                            <td style="background: {{ $order->brigadier->color }}" class="align-middle">{{ $order->object_address }}</td>
-                            <td style="background: {{ $order->brigadier->color }}" class="align-middle">{{ $order->objectType->name }}</td>
-                            <td style="background: {{ $order->brigadier->color }}" class="align-middle">{!! $order->productsWithCount !!}</td>
-                            <td style="background: {{ $order->brigadier->color }}" class="align-middle">{{ $order->products_sku()->count() }}</td>
-                            <td style="background: {{ $order->brigadier->color }}" class="align-middle">{{ $order->brigadier->name }}</td>
-                            <td style="background: {{ $order->brigadier->color }}" class="align-middle"></td>
+                            <td style="background: {{ $schedule->brigadier->color }}" class="align-middle">{{ $schedule->order_id }}</td>
+                            <td style="background: {{ $schedule->brigadier->color }}" class="align-middle">{{ $schedule->district->shortname }}</td>
+                            <td style="background: {{ $schedule->brigadier->color }}" class="align-middle">{{ $schedule->area->name }}</td>
+                            <td style="background: {{ $schedule->brigadier->color }}" class="align-middle">{{ $schedule->object_address }}</td>
+                            <td style="background: {{ $schedule->brigadier->color }}" class="align-middle">{{ $schedule->objectType->name }}</td>
+                            <td style="background: {{ $schedule->brigadier->color }}" class="align-middle">{!! $schedule->mafs !!}</td>
+                            <td style="background: {{ $schedule->brigadier->color }}" class="align-middle">{{ $schedule->mafs_count }}</td>
+                            <td style="background: {{ $schedule->brigadier->color }}" class="align-middle">{{ $schedule->brigadier->name }}</td>
+                            <td style="background: {{ $schedule->brigadier->color }}" class="align-middle">{{ $schedule->comment }}</td>
                             </tr>
                         @endforeach
                     @endif
-                    {!! (!$orders) ? '</tr>': '' !!}
-
+                    {!! (!$schs) ? '</tr>': '' !!}
 
             @endforeach
 

+ 1 - 1
routes/web.php

@@ -146,7 +146,7 @@ Route::middleware('auth:web')->group(function () {
     Route::get('reports', [ReportController::class, 'index'])->name('reports.index');
 
     Route::get('schedule', [ScheduleController::class, 'index'])->name('schedule.index');
-
+    Route::post('schedule/create_from_order', [ScheduleController::class, 'createFromOrder'])->name('schedule.create-from-order');
 
     // ajax search products
     Route::get('product/search', [ProductController::class, 'search'])->name('product.search');