portal: 90% threshold for budget notices; sweep 3x a day
Trigger becomes proportional (90% of the balance used) instead of a $2 floor, so a member on $15 and one on $35 are treated the same. The once-per-crossing latch keys on the same fraction. membership_sweep moves from '0 3 * * *' to '0 3,11,19 * * *' so the notice arrives within hours of crossing rather than up to a day later. BUDGET_NOTICES remains off.
This commit is contained in:
1 parent
26be6156ae
commit
7d2507a927
2 files changed
+9
-8
No files matched your search
@@ -15,7 +15,7 @@
|
||||
"sendmail": {},
|
||||
"scheduler": {
|
||||
"membership_sweep": {
|
||||
"schedule": "0 3 * * *",
|
||||
"schedule": "0 3,11,19 * * *",
|
||||
"command": "/app/code/sweep.sh"
|
||||
},
|
||||
"rag_refresh": {
|
||||
|
||||
+8
-7
@@ -3973,9 +3973,10 @@ async def index():
|
||||
|
||||
# Generic on purpose: the balance can be short because the monthly allowance is spent,
|
||||
# because purchased credit is spent, or a mix — the letter says "balance" so it is true
|
||||
# either way. The trigger is an absolute floor, not a percentage, so it means the same
|
||||
# thing to a member on a $15 allowance and a member on $35.
|
||||
BUDGET_LOW_WATER = float(os.environ.get("BUDGET_LOW_WATER", "2.00"))
|
||||
# either way. The trigger is proportional — 90% of the balance used — so it means the same
|
||||
# thing to a member on $15 and one on $35: the letter arrives when roughly a tenth is left,
|
||||
# on whichever sweep follows, rather than at an arbitrary absolute amount.
|
||||
BUDGET_NOTICE_AT = float(os.environ.get("BUDGET_NOTICE_AT", "0.90"))
|
||||
|
||||
PINE_LOGO_SVG = """<svg width="56" height="56" viewBox="0 0 130 130" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
|
||||
<circle cx="65" cy="14" r="5" fill="#5b8c5a"/>
|
||||
@@ -4131,10 +4132,10 @@ async def budget_notice_sweep(send: bool = False) -> dict:
|
||||
continue
|
||||
|
||||
remaining = float(budget) - spend
|
||||
if remaining >= BUDGET_LOW_WATER:
|
||||
# Back above the line — they added funds, or the allowance reset. Clear the latch so
|
||||
# the NEXT crossing sends a fresh notice. That is what makes it once each time, and
|
||||
# it is why this is a latch rather than a key on the budget cycle.
|
||||
if spend < BUDGET_NOTICE_AT * float(budget):
|
||||
# Above the line — they added funds, or the allowance reset. Clear the latch so the
|
||||
# NEXT crossing sends a fresh notice. That is what makes it once each time, and it
|
||||
# is why this is a latch rather than a key on the budget cycle.
|
||||
conn.execute("DELETE FROM budget_notices WHERE email = ?", (email,))
|
||||
conn.commit()
|
||||
continue
|
||||
|
||||
Reference in new issue
Block a user