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:
@@ -140,36 +140,6 @@ class PromoCodeService:
|
|||||||
# This shouldn't happen since we checked above, but just in case
|
# This shouldn't happen since we checked above, but just in case
|
||||||
return False, _("error_applying_promo_discount")
|
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(
|
logging.info(
|
||||||
f"Discount promo code {code_input_upper} activated for user {user_id}: "
|
f"Discount promo code {code_input_upper} activated for user {user_id}: "
|
||||||
f"{promo_data.discount_percentage}% off"
|
f"{promo_data.discount_percentage}% off"
|
||||||
@@ -236,7 +206,7 @@ class PromoCodeService:
|
|||||||
payment_id: int
|
payment_id: int
|
||||||
) -> bool:
|
) -> 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.
|
Call this AFTER successful payment.
|
||||||
"""
|
"""
|
||||||
payment_record = await payment_dal.get_payment_by_db_id(session, payment_id)
|
payment_record = await payment_dal.get_payment_by_db_id(session, payment_id)
|
||||||
@@ -300,7 +270,7 @@ class PromoCodeService:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
promo_incremented = await promo_code_dal.increment_promo_code_usage(
|
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:
|
if not promo_incremented:
|
||||||
logging.error(
|
logging.error(
|
||||||
|
|||||||
@@ -615,7 +615,7 @@ class SubscriptionService:
|
|||||||
)
|
)
|
||||||
if activation:
|
if activation:
|
||||||
await promo_code_dal.increment_promo_code_usage(
|
await promo_code_dal.increment_promo_code_usage(
|
||||||
session, promo_code_id_from_payment
|
session, promo_code_id_from_payment, allow_overflow=True
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
logging.warning(
|
logging.warning(
|
||||||
|
|||||||
@@ -159,13 +159,16 @@ async def delete_promo_code(session: AsyncSession, promo_id: int) -> Optional[Pr
|
|||||||
|
|
||||||
|
|
||||||
async def increment_promo_code_usage(
|
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 = (
|
stmt = (
|
||||||
update(PromoCode)
|
update(PromoCode)
|
||||||
.where(
|
.where(*conditions)
|
||||||
PromoCode.promo_code_id == promo_code_id,
|
|
||||||
PromoCode.current_activations < PromoCode.max_activations,
|
|
||||||
)
|
|
||||||
.values(current_activations=PromoCode.current_activations + 1)
|
.values(current_activations=PromoCode.current_activations + 1)
|
||||||
)
|
)
|
||||||
result = await session.execute(stmt)
|
result = await session.execute(stmt)
|
||||||
@@ -175,6 +178,11 @@ async def increment_promo_code_usage(
|
|||||||
|
|
||||||
promo = await get_promo_code_by_id(session, promo_code_id)
|
promo = await get_promo_code_by_id(session, promo_code_id)
|
||||||
if promo:
|
if promo:
|
||||||
|
if allow_overflow:
|
||||||
|
logging.warning(
|
||||||
|
f"Failed to increment promo usage for promo {promo.code} (ID: {promo_code_id})."
|
||||||
|
)
|
||||||
|
else:
|
||||||
logging.warning(
|
logging.warning(
|
||||||
f"Promo code {promo.code} (ID: {promo_code_id}) already reached max activations."
|
f"Promo code {promo.code} (ID: {promo_code_id}) already reached max activations."
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user