Bläddra i källkod

chore: added automated migration system for CI/CD

unknown 22 timmar sedan
förälder
incheckning
0c44e3c775

+ 17 - 0
backend/migrations/001_warehouse.sql

@@ -0,0 +1,17 @@
+-- Migration: 001_warehouse
+-- Created: 2026-04-19
+-- Description: Create warehouse_stock table
+
+CREATE TABLE IF NOT EXISTS `warehouse_stock` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `material_id` int(11) NOT NULL,
+  `color_name` varchar(100) NOT NULL,
+  `quantity` decimal(10,2) DEFAULT 0.00,
+  `notes` text DEFAULT NULL,
+  `is_active` tinyint(1) DEFAULT 1,
+  `created_at` timestamp NULL DEFAULT current_timestamp(),
+  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
+  PRIMARY KEY (`id`),
+  KEY `material_id` (`material_id`),
+  CONSTRAINT `fk_warehouse_material` FOREIGN KEY (`material_id`) REFERENCES `materials` (`id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

+ 64 - 0
backend/run_migrations.py

@@ -0,0 +1,64 @@
+import os
+import db
+import sys
+
+# Ensure backend dir is in path
+sys.path.append(os.path.dirname(os.path.abspath(__file__)))
+
+MIGRATIONS_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "migrations")
+
+def init_migrations_table():
+    query = """
+    CREATE TABLE IF NOT EXISTS `schema_migrations` (
+        `id` int(11) NOT NULL AUTO_INCREMENT,
+        `migration_name` varchar(255) NOT NULL,
+        `applied_at` timestamp DEFAULT CURRENT_TIMESTAMP,
+        PRIMARY KEY (`id`),
+        UNIQUE KEY `migration_name` (`migration_name`)
+    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+    """
+    db.execute_commit(query)
+
+def get_applied_migrations():
+    rows = db.execute_query("SELECT migration_name FROM schema_migrations")
+    return [r['migration_name'] for r in rows]
+
+def run_migrations():
+    print(f"Checking for migrations in {MIGRATIONS_DIR}...")
+    init_migrations_table()
+    applied = get_applied_migrations()
+    
+    # Get all .sql files from migrations dir
+    files = [f for f in os.listdir(MIGRATIONS_DIR) if f.endswith(".sql")]
+    files.sort() # Ensure they run in order (001, 002...)
+
+    count = 0
+    for filename in files:
+        if filename not in applied:
+            print(f"Applying migration: {filename}...")
+            filepath = os.path.join(MIGRATIONS_DIR, filename)
+            with open(filepath, "r", encoding="utf-8") as f:
+                sql = f.read()
+                
+            # Execute the migration (handling potential multiple statements)
+            # Simple splitter by semicolon (works for basic schemas)
+            statements = [s.strip() for s in sql.split(";") if s.strip()]
+            for stmt in statements:
+                db.execute_commit(stmt)
+            
+            # Mark as applied
+            db.execute_commit("INSERT INTO schema_migrations (migration_name) VALUES (%s)", (filename,))
+            print(f"Successfully applied {filename}")
+            count += 1
+            
+    if count == 0:
+        print("No new migrations to apply.")
+    else:
+        print(f"Applied {count} migrations.")
+
+if __name__ == "__main__":
+    try:
+        run_migrations()
+    except Exception as e:
+        print(f"MIGRATION ERROR: {e}")
+        sys.exit(1)

+ 6 - 0
backend/scratch/check_db.py

@@ -0,0 +1,6 @@
+import db
+try:
+    res = db.execute_query('SHOW TABLES LIKE "warehouse_stock"')
+    print(f"RESULT: {res}")
+except Exception as e:
+    print(f"ERROR: {e}")

+ 21 - 0
backend/scratch/migrate_db.py

@@ -0,0 +1,21 @@
+import db
+query = """
+CREATE TABLE IF NOT EXISTS `warehouse_stock` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `material_id` int(11) NOT NULL,
+  `color_name` varchar(100) NOT NULL,
+  `quantity` decimal(10,2) DEFAULT 0.00,
+  `notes` text DEFAULT NULL,
+  `is_active` tinyint(1) DEFAULT 1,
+  `created_at` timestamp NULL DEFAULT current_timestamp(),
+  `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
+  PRIMARY KEY (`id`),
+  KEY `material_id` (`material_id`),
+  CONSTRAINT `fk_warehouse_material` FOREIGN KEY (`material_id`) REFERENCES `materials` (`id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
+"""
+try:
+    db.execute_commit(query)
+    print("TABLE CREATED SUCCESSFULLY")
+except Exception as e:
+    print(f"ERROR: {e}")

+ 2 - 0
server_update.sh

@@ -22,6 +22,8 @@ bash build_frontend.sh
 # 3. Обновляем бэкенд
 echo "updating backend..."
 ./backend/venv/bin/pip install -r backend/requirements.txt
+echo "running database migrations..."
+./backend/venv/bin/python3 backend/run_migrations.py
 
 # 4. Перезапуск
 echo "restarting services..."

+ 1 - 0
src/pages/Admin.vue

@@ -350,6 +350,7 @@ import PostsSection from "@/components/admin/PostsSection.vue";
 import PortfolioSection from "@/components/admin/PortfolioSection.vue";
 import AuditSection from "@/components/admin/AuditSection.vue";
 import ReviewsSection from "@/components/admin/ReviewsSection.vue";
+import WarehouseSection from "@/components/admin/WarehouseSection.vue";
 
 // API & Stores
 import { useAuthStore } from "@/stores/auth";