Alexander Musikhin 3 дней назад
Родитель
Сommit
a1c5c86e07

+ 60 - 0
.env.testing

@@ -0,0 +1,60 @@
+# common settings
+COMPOSE_PROJECT_NAME=strprfcrm
+COMPOSE_PROFILES=local
+
+# Set external ports
+APP_ADDR=http://127.0.0.1
+WEB_PORT=8090
+# external port of DB for connect by other soft
+DB_EXT_PORT=3306
+WS_PORT=3090
+WS_ADDR=/ws
+WS_DEBUG_PORT=9229
+MINIO_DEBUG_PORT=39757
+FORCE_HTTPS=false
+
+APP_NAME="Stroyprofit CRM"
+APP_ENV=local
+APP_KEY=base64:nIrpAXvd/2pEWdtUMQXuf6xdF1C+p7e6bErjt1hMIMk=
+APP_DEBUG=true
+APP_URL=${APP_ADDR}
+APP_LOCALE=ru
+APP_TIMEZONE=Europe/Moscow
+
+LOG_CHANNEL=stack
+LOG_DEPRECATIONS_CHANNEL=null
+LOG_LEVEL=debug
+
+DB_CONNECTION=mysql
+DB_HOST=db
+DB_PORT=3306
+DB_DATABASE=crm_testing
+DB_USERNAME=dbuser
+DB_PASSWORD=password
+
+BROADCAST_DRIVER=redis
+CACHE_DRIVER=redis
+FILESYSTEM_DISK=local
+QUEUE_CONNECTION=redis
+SESSION_DRIVER=file
+SESSION_LIFETIME=120
+
+REDIS_CLIENT=predis
+REDIS_HOST=redis
+REDIS_PASSWORD=sOmE_sEcUrE_pAsS
+REDIS_PORT=6379
+
+JWT_SECRET=c05c4346dc03362dabbf94c18a1befe78e9b301837f3163e43a57201d9cc09cb
+
+# Default pagination limit
+PAGINATION_LIMIT=2000
+
+WORDS_IN_TABLE_CELL_LIMIT=15
+
+# FCM settings
+FCM_PROJECT_ID=
+FCM_CLIENT_EMAIL=
+FCM_PRIVATE_KEY=
+
+# id Artemenko Denis
+APP_DEFAULT_MAF_ORDER_USER_ID=1

+ 2 - 2
database/migrations/2026_01_24_200000_create_inventory_movements_table.php

@@ -66,8 +66,8 @@ return new class extends Migration
             $table->timestamps();
 
             // Индексы для быстрого расчёта остатков
-            $table->index(['spare_part_id', 'movement_type', 'with_documents']);
-            $table->index(['spare_part_order_id', 'movement_type']);
+            $table->index(['spare_part_id', 'movement_type', 'with_documents'], 'inv_mov_part_type_docs_idx');
+            $table->index(['spare_part_order_id', 'movement_type'], 'inv_mov_order_type_idx');
             $table->index(['source_type', 'source_id']);
             $table->index('created_at');
         });

+ 41 - 25
database/migrations/2026_01_24_200003_refactor_spare_part_orders_table.php

@@ -43,27 +43,27 @@ return new class extends Migration
         }
 
         // 4. Обновляем индекс
-        Schema::table('spare_part_orders', function (Blueprint $table) {
-            // Отключаем проверку внешних ключей
-            DB::statement('SET FOREIGN_KEY_CHECKS=0');
-
-            // Удаляем старый индекс если существует
-            $indexName = 'spare_part_orders_spare_part_id_status_remaining_quantity_index';
-            $indexes = DB::select("SHOW INDEX FROM spare_part_orders WHERE Key_name = ?", [$indexName]);
-            if (!empty($indexes)) {
-                $table->dropIndex($indexName);
-            }
-
-            // Проверяем, есть ли уже новый индекс
-            $newIndexName = 'spare_part_orders_spare_part_id_status_available_qty_index';
-            $newIndexes = DB::select("SHOW INDEX FROM spare_part_orders WHERE Key_name = ?", [$newIndexName]);
-            if (empty($newIndexes)) {
-                $table->index(['spare_part_id', 'status', 'available_qty']);
-            }
-
-            // Включаем обратно
-            DB::statement('SET FOREIGN_KEY_CHECKS=1');
-        });
+        // Отключаем проверку внешних ключей ДО изменения схемы
+        DB::statement('SET FOREIGN_KEY_CHECKS=0');
+
+        // Проверяем, есть ли уже новый индекс
+        $newIndexName = 'spo_part_status_avail_idx';
+        $newIndexes = DB::select("SHOW INDEX FROM spare_part_orders WHERE Key_name = ?", [$newIndexName]);
+
+        if (empty($newIndexes)) {
+            // Создаём новый индекс с коротким именем
+            DB::statement('CREATE INDEX spo_part_status_avail_idx ON spare_part_orders (spare_part_id, status, available_qty)');
+        }
+
+        // Удаляем старый индекс если существует
+        $oldIndexName = 'spare_part_orders_spare_part_id_status_remaining_quantity_index';
+        $oldIndexes = DB::select("SHOW INDEX FROM spare_part_orders WHERE Key_name = ?", [$oldIndexName]);
+        if (!empty($oldIndexes)) {
+            DB::statement("DROP INDEX `{$oldIndexName}` ON spare_part_orders");
+        }
+
+        // Включаем обратно
+        DB::statement('SET FOREIGN_KEY_CHECKS=1');
     }
 
     /**
@@ -71,13 +71,29 @@ return new class extends Migration
      */
     public function down(): void
     {
-        // Убираем constraint
-        DB::statement('ALTER TABLE spare_part_orders DROP CONSTRAINT IF EXISTS chk_available_qty_non_negative');
+        // Убираем constraint (MySQL не поддерживает DROP CONSTRAINT IF EXISTS)
+        try {
+            DB::statement('ALTER TABLE spare_part_orders DROP CHECK chk_available_qty_non_negative');
+        } catch (\Exception $e) {
+            // Constraint не существует, продолжаем
+        }
+
+        DB::statement('SET FOREIGN_KEY_CHECKS=0');
 
+        // Переименовываем колонку
         Schema::table('spare_part_orders', function (Blueprint $table) {
-            $table->dropIndex(['spare_part_id', 'status', 'available_qty']);
             $table->renameColumn('available_qty', 'remaining_quantity');
-            $table->index(['spare_part_id', 'status', 'remaining_quantity']);
         });
+
+        // Создаём старый индекс
+        DB::statement('CREATE INDEX spare_part_orders_spare_part_id_status_remaining_quantity_index ON spare_part_orders (spare_part_id, status, remaining_quantity)');
+
+        // Удаляем новый индекс
+        $newIndexes = DB::select("SHOW INDEX FROM spare_part_orders WHERE Key_name = 'spo_part_status_avail_idx'");
+        if (!empty($newIndexes)) {
+            DB::statement('DROP INDEX spo_part_status_avail_idx ON spare_part_orders');
+        }
+
+        DB::statement('SET FOREIGN_KEY_CHECKS=1');
     }
 };

+ 1 - 0
docker-compose.yml

@@ -99,6 +99,7 @@ services:
         volumes:
             - ./docker/mysql/my.cnf:/etc/my.cnf
             - ./docker/database:/var/lib/mysql:delegated
+            - ./docker/mysql/init:/docker-entrypoint-initdb.d
         networks:
             - str-network
         ports:

+ 12 - 0
docker/mysql/init/01-create-databases.sql

@@ -0,0 +1,12 @@
+CREATE DATABASE IF NOT EXISTS crm
+    CHARACTER SET utf8mb4
+    COLLATE utf8mb4_unicode_ci;
+
+CREATE DATABASE IF NOT EXISTS crm_testing
+    CHARACTER SET utf8mb4
+    COLLATE utf8mb4_unicode_ci;
+
+GRANT ALL PRIVILEGES ON crm.* TO 'dbuser'@'%';
+GRANT ALL PRIVILEGES ON crm_testing.* TO 'dbuser'@'%';
+
+FLUSH PRIVILEGES;