Tau.Acuvim
Mirror the customer-side rate hierarchy (Municipality → Tariff →
TariffPeriod) to the central DB, scoped by CustomerId.
Per-municipality rate structure is preserved exactly as customers
configure it locally — each tariff still references its municipality
and carries its own per-period TOU rates.
Backend
- New fleet entities: FleetMunicipality, FleetTariff, FleetTariffPeriod.
Composite PKs (CustomerId, Id) like Sites/Devices so two customers'
rate trees never collide. FleetTariff has a real FK to
FleetMunicipality on (CustomerId, MunicipalityId); FleetTariffPeriod
cascades from its FleetTariff parent.
- Two new push batch types: "municipalities" (full set) and "tariffs"
(full set with periods nested inside each tariff). Push order per
tick: sites → devices → municipalities → tariffs → measurements.
- FleetIngestService dispatches the new types. Municipalities upsert
by (CustomerId, Id). Tariffs run inside a single transaction per
batch: upsert the tariff row, DELETE all periods for that tariff,
INSERT the new set — atomic period replacement matches the
customer-side UpsertTariffRequest semantics.
- FleetPushState gains ResourceMunicipalities + ResourceTariffs
constants so the per-resource cursor/backoff state has slots for them.
- FleetQueryService.GetCustomerDetailAsync now includes municipalities
and tariffs (with periods, with municipality name joined client-side
from the lookup dict). New DTOs: FleetMunicipalityViewDto,
FleetTariffViewDto, FleetTariffPeriodViewDto.
- AdminDbContext migration AddFleetRates creates the three tables and
their indexes/FKs.
Frontend
- Customer detail page gains a "Tariffs (N)" tab. Each tariff renders
as a collapsible card with its municipality, active flag, effective
window, default rate / fixed charge / VAT, and an inline period
table (Period name, day-of-week bitmask formatted as MTWTFSS, start,
end, rate). Empty state when no tariffs synced yet.
Verified end-to-end on the dev host
- Created "Phase23 Test City" municipality + "Domestic TOU" tariff
with two periods (Peak weekdays 17:00-20:00 @ 3.75, Off-Peak
weekends 00:00-23:59 @ 1.20) on the Client.
- Within one push tick (~20s) all three rows landed on Admin:
fleet.Municipalities (1), fleet.Tariffs (1), fleet.TariffPeriods (2).
- /api/fleet/customers/{id}/detail returns the full tree with
municipality name resolved.
Tests: 61/61 still passing.
Design doc (FLEET-DESIGN.md §11) updated — tariff sync row marked
shipped, cross-customer cost compute flagged as the natural next step.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|---|---|---|
| console | ||
| docs | ||
| firmware | ||
| portal | ||
| .gitignore | ||
| CLAUDE.md | ||