Commit graph

5 commits

Author SHA1 Message Date
d223592aec Exclude sub-meters from category subtotals in Estimates/Reports/internal API
Water Softener is configured as a submeter (parent_meter_id) of Main Hotel
Water, but estimates.js, reports.js, and internal.js's cost + estimate
routes summed every active meter flatly regardless of parent/child, double-
counting the softener's consumption on top of the main meter's own reading.

Sub-meter rows are still shown individually (useful for diagnostics), just
excluded from the category subtotal/total sums, with a 'submeter' badge on
the row explaining why. Fixes the water figures on Estimates, Reports, and
downstream consumers of internal.js (Directors report, Weekly Actuals).
2026-08-17 09:56:02 +00:00
a41b1171d3 Group Reports/Estimates by category, merge extras, add data-basis column
Reports and Estimates now group meters by category with a per-category
subtotal (in that category's own unit) instead of one flat list — the
grand-total row no longer sums consumption across categories, since
mixing kWh/m3/L is meaningless; money totals still sum fine.

On Reports: CCL, RAB levy and fixed extras collapse into one "Extras"
column/stat (still separately editable/stored, just merged for
display). New "Basis" column classifies how each meter's figure was
derived — Complete, Distributed (interpolated across a sparse-reading
gap), Up to date / As of [date] (real data short of period end), or
No data — via a new classifyBasis() in cost-calc.js.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 14:28:57 +00:00
3b261a4d8d Add Nuclear RAB levy, metering charge and DUoS catch-all to tariff cost model
The June electricity bill showed £252.72 (7.5% of the bill) in charges the
cost model didn't account for: Nuclear RAB Levy, Metering Charge, and DUoS
Availability/Excess/Reactive. RAB levy and metering charge are modeled
directly (same shape as CCL / standing charge); the DUoS charges need kVA
capacity and kVArh reactive energy that only the supplier's own meter reads,
so they're covered by one adjustable "other network charges" £/month field
to update manually from each bill.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-28 13:07:20 +00:00
7ab048931f Split cost/estimate across mid-period tariff changes
Rate changes are often scheduled ahead of time or confirmed by finance
after the fact and backdated — assign-tariff already supported any
effective_from date, but cost-calc previously priced a whole period at
a single tariff (whichever was in force on the period-end date),
silently mispricing the days on the other side of a change.

getTariffSegments() finds every tariff assignment overlapping a date
range; getMeterCostForPeriod/getMeterEstimateForPeriod now split
consumption pro-rata by day count across segments and price each
against its own tariff, summing to the period total. Estimates project
the remaining days across a future-scheduled change the same way,
rather than assuming today's tariff holds for the rest of the period.

Also consolidates internal.js's cost/estimate routes (previously their
own duplicate calc) onto the same shared functions reports.js and
estimates.js use, so the Directors' report can't drift from the in-app
numbers.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 17:43:45 +00:00
4fc5230d79 Initial commit — utilities app (meter readings, tariffs, cost tracking)
Fastify + pg backend, React/TS/Vite frontend. Categories (electric,
gas, oil, water), meters with sub-metering rollup, tariffs with
time-of-use rate windows, standing charges, Climate Change Levy and
VAT, manual reading entry, consumption/cost reports, period cost
estimates, and an API-key-gated /api/internal/* surface for the
reports app's Directors Report.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 17:33:42 +00:00