diff --git a/backend/migrations/add_admin_restricted_pages.py b/backend/migrations/add_admin_restricted_pages.py index 730f72d..eb933a9 100644 --- a/backend/migrations/add_admin_restricted_pages.py +++ b/backend/migrations/add_admin_restricted_pages.py @@ -16,7 +16,7 @@ async def run_migration(): """Add admin_restricted_pages column to kitchen_settings table.""" logger.info("Running admin restricted pages migration...") - sql = "ALTER TABLE kitchen_settings ADD COLUMN admin_restricted_pages TEXT" + sql = "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS admin_restricted_pages TEXT" try: async with engine.begin() as conn: diff --git a/backend/migrations/add_budget_settings.py b/backend/migrations/add_budget_settings.py index 5764cef..dc94860 100644 --- a/backend/migrations/add_budget_settings.py +++ b/backend/migrations/add_budget_settings.py @@ -19,7 +19,7 @@ async def migrate(): await conn.execute(text( """ ALTER TABLE kitchen_settings - ADD COLUMN forecast_api_url VARCHAR(500) + ADD COLUMN IF NOT EXISTS forecast_api_url VARCHAR(500) """ )) print("+ Added forecast_api_url column") @@ -34,7 +34,7 @@ async def migrate(): await conn.execute(text( """ ALTER TABLE kitchen_settings - ADD COLUMN forecast_api_key VARCHAR(500) + ADD COLUMN IF NOT EXISTS forecast_api_key VARCHAR(500) """ )) print("+ Added forecast_api_key column") @@ -49,7 +49,7 @@ async def migrate(): await conn.execute(text( """ ALTER TABLE kitchen_settings - ADD COLUMN budget_gp_target NUMERIC(5,2) DEFAULT 65.00 + ADD COLUMN IF NOT EXISTS budget_gp_target NUMERIC(5,2) DEFAULT 65.00 """ )) print("+ Added budget_gp_target column") @@ -64,7 +64,7 @@ async def migrate(): await conn.execute(text( """ ALTER TABLE kitchen_settings - ADD COLUMN budget_lookback_weeks INTEGER DEFAULT 4 + ADD COLUMN IF NOT EXISTS budget_lookback_weeks INTEGER DEFAULT 4 """ )) print("+ Added budget_lookback_weeks column") diff --git a/backend/migrations/add_cost_distributions.py b/backend/migrations/add_cost_distributions.py index 720283a..a38ce18 100644 --- a/backend/migrations/add_cost_distributions.py +++ b/backend/migrations/add_cost_distributions.py @@ -112,7 +112,7 @@ async def migrate(): # Add cost_distribution_max_days to kitchen_settings try: await conn.execute(text( - "ALTER TABLE kitchen_settings ADD COLUMN cost_distribution_max_days INTEGER DEFAULT 90" + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS cost_distribution_max_days INTEGER DEFAULT 90" )) print("+ Added cost_distribution_max_days to kitchen_settings") except Exception as e: diff --git a/backend/migrations/add_dext_integration.py b/backend/migrations/add_dext_integration.py index 99f2a21..af5ef8d 100644 --- a/backend/migrations/add_dext_integration.py +++ b/backend/migrations/add_dext_integration.py @@ -26,7 +26,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE invoices ADD COLUMN notes TEXT" + "ALTER TABLE invoices ADD COLUMN IF NOT EXISTS notes TEXT" )) logger.info("Added notes column to invoices") except Exception as e: @@ -39,7 +39,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE invoices ADD COLUMN dext_sent_at TIMESTAMP" + "ALTER TABLE invoices ADD COLUMN IF NOT EXISTS dext_sent_at TIMESTAMP" )) logger.info("Added dext_sent_at column to invoices") except Exception as e: @@ -52,7 +52,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE invoices ADD COLUMN dext_sent_by_user_id INTEGER REFERENCES users(id)" + "ALTER TABLE invoices ADD COLUMN IF NOT EXISTS dext_sent_by_user_id INTEGER REFERENCES users(id)" )) logger.info("Added dext_sent_by_user_id column to invoices") except Exception as e: @@ -67,7 +67,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE kitchen_settings ADD COLUMN smtp_host VARCHAR(255)" + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS smtp_host VARCHAR(255)" )) logger.info("Added smtp_host column to kitchen_settings") except Exception as e: @@ -80,7 +80,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE kitchen_settings ADD COLUMN smtp_port INTEGER DEFAULT 587" + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS smtp_port INTEGER DEFAULT 587" )) logger.info("Added smtp_port column to kitchen_settings") except Exception as e: @@ -93,7 +93,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE kitchen_settings ADD COLUMN smtp_username VARCHAR(255)" + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS smtp_username VARCHAR(255)" )) logger.info("Added smtp_username column to kitchen_settings") except Exception as e: @@ -106,7 +106,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE kitchen_settings ADD COLUMN smtp_password VARCHAR(500)" + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS smtp_password VARCHAR(500)" )) logger.info("Added smtp_password column to kitchen_settings") except Exception as e: @@ -119,7 +119,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE kitchen_settings ADD COLUMN smtp_use_tls BOOLEAN DEFAULT TRUE" + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS smtp_use_tls BOOLEAN DEFAULT TRUE" )) logger.info("Added smtp_use_tls column to kitchen_settings") except Exception as e: @@ -132,7 +132,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE kitchen_settings ADD COLUMN smtp_from_email VARCHAR(255)" + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS smtp_from_email VARCHAR(255)" )) logger.info("Added smtp_from_email column to kitchen_settings") except Exception as e: @@ -145,7 +145,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE kitchen_settings ADD COLUMN smtp_from_name VARCHAR(255) DEFAULT 'Kitchen Invoice System'" + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS smtp_from_name VARCHAR(255) DEFAULT 'Kitchen Invoice System'" )) logger.info("Added smtp_from_name column to kitchen_settings") except Exception as e: @@ -160,7 +160,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE kitchen_settings ADD COLUMN dext_email VARCHAR(255)" + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS dext_email VARCHAR(255)" )) logger.info("Added dext_email column to kitchen_settings") except Exception as e: @@ -173,7 +173,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE kitchen_settings ADD COLUMN dext_include_notes BOOLEAN DEFAULT TRUE" + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS dext_include_notes BOOLEAN DEFAULT TRUE" )) logger.info("Added dext_include_notes column to kitchen_settings") except Exception as e: @@ -186,7 +186,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE kitchen_settings ADD COLUMN dext_include_non_stock BOOLEAN DEFAULT TRUE" + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS dext_include_non_stock BOOLEAN DEFAULT TRUE" )) logger.info("Added dext_include_non_stock column to kitchen_settings") except Exception as e: @@ -199,7 +199,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE kitchen_settings ADD COLUMN dext_auto_send_enabled BOOLEAN DEFAULT FALSE" + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS dext_auto_send_enabled BOOLEAN DEFAULT FALSE" )) logger.info("Added dext_auto_send_enabled column to kitchen_settings") except Exception as e: diff --git a/backend/migrations/add_dext_manual_send.py b/backend/migrations/add_dext_manual_send.py index 76f3e74..3f9d1e0 100644 --- a/backend/migrations/add_dext_manual_send.py +++ b/backend/migrations/add_dext_manual_send.py @@ -13,7 +13,7 @@ async def migrate(): await conn.execute(text( """ ALTER TABLE kitchen_settings - ADD COLUMN dext_manual_send_enabled BOOLEAN DEFAULT TRUE + ADD COLUMN IF NOT EXISTS dext_manual_send_enabled BOOLEAN DEFAULT TRUE """ )) print("✓ Added dext_manual_send_enabled column") diff --git a/backend/migrations/add_dispute_attachment_public_hash.py b/backend/migrations/add_dispute_attachment_public_hash.py index ba46bb3..e1ccf86 100644 --- a/backend/migrations/add_dispute_attachment_public_hash.py +++ b/backend/migrations/add_dispute_attachment_public_hash.py @@ -28,7 +28,7 @@ async def run_migration(): logger.info("Adding 'public_hash' column to dispute_attachments table") await conn.execute(text(""" ALTER TABLE dispute_attachments - ADD COLUMN public_hash VARCHAR(64) UNIQUE; + ADD COLUMN IF NOT EXISTS public_hash VARCHAR(64) UNIQUE; """)) # Create index for fast lookups diff --git a/backend/migrations/add_gross_sell_price.py b/backend/migrations/add_gross_sell_price.py index ae8f4bd..19e88d9 100644 --- a/backend/migrations/add_gross_sell_price.py +++ b/backend/migrations/add_gross_sell_price.py @@ -1,22 +1,22 @@ -"""Add gross_sell_price column to recipes table.""" -import logging -from sqlalchemy import text -from database import engine - -logger = logging.getLogger(__name__) - - -async def migrate(): - async with engine.begin() as conn: - result = await conn.execute(text( - "SELECT column_name FROM information_schema.columns " - "WHERE table_name = 'recipes' AND column_name = 'gross_sell_price'" - )) - if result.scalar_one_or_none(): - logger.info("recipes.gross_sell_price already exists, skipping") - return - - await conn.execute(text( - "ALTER TABLE recipes ADD COLUMN gross_sell_price NUMERIC(10,2) DEFAULT NULL" - )) - logger.info("Added recipes.gross_sell_price column") +"""Add gross_sell_price column to recipes table.""" +import logging +from sqlalchemy import text +from database import engine + +logger = logging.getLogger(__name__) + + +async def migrate(): + async with engine.begin() as conn: + result = await conn.execute(text( + "SELECT column_name FROM information_schema.columns " + "WHERE table_name = 'recipes' AND column_name = 'gross_sell_price'" + )) + if result.scalar_one_or_none(): + logger.info("recipes.gross_sell_price already exists, skipping") + return + + await conn.execute(text( + "ALTER TABLE recipes ADD COLUMN IF NOT EXISTS gross_sell_price NUMERIC(10,2) DEFAULT NULL" + )) + logger.info("Added recipes.gross_sell_price column") diff --git a/backend/migrations/add_invoice_features.py b/backend/migrations/add_invoice_features.py index 9c643ff..4496584 100644 --- a/backend/migrations/add_invoice_features.py +++ b/backend/migrations/add_invoice_features.py @@ -22,11 +22,11 @@ async def run_migration(): # Run each migration in its own transaction migrations = [ - "ALTER TABLE invoices ADD COLUMN document_type VARCHAR(50) DEFAULT 'invoice'", - "ALTER TABLE invoices ADD COLUMN order_number VARCHAR(100)", - "ALTER TABLE invoices ADD COLUMN duplicate_status VARCHAR(50)", - "ALTER TABLE invoices ADD COLUMN duplicate_of_id INTEGER REFERENCES invoices(id)", - "ALTER TABLE invoices ADD COLUMN related_document_id INTEGER REFERENCES invoices(id)", + "ALTER TABLE invoices ADD COLUMN IF NOT EXISTS document_type VARCHAR(50) DEFAULT 'invoice'", + "ALTER TABLE invoices ADD COLUMN IF NOT EXISTS order_number VARCHAR(100)", + "ALTER TABLE invoices ADD COLUMN IF NOT EXISTS duplicate_status VARCHAR(50)", + "ALTER TABLE invoices ADD COLUMN IF NOT EXISTS duplicate_of_id INTEGER REFERENCES invoices(id)", + "ALTER TABLE invoices ADD COLUMN IF NOT EXISTS related_document_id INTEGER REFERENCES invoices(id)", ] for sql in migrations: @@ -76,7 +76,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE suppliers ADD COLUMN aliases JSON DEFAULT '[]'" + "ALTER TABLE suppliers ADD COLUMN IF NOT EXISTS aliases JSON DEFAULT '[]'" )) logger.info("Added aliases column to suppliers") except Exception as e: @@ -89,7 +89,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE invoices ADD COLUMN net_total NUMERIC(10, 2)" + "ALTER TABLE invoices ADD COLUMN IF NOT EXISTS net_total NUMERIC(10, 2)" )) logger.info("Added net_total column to invoices") except Exception as e: @@ -102,7 +102,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE line_items ADD COLUMN is_non_stock BOOLEAN DEFAULT FALSE" + "ALTER TABLE line_items ADD COLUMN IF NOT EXISTS is_non_stock BOOLEAN DEFAULT FALSE" )) logger.info("Added is_non_stock column to line_items") except Exception as e: @@ -115,7 +115,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE invoices ADD COLUMN vendor_name VARCHAR(255)" + "ALTER TABLE invoices ADD COLUMN IF NOT EXISTS vendor_name VARCHAR(255)" )) logger.info("Added vendor_name column to invoices") except Exception as e: @@ -128,7 +128,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE invoices ADD COLUMN ocr_raw_json TEXT" + "ALTER TABLE invoices ADD COLUMN IF NOT EXISTS ocr_raw_json TEXT" )) logger.info("Added ocr_raw_json column to invoices") except Exception as e: @@ -141,7 +141,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE invoices ADD COLUMN supplier_match_type VARCHAR(20)" + "ALTER TABLE invoices ADD COLUMN IF NOT EXISTS supplier_match_type VARCHAR(20)" )) logger.info("Added supplier_match_type column to invoices") except Exception as e: @@ -189,7 +189,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE line_items ADD COLUMN unit VARCHAR(50)" + "ALTER TABLE line_items ADD COLUMN IF NOT EXISTS unit VARCHAR(50)" )) logger.info("Added unit column to line_items") except Exception as e: @@ -202,7 +202,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE line_items ADD COLUMN order_quantity NUMERIC(10, 3)" + "ALTER TABLE line_items ADD COLUMN IF NOT EXISTS order_quantity NUMERIC(10, 3)" )) logger.info("Added order_quantity column to line_items") except Exception as e: @@ -215,7 +215,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE line_items ADD COLUMN tax_rate VARCHAR(50)" + "ALTER TABLE line_items ADD COLUMN IF NOT EXISTS tax_rate VARCHAR(50)" )) logger.info("Added tax_rate column to line_items") except Exception as e: @@ -228,7 +228,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE line_items ADD COLUMN tax_amount NUMERIC(10, 2)" + "ALTER TABLE line_items ADD COLUMN IF NOT EXISTS tax_amount NUMERIC(10, 2)" )) logger.info("Added tax_amount column to line_items") except Exception as e: @@ -241,7 +241,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE line_items ADD COLUMN raw_content TEXT" + "ALTER TABLE line_items ADD COLUMN IF NOT EXISTS raw_content TEXT" )) logger.info("Added raw_content column to line_items") except Exception as e: @@ -254,7 +254,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE line_items ADD COLUMN pack_quantity INTEGER" + "ALTER TABLE line_items ADD COLUMN IF NOT EXISTS pack_quantity INTEGER" )) logger.info("Added pack_quantity column to line_items") except Exception as e: @@ -267,7 +267,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE line_items ADD COLUMN unit_size NUMERIC(10, 3)" + "ALTER TABLE line_items ADD COLUMN IF NOT EXISTS unit_size NUMERIC(10, 3)" )) logger.info("Added unit_size column to line_items") except Exception as e: @@ -280,7 +280,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE line_items ADD COLUMN unit_size_type VARCHAR(10)" + "ALTER TABLE line_items ADD COLUMN IF NOT EXISTS unit_size_type VARCHAR(10)" )) logger.info("Added unit_size_type column to line_items") except Exception as e: @@ -293,7 +293,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE line_items ADD COLUMN portions_per_unit INTEGER DEFAULT 1" + "ALTER TABLE line_items ADD COLUMN IF NOT EXISTS portions_per_unit INTEGER DEFAULT 1" )) logger.info("Added portions_per_unit column to line_items") except Exception as e: @@ -306,7 +306,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE line_items ADD COLUMN cost_per_item NUMERIC(10, 4)" + "ALTER TABLE line_items ADD COLUMN IF NOT EXISTS cost_per_item NUMERIC(10, 4)" )) logger.info("Added cost_per_item column to line_items") except Exception as e: @@ -319,7 +319,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE line_items ADD COLUMN cost_per_portion NUMERIC(10, 4)" + "ALTER TABLE line_items ADD COLUMN IF NOT EXISTS cost_per_portion NUMERIC(10, 4)" )) logger.info("Added cost_per_portion column to line_items") except Exception as e: @@ -384,7 +384,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE product_definitions ADD COLUMN saved_by_user_id INTEGER REFERENCES users(id)" + "ALTER TABLE product_definitions ADD COLUMN IF NOT EXISTS saved_by_user_id INTEGER REFERENCES users(id)" )) logger.info("Added saved_by_user_id column to product_definitions") except Exception as e: @@ -397,7 +397,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE product_definitions ADD COLUMN source_invoice_id INTEGER REFERENCES invoices(id) ON DELETE SET NULL" + "ALTER TABLE product_definitions ADD COLUMN IF NOT EXISTS source_invoice_id INTEGER REFERENCES invoices(id) ON DELETE SET NULL" )) logger.info("Added source_invoice_id column to product_definitions") except Exception as e: @@ -410,7 +410,7 @@ async def run_migration(): try: async with engine.begin() as conn: await conn.execute(text( - "ALTER TABLE product_definitions ADD COLUMN source_invoice_number VARCHAR(100)" + "ALTER TABLE product_definitions ADD COLUMN IF NOT EXISTS source_invoice_number VARCHAR(100)" )) logger.info("Added source_invoice_number column to product_definitions") except Exception as e: diff --git a/backend/migrations/add_kitchen_details.py b/backend/migrations/add_kitchen_details.py index bf58c38..f93518a 100644 --- a/backend/migrations/add_kitchen_details.py +++ b/backend/migrations/add_kitchen_details.py @@ -23,7 +23,7 @@ async def migrate(): for col_name, col_type in COLUMNS: try: await conn.execute(text( - f"ALTER TABLE kitchen_settings ADD COLUMN {col_name} {col_type}" + f"ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS {col_name} {col_type}" )) print(f"+ Added {col_name} column to kitchen_settings") except Exception as e: diff --git a/backend/migrations/add_newbook_arrival_tracking.py b/backend/migrations/add_newbook_arrival_tracking.py index 861d5e1..e6406d9 100644 --- a/backend/migrations/add_newbook_arrival_tracking.py +++ b/backend/migrations/add_newbook_arrival_tracking.py @@ -26,9 +26,9 @@ async def run_migration(): # Add arrival tracking columns to newbook_daily_occupancy table arrival_columns = [ - "ALTER TABLE newbook_daily_occupancy ADD COLUMN arrival_count INTEGER", - "ALTER TABLE newbook_daily_occupancy ADD COLUMN arrival_booking_ids JSONB", - "ALTER TABLE newbook_daily_occupancy ADD COLUMN arrival_booking_details JSONB", + "ALTER TABLE newbook_daily_occupancy ADD COLUMN IF NOT EXISTS arrival_count INTEGER", + "ALTER TABLE newbook_daily_occupancy ADD COLUMN IF NOT EXISTS arrival_booking_ids JSONB", + "ALTER TABLE newbook_daily_occupancy ADD COLUMN IF NOT EXISTS arrival_booking_details JSONB", ] for sql in arrival_columns: diff --git a/backend/migrations/add_newbook_tables.py b/backend/migrations/add_newbook_tables.py index b5bbdda..59f7aae 100644 --- a/backend/migrations/add_newbook_tables.py +++ b/backend/migrations/add_newbook_tables.py @@ -23,15 +23,15 @@ async def run_migration(): # Add Newbook columns to kitchen_settings table settings_columns = [ - "ALTER TABLE kitchen_settings ADD COLUMN newbook_api_username VARCHAR(255)", - "ALTER TABLE kitchen_settings ADD COLUMN newbook_api_password VARCHAR(500)", - "ALTER TABLE kitchen_settings ADD COLUMN newbook_api_key VARCHAR(500)", - "ALTER TABLE kitchen_settings ADD COLUMN newbook_api_region VARCHAR(10)", - "ALTER TABLE kitchen_settings ADD COLUMN newbook_instance_id VARCHAR(100)", - "ALTER TABLE kitchen_settings ADD COLUMN newbook_last_sync TIMESTAMP", - "ALTER TABLE kitchen_settings ADD COLUMN newbook_auto_sync_enabled BOOLEAN DEFAULT FALSE", - "ALTER TABLE kitchen_settings ADD COLUMN newbook_breakfast_gl_codes VARCHAR(500)", - "ALTER TABLE kitchen_settings ADD COLUMN newbook_dinner_gl_codes VARCHAR(500)", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS newbook_api_username VARCHAR(255)", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS newbook_api_password VARCHAR(500)", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS newbook_api_key VARCHAR(500)", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS newbook_api_region VARCHAR(10)", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS newbook_instance_id VARCHAR(100)", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS newbook_last_sync TIMESTAMP", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS newbook_auto_sync_enabled BOOLEAN DEFAULT FALSE", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS newbook_breakfast_gl_codes VARCHAR(500)", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS newbook_dinner_gl_codes VARCHAR(500)", ] for sql in settings_columns: @@ -163,7 +163,7 @@ async def run_migration(): # Add room_count column if it doesn't exist try: async with engine.begin() as conn: - await conn.execute(text("ALTER TABLE newbook_room_categories ADD COLUMN room_count INTEGER DEFAULT 0")) + await conn.execute(text("ALTER TABLE newbook_room_categories ADD COLUMN IF NOT EXISTS room_count INTEGER DEFAULT 0")) logger.info("Added room_count column to newbook_room_categories") except Exception as e: if "already exists" in str(e).lower() or "duplicate column" in str(e).lower(): diff --git a/backend/migrations/add_recipe_batch_type.py b/backend/migrations/add_recipe_batch_type.py index de35b95..85d7786 100644 --- a/backend/migrations/add_recipe_batch_type.py +++ b/backend/migrations/add_recipe_batch_type.py @@ -1,28 +1,28 @@ -"""Add batch_output_type, batch_yield_qty, batch_yield_unit to recipes table.""" -import logging -from sqlalchemy import text -from database import engine - -logger = logging.getLogger(__name__) - - -async def migrate(): - async with engine.begin() as conn: - result = await conn.execute(text( - "SELECT column_name FROM information_schema.columns " - "WHERE table_name = 'recipes' AND column_name = 'batch_output_type'" - )) - if result.scalar_one_or_none(): - logger.info("recipes.batch_output_type already exists, skipping") - return - - await conn.execute(text( - "ALTER TABLE recipes ADD COLUMN batch_output_type VARCHAR(20) NOT NULL DEFAULT 'portions'" - )) - await conn.execute(text( - "ALTER TABLE recipes ADD COLUMN batch_yield_qty NUMERIC(10,3) DEFAULT NULL" - )) - await conn.execute(text( - "ALTER TABLE recipes ADD COLUMN batch_yield_unit VARCHAR(10) DEFAULT NULL" - )) - logger.info("Added batch output type columns to recipes") +"""Add batch_output_type, batch_yield_qty, batch_yield_unit to recipes table.""" +import logging +from sqlalchemy import text +from database import engine + +logger = logging.getLogger(__name__) + + +async def migrate(): + async with engine.begin() as conn: + result = await conn.execute(text( + "SELECT column_name FROM information_schema.columns " + "WHERE table_name = 'recipes' AND column_name = 'batch_output_type'" + )) + if result.scalar_one_or_none(): + logger.info("recipes.batch_output_type already exists, skipping") + return + + await conn.execute(text( + "ALTER TABLE recipes ADD COLUMN IF NOT EXISTS batch_output_type VARCHAR(20) NOT NULL DEFAULT 'portions'" + )) + await conn.execute(text( + "ALTER TABLE recipes ADD COLUMN IF NOT EXISTS batch_yield_qty NUMERIC(10,3) DEFAULT NULL" + )) + await conn.execute(text( + "ALTER TABLE recipes ADD COLUMN IF NOT EXISTS batch_yield_unit VARCHAR(10) DEFAULT NULL" + )) + logger.info("Added batch output type columns to recipes") diff --git a/backend/migrations/add_recipe_ingredient_unit.py b/backend/migrations/add_recipe_ingredient_unit.py index 08b63d0..d490bd0 100644 --- a/backend/migrations/add_recipe_ingredient_unit.py +++ b/backend/migrations/add_recipe_ingredient_unit.py @@ -1,22 +1,22 @@ -"""Add unit column to recipe_ingredients table for display unit override.""" -import logging -from sqlalchemy import text -from database import engine - -logger = logging.getLogger(__name__) - - -async def migrate(): - async with engine.begin() as conn: - result = await conn.execute(text( - "SELECT column_name FROM information_schema.columns " - "WHERE table_name = 'recipe_ingredients' AND column_name = 'unit'" - )) - if result.scalar_one_or_none(): - logger.info("recipe_ingredients.unit already exists, skipping") - return - - await conn.execute(text( - "ALTER TABLE recipe_ingredients ADD COLUMN unit VARCHAR(10) DEFAULT NULL" - )) - logger.info("Added unit column to recipe_ingredients") +"""Add unit column to recipe_ingredients table for display unit override.""" +import logging +from sqlalchemy import text +from database import engine + +logger = logging.getLogger(__name__) + + +async def migrate(): + async with engine.begin() as conn: + result = await conn.execute(text( + "SELECT column_name FROM information_schema.columns " + "WHERE table_name = 'recipe_ingredients' AND column_name = 'unit'" + )) + if result.scalar_one_or_none(): + logger.info("recipe_ingredients.unit already exists, skipping") + return + + await conn.execute(text( + "ALTER TABLE recipe_ingredients ADD COLUMN IF NOT EXISTS unit VARCHAR(10) DEFAULT NULL" + )) + logger.info("Added unit column to recipe_ingredients") diff --git a/backend/migrations/add_recipe_ingredient_yield.py b/backend/migrations/add_recipe_ingredient_yield.py index bad5942..7e00797 100644 --- a/backend/migrations/add_recipe_ingredient_yield.py +++ b/backend/migrations/add_recipe_ingredient_yield.py @@ -1,33 +1,33 @@ -"""Move yield_percent from ingredients to recipe_ingredients (per-use yield).""" -import logging -from sqlalchemy import text -from database import engine - -logger = logging.getLogger(__name__) - - -async def migrate(): - async with engine.begin() as conn: - # Check if column already exists - result = await conn.execute(text( - "SELECT column_name FROM information_schema.columns " - "WHERE table_name = 'recipe_ingredients' AND column_name = 'yield_percent'" - )) - if result.scalar_one_or_none(): - logger.info("recipe_ingredients.yield_percent already exists, skipping") - return - - # Add yield_percent to recipe_ingredients with default 100 - await conn.execute(text( - "ALTER TABLE recipe_ingredients ADD COLUMN yield_percent NUMERIC(5,2) DEFAULT 100.00 NOT NULL" - )) - logger.info("Added recipe_ingredients.yield_percent column") - - # Populate from existing ingredient yields - await conn.execute(text( - "UPDATE recipe_ingredients ri " - "SET yield_percent = i.yield_percent " - "FROM ingredients i " - "WHERE ri.ingredient_id = i.id AND i.yield_percent != 100.00" - )) - logger.info("Populated recipe_ingredients.yield_percent from existing ingredient values") +"""Move yield_percent from ingredients to recipe_ingredients (per-use yield).""" +import logging +from sqlalchemy import text +from database import engine + +logger = logging.getLogger(__name__) + + +async def migrate(): + async with engine.begin() as conn: + # Check if column already exists + result = await conn.execute(text( + "SELECT column_name FROM information_schema.columns " + "WHERE table_name = 'recipe_ingredients' AND column_name = 'yield_percent'" + )) + if result.scalar_one_or_none(): + logger.info("recipe_ingredients.yield_percent already exists, skipping") + return + + # Add yield_percent to recipe_ingredients with default 100 + await conn.execute(text( + "ALTER TABLE recipe_ingredients ADD COLUMN IF NOT EXISTS yield_percent NUMERIC(5,2) DEFAULT 100.00 NOT NULL" + )) + logger.info("Added recipe_ingredients.yield_percent column") + + # Populate from existing ingredient yields + await conn.execute(text( + "UPDATE recipe_ingredients ri " + "SET yield_percent = i.yield_percent " + "FROM ingredients i " + "WHERE ri.ingredient_id = i.id AND i.yield_percent != 100.00" + )) + logger.info("Populated recipe_ingredients.yield_percent from existing ingredient values") diff --git a/backend/migrations/add_resos_arrival_widget_filter.py b/backend/migrations/add_resos_arrival_widget_filter.py index 7e163dc..ba3937f 100644 --- a/backend/migrations/add_resos_arrival_widget_filter.py +++ b/backend/migrations/add_resos_arrival_widget_filter.py @@ -24,7 +24,7 @@ async def run_migration(): logger.info("Running Resos arrival widget filter migration...") # Add arrival widget service filter column - sql = "ALTER TABLE kitchen_settings ADD COLUMN resos_arrival_widget_service_filter VARCHAR(255)" + sql = "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS resos_arrival_widget_service_filter VARCHAR(255)" try: async with engine.begin() as conn: diff --git a/backend/migrations/add_resos_integration.py b/backend/migrations/add_resos_integration.py index eb0df00..d621fb0 100644 --- a/backend/migrations/add_resos_integration.py +++ b/backend/migrations/add_resos_integration.py @@ -23,16 +23,16 @@ async def run_migration(): # Add Resos columns to kitchen_settings table settings_columns = [ - "ALTER TABLE kitchen_settings ADD COLUMN resos_api_key VARCHAR(500)", - "ALTER TABLE kitchen_settings ADD COLUMN resos_last_sync TIMESTAMP", - "ALTER TABLE kitchen_settings ADD COLUMN resos_auto_sync_enabled BOOLEAN DEFAULT FALSE", - "ALTER TABLE kitchen_settings ADD COLUMN resos_large_group_threshold INTEGER DEFAULT 8", - "ALTER TABLE kitchen_settings ADD COLUMN resos_note_keywords TEXT", - "ALTER TABLE kitchen_settings ADD COLUMN resos_allergy_keywords TEXT", - "ALTER TABLE kitchen_settings ADD COLUMN resos_custom_field_mapping JSONB", - "ALTER TABLE kitchen_settings ADD COLUMN resos_opening_hours_mapping JSONB", - "ALTER TABLE kitchen_settings ADD COLUMN resos_restaurant_table_entities TEXT", - "ALTER TABLE kitchen_settings ADD COLUMN resos_flag_icon_mapping JSONB", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS resos_api_key VARCHAR(500)", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS resos_last_sync TIMESTAMP", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS resos_auto_sync_enabled BOOLEAN DEFAULT FALSE", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS resos_large_group_threshold INTEGER DEFAULT 8", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS resos_note_keywords TEXT", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS resos_allergy_keywords TEXT", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS resos_custom_field_mapping JSONB", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS resos_opening_hours_mapping JSONB", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS resos_restaurant_table_entities TEXT", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS resos_flag_icon_mapping JSONB", ] for sql in settings_columns: @@ -154,7 +154,7 @@ async def run_migration(): # Add unique_flag_types column to resos_daily_stats if it doesn't exist try: async with engine.begin() as conn: - await conn.execute(text("ALTER TABLE resos_daily_stats ADD COLUMN unique_flag_types JSONB")) + await conn.execute(text("ALTER TABLE resos_daily_stats ADD COLUMN IF NOT EXISTS unique_flag_types JSONB")) logger.info("Added unique_flag_types column to resos_daily_stats") except Exception as e: if "already exists" in str(e).lower() or "duplicate column" in str(e).lower(): @@ -165,7 +165,7 @@ async def run_migration(): # Add table_name column to resos_bookings (Phase 8.1) try: async with engine.begin() as conn: - await conn.execute(text("ALTER TABLE resos_bookings ADD COLUMN table_name VARCHAR(100)")) + await conn.execute(text("ALTER TABLE resos_bookings ADD COLUMN IF NOT EXISTS table_name VARCHAR(100)")) logger.info("Added table_name column to resos_bookings") except Exception as e: if "already exists" in str(e).lower() or "duplicate column" in str(e).lower(): @@ -176,7 +176,7 @@ async def run_migration(): # Add GL code columns for food/beverage split (Phase 8.1) try: async with engine.begin() as conn: - await conn.execute(text("ALTER TABLE kitchen_settings ADD COLUMN sambapos_food_gl_codes TEXT")) + await conn.execute(text("ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS sambapos_food_gl_codes TEXT")) logger.info("Added sambapos_food_gl_codes column to kitchen_settings") except Exception as e: if "already exists" in str(e).lower() or "duplicate column" in str(e).lower(): @@ -186,7 +186,7 @@ async def run_migration(): try: async with engine.begin() as conn: - await conn.execute(text("ALTER TABLE kitchen_settings ADD COLUMN sambapos_beverage_gl_codes TEXT")) + await conn.execute(text("ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS sambapos_beverage_gl_codes TEXT")) logger.info("Added sambapos_beverage_gl_codes column to kitchen_settings") except Exception as e: if "already exists" in str(e).lower() or "duplicate column" in str(e).lower(): diff --git a/backend/migrations/add_resos_manual_breakfast.py b/backend/migrations/add_resos_manual_breakfast.py index da64f8f..a33cc10 100644 --- a/backend/migrations/add_resos_manual_breakfast.py +++ b/backend/migrations/add_resos_manual_breakfast.py @@ -27,8 +27,8 @@ async def run_migration(): logger.info("Running Resos manual breakfast configuration migration...") migrations = [ - "ALTER TABLE kitchen_settings ADD COLUMN resos_enable_manual_breakfast BOOLEAN DEFAULT FALSE", - "ALTER TABLE kitchen_settings ADD COLUMN resos_manual_breakfast_periods JSONB" + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS resos_enable_manual_breakfast BOOLEAN DEFAULT FALSE", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS resos_manual_breakfast_periods JSONB" ] async with engine.begin() as conn: diff --git a/backend/migrations/add_sambapos_excluded_items.py b/backend/migrations/add_sambapos_excluded_items.py index 599f13e..66b63b2 100644 --- a/backend/migrations/add_sambapos_excluded_items.py +++ b/backend/migrations/add_sambapos_excluded_items.py @@ -17,7 +17,7 @@ async def run_migration(): logger.info("Running SambaPOS excluded items migration...") # Add column for excluded items (TEXT to allow for many items with long names) - sql = "ALTER TABLE kitchen_settings ADD COLUMN sambapos_excluded_items TEXT" + sql = "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS sambapos_excluded_items TEXT" try: async with engine.begin() as conn: diff --git a/backend/migrations/add_sambapos_portion_name.py b/backend/migrations/add_sambapos_portion_name.py index 9d0202c..5de3b4f 100644 --- a/backend/migrations/add_sambapos_portion_name.py +++ b/backend/migrations/add_sambapos_portion_name.py @@ -1,22 +1,22 @@ -"""Add sambapos_portion_name column to recipes table.""" -import logging -from sqlalchemy import text -from database import engine - -logger = logging.getLogger(__name__) - - -async def migrate(): - async with engine.begin() as conn: - result = await conn.execute(text( - "SELECT column_name FROM information_schema.columns " - "WHERE table_name = 'recipes' AND column_name = 'sambapos_portion_name'" - )) - if result.scalar_one_or_none(): - logger.info("recipes.sambapos_portion_name already exists, skipping") - return - - await conn.execute(text( - "ALTER TABLE recipes ADD COLUMN sambapos_portion_name VARCHAR(255) DEFAULT NULL" - )) - logger.info("Added recipes.sambapos_portion_name column") +"""Add sambapos_portion_name column to recipes table.""" +import logging +from sqlalchemy import text +from database import engine + +logger = logging.getLogger(__name__) + + +async def migrate(): + async with engine.begin() as conn: + result = await conn.execute(text( + "SELECT column_name FROM information_schema.columns " + "WHERE table_name = 'recipes' AND column_name = 'sambapos_portion_name'" + )) + if result.scalar_one_or_none(): + logger.info("recipes.sambapos_portion_name already exists, skipping") + return + + await conn.execute(text( + "ALTER TABLE recipes ADD COLUMN IF NOT EXISTS sambapos_portion_name VARCHAR(255) DEFAULT NULL" + )) + logger.info("Added recipes.sambapos_portion_name column") diff --git a/backend/migrations/add_sambapos_settings.py b/backend/migrations/add_sambapos_settings.py index b8a3b2a..81a469f 100644 --- a/backend/migrations/add_sambapos_settings.py +++ b/backend/migrations/add_sambapos_settings.py @@ -18,12 +18,12 @@ async def run_migration(): # Add SambaPOS columns to kitchen_settings table settings_columns = [ - "ALTER TABLE kitchen_settings ADD COLUMN sambapos_db_host VARCHAR(255)", - "ALTER TABLE kitchen_settings ADD COLUMN sambapos_db_port INTEGER DEFAULT 1433", - "ALTER TABLE kitchen_settings ADD COLUMN sambapos_db_name VARCHAR(255)", - "ALTER TABLE kitchen_settings ADD COLUMN sambapos_db_username VARCHAR(255)", - "ALTER TABLE kitchen_settings ADD COLUMN sambapos_db_password VARCHAR(500)", - "ALTER TABLE kitchen_settings ADD COLUMN sambapos_tracked_categories VARCHAR(1000)", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS sambapos_db_host VARCHAR(255)", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS sambapos_db_port INTEGER DEFAULT 1433", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS sambapos_db_name VARCHAR(255)", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS sambapos_db_username VARCHAR(255)", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS sambapos_db_password VARCHAR(500)", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS sambapos_tracked_categories VARCHAR(1000)", ] for sql in settings_columns: diff --git a/backend/migrations/add_step_title.py b/backend/migrations/add_step_title.py index fb2b73a..7bb224c 100644 --- a/backend/migrations/add_step_title.py +++ b/backend/migrations/add_step_title.py @@ -1,23 +1,23 @@ -"""Add title column to recipe_steps table.""" -import logging -from sqlalchemy import text -from database import engine - -logger = logging.getLogger(__name__) - - -async def migrate(): - async with engine.begin() as conn: - # Check if column already exists - result = await conn.execute(text( - "SELECT column_name FROM information_schema.columns " - "WHERE table_name = 'recipe_steps' AND column_name = 'title'" - )) - if result.scalar_one_or_none(): - logger.info("recipe_steps.title already exists, skipping") - return - - await conn.execute(text( - "ALTER TABLE recipe_steps ADD COLUMN title VARCHAR(255) DEFAULT NULL" - )) - logger.info("Added recipe_steps.title column") +"""Add title column to recipe_steps table.""" +import logging +from sqlalchemy import text +from database import engine + +logger = logging.getLogger(__name__) + + +async def migrate(): + async with engine.begin() as conn: + # Check if column already exists + result = await conn.execute(text( + "SELECT column_name FROM information_schema.columns " + "WHERE table_name = 'recipe_steps' AND column_name = 'title'" + )) + if result.scalar_one_or_none(): + logger.info("recipe_steps.title already exists, skipping") + return + + await conn.execute(text( + "ALTER TABLE recipe_steps ADD COLUMN IF NOT EXISTS title VARCHAR(255) DEFAULT NULL" + )) + logger.info("Added recipe_steps.title column") diff --git a/backend/migrations/add_sub_recipe_unit.py b/backend/migrations/add_sub_recipe_unit.py index 0f8e514..8d15226 100644 --- a/backend/migrations/add_sub_recipe_unit.py +++ b/backend/migrations/add_sub_recipe_unit.py @@ -1,22 +1,22 @@ -"""Add portions_needed_unit to recipe_sub_recipes table.""" -import logging -from sqlalchemy import text -from database import engine - -logger = logging.getLogger(__name__) - - -async def migrate(): - async with engine.begin() as conn: - result = await conn.execute(text( - "SELECT column_name FROM information_schema.columns " - "WHERE table_name = 'recipe_sub_recipes' AND column_name = 'portions_needed_unit'" - )) - if result.scalar_one_or_none(): - logger.info("recipe_sub_recipes.portions_needed_unit already exists, skipping") - return - - await conn.execute(text( - "ALTER TABLE recipe_sub_recipes ADD COLUMN portions_needed_unit VARCHAR(10) DEFAULT NULL" - )) - logger.info("Added portions_needed_unit column to recipe_sub_recipes") +"""Add portions_needed_unit to recipe_sub_recipes table.""" +import logging +from sqlalchemy import text +from database import engine + +logger = logging.getLogger(__name__) + + +async def migrate(): + async with engine.begin() as conn: + result = await conn.execute(text( + "SELECT column_name FROM information_schema.columns " + "WHERE table_name = 'recipe_sub_recipes' AND column_name = 'portions_needed_unit'" + )) + if result.scalar_one_or_none(): + logger.info("recipe_sub_recipes.portions_needed_unit already exists, skipping") + return + + await conn.execute(text( + "ALTER TABLE recipe_sub_recipes ADD COLUMN IF NOT EXISTS portions_needed_unit VARCHAR(10) DEFAULT NULL" + )) + logger.info("Added portions_needed_unit column to recipe_sub_recipes") diff --git a/backend/migrations/add_supplier_po_fields.py b/backend/migrations/add_supplier_po_fields.py index ad35012..ce723f9 100644 --- a/backend/migrations/add_supplier_po_fields.py +++ b/backend/migrations/add_supplier_po_fields.py @@ -1,40 +1,40 @@ -""" -Migration: Add order_email and account_number columns to suppliers table. -Used for Purchase Order email sending and supplier identification. -""" -import asyncio -from sqlalchemy import text -from database import engine - - -async def migrate(): - async with engine.begin() as conn: - # Add order_email column - try: - await conn.execute(text( - "ALTER TABLE suppliers ADD COLUMN order_email VARCHAR(255)" - )) - print("+ Added order_email column to suppliers") - except Exception as e: - if "already exists" in str(e).lower() or "duplicate column" in str(e).lower(): - print("- order_email column already exists, skipping") - else: - raise - - # Add account_number column - try: - await conn.execute(text( - "ALTER TABLE suppliers ADD COLUMN account_number VARCHAR(100)" - )) - print("+ Added account_number column to suppliers") - except Exception as e: - if "already exists" in str(e).lower() or "duplicate column" in str(e).lower(): - print("- account_number column already exists, skipping") - else: - raise - - -if __name__ == "__main__": - print("Running migration: add_supplier_po_fields") - asyncio.run(migrate()) - print("Migration complete!") +""" +Migration: Add order_email and account_number columns to suppliers table. +Used for Purchase Order email sending and supplier identification. +""" +import asyncio +from sqlalchemy import text +from database import engine + + +async def migrate(): + async with engine.begin() as conn: + # Add order_email column + try: + await conn.execute(text( + "ALTER TABLE suppliers ADD COLUMN IF NOT EXISTS order_email VARCHAR(255)" + )) + print("+ Added order_email column to suppliers") + except Exception as e: + if "already exists" in str(e).lower() or "duplicate column" in str(e).lower(): + print("- order_email column already exists, skipping") + else: + raise + + # Add account_number column + try: + await conn.execute(text( + "ALTER TABLE suppliers ADD COLUMN IF NOT EXISTS account_number VARCHAR(100)" + )) + print("+ Added account_number column to suppliers") + except Exception as e: + if "already exists" in str(e).lower() or "duplicate column" in str(e).lower(): + print("- account_number column already exists, skipping") + else: + raise + + +if __name__ == "__main__": + print("Running migration: add_supplier_po_fields") + asyncio.run(migrate()) + print("Migration complete!") diff --git a/backend/migrations/add_supplier_skip_dext.py b/backend/migrations/add_supplier_skip_dext.py index 1e8043a..0d751b7 100644 --- a/backend/migrations/add_supplier_skip_dext.py +++ b/backend/migrations/add_supplier_skip_dext.py @@ -13,7 +13,7 @@ async def migrate(): await conn.execute(text( """ ALTER TABLE suppliers - ADD COLUMN skip_dext BOOLEAN NOT NULL DEFAULT FALSE + ADD COLUMN IF NOT EXISTS skip_dext BOOLEAN NOT NULL DEFAULT FALSE """ )) print("✓ Added skip_dext column to suppliers table") diff --git a/backend/migrations/add_vat_rate_settings.py b/backend/migrations/add_vat_rate_settings.py index 7549764..1b17119 100644 --- a/backend/migrations/add_vat_rate_settings.py +++ b/backend/migrations/add_vat_rate_settings.py @@ -18,8 +18,8 @@ async def run_migration(): # Add VAT rate columns to kitchen_settings table settings_columns = [ - "ALTER TABLE kitchen_settings ADD COLUMN newbook_breakfast_vat_rate NUMERIC(5, 4) DEFAULT 0.10", - "ALTER TABLE kitchen_settings ADD COLUMN newbook_dinner_vat_rate NUMERIC(5, 4) DEFAULT 0.10", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS newbook_breakfast_vat_rate NUMERIC(5, 4) DEFAULT 0.10", + "ALTER TABLE kitchen_settings ADD COLUMN IF NOT EXISTS newbook_dinner_vat_rate NUMERIC(5, 4) DEFAULT 0.10", ] for sql in settings_columns: @@ -36,8 +36,8 @@ async def run_migration(): # Add GL group columns to newbook_gl_accounts table (if not present) gl_columns = [ - "ALTER TABLE newbook_gl_accounts ADD COLUMN gl_group_id VARCHAR(50)", - "ALTER TABLE newbook_gl_accounts ADD COLUMN gl_group_name VARCHAR(255)", + "ALTER TABLE newbook_gl_accounts ADD COLUMN IF NOT EXISTS gl_group_id VARCHAR(50)", + "ALTER TABLE newbook_gl_accounts ADD COLUMN IF NOT EXISTS gl_group_name VARCHAR(255)", ] for sql in gl_columns: