diff --git a/bot/services/promo_code_service.py b/bot/services/promo_code_service.py index eb17aef..3fb90ad 100644 --- a/bot/services/promo_code_service.py +++ b/bot/services/promo_code_service.py @@ -140,36 +140,6 @@ class PromoCodeService: # This shouldn't happen since we checked above, but just in case return False, _("error_applying_promo_discount") - promo_incremented = await promo_code_dal.increment_promo_code_usage( - session, promo_data.promo_code_id - ) - if not promo_incremented: - await active_discount_dal.clear_active_discount(session, user_id) - logging.info( - "Discount promo %s reached max activations during activation for user %s.", - promo_data.code, - user_id, - ) - return False, _("promo_code_not_found_or_not_discount", code=code_input_upper) - - activation_recorded = await promo_code_dal.record_promo_activation( - session, - promo_data.promo_code_id, - user_id, - payment_id=None, - ) - if not activation_recorded: - await active_discount_dal.clear_active_discount(session, user_id) - await promo_code_dal.decrement_promo_code_usage( - session, promo_data.promo_code_id - ) - logging.error( - "Failed to record discount activation for user %s, promo %s.", - user_id, - promo_data.promo_code_id, - ) - return False, _("error_applying_promo_discount") - logging.info( f"Discount promo code {code_input_upper} activated for user {user_id}: " f"{promo_data.discount_percentage}% off" @@ -236,7 +206,7 @@ class PromoCodeService: payment_id: int ) -> bool: """ - Consume active discount: record activation, increment usage, clear active discount. + Consume active discount: link activation to payment, increment usage, clear active discount. Call this AFTER successful payment. """ payment_record = await payment_dal.get_payment_by_db_id(session, payment_id) @@ -300,7 +270,7 @@ class PromoCodeService: return False promo_incremented = await promo_code_dal.increment_promo_code_usage( - session, promo_code_id + session, promo_code_id, allow_overflow=True ) if not promo_incremented: logging.error( diff --git a/bot/services/subscription_service.py b/bot/services/subscription_service.py index 506256e..dc34b6e 100644 --- a/bot/services/subscription_service.py +++ b/bot/services/subscription_service.py @@ -615,7 +615,7 @@ class SubscriptionService: ) if activation: await promo_code_dal.increment_promo_code_usage( - session, promo_code_id_from_payment + session, promo_code_id_from_payment, allow_overflow=True ) else: logging.warning( diff --git a/db/dal/promo_code_dal.py b/db/dal/promo_code_dal.py index e7223e5..569380b 100644 --- a/db/dal/promo_code_dal.py +++ b/db/dal/promo_code_dal.py @@ -159,13 +159,16 @@ async def delete_promo_code(session: AsyncSession, promo_id: int) -> Optional[Pr async def increment_promo_code_usage( - session: AsyncSession, promo_code_id: int) -> Optional[PromoCode]: + session: AsyncSession, + promo_code_id: int, + allow_overflow: bool = False) -> Optional[PromoCode]: + conditions = [PromoCode.promo_code_id == promo_code_id] + if not allow_overflow: + conditions.append(PromoCode.current_activations < PromoCode.max_activations) + stmt = ( update(PromoCode) - .where( - PromoCode.promo_code_id == promo_code_id, - PromoCode.current_activations < PromoCode.max_activations, - ) + .where(*conditions) .values(current_activations=PromoCode.current_activations + 1) ) result = await session.execute(stmt) @@ -175,9 +178,14 @@ async def increment_promo_code_usage( promo = await get_promo_code_by_id(session, promo_code_id) if promo: - logging.warning( - f"Promo code {promo.code} (ID: {promo_code_id}) already reached max activations." - ) + if allow_overflow: + logging.warning( + f"Failed to increment promo usage for promo {promo.code} (ID: {promo_code_id})." + ) + else: + logging.warning( + f"Promo code {promo.code} (ID: {promo_code_id}) already reached max activations." + ) return None