Răsfoiți Sursa

added order for mount generation, fields to maf, field to responsible

Alexander Musikhin 7 luni în urmă
părinte
comite
8c36e1adda

+ 2 - 0
app/Http/Controllers/ProductController.php

@@ -38,6 +38,8 @@ class ProductController extends Controller
             'note'                      => 'Примечания',
             'created_at'                => 'Дата создания',
             'certificate_id'            => 'Сертификат',
+            'passport_name'             => 'Наименование по паспорту',
+            'statement_name'            => 'Наименование в ведомости',
         ],
         'searchFields' =>  [
             'nomenclature_number',

+ 2 - 0
app/Http/Controllers/ResponsibleController.php

@@ -20,11 +20,13 @@ class ResponsibleController extends Controller
             'area-name'     => 'Район',
             'name'          => 'ФИО',
             'phone'         => 'Телефон',
+            'post'          => 'Должность',
             'created_at'    => 'Дата создания'
         ],
         'searchFields' => [
             'name',
             'phone',
+            'post',
         ],
         'ranges' => [],
         'filters' => [],

+ 2 - 0
app/Http/Requests/StoreProductRequest.php

@@ -35,6 +35,8 @@ class StoreProductRequest extends FormRequest
             'total_price'           => 'required|numeric',
             'manufacturer_name'     => 'required|string',
             'note'                  => 'nullable|string',
+            'passport_name'         => 'nullable|string',
+            'statement_name'        => 'nullable|string',
         ];
     }
 }

+ 1 - 0
app/Http/Requests/StoreResponsibleRequest.php

@@ -25,6 +25,7 @@ class StoreResponsibleRequest extends FormRequest
             'area_id'   => 'nullable|exists:areas,id',
             'name'      => 'required|string',
             'phone'     => 'required|string',
+            'post'      => 'nullable|string',
         ];
     }
 }

+ 6 - 0
app/Models/Dictionary/Area.php

@@ -2,6 +2,7 @@
 
 namespace App\Models\Dictionary;
 
+use App\Models\Responsible;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\Relations\BelongsTo;
 use Illuminate\Database\Eloquent\SoftDeletes;
@@ -23,4 +24,9 @@ class Area extends Model
     {
         return $this->belongsTo(District::class);
     }
+
+    public function responsible(): BelongsTo
+    {
+        return $this->belongsTo(Responsible::class);
+    }
 }

+ 4 - 2
app/Models/Order.php

@@ -248,11 +248,13 @@ class Order extends Model
             }
         }
         $s = '';
+        $openTag = '<div>';
+        $closeTag = '</div>';
 
         foreach ($ret as $product) {
-            ;
+
             $order_numbers = (isset($product['order_numbers'])) ? ' (' . implode(', ', array_unique($product['order_numbers'])) . ')' : '';
-            $s .= '<div>' . $product['name'] . ' - ' . $product['count'] . $order_numbers . '</div>';
+            $s .= $openTag . $product['name'] . ' - ' . $product['count'] . $order_numbers . $closeTag;
         }
 
         return Attribute::make(

+ 2 - 0
app/Models/Product.php

@@ -36,6 +36,8 @@ class Product extends Model
         'manufacturer_name',
         'note',
         'certificate_id',
+        'passport_name',
+        'statement_name',
     ];
 
     // set year attribute to current selected year

+ 1 - 0
app/Models/Responsible.php

@@ -14,6 +14,7 @@ class Responsible extends Model
     protected $fillable = [
         'name',
         'phone',
+        'post',
     ];
 
     public function area(): HasOne

+ 44 - 1
app/Services/GenerateDocumentsService.php

@@ -6,6 +6,8 @@ use App\Models\Order;
 use Exception;
 use Illuminate\Support\Facades\Storage;
 use Illuminate\Support\Str;
+use PhpOffice\PhpSpreadsheet\IOFactory;
+use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
 
 class GenerateDocumentsService
 {
@@ -39,7 +41,8 @@ class GenerateDocumentsService
         }
 
         // generate xlsx order file
-        // ...
+        $this->generateOrderForMount($order);
+
         // create zip archive
         $fileModel = (new FileService())->createZipArchive('orders/' . $order->id . '/tmp', self::INSTALL_FILENAME . $order->common_name . '.zip', $userId);
 
@@ -50,4 +53,44 @@ class GenerateDocumentsService
         // return link
         return $fileModel?->link ?? '';
     }
+
+    private function generateOrderForMount(Order $order): void
+    {
+        $inputFileType = 'Xlsx'; // Xlsx - Xml - Ods - Slk - Gnumeric - Csv
+        $inputFileName = './templates/OrderForMount.xlsx';
+
+        $reader = IOFactory::createReader($inputFileType);
+        $spreadsheet = $reader->load($inputFileName);
+        $sheet = $spreadsheet->getActiveSheet();
+
+        // менеджер
+        $sheet->setCellValue('F8', $order->user->name);
+        $sheet->setCellValue('X8', $order->user->phone);
+
+        // округ и район
+        $sheet->setCellValue('L10', $order->district->shortname);
+        $sheet->setCellValue('W10', $order->area->name);
+
+        if($order->area->responsible) {
+            // ответственный
+            $sheet->setCellValue('C12', $order->area->responsible?->name
+                . ', ' . $order->area->responsible?->phone . ', ' . $order->area->responsible?->post);
+        } else {
+            $sheet->setCellValue('C12', '');
+        }
+        // адрес
+        $sheet->setCellValue('L14', $order->object_address);
+        $str = Str::replace('<div>', '', $order->products_with_count);
+        $str = Str::replace('</div>', "\n", $str);
+
+        // мафы
+        $sheet->setCellValue('G33', Str::trim($str));
+
+        //
+        $fileName = 'Заявка на монтаж - ' . $order->object_address . '.xlsx';
+        $writer = new Xlsx($spreadsheet);
+        Storage::disk('public')->makeDirectory('orders/' . $order->id . '/tmp');
+
+        $writer->save(storage_path('app/public/orders/') . $order->id .'/tmp/' . $fileName);
+    }
 }

+ 28 - 0
database/migrations/2025_04_27_201914_add_fields_to_responsibles_table.php

@@ -0,0 +1,28 @@
+<?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::table('responsibles', function (Blueprint $table) {
+            $table->string('post')->nullable();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::table('responsibles', function (Blueprint $table) {
+            $table->dropColumn('post');
+        });
+    }
+};

+ 29 - 0
database/migrations/2025_04_27_202322_add_fields_to_products_table.php

@@ -0,0 +1,29 @@
+<?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::table('products', function (Blueprint $table) {
+            $table->string('passport_name')->nullable()->after('note');
+            $table->string('statement_name')->nullable()->after('passport_name');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::table('products', function (Blueprint $table) {
+            $table->dropColumn(['passport_name', 'statement_name']);
+        });
+    }
+};

+ 2 - 0
resources/views/catalog/edit.blade.php

@@ -35,6 +35,8 @@
                         @include('partials.input', ['name' => 'product_price', 'type' => 'number', 'title' => 'Цена товара', 'required' => true, 'value' => $product->product_price ?? ''])
                         @include('partials.input', ['name' => 'installation_price', 'type' => 'number', 'title' => 'Цена установки', 'required' => true, 'value' => $product->installation_price ?? ''])
                         @include('partials.input', ['name' => 'total_price', 'type' => 'number', 'title' => 'Итоговая цена', 'required' => true, 'value' => $product->total_price ?? ''])
+                        @include('partials.input', ['name' => 'passport_name', 'title' => 'Наименование по паспорту', 'value' => $product->passport_name ?? ''])
+                        @include('partials.input', ['name' => 'statement_name', 'title' => 'Наименование в ведомости', 'value' => $product->statement_name ?? ''])
 
                     </div>
                     <div class="col-xl-6">

+ 1 - 0
resources/views/responsibles/edit.blade.php

@@ -12,6 +12,7 @@
                 @include('partials.select', ['name' => 'area_id', 'title' => 'Район', 'options' => $areas, 'value' => $responsible->area?->id])
                 @include('partials.input', ['name' => 'name', 'title' => 'ФИО', 'required' => true, 'value' => $responsible->name])
                 @include('partials.input', ['name' => 'phone', 'title' => 'Телефон', 'required' => true, 'value' => $responsible->phone])
+                @include('partials.input', ['name' => 'post', 'title' => 'Должность', 'value' => $responsible->post])
 
                 @include('partials.submit', ['name' => 'Сохранить', 'delete' => ['form_id' => 'destroy', 'title' => 'Удалить']])
             </div>