3 Комити edef9ceba6 ... d8c801961a

Аутор SHA1 Порука Датум
  Alexander Musikhin d8c801961a fix doc generation, added colors to reclamations statuses пре 1 недеља
  Alexander Musikhin e357c6a79f changed template пре 1 недеља
  Alexander Musikhin f8ccc30dd4 added status column to scheduler пре 1 недеља

+ 83 - 0
app/Http/Controllers/ScheduleController.php

@@ -16,6 +16,7 @@ use App\Models\Dictionary\District;
 use App\Models\Order;
 use App\Models\ProductSKU;
 use App\Models\Reclamation;
+use App\Models\ReclamationStatus;
 use App\Models\Role;
 use App\Models\Schedule;
 use App\Models\User;
@@ -65,6 +66,8 @@ class ScheduleController extends Controller
             ->whereBetween('installation_date', [$weekDates['mon'], $weekDates['sun']])
             ->with(['brigadier', 'district', 'area'])
             ->get();
+        $this->data['scheduleStatusMap'] = $this->buildScheduleStatusMap($result);
+
         foreach ($result as $schedule) {
             $schedules[$schedule->installation_date][] = $schedule;
         }
@@ -343,4 +346,84 @@ class ScheduleController extends Controller
             ->with(['success' => 'Задача генерации графика создана!']);
 
     }
+
+    private function buildScheduleStatusMap($schedules): array
+    {
+        $statusMap = [];
+        $orderIds = [];
+        $reclamationScheduleIds = [];
+
+        foreach ($schedules as $schedule) {
+            $statusMap[$schedule->id] = [
+                'name' => '-',
+                'color' => 'secondary',
+            ];
+
+            if ($schedule->source === 'Площадки' && $schedule->order_id) {
+                $orderIds[] = (int)$schedule->order_id;
+                continue;
+            }
+
+            if ($schedule->source === 'Рекламации') {
+                $reclamationId = $this->extractReclamationId((string)$schedule->address_code);
+                if ($reclamationId) {
+                    $reclamationScheduleIds[$reclamationId][] = $schedule->id;
+                }
+            }
+        }
+
+        if ($orderIds) {
+            $orderStatuses = Order::query()
+                ->withoutGlobalScopes()
+                ->whereIn('id', array_unique($orderIds))
+                ->pluck('order_status_id', 'id')
+                ->all();
+
+            foreach ($schedules as $schedule) {
+                if ($schedule->source !== 'Площадки' || !$schedule->order_id) {
+                    continue;
+                }
+
+                $statusId = $orderStatuses[(int)$schedule->order_id] ?? null;
+                if ($statusId) {
+                    $statusMap[$schedule->id] = [
+                        'name' => Order::STATUS_NAMES[$statusId] ?? '-',
+                        'color' => Order::STATUS_COLOR[$statusId] ?: 'secondary',
+                    ];
+                }
+            }
+        }
+
+        if ($reclamationScheduleIds) {
+            $reclamationStatuses = Reclamation::query()
+                ->withoutGlobalScopes()
+                ->whereIn('id', array_keys($reclamationScheduleIds))
+                ->pluck('status_id', 'id')
+                ->all();
+
+            foreach ($reclamationScheduleIds as $reclamationId => $scheduleIds) {
+                $statusId = $reclamationStatuses[$reclamationId] ?? null;
+                $statusName = $statusId ? (Reclamation::STATUS_NAMES[$statusId] ?? '-') : '-';
+                $statusColor = $statusId ? (ReclamationStatus::STATUS_COLOR[$statusId] ?? 'secondary') : 'secondary';
+
+                foreach ($scheduleIds as $scheduleId) {
+                    $statusMap[$scheduleId] = [
+                        'name' => $statusName,
+                        'color' => $statusColor,
+                    ];
+                }
+            }
+        }
+
+        return $statusMap;
+    }
+
+    private function extractReclamationId(string $addressCode): ?int
+    {
+        if (preg_match('/^РЕКЛ-(\d+)$/u', $addressCode, $matches)) {
+            return (int)$matches[1];
+        }
+
+        return null;
+    }
 }

+ 12 - 1
app/Models/ReclamationStatus.php

@@ -6,7 +6,18 @@ use Illuminate\Database\Eloquent\Model;
 
 class ReclamationStatus extends Model
 {
-
+    const STATUS_COLOR = [
+        Reclamation::STATUS_NEW => 'secondary',
+        Reclamation::STATUS_WAIT => 'warning',
+        Reclamation::STATUS_IN_WORK => 'info',
+        Reclamation::STATUS_SUBSCRIBE_ACT => 'primary',
+        Reclamation::STATUS_DONE => 'success',
+        Reclamation::STATUS_SENT => 'dark',
+        Reclamation::STATUS_DO_DOCS => 'primary',
+        Reclamation::STATUS_HANDOVER_TO_CHECK => 'warning',
+        Reclamation::STATUS_PAID => 'success',
+        Reclamation::STATUS_CLOSED_NO_PAY => 'danger',
+    ];
 
     public $timestamps = false;
 }

+ 45 - 2
app/Services/GenerateDocumentsService.php

@@ -36,6 +36,13 @@ class GenerateDocumentsService
     public function generateInstallationPack(Order $order, int $userId): string
     {
         $techDocsPath = base_path('/tech-docs/');
+        $order = Order::query()
+            ->withoutGlobalScopes()
+            ->whereKey($order->id)
+            ->where('year', $order->year)
+            ->with('documents')
+            ->firstOrFail();
+
         $products_sku = $order->products_sku()
             ->withoutGlobalScopes()
             ->where('year', $order->year)
@@ -57,6 +64,14 @@ class GenerateDocumentsService
             }
         }
 
+        $orderDocumentsDir = 'orders/' . $order->id . '/tmp/Документы площадки';
+        foreach ($order->documents as $document) {
+            if ($this->shouldSkipArchiveDocument($document)) {
+                continue;
+            }
+            $this->copyFileToDir($document->path, $orderDocumentsDir, $document->original_name);
+        }
+
         // generate xlsx order file
         $this->generateOrderForMount($order);
 
@@ -100,6 +115,11 @@ class GenerateDocumentsService
         $str = Str::replace('<div>', '', $order->products_with_count);
         $str = Str::replace('</div>', "\n", $str);
 
+        // дата монтажа
+        $installationDate = ($order->installation_date) ? DateHelper::getHumanDate($order->installation_date, true) : '';
+        $sheet->setCellValue('L15', $installationDate);
+
+
         // мафы
         $sheet->setCellValue('G33', Str::trim($str));
 
@@ -607,16 +627,39 @@ class GenerateDocumentsService
     }
 
     private function shouldSkipDocumentForPaymentPack($file): bool
+    {
+        return $this->shouldSkipArchiveDocument($file);
+    }
+
+    private function shouldSkipArchiveDocument($file): bool
     {
         if (!$file) {
             return true;
         }
 
-        if ($file->mime_type === 'application/zip') {
+        $fileName = Str::lower((string)$file->original_name);
+        $mimeType = Str::lower((string)$file->mime_type);
+
+        $archiveSuffixes = [
+            '.zip',
+            '.rar',
+            '.7z',
+            '.tar',
+            '.tar.gz',
+            '.tgz',
+            '.tar.bz2',
+            '.tbz2',
+            '.bz2',
+            '.tar.xz',
+            '.txz',
+            '.xz',
+        ];
+
+        if (Str::endsWith($fileName, $archiveSuffixes)) {
             return true;
         }
 
-        if (Str::endsWith((string)$file->original_name, '.zip')) {
+        if (str_contains($mimeType, 'zip') || str_contains($mimeType, 'compressed') || str_contains($mimeType, '7z') || str_contains($mimeType, 'rar')) {
             return true;
         }
 

+ 6 - 1
resources/views/reclamations/edit.blade.php

@@ -5,7 +5,12 @@
     <div class="px-3">
         <div class="row">
             <div class="col-xl-6">
-                <h4>Рекламация</h4>
+                <h4 class="d-flex align-items-center gap-2">
+                    Рекламация
+                    <span class="badge text-bg-{{ \App\Models\ReclamationStatus::STATUS_COLOR[$reclamation->status_id] ?? 'secondary' }}">
+                        {{ $reclamation->status?->name ?? (\App\Models\Reclamation::STATUS_NAMES[$reclamation->status_id] ?? '-') }}
+                    </span>
+                </h4>
             </div>
             <div class="col-xl-6 action-toolbar mb-2">
                 <a href="{{ $previous_url ?? route('reclamations.index', session('gp_reclamations')) }}"

+ 7 - 6
resources/views/schedule/index.blade.php

@@ -89,7 +89,7 @@
                 <th>Кол-во позиций</th>
                 <th>Бригадир</th>
                 @if(hasRole('admin'))
-                    <th>Транспорт</th>
+                    <th>Статус площадки/рекламации</th>
                     <th>Комментарий</th>
                 @endif
                 <th>Примечание</th>
@@ -151,7 +151,12 @@
                                 class="align-middle">{{ $schedule->brigadier->name }}</td>
                             @if(hasRole('admin'))
                                 <td style="background: {{ $schedule->brigadier->color }}"
-                                    class="align-middle transport-{{ $schedule->id }}">{{ $schedule->transport }}</td>
+                                    class="align-middle">
+                                    @php
+                                        $scheduleStatus = $scheduleStatusMap[$schedule->id] ?? ['name' => '-', 'color' => 'secondary'];
+                                    @endphp
+                                    <span class="badge text-bg-{{ $scheduleStatus['color'] }}">{{ $scheduleStatus['name'] }}</span>
+                                </td>
                                 <td style="background: {{ $schedule->brigadier->color }}"
                                     class="align-middle admin-comment-{{ $schedule->id }}">{{ $schedule->admin_comment }}</td>
                             @endif
@@ -343,7 +348,6 @@
                                     @include('partials.textarea', ['name' => 'mafs', 'title' => 'МАФы', 'required' => true])
                                     @include('partials.input',  ['name' => 'mafs_count', 'title' => 'Кол-во МАФ', 'type' => 'number', 'required' => true])
                                     @include('partials.select', ['name' => 'brigadier_id', 'title' => 'Бригадир', 'options' => $brigadiers, 'required' => true, 'first_empty' => true])
-                                    @include('partials.input',  ['name' => 'transport', 'title' => 'Транспорт'])
                                     @include('partials.textarea', ['name' => 'admin_comment', 'title' => 'Комментарий'])
                                     @include('partials.textarea', ['name' => 'comment', 'title' => 'Примечание'])
                                     <div class="text-center">
@@ -378,7 +382,6 @@
                 let scheduleBrigadier = $(this).attr('data-schedule-brigadier');
                 let scheduleAddress = $(this).attr('data-schedule-address');
                 let scheduleComment = $('.comment-' + scheduleId).text();
-                let scheduleTransport = $('.transport-' + scheduleId).text();
                 let scheduleAdminComment = $('.admin-comment-' + scheduleId).text();
                 let scheduleMafs = $('.mafs-' + scheduleId).text();
                 let scheduleObjectType = $('.object-type-' + scheduleId).text();
@@ -393,7 +396,6 @@
                 $('form#scheduleEditForm select[name=area_id]').val(scheduleArea);
                 $('form#scheduleEditForm select[name=brigadier_id]').val(scheduleBrigadier);
                 $('form#scheduleEditForm textarea[name=comment]').text(scheduleComment);
-                $('form#scheduleEditForm input[name=transport]').val(scheduleTransport);
                 $('form#scheduleEditForm textarea[name=admin_comment]').text(scheduleAdminComment);
                 $('form#scheduleEditForm textarea[name=mafs]').text(scheduleMafs);
                 $('form#scheduleEditForm input[name=mafs_count]').val(scheduleMafsCount);
@@ -421,7 +423,6 @@
                 $('form#scheduleEditForm select[name=area_id]').val('');
                 $('form#scheduleEditForm select[name=brigadier_id]').val('');
                 $('form#scheduleEditForm textarea[name=comment]').text('');
-                $('form#scheduleEditForm input[name=transport]').val('');
                 $('form#scheduleEditForm textarea[name=admin_comment]').text('');
                 $('form#scheduleEditForm textarea[name=mafs]').text('');
                 $('form#scheduleEditForm input[name=mafs_count]').val('');

BIN
templates/Inventory.xlsx


BIN
templates/OrderForMount.xlsx


BIN
templates/Passport.xlsx