Skip to content

Sponsor Reports: show-wide By Item view for the warehouse pull sheet - #1025

Open
caseylocker wants to merge 2 commits into
masterfrom
feature/purchase-details-by-item-all-sponsors
Open

Sponsor Reports: show-wide By Item view for the warehouse pull sheet#1025
caseylocker wants to merge 2 commits into
masterfrom
feature/purchase-details-by-item-all-sponsors

Conversation

@caseylocker

@caseylocker caseylocker commented Jul 28, 2026

Copy link
Copy Markdown

ref: https://app.clickup.com/t/86bb4gpu5

Why

The By Item view (#1009) only rolls items up within a sponsor, so there was no way to read a show-wide total for an item. The warehouse pulls the bulk number for a show first, then assigns that inventory out — and had no view for the first half of that.

Requested by Jeremy Muir (Slack, 2026-07-27): "a filter that is across all sponsors by item (total number of 43" led Monitors for the show) … and then if you click on that item it could show the breakdown of that item in particular (I.E 10 monitors go to Intel booth, 3 go to Nvidia meeting room)", so that "our warehouse [can] pull the total equipment for the show and then start assigning that inventory once they have the bulk number pulled."

What

  • Layout toggle on By Item: By Sponsor (unchanged) and All Sponsors — one row per item_code across every sponsor. The drill-down gains a Sponsor column alongside the existing Destination, so it answers "10 to Intel booth, 3 to Nvidia meeting room" directly.
  • Sortable columns — Item Code / Item Name / Qty / Orders — defaulting to Item Code ascending. order/orderDir live in the by-item slice so the choice survives the Orders toggle.
  • Expand All / Collapse All across the group accordions and the per-item drill-downs.
  • Export CSV in this view now passes order=item_code to the existing lines CSV endpoint, so every line for one item lands together with its sponsor and booth.

Client-side rollup over rows the existing whole-set fetch already loads. No new API call and no backend change.

Notes for review

  • Both layouts share one accumulator (accumulateRow) and one group container (ItemGroup), so neither the purchased-qty semantics nor the card styling can drift between them. An earlier iteration hand-rolled the all-sponsors container and immediately diverged visually; that is why it is one component.
  • Canceled lines stay excluded from qty / money / orders / statusMix while still rendering struck-through — unchanged from feat(sponsor-reports): add By Item view to Purchase Details report #1009, now shared by both layouts.
  • Pending counts toward the pull total. This is a fulfilment number, not a finance one: you pull what was ordered regardless of payment. On summit 73 that is 9 of 26 purchased lines, so it materially changes the figure.
  • Sorting runs before paging in the all-sponsors layout, where the page is a slice of the item list, and is stable — so the canonical qty-desc rollup order survives underneath as the tiebreak.
  • The CSV columns were already right. PURCHASE_DETAILS_LINES_CSV_COLUMNS matches the logistics OVERALL sheet exactly; only the ordering was wrong (it defaulted to sponsor name, scattering an item's lines). item_code was already declared in the endpoint's ordering_fields and the CSV path runs through filter_queryset, so this is a query param, not a new contract.
  • Per-show scoping is structural — every report route is /summits/{summit_id}/reports/… and the queryset filters purchase__summit_id, so no cross-show mixing is possible and no filter was needed for it.

Testing

Full suite green: 153 suites / 1427 tests. New coverage includes cross-layout Σ-qty reconciliation against a total computed from the fixture, sort stability and sort-before-paging, expansion-key separation between the two layouts, and the expand/collapse semantics.

Reviewed by Codex ahead of this PR: mergeable, no Critical or Major correctness findings; its two Minor test-quality findings are addressed in this branch.

⚠️ Validate against prod, not dev. The dev sponsor-reports-api predates #30/#33/#34, so there: qty-0 catalog rows still appear (412 of 475 on summit 73), the Booth column is empty because sponsor_booth doesn't exist in that build, and the finance columns are blank.

Deliberately not in scope

  • Total column sortable — Jeremy named only Item Code / Item Name / Qty / Orders.
  • Export following the on-screen sort — the file is always item-ordered, which suits a pull sheet.
  • Gated 3rd-party vendor access to reports, raised in the same Slack thread. There is no row-level or per-vendor scoping in the reports API today; that needs its own ticket and a security review.

Summary by CodeRabbit

  • New Features

    • Added sortable columns to the By Item purchase details report.
    • Added Sponsor and All Sponsors layout options.
    • Added expand-all and collapse-all controls for item details.
    • Added item-level aggregation across sponsors.
    • Updated CSV exports to preserve By Item ordering.
  • Bug Fixes

    • Improved handling of canceled lines and item totals in report rollups.
    • Preserved filters when exporting ordered CSV data.

…sheet

The By Item report only rolled up within a sponsor, so there was no way to
read a show-wide total for an item. The warehouse pulls the bulk number for a
show first, then assigns that inventory out, and had no view for the first
half of that.

Adds a layout toggle to the By Item view:
- By Sponsor (as before): sponsor accordions -> per-item aggregates
- All Sponsors: one row per item_code across every sponsor, drilling down to
  the contributing orders with the sponsor and destination each unit goes to

Both layouts share one accumulator, so what counts as purchased cannot drift
between them: canceled lines stay excluded from qty/money/orders while still
showing struck-through, and every payment status including Pending counts
toward the pull total. Both render through one group container, so the card
surface, summary divider and table inset match by construction.

Also here:
- Sortable Item Code / Item Name / Qty / Orders columns, defaulting to Item
  Code ascending; order/orderDir live in the by-item slice so the choice
  survives the Orders toggle. Sorting runs before paging in the all-sponsors
  layout, and is stable, so the canonical qty-desc rollup survives as the
  tiebreak.
- Expand All / Collapse All over both the group accordions and the per-item
  drill-downs. Collapse All returns to the default view rather than closing
  the groups as well.
- Export CSV in this view now orders the per-line manifest by item code, so
  every line for one item lands together with its sponsor and booth — the
  OVERALL sheet the logistics team reconciles against. item_code was already
  in the endpoint's ordering_fields; no backend change.

The rollup is derived client-side from rows the whole-set fetch already
loads, so none of this adds an API call.

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

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@caseylocker, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 51 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 39a6fe68-772c-4e23-821e-8b5b65c0b830

📥 Commits

Reviewing files that changed from the base of the PR and between f7e0bf5 and 6ae3a93.

📒 Files selected for processing (2)
  • src/components/sponsors/reports/ByItemView.js
  • src/pages/sponsors/sponsor-reports/purchase-details-report-page/__tests__/index.test.js
📝 Walkthrough

Walkthrough

The By Item purchase details report now supports cross-sponsor aggregation, client-side sorting, sponsor and all-sponsors layouts, bulk expansion controls, Redux sort state, and CSV exports ordered by item code.

Changes

By Item report

Layer / File(s) Summary
Shared aggregation and sorting
src/components/sponsors/reports/ByItemView.js, src/components/sponsors/reports/__tests__/ByItemView.test.js
Shared helpers aggregate item rows across sponsors, preserve contributor details, exclude canceled-only quantities, and sort derived items with stable behavior.
Layouts and interaction controls
src/components/sponsors/reports/ByItemView.js, src/components/sponsors/reports/__tests__/ByItemView.test.js, src/i18n/en.json
The view supports sponsor and all-sponsors layouts, sortable headers, layout-specific pagination, contributor expansion, and expand/collapse-all controls.
Redux and CSV integration
src/actions/sponsor-reports-actions.js, src/reducers/sponsors/sponsor-reports-purchase-details-by-item-reducer.js, src/pages/sponsors/sponsor-reports/purchase-details-report-page/index.js
By Item sort state is stored and wired through the report page, while CSV export forwards item_code ordering.
Integration tests
src/actions/__tests__/sponsor-reports-actions.test.js, src/pages/sponsors/sponsor-reports/purchase-details-report-page/__tests__/index.test.js, src/reducers/sponsors/__tests__/sponsor-reports-purchase-details-by-item-reducer.test.js
Tests cover ordered export requests, page wiring, default sort state, and reducer updates.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant ByItemView
  participant PurchaseDetailsReportPage
  participant Redux
  participant ExportPurchaseDetailsLinesCsv
  User->>ByItemView: choose layout or sort column
  ByItemView->>PurchaseDetailsReportPage: invoke callback
  PurchaseDetailsReportPage->>Redux: update By Item sort state
  Redux-->>PurchaseDetailsReportPage: provide order and orderDir
  User->>PurchaseDetailsReportPage: export By Item lines
  PurchaseDetailsReportPage->>ExportPurchaseDetailsLinesCsv: pass filters and item_code
Loading

Possibly related PRs

Suggested reviewers: santipalenque, smarcet

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly reflects the main change: adding a show-wide By Item view for sponsor reports.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/purchase-details-by-item-all-sponsors

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@caseylocker caseylocker self-assigned this Jul 28, 2026

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/actions/__tests__/sponsor-reports-actions.test.js (1)

1025-1041: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Add the negative case alongside this one. The default (no-order) export now always spreads order: null; assert that the emitted params carry no order key so a serializer change can't silently start sending an empty ordering param on the Line Items export.

💚 Suggested addition
it("exportPurchaseDetailsLinesCsv omits the ordering param when no alias is given", async () => {
  await exportPurchaseDetailsLinesCsv({ status: "Paid" })(dispatch, getState);
  const [, params] = getCSV.mock.calls[0];
  expect(params.order).toBeUndefined();
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/actions/__tests__/sponsor-reports-actions.test.js` around lines 1025 -
1041, Add a test beside the existing exportPurchaseDetailsLinesCsv ordering test
that invokes the action without an ordering alias and asserts the generated
params have no order key (params.order is undefined).
src/components/sponsors/reports/ByItemView.js (1)

252-259: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Stale ItemTable doc comment sits above ItemGroup. Lines 252-255 describe ItemTable/showSponsor but are attached to ItemGroup; move them down to the ItemTable declaration at Line 288.

♻️ Suggested move
-// The item table both layouts render: one row per item_code with the purchased
-// aggregates, expanding to the orders that contributed. `showSponsor` adds the
-// Sponsor column to the drill-down for the all-sponsors layout, where the
-// sponsor is no longer carried by a parent accordion.
 // The group container BOTH layouts render: an accordion whose summary carries

and above const ItemTable = ({ (Line 288):

+// The item table both layouts render: one row per item_code with the purchased
+// aggregates, expanding to the orders that contributed. `showSponsor` adds the
+// Sponsor column to the drill-down for the all-sponsors layout, where the
+// sponsor is no longer carried by a parent accordion.
 const ItemTable = ({
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/sponsors/reports/ByItemView.js` around lines 252 - 259, Move
the stale documentation comment from above ItemGroup to directly above the
ItemTable declaration. Keep the existing ItemTable/showSponsor explanation
unchanged and leave the ItemGroup documentation with only content describing
ItemGroup.
src/pages/sponsors/sponsor-reports/purchase-details-report-page/__tests__/index.test.js (1)

200-207: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

By Item fixture lacks the new order/orderDir slice fields. mapStateToProps now reads them, so ByItemView renders with order === undefined here — no column is ever active and the page-level sort wiring stays untested. Mirror the reducer's defaults.

💚 Proposed fix
     sponsorReportsPurchaseDetailsByItemState: {
       data: byItemData,
       summary: null,
       currentPage: 1,
       perPage: 10,
+      order: "itemCode",
+      orderDir: 1,
       filters: byItemFilters,
       readError: byItemReadError
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/pages/sponsors/sponsor-reports/purchase-details-report-page/__tests__/index.test.js`
around lines 200 - 207, Update the sponsorReportsPurchaseDetailsByItemState
fixture used by the ByItemView tests to include the reducer-default order and
orderDir fields. Keep their values aligned with the reducer defaults so
mapStateToProps receives valid sorting state and the page-level sort behavior is
exercised.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/pages/sponsors/sponsor-reports/purchase-details-report-page/__tests__/index.test.js`:
- Around line 83-90: The mocked action factory must include
setPurchaseDetailsByItemSort because mapDispatchToProps binds it and page-level
sorting invokes the resulting prop. Add a Jest mock for
setPurchaseDetailsByItemSort alongside setPurchaseDetailsByItemPaging, returning
the expected sort action shape used by handleByItemSort.

---

Nitpick comments:
In `@src/actions/__tests__/sponsor-reports-actions.test.js`:
- Around line 1025-1041: Add a test beside the existing
exportPurchaseDetailsLinesCsv ordering test that invokes the action without an
ordering alias and asserts the generated params have no order key (params.order
is undefined).

In `@src/components/sponsors/reports/ByItemView.js`:
- Around line 252-259: Move the stale documentation comment from above ItemGroup
to directly above the ItemTable declaration. Keep the existing
ItemTable/showSponsor explanation unchanged and leave the ItemGroup
documentation with only content describing ItemGroup.

In
`@src/pages/sponsors/sponsor-reports/purchase-details-report-page/__tests__/index.test.js`:
- Around line 200-207: Update the sponsorReportsPurchaseDetailsByItemState
fixture used by the ByItemView tests to include the reducer-default order and
orderDir fields. Keep their values aligned with the reducer defaults so
mapStateToProps receives valid sorting state and the page-level sort behavior is
exercised.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7a1b9a98-599a-4892-8b0c-f3fe72d70186

📥 Commits

Reviewing files that changed from the base of the PR and between 53b15bf and f7e0bf5.

📒 Files selected for processing (9)
  • src/actions/__tests__/sponsor-reports-actions.test.js
  • src/actions/sponsor-reports-actions.js
  • src/components/sponsors/reports/ByItemView.js
  • src/components/sponsors/reports/__tests__/ByItemView.test.js
  • src/i18n/en.json
  • src/pages/sponsors/sponsor-reports/purchase-details-report-page/__tests__/index.test.js
  • src/pages/sponsors/sponsor-reports/purchase-details-report-page/index.js
  • src/reducers/sponsors/__tests__/sponsor-reports-purchase-details-by-item-reducer.test.js
  • src/reducers/sponsors/sponsor-reports-purchase-details-by-item-reducer.js

…el sorting

The revert of the client-side rollup CSV also took out the
setPurchaseDetailsByItemSort entry it had added to the page test's action
mock, so mapDispatchToProps bound the prop to undefined. Nothing caught it:
there was no page-level test that sorts. Adding one first reproduced it as
"TypeError: setByItemSort is not a function".

Restores the mock, mirrors the reducer's order/orderDir defaults in the
buildState fixture (without them no column renders active), and adds the
page-level test that clicks a sort header and asserts the thunk fires.

Also moves the ItemTable doc comment back above ItemTable — inserting
ItemGroup had orphaned it above the wrong function.
@caseylocker

Copy link
Copy Markdown
Author

Worked through the three nitpicks from the review body. Two applied, one declined.

Fixture missing order/orderDir (purchase-details-report-page/__tests__/index.test.js): applied in 6ae3a93. This is the same gap as the mock issue seen from the other side. Without those fields no column rendered as active, so the page level sort path could not be exercised at all. The fixture now mirrors the reducer defaults, and the new page level sort test depends on it.

Stale ItemTable doc comment (ByItemView.js): applied. Inserting ItemGroup left that comment sitting above the wrong function. Moved back above ItemTable.

Negative case for the ordering param (sponsor-reports-actions.test.js): declining, already covered. The existing test exportPurchaseDetailsLinesCsv → lines URL, no order, lines filename calls the action with no alias and asserts expect(params).not.toHaveProperty("order"), which is the assertion suggested. buildReportQuery gates on if (order), so null never reaches the params, and that test fails if a change ever lets it through.

Full suite green at 153 suites / 1428 tests.

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 PR enhances the Sponsor Reports → Purchase Details By Item view to support a warehouse “pull sheet” workflow by adding a show-wide, item-aggregated layout (across all sponsors), plus persistent client-side sorting, bulk expand/collapse controls, and CSV export ordering by item code so lines for the same item are grouped together.

Changes:

  • Added a By Sponsor / All Sponsors layout toggle, including show-wide item rollups with sponsor attribution in the drill-down.
  • Implemented sortable rollup columns (persisted in the by-item reducer slice) and expand/collapse all across groups and item drill-downs.
  • Updated lines CSV export from the By Item view to pass order=item_code to group exported lines by item.

Reviewed changes

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

Show a summary per file
File Description
src/reducers/sponsors/sponsor-reports-purchase-details-by-item-reducer.js Adds persisted sort state (order/orderDir) for the By Item slice.
src/reducers/sponsors/tests/sponsor-reports-purchase-details-by-item-reducer.test.js Adds coverage for default sort and SET_SORT behavior.
src/pages/sponsors/sponsor-reports/purchase-details-report-page/index.js Wires new layout toggle, sorting, item rollup, and CSV export ordering into the page.
src/pages/sponsors/sponsor-reports/purchase-details-report-page/tests/index.test.js Tests CSV export ordering and sort dispatch wiring from the page.
src/i18n/en.json Adds UI strings for layout toggle, pagination label, and expand/collapse actions.
src/components/sponsors/reports/ByItemView.js Implements shared accumulation for both layouts, show-wide item grouping, sorting UI, and expand/collapse all.
src/components/sponsors/reports/tests/ByItemView.test.js Adds extensive tests for show-wide grouping, sorting behavior, and expand/collapse semantics.
src/actions/sponsor-reports-actions.js Adds sort action + LINES_ORDER_BY_ITEM constant and updates lines CSV export to accept an order param.
src/actions/tests/sponsor-reports-actions.test.js Tests passing the ordering alias through to the lines CSV export query.

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

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