Skip to content

July 10, 2026 — Backend

Release date: Friday, July 10, 2026

Summary

This week added two BMS-facing API surfaces: portfolio dashboard read models for buildings and coverage lines (slim, unpaginated lists the UI can join client-side), and per-user UI preferences persisted server-side so layout, theme, and dashboard widget state survive across devices.

Shipped

  • Portfolio dashboard APIs: GET /api/v1/portfolio/buildings and GET /api/v1/portfolio/coverage-lines?year= return full slim lists for UI aggregation; guarded by building.view and coverage.view respectively; no backend KPIs or pagination.
  • User UI preferences: GET and PATCH /api/v1/me/preferences store a versioned JSON payload (view mode, theme, sidebar, table settings, dashboard widgets/layout); JWT-only; PATCH is a full replace (upsert).
  • Schema: New UserUiPreference table with one row per user; migration 20260710130000_add_user_ui_preference.
  • Docs and contract: docs/USER_UI_PREFERENCES.md, portfolio notes in docs/API_REFERENCE_DATA.md, http/api.http, and OpenAPI regenerated.

Engineering (commit recap)

Backend — week of July 5 – July 10, 2026

Window: 2026-07-04 < commit date < 2026-07-11 (git log --no-merges).

Summary

Two feature commits landed on July 10. The portfolio module introduces dedicated read endpoints that avoid changing existing list APIs—buildings and coverage lines are mapped to slim DTOs for dashboard joins on buildingId. The user UI preferences module adds a UserUiPreference entity, validation DTOs with defaults on GET, and full-replace PATCH semantics separate from notification preferences.

Themes

  • Portfolio read models: New PortfolioModule with controller, service, mapper, and specs; buildings exclude soft-deleted rows; coverage lines filter by year; optional page/limit query params are accepted but ignored for backward compatibility with existing UI clients.
  • User UI preferences: MeUiPreferenceController and UserUiPreferenceService with nested payload validation (buildingsViewMode, theme, sidebarCollapsed, tables, dashboardWidgets, dashboardLayout); defaults returned when no row exists (updatedAt: null).
  • Testing: Controller, service, mapper, and DTO specs for both features (portfolio query DTO edge cases; preference defaults, full replace, validation).
  • Documentation: USER_UI_PREFERENCES.md describes request/response shape and full-replace semantics; NOTIFICATIONS.md links to UI prefs; API reference updated for portfolio endpoints.

Notable fixes or risks (if any)

  • PATCH body shape: Clients must send { "version": 1, "payload": { ... } }—top-level preference fields are rejected (400) under global forbidNonWhitelisted. Frontend should wrap prefs in payload and read response.data.payload.
  • No server-side aggregates: Portfolio endpoints intentionally omit KPIs, health rules, and summaries; the UI computes those from the returned lists.
  • Deploy: Restart the API after build so new routes (/portfolio/*, /me/preferences) are registered.