From 5d00124ca0e5c8ba7898048d6bf33b894f0cfba7 Mon Sep 17 00:00:00 2001 From: kavore <161734431+kavore@users.noreply.github.com> Date: Thu, 12 Feb 2026 16:44:14 +0300 Subject: [PATCH] fix(users): update referral code handling to ensure uniqueness and proper formatting Implement logic to clean and standardize referral codes in the users table. This includes setting referral codes to NULL if they are empty or consist only of whitespace, and generating unique referral codes for users with duplicates. The changes enhance data integrity and ensure consistent formatting of referral codes across the database. --- bot/handlers/user/payment.py | 2 +- db/alembic_runner.py | 51 ++++++++++++++++++++++++++++-------- db/dal/payment_dal.py | 9 ++++++- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/bot/handlers/user/payment.py b/bot/handlers/user/payment.py index 8d2f3c7..25f358d 100644 --- a/bot/handlers/user/payment.py +++ b/bot/handlers/user/payment.py @@ -624,7 +624,7 @@ async def yookassa_webhook_route(request: web.Request): logging.error( f"YooKassa webhook payment {payment_data_from_notification.id} lacks metadata. Cannot process." ) - return web.Response(status=503, text="yookassa_missing_metadata") + return web.Response(status=200, text="yookassa_missing_metadata") # Safely extract payment_method details (SDK objects may not have to_dict) pm_obj = getattr(payment_data_from_notification, 'payment_method', None) diff --git a/db/alembic_runner.py b/db/alembic_runner.py index 38deb04..92129d4 100644 --- a/db/alembic_runner.py +++ b/db/alembic_runner.py @@ -67,6 +67,45 @@ def _run_legacy_migrator_compatibility(connection: Connection) -> None: for column in inspect(connection).get_columns("users") } if "referral_code" in users_columns: + connection.execute( + text( + """ + UPDATE users + SET referral_code = NULLIF(UPPER(BTRIM(referral_code)), '') + WHERE referral_code IS NOT NULL + """ + ) + ) + connection.execute( + text( + """ + WITH duplicate_codes AS ( + SELECT + user_id, + ROW_NUMBER() OVER ( + PARTITION BY referral_code + ORDER BY user_id + ) AS rn + FROM users + WHERE referral_code IS NOT NULL + ) + UPDATE users AS u + SET referral_code = UPPER( + SUBSTRING( + md5( + u.user_id::text + || clock_timestamp()::text + || random()::text + ) + FROM 1 FOR 9 + ) + ) + FROM duplicate_codes AS d + WHERE u.user_id = d.user_id + AND d.rn > 1 + """ + ) + ) connection.execute( text( """ @@ -84,7 +123,7 @@ def _run_legacy_migrator_compatibility(connection: Connection) -> None: ) ) AS referral_code FROM users - WHERE referral_code IS NULL OR referral_code = '' + WHERE referral_code IS NULL ) UPDATE users AS u SET referral_code = g.referral_code @@ -102,16 +141,6 @@ def _run_legacy_migrator_compatibility(connection: Connection) -> None: """ ) ) - connection.execute( - text( - """ - UPDATE users - SET referral_code = UPPER(referral_code) - WHERE referral_code IS NOT NULL - AND referral_code <> UPPER(referral_code) - """ - ) - ) db_inspector = inspect(connection) if db_inspector.has_table("payments"): diff --git a/db/dal/payment_dal.py b/db/dal/payment_dal.py index 1c79525..18452f7 100644 --- a/db/dal/payment_dal.py +++ b/db/dal/payment_dal.py @@ -225,7 +225,14 @@ async def mark_provider_payment_processing_once( Payment.status != "processing", ] if expected_status_prefix: - conditions.append(Payment.status.like(f"{expected_status_prefix}%")) + if expected_status_prefix == "pending": + # YooKassa may keep authorized payments in waiting_for_capture + # before reporting a final successful capture webhook. + conditions.append( + Payment.status.in_(("waiting_for_capture", "pending", "pending_yookassa")) + ) + else: + conditions.append(Payment.status.like(f"{expected_status_prefix}%")) stmt = ( update(Payment)