1- """ensure_whatsapp_agent_exists
1+ """fix_agent_id_with_correct_order
22
3- Revision ID: 3f8b2e4c9a71
3+ Revision ID: 7a9c3e5f2b1d
44Revises: d654ae68d8e9
5- Create Date: 2025-10-29 01:30 :00.000000
5+ Create Date: 2025-10-29 02:00 :00.000000
66
77"""
88from typing import Sequence , Union
1414from util .config import config
1515
1616# revision identifiers, used by Alembic.
17- revision : str = "3f8b2e4c9a71 "
17+ revision : str = "7a9c3e5f2b1d "
1818down_revision : Union [str , None ] = "d654ae68d8e9"
1919branch_labels : Union [str , Sequence [str ], None ] = None
2020depends_on : Union [str , Sequence [str ], None ] = None
2121
2222
2323def upgrade () -> None :
2424 # This migration ensures the agent exists with the correct ID and WhatsApp fields
25- # Handles three scenarios :
26- # 1. Production: agent exists with wrong ID (9e0c5a1a...) -> migrate messages, delete old, create correct
27- # 2. Local/Staging: multiple agents exist -> migrate messages, delete duplicates, upsert correct one
28- # 3. Fresh DB: agent doesn't exist -> create it
25+ # Order matters :
26+ # 1. Create/upsert correct agent FIRST (must exist before messages can reference it)
27+ # 2. Migrate messages from wrong agent -> correct agent (safe now)
28+ # 3. Delete wrong agent (safe because messages no longer reference it)
2929 # Idempotent: safe to run multiple times
3030
3131 assert THE_AGENT .whatsapp_phone_number is not None , "Agent phone number must be set"
@@ -34,8 +34,15 @@ def upgrade() -> None:
3434 encryption_key = config .token_encrypt_secret .get_secret_value ()
3535 wa_phone_plaintext = THE_AGENT .whatsapp_phone_number .get_secret_value ()
3636
37- # Step 1: Migrate any chat messages from wrong agent ID to correct ID
38- # This handles local/staging where messages reference the wrong agent
37+ # Temporarily drop foreign key constraints to allow ID updates
38+ # This is necessary because we may need to change the agent's primary key
39+ op .execute (text ("ALTER TABLE chat_messages DROP CONSTRAINT IF EXISTS chat_messages_author_id_fkey" ))
40+ op .execute (text ("ALTER TABLE price_alerts DROP CONSTRAINT IF EXISTS price_alerts_owner_id_fkey" ))
41+ op .execute (text ("ALTER TABLE sponsorships DROP CONSTRAINT IF EXISTS sponsorships_sponsor_id_fkey" ))
42+ op .execute (text ("ALTER TABLE sponsorships DROP CONSTRAINT IF EXISTS sponsorships_receiver_id_fkey" ))
43+
44+ # Step 1: Migrate messages from wrong agent ID to correct ID (before agent exists)
45+ # Safe because FK constraint is temporarily dropped
3946 op .execute (text ("""
4047 UPDATE chat_messages
4148 SET author_id = :correct_id
@@ -50,7 +57,7 @@ def upgrade() -> None:
5057 ))
5158
5259 # Step 2: Delete any agent with matching telegram_user_id but wrong ID
53- # Now safe to delete since messages have been migrated
60+ # Safe now because messages no longer reference it
5461 op .execute (text ("""
5562 DELETE FROM simulants
5663 WHERE telegram_user_id = :telegram_user_id
@@ -60,8 +67,8 @@ def upgrade() -> None:
6067 telegram_user_id = THE_AGENT .telegram_user_id ,
6168 ))
6269
63- # Step 3: Upsert the agent with correct ID and all current fields
64- # Insert if not exists, update if exists
70+ # Step 3: Insert correct agent (or update if somehow already exists)
71+ # Safe now because no unique constraint conflicts
6572 op .execute (text ("""
6673 INSERT INTO simulants (
6774 id,
@@ -105,8 +112,29 @@ def upgrade() -> None:
105112 created_at = "2024-01-01" ,
106113 ))
107114
115+ # Re-add foreign key constraints
116+ op .execute (text ("""
117+ ALTER TABLE chat_messages
118+ ADD CONSTRAINT chat_messages_author_id_fkey
119+ FOREIGN KEY (author_id) REFERENCES simulants(id)
120+ """ ))
121+ op .execute (text ("""
122+ ALTER TABLE price_alerts
123+ ADD CONSTRAINT price_alerts_owner_id_fkey
124+ FOREIGN KEY (owner_id) REFERENCES simulants(id)
125+ """ ))
126+ op .execute (text ("""
127+ ALTER TABLE sponsorships
128+ ADD CONSTRAINT sponsorships_sponsor_id_fkey
129+ FOREIGN KEY (sponsor_id) REFERENCES simulants(id)
130+ """ ))
131+ op .execute (text ("""
132+ ALTER TABLE sponsorships
133+ ADD CONSTRAINT sponsorships_receiver_id_fkey
134+ FOREIGN KEY (receiver_id) REFERENCES simulants(id)
135+ """ ))
136+
108137
109138def downgrade () -> None :
110- # No downgrade. We don't want to delete the agent in production.
111- # Too risky - simply add a new migration.
139+ # No downgrade - we don't want to delete the agent in production
112140 pass
0 commit comments