Add TCO (total cost of ownership) reporting#82
Merged
Conversation
0da1efa to
04f36f2
Compare
Plans a fleet-wide/per-vehicle total-cost-of-ownership tab built on top of the existing Glovebox document pipeline, with straight-line depreciation and CSV export.
Corrected against the actual SQLBoiler-generated types (VehicleTcoSetting, types.NullDecimal) rather than the plan's assumed VehicleTCOSetting/null.Float64.
Exposes the TCOService (settings CRUD, vehicle/fleet summaries, CSV export) built in Tasks 1-4 over HTTP, following the documents.go controller pattern for tenant/vehicle authorization.
Implement frontend types and service layer for TCO reporting feature. - TCOSettings, LineItem, VehicleTCOSummary, FleetTotals, FleetTCOSummary types - TCOService singleton with methods for settings, summary, vehicle detail, and CSV export - Follows existing document-service pattern with ApiService and TenantService integration Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds 'dimo.document.vehicle.fuel' to CE_TYPE_TO_LABEL and UPLOAD_CATEGORIES. Introduces COST_ELIGIBLE_CATEGORIES Set to track which document types can carry cost amounts and count toward TCO operating costs. Mirrors the backend's CostEligibleCETypes from tco_service.go. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds tco-view.ts rendering the fleet TCO summary table (via TCOService from Task 6), with a CSV export button, and wires it into the side nav and app-root router as a new /:tenantId/tco route.
…r-vehicle export Replaces Task 9's openVehicle stub with a full drilldown view: category cost breakdown, line-item table, an acquisition settings form (purchase price/date/useful life), and a per-vehicle CSV export.
…settings error on vehicle switch Deleted Glovebox documents (tombstone CEs) kept contributing to TCO cost totals and CSV exports forever because VehicleSummary read the same fetch-api entries as ListDocuments but never filtered tombstoned ids. Extracted the tombstone-id-parsing logic into a shared gateway.TombstonedIDs helper so both call sites stay in sync going forward. Also fixes tco-view's openVehicle leaking a stale settingsError from a previous vehicle's failed save into the next vehicle's drilldown.
…issing permissions and hidden vehicles Restyled tco-view.ts to use the app's shared header.top-bar/tenant-switcher/ table conventions (previously it had ad-hoc styling that didn't match the rest of the app). The fleet table now loads the vehicle list first (fast) and fills in each vehicle's cost figures in the background (mirroring Glovebox's doc-count prefetch pattern), instead of blocking the whole view on the slowest vehicle's fetch-api round trip. Vehicles the dev license lacks SACD permissions for previously returned a raw 500 and left their row stuck in perpetual "loading" once the table started rendering progressively. TCOService.VehicleSummary now detects this case the same way DocumentsController.ListDocuments already does, and the row shows a "No access" badge instead. Vehicles hidden via the Fleet List view are now hidden here too by default, with the same "Show hidden vehicles" toggle used there.
… paginate Caching: TCOCache (mirrors FleetCache) holds the last-loaded vehicle list and per-vehicle cost figures, keyed by tenant. Revisiting the TCO tab now paints instantly from cache instead of re-fetching the whole fleet; a manual refresh button forces a full reload. Cache is invalidated whenever something could make it stale — a Glovebox upload, a delete, a settings save, or a backfilled amount. Backfill: documents uploaded without an amount (including everything from before this feature existed) can now get one after the fact. Since CloudEvents are immutable, backfilling emits a new "cost-amendment" CE that references the original document by id rather than mutating it — the same pattern dimo.tombstone already uses for delete. VehicleTCOSummary now returns a MissingAmounts list; the drilldown offers an inline amount input per missing document. Pagination: the fleet table shows 10 vehicles per page. The "Fleet total" footer row is always summed across every visible vehicle regardless of which page is showing, not just the current page.
…zation main merged per-member fleet-group access control (VehicleService.GetVehicle/ ListVehicles gained an allowedGroupIDs param) since this branch was cut. TCOService.VehicleSummary/FleetSummary and TCOController now thread GetAllowedGroups(c) through the same way documents.go/telemetry.go already do, so limited members are correctly scoped to their accessible groups instead of failing to compile. Also regenerates xliff/es.xlf and src/generated/locales/es.ts for the new TCO strings — CI's localize:check requires these committed in sync with source.
04f36f2 to
44a60cf
Compare
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.
Summary
Adds a fleet-wide and per-vehicle Total Cost of Ownership report, built on top of the existing Glovebox document pipeline.
vehicle_tco_settingstable (optional per-vehicle acquisition price/date/useful-life),TCOService(cost-eligibility filtering, amount extraction, straight-line depreciation, CSV export), andTCOControllerexposing/tco/*routes under the existing tenant-scoped JWT auth.FleetCachepattern, invalidated on upload/delete/settings-save/backfill), a way to backfill cost amounts onto documents that were uploaded without one (via a non-mutating "cost-amendment" CloudEvent, following the same patterndimo.tombstoneuses for delete), respecting hidden vehicles from the Fleet List view, and pagination (10 rows/page, fleet total always summed across all vehicles).Test plan
go build ./...,go vet ./...,go test ./...all pass (unit tests cover cost-eligibility, amount extraction, depreciation math, CSV export, tombstone exclusion, and cost-amendment parsing)tsc --noEmitandnpm run buildpass with no new lint errors/tco/*routes are correctly gated behind JWT auth (same as/documents/*), fleet table + drilldown render against a live tenant, styling matches the rest of the app🤖 Generated with Claude Code