Tau.Acuvim
Per-customer cost over a UTC time range, joining the fleet hierarchy:
hourly_per_device CA × Devices × Sites × Municipalities × active Tariff
× period (in the municipality's local time) → per-bucket kWh × rate.
Per-day rollup + per-device breakdown. VAT applied per bucket so cost
stays correct across mid-window tariff changes.
Backend
- FleetCostService.ComputeAsync(customerId, fromUtc, toUtc):
- Loads device→site→municipality mapping (small per customer).
- Loads tariffs (with periods) grouped by municipality, ordered by
EffectiveFrom desc for active-tariff lookup.
- Reads hourly buckets in range from fleet.hourly_per_device via
raw ADO (the CA isn't an EF entity).
- For each bucket: pick active tariff for the bucket's date, convert
bucket start to local time via Municipality.TimeZoneId, pick the
matching period (or default rate), compute base + VAT.
- Rolls up per UTC date + per device. Tracks BucketsWithoutTariff
when site has no muni or no tariff covers the bucket date.
- New DTOs: FleetCostDto / FleetCostDayDto / FleetCostDeviceDto.
- Endpoint: GET /api/fleet/customers/{id}/cost?from&to. AdminOnly.
Validation: to > from, range <= 366 days (BadRequest on violation).
- Period-selection helper duplicated from CostCalculator (5 lines;
generic abstraction across TariffPeriod / FleetTariffPeriod is
more code than the duplication).
- Fixed monthly charges deliberately NOT applied (whole-month billing
concept; FixedMonthlyChargesIncluded=false in the response).
Frontend
- AdminCustomerDetailPage gets a Cost tab:
- RangePicker with quick ranges (Today, Last 7d, Last 30d, This
month). Default last 7 days.
- 4 Statistic cards: total kWh, base cost, VAT, total.
- Warning alerts: when buckets-without-tariff > 0; always-on info
that fixed monthly charges aren't included.
- Per-day table + per-device table.
Verified end-to-end on the running stack
- Patched DEV0001's existing site to LocalMunicipalityId=1
(Phase 23 test municipality with Domestic TOU tariff).
- Ingested 3 measurements at 10:00 / 10:20 / 10:40 UTC with kWh
totals 2000 / 2020 / 2050 → hourly CA bucket has delta = 50 kWh.
- Total kWh in window = 56 (50 from new bucket + 6 from earlier
Phase 14 backfill bucket).
- Tariff resolution: 10:00-12:00 UTC = 12:00-14:00 SAST, which is
neither Peak (17:00-20:00 weekdays) nor Off-Peak (weekends only)
→ defaults to 2.50/kWh.
- 56 × 2.50 = 140.00 base ✓
- 140 × 0.15 = 21.00 VAT ✓
- Total 161.00 ✓ exactly what the API returned.
Docs: FLEET-DESIGN.md §11 row updated — tariff sync + cost compute
both marked as shipped.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|---|---|---|
| console | ||
| docs | ||
| firmware | ||
| portal | ||
| .gitignore | ||
| CLAUDE.md | ||