Balances: one reservation rule (earned first) + purchased-grade credited pool

- balances(): live campaign budgets are set aside up front, earned pool first then
  purchased, so dashboard numbers never move per impression; new 'in campaigns' line
- earned pool gains a purchase_grade portion for refunds/comps: shows under Purchased
  as 'credited to you' and funds login ads (daily login charge draws on it first)
- viewing credits always spend before credited purchased money
- dashboard/donut/spend banner/earn pane/positions show purchased, credited, earned, in campaigns
- chatbot canned answer + AI prompt: the balance rule

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-10 11:16:40 -05:00
parent af6d2db711
commit 4487a90d16
6 changed files with 45 additions and 25 deletions
+1
View File
@@ -72,6 +72,7 @@ async function bootstrap() {
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4`);
const alterSafe0 = async sql => { try { await q(sql); } catch (e) { if (!['ER_DUP_FIELDNAME', 'ER_DUP_KEYNAME'].includes(e.code)) throw e; } };
await alterSafe0('ALTER TABLE earned_credits ADD COLUMN milestones VARCHAR(255) NULL'); // comma-joined granted milestone keys
await alterSafe0('ALTER TABLE earned_credits ADD COLUMN purchase_grade INT NOT NULL DEFAULT 0'); // part of the pool that is refunded/credited PURCHASED money: shows as purchased, funds login ads
await alterSafe0('ALTER TABLE earned_credits ADD COLUMN login_day CHAR(10) NULL'); // last daily-login-bonus day
await alterSafe0('ALTER TABLE earned_credits ADD COLUMN login_streak INT NOT NULL DEFAULT 0'); // consecutive-day streak
// additive columns (MySQL 8 has no IF NOT EXISTS for columns)