Skip to content

Pallets For Sale

The Pallets For Sale tool lives at /sales/pallets on the ReturnPro dashboard. It was ported from Alejandro's Lovable project so the rules round-trip between the two apps; both teams edit the same rule set, both apps read the same trend snapshots.

What it does

Sales reps upload a fresh FMSI XLSX export. The tool streams-parses the file in the browser via a Rust/WASM module, applies eight exclusion-rule groups that decide which pallets are available for sale, and writes back the rule decisions plus a snapshot for trend analysis.

Auth: dual Supabase

The page is gated behind ReturnPro auth, but the data lives in the legacy Lovable Supabase.

ConcernBackend
Auth (session, role, sales_access flag)ReturnPro Supabase (vvutttwunexshxkmygik.supabase.co).
Pallet data, exclusion rules, trend snapshotsSales (Lovable legacy) Supabase (tgysafeenbcosudycymw.supabase.co).

The middleware at dashboard-returnpro/middleware.ts enforces auth on all /sales/* routes; the page-level permission check uses usePermissions().hasSalesAccess which reads user_profiles.sales_access from the ReturnPro instance.

The Sales (Lovable) client is constructed with plain createClient (not createBrowserClient) and persistSession: false — it is a data-only client and does not own the auth session.

Streaming XLSX parser

FMSI exports run >400 k rows. Loading the whole workbook into memory crashes mobile Safari. The tool ships a Rust/WASM streaming parser built on the calamine crate that:

  • Parses the XLSX in the browser (no server upload).
  • Emits zero-copy Transferable ArrayBuffer batches to the React side via postMessage.
  • Streams rows past the dim transformations and rule engine without ever materializing the whole sheet.

This keeps memory flat at a few MB regardless of the file's row count.

Exclusion rule groups

The tool implements eight exclusion rule groups. Each group operates on a different dimension of the pallet record:

  1. Sorting category.
  2. Place name.
  3. Consignment facility.
  4. Owned-program exclusion.
  5. Exclusion reasons.
  6. B2B exclusions.
  7. Conditional sorting.
  8. Stored-to-non-listable.

Rules are stored in the Sales Supabase. Editing rules in either ReturnPro's /sales/pallets UI or in Alejandro's Lovable app round-trips because both apps point at the same rules table.

Trend snapshots

After each run, the tool writes a snapshot of the rule-decision counts to the Sales Supabase. The trend chart on the page reads recent snapshots so you can see how the available-pallet count has shifted over time without re-running the parser on historical files.

Operational notes

  • The page is at /sales/pallets. The auth middleware redirects unauthenticated users to login; users without sales_access see a forbidden page.
  • The Rust/WASM module is pre-built and committed; rebuilding it requires the Rust toolchain (wasm-pack build).
  • Because data lives in the Sales (Lovable) Supabase, dropping that instance breaks the tool. There is no failover; if the legacy DB is decommissioned, the rules and snapshots need to migrate first.

For full background, see the project memory entry for Pallets For Sale (project lead notes, Rust/WASM tradeoffs, and Lovable-app interop) at dashboard-returnpro/CLAUDE.md.

Built by Carlos Lenis in Miami