If a screen finds two records but an export includes something else, which result should a user trust? I wanted to define “the same conditions” before adding the export button.
The earlier reporting article explained counting and output scope. Here I implement a new independent query model that feeds pages, exported values and summary from one normalized selection.
Choose company scope before applying search
The query accepts company_id, status and q. A real server must choose company from an authenticated context rather than an arbitrary client field. This example receives already-read synthetic rows and applies company filtering. Which records may be read and how a search narrows them remain different decisions.
Rows contain an identifier, synthetic ordering tick, quantity and state. No client names are imported. Search is deliberately limited to a case-insensitive ID substring. I do not present it as a full search engine; the experiment tests which conditions all read paths should share.
Interpret the query once
make_snapshot accepts known keys, applies defaults and normalizes the search term. Undefined keys are rejected rather than silently ignored. It selects rows, establishes an order and creates an immutable copy. Other functions consume that result instead of interpreting the conditions again.
page returns a portion, export_rows returns every selected row, and summary counts and totals the same selection. No second export filter is introduced. Letter-case normalization also happens once, preventing the page and export from interpreting the search term differently. Whether export means the visible page or all matching rows is a product contract. This implementation returns the complete selection as Python values, not an actual generated or downloaded file.
Exclude fields from the response, not just the screen
Returned rows contain only ID, tick, quantity and state, even if source objects have additional fields. Hiding an internal note visually should not allow it to appear in export. A test adds a synthetic secret field and verifies its absence from the projection, without using actual sensitive data.
That allowlist does not complete every role’s permission policy. A real server must determine accessible records and fields before making the appropriate projection. This module assumes a trusted caller supplies the correct company scope. A useful search function does not establish that authentication and API enforcement have also been built.
Concatenate pages and compare the complete selection
Selecting draft records in company A produces two synthetic rows with a quantity sum of nine. With a page size of one, the first and next page together must exactly equal export_rows. Rows sharing a tick use ID as a stable tie-breaker. The test compares identities and values rather than only a matching count.
Editing the source array does not alter an existing snapshot. This is not a consistent database-read implementation: copying an already inconsistent input array cannot repair its upstream read. A production store needs its own read boundary. I preserve that input condition alongside the actual result of this experiment.
Let the button describe its output scope
A complete filtered export should be described that way. Exporting only the current page needs a different promise, and exporting selected rows needs an explicit selection rule within the authorized query. Pagination, selection and permissions must not silently change behind the phrase “same conditions.”
The package checks every page against export, limited fields, empty results and invalid conditions. It does not test real file delivery or rendered-browser interaction. I share a way to verify that the search box and export action answer the same question, with code and fixed synthetic execution evidence.