Skip to content

fix(levelcode): report account activity spend at RETAIL, not raw wire cost#383

Merged
ndemianc merged 1 commit into
developfrom
fix/activity-retail-credits
Jul 24, 2026
Merged

fix(levelcode): report account activity spend at RETAIL, not raw wire cost#383
ndemianc merged 1 commit into
developfrom
fix/activity-retail-credits

Conversation

@ndemianc

Copy link
Copy Markdown
Member

The account page has been showing two different units for the same quantity: a retail-converted balance (1,279 credits left) above, and per-day / per-model spend summed straight from usage_events.cost_micros below.

The ledger stores what a request cost us at the wire. So those rows understated what the customer actually spent — by the margin — and could not be reconciled against the credits the same page reported as spent.

This is a real bug independent of credits: the per-model "cost" on the account page has been understating user spend in dollars all along.

What changed

Activity.for_user takes an optional plan_key and converts the aggregates through retail_micros — one rounding per figure, rather than one per ledger row. The account controller passes the caller's plan.

Left opt-in rather than baked into the aggregation, deliberately: this is a shared service, and an operator-side caller wants real COGS, not what the customer was charged. Passing no plan_key still yields raw cost.

Why the admin panel is not converted

Its figures carry no retail conversion — they are real COGS, what we pay providers. Credits are a retail unit (≈2× cost via CREDIT_COGS_RATIO), so rendering them there would conflate what we pay with what the customer is charged, and destroy the one view where margin is legible. Dollars are correct there.

Verification

971 examples, 0 failures. New specs assert the retail figure on the per-model row, the per-day total and the per-day model rows — with a precondition that retail actually exceeds cost, so the assertion cannot pass vacuously. One more pins that the no-plan_key path still returns raw cost.

Deploy order

The matching frontend change (onetime #88) renders these figures as credits. Ship this first — until it lands, that UI would divide raw cost and understate spend by the margin.

🤖 Generated with Claude Code

… cost

The account page showed two units for the same quantity: a RETAIL-converted
balance ("1,279 credits left") above, and per-day / per-model spend summed
straight from usage_events.cost_micros below. The ledger stores what a request
cost US at the wire, so those rows understated what the customer actually spent —
by the margin — and could not be reconciled against the credits the same page
reported as spent.

Activity.for_user now takes an optional plan_key and converts the AGGREGATES
through retail_micros (one rounding per figure, not one per ledger row). The
account controller passes the caller's plan.

Left opt-in rather than baked into the aggregation, deliberately: this is a
shared service, and an operator-side caller wants real COGS, not what the
customer was charged. Passing no plan_key still yields raw cost. (The admin panel
does not use this service today, and stays in dollars for exactly that reason —
credits are a retail unit, so showing them there would conflate what we pay with
what we charge.)

Verified: 971 examples, 0 failures. New specs assert the retail figure on the
per-model row, the per-day total AND the per-day model rows, with a precondition
that retail actually exceeds cost so the assertion cannot pass vacuously — plus
one pinning that the no-plan_key path still returns raw cost.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a unit mismatch on the Levelcode account activity endpoint by reporting customer-facing spend in the same retail denomination as the displayed balance, while preserving an opt-in path for operator/internal callers to retrieve raw COGS.

Changes:

  • Add optional plan_key: to Levelcode::Activity.for_user to convert aggregated cost_micros values via Levelcode.retail_micros when provided.
  • Pass current_plan_key from the account activity controller action so the account page receives retail-denominated spend.
  • Add request specs asserting retail conversion for per-model + per-day figures, and that omitting plan_key preserves raw cost.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
spec/requests/api/levelcode/v1/account_spec.rb Adds coverage for retail spend reporting and the opt-in raw-cost behavior.
app/services/levelcode/activity.rb Introduces plan_key: and applies retail conversion to aggregated cost figures when present.
app/controllers/api/levelcode/v1/account_controller.rb Passes the current plan key into Activity.for_user for retail reporting on the account activity endpoint.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@ndemianc
ndemianc merged commit e196bf0 into develop Jul 24, 2026
4 checks passed
@ndemianc
ndemianc deleted the fix/activity-retail-credits branch July 24, 2026 01:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants