Alexander Musikhin пре 6 месеци
родитељ
комит
8a81c3d8bc

+ 87 - 0
app/Http/Controllers/ReportController.php

@@ -0,0 +1,87 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Helpers\Price;
+use App\Models\ObjectType;
+use App\Models\Order;
+use App\Models\OrderStatus;
+use App\Models\Product;
+use App\Models\ProductSKU;
+use Illuminate\Http\Request;
+use Illuminate\Support\Str;
+
+class ReportController extends Controller
+{
+    protected array $data = [
+        'active'    => 'reports',
+        'title'     => 'Отчёты',
+        'id'        => 'reports',
+    ];
+
+
+    public function index()
+    {
+        $doneStatuses = [5, 7, 8, 9, 10];
+        $objectTypes = ObjectType::query()->get()->pluck('name', 'id')->toArray();
+        $this->data['objectTypes'] = $objectTypes;
+        $this->data['totalOrders']  = Order::all()->count();
+        $this->data['doneOrders']  = Order::query()->whereIn('order_status_id', [9, 10])->count();
+
+
+        $this->data['totalMafs']    = ProductSKU::all()->count();
+        $this->data['doneMafs']    = ProductSKU::query()->
+            whereHas('order', function ($query) {
+                $query->whereIn('order_status_id', [9, 10]);
+            })->count();
+
+
+        $this->data['totalSum'] = Price::format(
+            ProductSKU::query()->
+            whereHas('order', function ($query) use ($doneStatuses) {
+                $query->whereIn('order_status_id', $doneStatuses);
+            })
+            ->withSum('product', 'total_price')
+            ->get()
+            ->sum('product_sum_total_price')
+        );
+        foreach ($objectTypes as $objectTypeId => $objectType) {
+            // total by types
+            $this->data['totalOrdersType'][$objectTypeId]  = Order::where('object_type_id', '=', $objectTypeId)->count();
+            $this->data['totalMafsType'][$objectTypeId]     = ProductSKU::query()->
+                whereHas('order', function ($query) use ($objectTypeId) {
+                    $query->where('object_type_id', '=', $objectTypeId);
+                })->count();
+
+            // со статусами: в монтаже, готова к сдаче, не сдана замечания, сдана замечания, сдана - зеленый цвет
+
+            $this->data['doneOrdersType'][$objectTypeId]  = Order::query()
+                ->where('object_type_id', '=', $objectTypeId)
+                ->whereIn('order_status_id', $doneStatuses)
+                ->count();
+            $this->data['doneMafsType'][$objectTypeId]     = ProductSKU::query()->
+            whereHas('order', function ($query) use ($objectTypeId, $doneStatuses) {
+                $query->where('object_type_id', '=', $objectTypeId)
+                ->whereIn('order_status_id', $doneStatuses);
+            })->count();
+
+            // остальные - не готовы
+            $this->data['notDoneOrdersType'][$objectTypeId]  = Order::query()
+                ->where('object_type_id', '=', $objectTypeId)
+                ->whereNotIn('order_status_id', $doneStatuses)
+                ->count();
+            $this->data['notDoneMafsType'][$objectTypeId]     = ProductSKU::query()->
+            whereHas('order', function ($query) use ($objectTypeId, $doneStatuses) {
+                $query->where('object_type_id', '=', $objectTypeId)
+                    ->whereNotIn('order_status_id', $doneStatuses);
+            })->count();
+
+
+        }
+
+
+
+
+        return view('reports.index', $this->data);
+    }
+}

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

@@ -10,6 +10,8 @@
 
     <li class="nav-item"><a class="nav-link @if($active == 'catalog') active @endif"
                             href="{{ route('catalog.index', session('gp_catalog')) }}">Каталог</a></li>
+    <li class="nav-item"><a class="nav-link @if($active == 'reports') active @endif"
+                            href="{{ route('reports.index', session('gp_reports')) }}">Отчёты</a></li>
 
     @if(hasrole('admin'))
 

+ 118 - 0
resources/views/reports/index.blade.php

@@ -0,0 +1,118 @@
+
+@extends('layouts.app')
+@section('content')
+    <div class="row">
+        <div class="col-12 text-center">
+            <h1 class="text-success">Выполнение плана по сдаче МАФ</h1>
+        </div>
+    </div>
+    <hr>
+    <div class="row">
+        <div class="col-md-4">
+            <div class="text-center text-success fs-4 fw-bold" >
+               {{ $totalMafs }} / {{ $totalOrders }}
+            </div>
+            <div class="text-center">
+                Всего МАФ / Площадок
+            </div>
+        </div>
+        <div class="col-4">
+            <div class="text-center text-success fs-4 fw-bold" >
+               {{ $doneMafs }} / {{ $doneOrders }}
+            </div>
+            <div class="text-center">
+                Сдано МАФ / Площадок
+            </div>
+        </div>
+        <div class="col-md-4">
+            <div class="text-center text-success fs-4 fw-bold" >
+               {!! $totalSum !!}
+            </div>
+            <div class="text-center">
+                Сдано на сумму
+            </div>
+        </div>
+    </div>
+    <hr>
+    <div class="row">
+        <div class="col-md-4 offset-md-1">
+            <canvas id="total_orders" class="p-4 m-4"></canvas>
+        </div>
+
+        <div class="col-md-6 offset-md-1">
+            <canvas id="order_types"></canvas>
+        </div>
+    </div>
+
+
+    @dump(get_defined_vars())
+
+@endsection
+
+@php
+    $notDone = $labels = '';
+    foreach ($doneMafsType as $id => $count) {
+        $labels .= '"' . $objectTypes[$id] . ' (' . $doneMafsType[$id] .'/'. $notDoneMafsType[$id] . ')",';
+        $notDone .= '[' . $totalMafsType[$id] . ', ' . $doneMafsType[$id] . '],';
+    }
+@endphp
+
+@push('scripts')
+    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
+    <script>
+        const ctx = document.getElementById('order_types');
+        new Chart(ctx, {
+            type: 'bar',
+            data: {
+                labels: [{!! $labels  !!}],
+                datasets: [
+                    {
+                        label: 'Сдано',
+                        data: [{{ implode(',', $doneMafsType) }}],
+                        borderWidth: 1,
+                        backgroundColor: [
+                            'rgb(114,180,150)',
+                        ],
+                        grouped: false,
+                    },
+                    {
+                        label: 'Осталось сдать',
+                        data: [{{ $notDone }}],
+                        borderWidth: 1,
+                        backgroundColor: [
+                            'rgb(251,215,105)',
+                        ],
+                        grouped: false,
+                    }
+                ]
+            },
+            options: {
+                scales: {
+                    y: {
+                        beginAtZero: true
+                    }
+                },
+
+            }
+        });
+
+        // круговая диаграмма
+        const circleDiag = document.getElementById('total_orders');
+        new Chart(circleDiag, {
+            type: 'doughnut',
+            data: {
+                labels: ['Сдано', 'Осталось сдать'],
+                datasets: [{
+                    data: [{{ $doneMafs }}, {{ $totalMafs - $doneMafs }}],
+                    backgroundColor: [
+                        'rgb(114,180,150)',
+                        'rgb(251,215,105)',
+                    ]
+                }],
+
+            },
+        });
+
+
+    </script>
+@endpush

+ 5 - 0
routes/web.php

@@ -7,6 +7,7 @@ use App\Http\Controllers\OrderController;
 use App\Http\Controllers\ProductController;
 use App\Http\Controllers\ProductSKUController;
 use App\Http\Controllers\ReclamationController;
+use App\Http\Controllers\ReportController;
 use App\Http\Controllers\ResponsibleController;
 use App\Http\Controllers\UserController;
 use App\Models\Role;
@@ -139,6 +140,10 @@ Route::middleware('auth:web')->group(function () {
     Route::post('reclamations/{reclamation}/upload-photo-after', [ReclamationController::class, 'uploadPhotoAfter'])->name('reclamations.upload-photo-after');
     Route::post('reclamations/{reclamation}/upload-act', [ReclamationController::class, 'uploadAct'])->name('reclamations.upload-act');
     Route::post('reclamations/{reclamation}/update-details', [ReclamationController::class, 'updateDetails'])->name('reclamations.update-details');
+
+    Route::get('reports', [ReportController::class, 'index'])->name('reports.index');
+
+
     // ajax search products
     Route::get('product/search', [ProductController::class, 'search'])->name('product.search');