eeg_portal/eeg_frontend/src/app/services/consumption.ts
Bernhard Müller 4b7b26231f feat(community): add member consumption dashboard with coverage preview
Backend:
- ConsumptionDashboardService: aggregates consumption and community
  feed-in data with daily/hourly granularity based on date range
- Coverage calculation: min(consumption, communityFeedIn) per interval
- Ownership check on dashboard endpoint
- 6 new aggregate queries in MeteringDataRepository
- findActiveMeteringPointIdsByCommunityId in MembershipRepository
- 6 unit tests for ConsumptionDashboardService

Frontend:
- Apache ECharts via ngx-echarts for chart visualization
- ConsumptionDashboardComponent with metering point selector,
  date range picker, quick-range buttons (7/30/90 days)
- Chart: blue bars (consumption), green bars (covered), orange
  line (community feed-in), tooltip with coverage percentage
- Summary cards: total consumption, coverage %, feed-in, covered kWh
- Warning when user has no community membership
- Route /dashboard/consumption (MEMBER only)

Tests: 143/143 passing
2026-07-22 13:23:58 +02:00

53 lines
1.3 KiB
TypeScript

import { inject, Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment } from '../../environments/environment';
export interface IntervalData {
timestamp: string;
consumptionKwh: number;
communityFeedInKwh: number;
coveredKwh: number;
coveragePercent: number;
}
export interface Summary {
totalConsumptionKwh: number;
totalCoveredKwh: number;
totalCommunityFeedInKwh: number;
averageCoveragePercent: number;
}
export interface ConsumptionDashboardResponse {
meteringPointId: string;
atNumber: string;
energyCommunityId: string | null;
communityName: string | null;
from: string;
to: string;
granularity: 'DAILY' | 'HOURLY';
data: IntervalData[];
summary: Summary;
}
@Injectable({ providedIn: 'root' })
export class ConsumptionService {
private http = inject(HttpClient);
private apiUrl = `${environment.apiUrl}/api/community/consumption`;
getDashboard(
meteringPointId: string,
from: string,
to: string
): Observable<ConsumptionDashboardResponse> {
const params = new HttpParams()
.set('from', from)
.set('to', to);
return this.http.get<ConsumptionDashboardResponse>(
`${this.apiUrl}/${meteringPointId}/dashboard`,
{ params }
);
}
}