Skip to content

feat(sponsor-reports): surface partial line cancellations in the By Item and Lines Manifest views - #1056

Merged
smarcet merged 7 commits into
masterfrom
feature/partial-line-cancellation-reports
Aug 29, 2026
Merged

feat(sponsor-reports): surface partial line cancellations in the By Item and Lines Manifest views#1056
smarcet merged 7 commits into
masterfrom
feature/partial-line-cancellation-reports

Conversation

@caseylocker

@caseylocker caseylocker commented Aug 28, 2026

Copy link
Copy Markdown

ref: https://app.clickup.com/t/9014802374/86bbpjzmm

Both Purchase Details report views read the binary is_canceled only, so a partially cancelled line rendered as fully live and its cancelled units counted as purchased. The API has returned canceled_quantity, canceled_amount and is_partially_canceled since sponsor-reports-api #41; nothing here consumed them.

What changed

Two pure helpers plus a shared status token, exported from LinesManifestView.js (the one-way ByItemView -> LinesManifestView dependency already existed):

  • liveQuantity(row) and liveAmountCents(row) net the cancelled portion, clamped at 0, null-in/null-out for money.
  • lineStatus(row) resolves the line's own three-way state, and LineStatusPill renders it. A soft-cancelled or partially cancelled line leaves its parent order Paid, so purchase.status alone printed "Paid" on a row with real cancelled units.

By Item nets both units and money into the item aggregates. The money subtraction is exact rather than prorated: canceled_amount is the source's own frozen sum for the cancelled units, and the source charges partial events at floor unit price, so proration drifts by cents. Drill-down contributors carry the same live money they contribute, so the rows sum to their own header.

Lines Manifest shows the cancelled portion on the row: 3 / 5 units and $1980.00 / $3300.00. Live over charged for money, because that column is the only per-line money surface finance has and netting alone would drop the charged figure.

Deliberate, not oversights

  • A fully cancelled contributor keeps its ordered quantity and charged total. The row is struck through; 0 / $0.00 would erase what the cancellation was for. Item aggregates are unaffected either way, since a fully cancelled line never enters the if (!row.is_canceled) block.
  • bucketLinesBySponsor is untouched. liveLineCount counts lines, not units, and a partially cancelled line is still one live line to fulfil.
  • Active and fully cancelled rows render exactly as before.

Known divergence, tracked in 86bbmwk83

The Total Items tile is computed server side (purchase_details_summary, Sum('quantity') filtered on canceled_at IS NULL) and cannot be corrected from this repo. On dev summit 73 it reads 212 against a netted By Item Σ Qty of 201, a gap of 11. 86bbmwk83 closes it. If that ships in the same release there is no window; if not, the two disagree only on data containing a partially cancelled line.

Verified on dev

Deployment slot 13, backfill run, 8 partially cancelled lines. Every rendered figure was checked against the database:

Order Item Qty Line Total
000051 SJC-GR04 2 / 4 $700.00 / $1400.00
000051 SJC-L-D 2 / 3 $500.00 / $750.00
000051 FN-F04 3 / 5 $1980.00 / $3300.00
000052 SJC-F03 5 / 10 $675.00 / $1350.00
000034 SJC-EL15 1 / 2 $50.00 / $100.00

By Item drill-downs sum to their headers (SJC-L-D: 2+5+2 = 9 units, $500+$1250+$400 = $2150). All five sit under Paid orders, which is the trap this fixes.

yarn test: 183 suites, 1634 tests. eslint clean on the changed files.

Note for review

Partially Canceled and Pending both map to the warning tone, so they share a colour in the Status column. The labels differ and are readable, but they are not separable at a glance, most visibly in a By Item drill-down where the two sit adjacent. secondary is the only unused tone in TONE_BY_STATUS if you would rather they were distinct. Happy either way.

caseylocker and others added 7 commits August 28, 2026 15:55
…eport views

The three-way line state (canceled / partially canceled / parent order status)
was written three times: LineStatusPill, accumulateRow's contributor token, and
the ByItemView drill-down render. Collapse to lineStatus() plus a token-driven
LineStatusPill, both exported from LinesManifestView, which ByItemView already
imports from.

Also drop six tests that pass with the code deleted (a tone-map lookup, two
identity assertions, unreachable is_canceled branches) and five that duplicated
a surviving assertion, and trim the new comments to the eight that stop a
plausible wrong edit.

Co-Authored-By: Claude <noreply@anthropic.com>
…ifest rows

The Qty cell reads "3 / 5" while the money cell priced all 5, so the row
contradicted itself. Render both figures, matching the Qty cell: netting alone
would drop the charged amount, and this is the only per-line money surface
finance has (the Orders serializer carries no cancellation field).

Co-Authored-By: Claude <noreply@anthropic.com>
…color

Spec requires the partial state be visually distinct; only its label was
guarded. Asserts the rendered chip class rather than the tone lookup, so it
fails on real breakage instead of restating the map.

Co-Authored-By: Claude <noreply@anthropic.com>
@caseylocker caseylocker self-assigned this Aug 28, 2026
@coderabbitai

coderabbitai Bot commented Aug 28, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a4a6c105-69ae-4080-849a-9627d801398c


Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This pull request updates Sponsor Reports “Purchase Details” views to correctly represent partially canceled line items by netting canceled units/amounts in aggregates and surfacing a distinct per-line status indicator (rather than relying on the parent order status).

Changes:

  • Added shared helpers in LinesManifestView.js to compute live (net) quantity/amount and a three-way line status, plus a LineStatusPill renderer.
  • Updated By Item to net partially canceled units and cents into item aggregates and to display split quantities and line-level status in drill-down contributors.
  • Updated Lines Manifest to display split quantity and “live / charged” money for partially canceled lines, and to render the line-level status pill.
  • Added the “Partially Canceled” i18n string, updated status tone mapping, and expanded unit tests to cover the new behavior.

Reviewed changes

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

Show a summary per file
File Description
src/i18n/en.json Adds label for the new partially canceled line status.
src/components/sponsors/reports/StatusPill.js Adds a warning tone mapping for partially_canceled.
src/components/sponsors/reports/LinesManifestView.js Introduces shared “live” helpers, line-level status resolution, and updated row rendering for partial cancellations.
src/components/sponsors/reports/ByItemView.js Uses shared helpers to net aggregates and show partial-cancel splits/status in contributor drill-down rows.
src/components/sponsors/reports/tests/StatusPill.test.js Verifies color mapping for partially_canceled.
src/components/sponsors/reports/tests/LinesManifestView.test.js Adds coverage for live helpers and partially canceled rendering behaviors.
src/components/sponsors/reports/tests/ByItemView.test.js Adds coverage for aggregate netting and contributor split/status rendering for partial cancellations.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@smarcet
smarcet self-requested a review August 29, 2026 11:15

@smarcet smarcet left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

LGTM

@smarcet
smarcet merged commit bd32ebc into master Aug 29, 2026
10 checks passed
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.

3 participants