feat(well-show): generate the annual water quality report from well details - #354
Open
jirhiker wants to merge 6 commits into
Open
feat(well-show): generate the annual water quality report from well details#354jirhiker wants to merge 6 commits into
jirhiker wants to merge 6 commits into
Conversation
Adds a sandbox page that renders an owner-facing annual water quality report for a single well as a PDF: pick a well and a calendar year, preview it inline, download it. The report compares each result against EPA primary (MCL) and secondary (SMCL) drinking water standards so exceedances are called out rather than left for the reader to look up. Results print at the lab's precision — rounding an arsenic result of 0.012 mg/L to 0.01 would hide that it sits at the limit it is being compared against. Gated behind a new AMP.staging group while the report layout is under review. AMP.staging is deliberately not a rung on the Viewer -> Editor -> Admin ladder: holding AMP.Admin does not imply it, so the report cannot leak to admins before it is signed off. The local test identity holds it explicitly or the page is unreachable in dev. Refs BDMS-1189 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Puts the annual water quality report one click from the well it describes, instead of only in the standalone exporter where the well has to be looked up again. The report covers a single calendar year, so the button has to pick one. It reports on the most recent year the well was actually sampled rather than the current year — a well last sampled in 2024 would otherwise hand back an empty report, which reads as a broken button. Finding that year costs one row (newest sample, sorted descending), and the same row answers whether the well has any chemistry at all: with none, the button is disabled and says so on hover. The year's results are not fetched until the button is pressed. Most visits to a well page are not after a report, and the well and its contacts are already loaded by the page, so nothing extra is pulled for the common case. Generating and downloading the PDF is shared with the exporter's button rather than copied, and the reporting-window and sort rules now live in one place so the two entry points cannot drift into disagreeing about what a reporting year is. Gated on AMP.staging, matching the exporter. Closes BDMS-1189 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reworks the well details PDF actions into a report-type select plus the existing preview and download, replacing the standalone chemistry report button added in the previous commit. The button group grows a select offering "Field sheet" and "Chemistry report"; both actions then operate on whichever is chosen, so the group reads as one control rather than a row of per-report buttons that would grow with every new report type. Preview follows the selection. The field sheet keeps its existing preview route, and the chemistry report reuses the exporter page, which already renders a full preview — it now accepts thing_id and year so it opens on the report the well page asked for instead of an empty picker. A linked year outside the picker's five-year window is added to its options, since a well last sampled in 2019 must still be selectable on arrival. The chemistry report stays on AMP.staging: users without the group are not offered the option at all, and for a well with no chemistry on file both actions are disabled with the reason given, rather than generating an empty report. Refs BDMS-1189 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Selecting the chemistry report for a well with nothing on file disabled both preview and download, leaving the option a dead end. The exporter already generates that report and marks it as having no results, and a report stating a well has no chemistry on record is a legitimate thing to hand an owner, so the well page now does the same. A well that has never been sampled falls back to the current calendar year rather than having no year to report on. The actions are held back only while the reporting year is still being looked up, since acting early would report on the wrong year. The no-results case is called out on the controls up front instead of being discovered after opening the PDF. Refs BDMS-1189 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The report was built on `observation/water-chemistry`, which holds no water chemistry at all -- the data is in the legacy NMA tables. Every well therefore looked like it had never been sampled, which is why selecting the chemistry report on a well with decades of analyses offered nothing to generate. Points both entry points at `chemistry/results`, the new REST route over those tables. The response is flat and its ids are text, so `ChemistryObservation` (an alias for the generated type of an endpoint that serves none of this) becomes a hand-written `ChemistryResult`. Field parameters were split from laboratory results on `parameter_type`, which the legacy data does not carry. That split now follows `result_kind`, which reports the legacy table a result came from -- a field reading came off the wellhead, anything else came from a lab. Also corrects the staging group to `AMP.Staging`, the way Authentik and the API both spell it. Groups arrive as strings in the token's `groups` claim and are matched literally, so the old `AMP.staging` matched nothing: the report was unreachable everywhere except dev, where the test identity was seeded with the same wrong spelling. Verified against AR-0102, whose 2019 analyses come back as 20 major, 62 minor and 5 field results with a real secondary-standard exceedance (total dissolved solids 618 mg/L against a 500 mg/L guideline). Refs BDMS-1189 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Rebuilds the PDF against the reference report: navy masthead, letterspaced teal section rules with a source note on the right, bordered at-a-glance tiles, tinted exceedance callouts, a four-across well information grid, zebra tables with monospaced numerics, and status pills carrying each result's verdict. Three pages, matching the reference. Adds the water level section the reference leads with, so the report says what the water table did as well as what was in the water. Readings come from the groundwater level observations, and the newest reading from before the reporting year is carried in as well: a single year in isolation has nothing to compare against, and the at-a-glance change stat needs two points. Water elevation is the land surface elevation less the depth to water, printed only where a surveyed elevation is on file. The chemistry table keeps each parameter once, at its most recent value in the year, rather than the newest sample's rows. A well is rarely sampled for everything on one day -- majors from one trip, trace metals from another -- so keying the table to a single date dropped most of the record and left total dissolved solids called out as over its limit with no row to show for it. Rows are the ones measured against a standard, plus hardness, which has no standard but drives softener decisions; a hundred unregulated trace metals sitting at their detection limits buried the handful a reader can act on, so the rest are counted in a footnote instead. Legacy symbols with no lexicon term (CF, DO, ORP) are relabelled for print only. The API is right to leave them alone -- inventing a parameter name would put vocabulary in the record that nothing else knows -- but "CF" on a page handed to a well owner is noise, and none of them carry a standard, so relabelling cannot misapply a limit. No style sets lineHeight. react-pdf 4.4.0 renders any explicit value -- 1.0 and 1.55 alike -- with roughly double the leading, which double-spaced every wrapped paragraph. Its default metrics are correct. Hardness prints CaCO3 rather than a subscript for the same class of reason: Helvetica has no U+2083 and substitutes an italic f. The QR code, report ID, and supersedes line are left out rather than faked; no URL scheme or report registry exists to back them. Contact is aquifermapping@nmt.edu, (575) 835-5327. Refs BDMS-1189 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Preview DeploymentPreview URL: https://preview-feature-bdms-1189-chemistry-report-butto-auejgdbofq-uc.a.run.app |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes BDMS-1189.
What this does
Adds a report-type select to the PDF button group on the well details page, per the ticket's acceptance criteria. Both actions in the group act on the selection:
Preview follows the selection too: the field sheet keeps its existing preview route, and the chemistry report opens the exporter page, which already renders a full preview and now accepts
thing_idandyearso it lands on the report the well page asked for.Also included: the standalone Chemistry Report Exporter (sandbox), which is where the report layout is being iterated on.
Requires the API side first
Depends on
GET /chemistry/resultsfrom OcotilloAPI#870, already merged to staging. The report reads the legacy NMA chemistry tables through that route. The refactoredobservation/water-chemistryendpoint holds no water chemistry at all, so a report built on it came back empty for every well.Notable decisions
The reporting year is the most recent one sampled, not the current year. A well last sampled in 2019 would otherwise hand back an empty report, which reads as a broken button. A well with nothing on file still generates, marked as having no results — the same thing the exporter does, and better than a dead-end control.
The chemistry table shows each parameter once at its most recent value in the year. A well is rarely sampled for everything on one day: majors from one trip, trace metals from another. Keying the table to a single sample date dropped most of the record and left total dissolved solids called out as over its limit with no row to show for it.
Rows are curated to parameters measured against a standard, plus hardness. Sixty-odd unregulated trace metals sitting at their detection limits buried the ~20 a reader can act on; the rest are counted in a footnote.
Gated on
AMP.Stagingwhile the layout is under review — users without the group are not offered the option at all. This also corrects the group's spelling fromAMP.staging: groups arrive as literal strings in the token'sgroupsclaim, so the old spelling matched nothing and the feature was unreachable outside dev, where the test identity carried the same typo.No
lineHeightanywhere in the report styles. react-pdf 4.4.0 renders any explicit value — 1.0 and 1.55 alike — at roughly double the leading, which double-spaced every wrapped paragraph. Its defaults are correct.Verification
npx tsc --noEmitclean; 85 tests passNot included
🤖 Generated with Claude Code