- Add EdaCommunicationMethod enum (EMAIL, MESSENGER)
- Add EdaSettings entity with DB-persisted communication method
- Add AdminEdaSettingsController (GET/PUT /api/admin/eda-settings)
- Add EdaCommunicationRouter that resolves the correct EdaConsentService
- Add MessengerEdaConsentService as placeholder (throws UnsupportedOperationException)
- Add AdminEdaSettingsComponent in frontend with radio button selection
- Route /dashboard/admin-eda-settings (ADMIN only)
- Update EdaCommunicationEventListener to use router
- Remove @Profile from EmailEdaConsentService/SimulatedEdaConsentService
- Use @Lazy for EdaMailSender dependency to support non-prod contexts
- Fix pre-existing deleteUserTariff API call mismatch
- Add EmailEdaConsentService for prod consent requests via SMTP
- Add EdaMailSender, EdaMailParser, EdaMailPoller for IMAP polling
- Polling interval: 15 min (configurable via eda.email.poll-interval-ms)
- Consumption data ingestion from XLSX email attachments
- Add @Profile('!prod') to SimulatedEda*Services as fallback
- Add EMAIL_AUTO to DataSource enum for automated email imports
- Add EDA email configuration to application-prod.yml and application-dev.yml
- Add unit tests for all new services
- Add docs/PLAN-EDA-KOMMUNIKATION.md with full implementation plan
All 232 tests passing.
Root cause: ngx-echarts v18+ requires provideEcharts() in the app
config. Without it, NgxEchartsDirective silently fails to render
charts, causing the dashboard overview chart to appear empty.
Added provideEcharts() to app.config.ts and added
DashboardServiceIntegrationTest for the metering data overview endpoint.
The empty error callback in loadMeteringData() silently swallowed API
failures, causing the chart to show 'Keine Daten' instead of the actual
error. Added proper error logging and user-facing error message.
Also added DashboardServiceTest for getMeteringDataOverview with
scenarios for data, no metering points, empty time range, and
multiple metering points.
Switch interval_start/interval_end from LocalDateTime to Instant across the
entire metering data stack (entity, DTOs, parser, repository, services, controllers).
This eliminates DST-related unique constraint violations that occurred when two
different wall-clock times mapped to the same epoch millis during CET/CEST transitions.
Key changes:
- MeteringData entity: intervalStart/intervalEnd now Instant
- XlsxMeteringDataParser: produces Instant via JVM timezone conversion
- MeteringDataRepository: all queries use Instant parameters
- MeteringDataService: simplified deduplicate() (Instant has no DST ambiguity)
- Added hibernate.jdbc.time_zone=UTC and test profile for in-memory H2
- Added MeteringDataUploadIntegrationTest with real H2 database
- Added DST-specific parser and service tests
- All 216 tests passing
- Add TariffInviteServiceTest, GlobalExceptionHandlerTest, setup-test.ts
- Add compose plans/specs docs
- Extend .gitignore with *.xlsx, *.ps1, *.http, *.py, *.docx
- Remove stale test data files and scripts from working tree
- TariffService: extract ValidatedUserTariffPoints record from validateUserTariffRequest to eliminate redundant MeteringPoint loads in createUserTariff/updateUserTariff (saves 2 SELECT queries per create call)
- TariffService: move source != target check into validateUserTariffRequest for single-responsibility
- MeteringPoint: restrict CascadeType from ALL to PERSIST/MERGE and remove orphanRemoval to prevent accidental cascade deletes of independent Memberships
- MeteringPointService, MembershipService, MeteringDataService, TariffInviteService, TariffService: replace FQ org.springframework.security.access.AccessDeniedException with imported short form for consistency
The generated API service requires userId as a second parameter for
deleteUserTariff(). Inject AuthService and use getCurrentUserId() to
provide the required argument, unblocking the entire frontend test suite.
Add onCreate() method with @PrePersist annotation that sets createdAt
to LocalDateTime.now() on first persist, consistent with other entities
(UserTariff, CommunityTariff, etc.). Guard prevents overwriting existing
values. Two new tests verify auto-population and idempotency.
- Add getAllMemberships_returnsAllStatuses: verifies PENDING, ACTIVE, INACTIVE
- Add getAllMemberships_collectsDistinctUserIds: verifies distinct user ID collection
- Add getAllUsers_returnsSortedByCreatedAtDesc: verifies sorting order
- Add getAllUsers_returnsEmptyList: edge case for empty user list
- Add getAllUsers_includesAllRegistrationStatuses: verifies all statuses present
- All 172 backend tests pass
Add method to retrieve all users ordered by creation date descending.
This supports the admin user management overview feature.
Tests:
- UserRepositoryTest: verify method exists and returns List<User>
Add @Transactional(readOnly = true) method that uses findAllWithDetails()
and batch-fetches users with the same lookup pattern as getPendingMemberships().
Returns List<PendingMembershipResponse> with all memberships (pending, active,
inactive) for the admin overview tab.
Tests: 3 new tests covering normal case, empty list, and missing user.
- Add createdAt LocalDateTime field with @Column(updatable = false)
- No @GeneratedValue - set manually during user creation
- Set createdAt in AuthService.register() and AdminDataInitializer
- Ignore createdAt in UserMapper (mapped manually, not from DTO)
- Add UserTest with 3 tests verifying field, annotation, and default
Add @Query with JOIN FETCH on meteringPoint and energyCommunity, no WHERE clause
to return all memberships regardless of status. Includes reflection-based unit test
verifying method existence and annotation correctness.
- Add frontend upload page with file selection, drag-and-drop, and preview
- Add preview endpoint (POST /api/community/metering-data/preview/xlsx)
- Validate FEED_IN only for PRODUCER, CONSUMPTION only for CONSUMER metering points
- Optimize deduplication with bulk query (fix N+1 problem)
- Eliminate duplicate DB query in validateRecords
- Add 4 new tests for data type validation
- Add navigation entry for admin users
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
- Add pendingMemberships field to AdminStats DTO
- Add 4th card 'Offene Mitgliedsanträge' to admin dashboard
- Rename 'Offene Freigaben' to 'Ausstehende Freischaltungen'
- Update DashboardService to count pending memberships
- Update tests to match new AdminStats structure
- Fix UserTariffController: use @CurrentUserId instead of broken extractUserId()
- Fix UserTariffController: use @PathVariable instead of @RequestParam for userId in delete
- Add @PreAuthorize annotations to all tariff endpoints (ADMIN for community, MEMBER for user)
- Add duplicate tariff prevention for (source, target) pairs
- Optimize membership check: replace N+1 query with efficient isActiveMemberOfCommunity()
- Update tests to match new membership check API
Backend:
- Add CommunityTariff entity (admin-managed max price + surcharge per community)
- Add UserTariff entity (user-agreed tariffs between metering points)
- Add TariffController (admin endpoints) and UserTariffController (user endpoints)
- Add TariffService with full validation (price <= max, ACTIVE state, membership)
- Add CommunityTariffChangedEvent and UserTariffChangedEvent
- Update NotificationListener to notify members on tariff changes
- Add 27 comprehensive tests for TariffService
Frontend:
- Add AdminTariffComponent (/dashboard/tariffs) for managing community tariffs
- Add UserTariffComponent (/dashboard/my-tariffs) for managing user tariffs
- Add routing and navigation entries
- Regenerate OpenAPI spec and frontend API client
Note: Old Tariff.java entity replaced by CommunityTariff + UserTariff
- Externalize CORS origins via app.cors-origins property (configurable per environment)
- Remove hardcoded JWT secret fallback; use env-var-only with safe test default
- Disable show-sql by default (enable only in dev profile)
- Create application-dev.yml with safe development defaults
- Add missing RouterLink import in MyMembershipsComponent (fixes runtime error)
- Add DashboardControllerTest with 4 tests for admin and user dashboard endpoints
- Fix incorrect class name imports in header, admin-user-approval, metering-points, verify-email specs
- Add missing ActivatedRoute/Router/AuthService providers in all spec files
- Replace stub login spec with 10 comprehensive tests (form validation, role redirect, error handling)
- Remove stale 'should render title' test from app.spec.ts
- Add UpdateMeteringPointRequest DTO (type-only update)
- Add PUT /{id} endpoint with owner and state validation
- Only NEW/REJECTED/ERROR states allow editing
- Frontend: inline edit form with type dropdown
- Frontend: updateMeteringPoint() service method
- Add 7 unit tests for update workflow
- Remove invalid JOIN FETCH mp.user from MembershipRepository query
(MeteringPoint has no @ManyToOne User field, only UUID userId)
- Fix OpenApiGeneratorTest: disable security filters for MockMvc,
use UTF-8 for getContentAsString and Files.writeString
Backend:
- Add deleteByIdAndUserId to MeteringPointRepository
- Add deleteOwnMeteringPoint with validation (owner, state checks)
- Add DELETE /{id} endpoint to MeteringPointController
Frontend:
- Add deleteMeteringPoint to MeteringPointService
- Add delete button with confirmation dialog
- Only show delete for inactive points (NEW, REJECTED, ERROR)
Business Rules:
- Only owner can delete own metering points
- Only inactive points (NEW, REJECTED, ERROR) can be deleted
- ACTIVE and WAITING_FOR_CONSENT points cannot be deleted
Tests:
- Add MeteringPointServiceTest with 10 unit tests
- All 37 tests passing
Backend:
- Add countByStatus() to MembershipRepository
- Add countByUserIdAndStatus() to MembershipRepository
- Add countByStatusAndEmailVerified() to UserRepository
- Add countByUserId() to MeteringPointRepository
- Optimize DashboardService to use count queries instead of findAll
Frontend:
- Add error signal and error message display
- Add loading spinner animation
Tests:
- Add DashboardServiceTest with 2 unit tests
- All 22 tests passing