- ID
- be7663-is-customized-gate-rollover-credits
BE-7663 Add is_customized gate to recalculate_adjustments_for_rollover_credits
- source :: https://hungryroot.atlassian.net/browse/BE-7663
- tags :: Hungryroot API Project
- status :: Status - Complete
At cutoff, rollover credits were being recalculated for uncustomized orders when they
shouldn't have been. BE-7548 added a DC gate; this ticket adds a hard gate on
=order.is_customized= so standard recurring uncustomized orders never enter
=recalculate_adjustments_for_rollover_credits=.
The gate lives in =app/services/api/order.py= inside =submit_order=:
#+begin_src python
needs_rollover_recalc = needs_rollover_recalc and (
order.should_calculate_rollover_credits_post_shuffle or order.is_customized
)
#+end_src
=should_calculate_rollover_credits_post_shuffle= is True for flex credits, budget range,
PAYG, and free-first-box rollover orders — the DC from BE-7548 is no longer referenced
here and has no effect.
Test
Find a standard uncustomized RECURRING order and manufacture the bug scenario by giving
the customer rollover credits manually:
#+begin_src python
from app.models import Order
from order_financials.const import PriceCalculationVersion
order = (
Order.objects.select_related("customer")
.filter(
is_customized=False,
status__in=[20], # RECURRING
rollover_credits=0,
)
.exclude(price_calculation_version=PriceCalculationVersion.PAY_AS_YOU_GO)
.first()
)
print("should_calculate_post_shuffle:", order.should_calculate_rollover_credits_post_shuffle)
# Must be False — if True, pick a different order (flex/budget-range/first-box)
order.customer.rollover_credits = 4
order.customer.save()
#+end_src
Inspect the gate logic:
#+begin_src python
from app.models import Order
order = Order.objects.select_related("customer").get(pk=order.id)
customer_has_rollover_credits = order.customer.rollover_credits > 0
too_many_applied = order.customer.rollover_credits < order.rollover_credits
needs_rollover_recalc = customer_has_rollover_credits or too_many_applied
gated = needs_rollover_recalc and (
order.should_calculate_rollover_credits_post_shuffle or order.is_customized
)
print("customer rollover_credits:", order.customer.rollover_credits)
print("order rollover_credits:", order.rollover_credits)
print("is_customized:", order.is_customized)
print("should_calculate_post_shuffle:", order.should_calculate_rollover_credits_post_shuffle)
print("needs_rollover_recalc (raw):", needs_rollover_recalc)
print("would recalculate (gated):", gated)
# Expect: would recalculate (gated): False
#+end_src
Flip =is_customized= to confirm the allow path:
#+begin_src python
order.is_customized = True
order.save()
# Re-run inspection — expect: would recalculate (gated): True
#+end_src
Clean up when done:
#+begin_src python
order.customer.rollover_credits = 0
order.customer.save()
order.is_customized = False
order.save()
#+end_src