fix(promo): count activations on payment

Allow promo usage increments to overflow the max limit when a payment completes so counters reflect paid activations only.
This commit is contained in:
kavore
2026-02-03 12:05:16 +03:00
parent d11b0cabaa
commit 3c84007f17
3 changed files with 19 additions and 41 deletions
+2 -32
View File
@@ -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(
+1 -1
View File
@@ -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(
+16 -8
View File
@@ -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