Commit Graph

69 Commits

Author SHA1 Message Date
675c10b949 feat(mako): add admin-selectable EDA communication method (email vs messenger)
- 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
2026-07-25 15:29:58 +02:00
459f976b67 feat(mako): add email-based EDA communication
- 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.
2026-07-25 15:29:43 +02:00
6cb4ff7a4a fix(frontend): add missing provideEcharts() to app config causing empty dashboard chart
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.
2026-07-24 15:57:35 +02:00
0ef4f94933 fix(frontend): add error handling for dashboard overview metering data API
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.
2026-07-24 15:27:36 +02:00
fb53b169a2 fix(community): migrate metering data timestamps from LocalDateTime to Instant to fix DST constraint violation
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
2026-07-24 13:23:35 +02:00
cfc32b3a7d chore: cleanup test data and add missing test files
- 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
2026-07-24 11:48:56 +02:00
2bb0f7114b refactor(community,tariff): fix code review findings - redundant DB queries, inconsistent imports, overly broad cascade
- 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
2026-07-24 10:24:38 +02:00
c6dfa31839 fix(frontend): pass userId to deleteUserTariff API to fix compilation error
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.
2026-07-24 09:43:37 +02:00
e46b21c8ca test(backend): add OpenAPI spec assertions + regenerate frontend API client
- Add acceptance criteria assertions to OpenApiGeneratorTest:
  - Verify /api/community/admin/memberships path exists
  - Verify /api/admin/users path exists
  - Verify getAllUsers operation exists
- Regenerate frontend API client from OpenAPI spec
- Fix frontend type error: remove unnecessary userId parameter
  from deleteUserTariff call (backend uses @CurrentUserId from JWT)
2026-07-24 07:30:26 +02:00
3e336ca3c9 feat(iam): add @PrePersist callback to auto-populate User.createdAt
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.
2026-07-24 07:11:52 +02:00
f1cf152091 chore: update OpenAPI spec, Angular config, and dev application settings 2026-07-23 15:03:17 +02:00
a8686718db chore(iam): enhance dev data initialization with test metering points and communities 2026-07-23 15:02:35 +02:00
765cbb0ec7 feat(dashboard): add metering data overview endpoint for user dashboard 2026-07-23 15:02:23 +02:00
5ff22e53bd feat(community): improve metering data upload with batch processing and deduplication 2026-07-23 15:02:02 +02:00
cab55c4abb Merge branch 'mimocode/cosmic-comet' of C:\Users\postm\.local\share\mimocode\worktree\f2606916-b9e4-4ea6-bb06-b44029fd350f\cosmic-comet 2026-07-23 14:17:46 +02:00
2261ffbbd3 feat-common-regenerate-openapi-spec 2026-07-23 14:16:35 +02:00
fe4ca2ccbd test(iam,community): add tests for getAllMemberships and getAllUsers
- 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
2026-07-23 14:13:14 +02:00
cf59de80bc feat(iam): add GET /api/admin/users endpoint for all-users overview 2026-07-23 14:07:13 +02:00
41e489a2dd Merge branch 'mimocode/clever-garden' 2026-07-23 14:03:14 +02:00
b7d7e22570 feat(iam): add AdminIamService.getAllUsers() 2026-07-23 14:02:23 +02:00
3fbf717bd5 feat(community): add GET /admin/memberships endpoint with tests 2026-07-23 13:59:53 +02:00
0092301ef4 Merge branch 'mimocode/misty-squid' 2026-07-23 13:55:55 +02:00
727105a92d Merge branch 'mimocode/proud-moon' 2026-07-23 13:55:47 +02:00
b80b22ea46 feat(iam): add UserRepository.findAllByOrderByCreatedAtDesc()
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>
2026-07-23 13:54:51 +02:00
a426a91cfa feat(community): add getAllMemberships() to MembershipService
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.
2026-07-23 13:53:04 +02:00
f7375dd9aa test(iam): verify createdAt is set during registration 2026-07-23 13:52:08 +02:00
72c29cfcc1 Merge branch 'mimocode/stellar-lagoon' into master 2026-07-23 13:47:19 +02:00
93c0151113 Merge branch 'mimocode/jolly-planet' into master 2026-07-23 13:47:06 +02:00
3f55d44fab feat(iam): add createdAt field to User entity
- 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
2026-07-23 13:45:55 +02:00
a96575d499 feat(community): extend PendingMembershipResponse with validFrom/validTo fields 2026-07-23 13:42:54 +02:00
c5ae6032c9 feat(community): add findAllWithDetails query to MembershipRepository
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.
2026-07-23 13:41:43 +02:00
a651ec946c feat(community): add metering data upload UI with preview and validation
- 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
2026-07-23 07:07:52 +02:00
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
975f76dbd3 feat(community): add metering data upload and query with XLSX support
Implement complete metering data management for energy communities:

- MeteringData entity with unique constraint (metering_point_id, interval_start, data_type)
- Bulk upload via JSON or XLSX (multipart) with validation
- XLSX parser using Apache POI with comma-decimal support
- Ownership check on GET endpoints (userId must match metering point owner)
- Deduplication: existing records overwritten on re-upload
- DataSource tracking (EMAIL_XLSX, API, MANUAL)
- Query endpoints: by metering point, by type, by upload batch

Additional fixes:
- MapStruct annotation processor: add to execution-level annotationProcessorPaths
  (Spring Boot parent POM was overriding plugin-level config)
- EnergyCommunityMapper + MeteringDataMapper: componentModel=spring
- UserMapper: ignore passwordResetToken/Expiry (unmapped target policy ERROR)
- TariffService: add TariffInviteRepository dependency + invitation check
- TariffServiceTest: add missing @Mock for TariffInviteRepository
- SecurityConfig: permit /actuator/health and /actuator/info
- pom.xml: add poi-ooxml, postgresql, spring-boot-starter-actuator
- .gitignore: add *.log, survey/, backend.log

Tests: 137/137 passing
2026-07-22 12:42:27 +02:00
949e1e6c34 feat(dashboard): add pending memberships card to admin overview
- 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
2026-07-22 10:59:01 +02:00
5949359216 fix(tariff): fix critical security and correctness issues from code review
- 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
2026-07-22 10:11:12 +02:00
0dfaa2d507 feat(tariff): implement complete tariff module with admin and user tariffs
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
2026-07-22 09:52:22 +02:00
fea8332976 refactor(mako,common): configurable topology delay, ThreadPool executor, event listener tests
- SimulatedEdaTopologyService: topology delay configurable via eda.simulation.topology-delay-ms
- Add AsyncConfig with ThreadPoolTaskExecutor (4 core, 8 max threads)
- Remove @EnableAsync from EegPortalApplication (now in AsyncConfig)
- Add topology-delay-ms and consent-delay-ms to application-dev.yml
- Add MakoConsentListenerTest (4 tests)
- Add MeteringPointEventListenerTest (5 tests)
- Add NotificationListenerTest (8 tests)
2026-07-22 09:21:25 +02:00
7baa1c72af refactor(common,community,mako): fix typos and remove dead code
- Rename MakoConsens* -> MakoConsent* (3 event classes + listener)
- Rename EdaCommuncationEventListener -> EdaCommunicationEventListener
- Rename PointType.PROSUME -> PROSUMER
- Remove dead SecurityConfig admin path matchers (actual security via @PreAuthorize)
- Regenerate OpenAPI spec and frontend API client
2026-07-22 09:15:27 +02:00
6770be9bef fix(security): externalize CORS origins, secure JWT secret default, fix RouterLink import
- 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)
2026-07-22 09:09:36 +02:00
0bfa0d98d5 test(dashboard,frontend): add DashboardControllerTest, fix broken spec files and add login tests
- 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
2026-07-22 08:39:58 +02:00
ef4eefa4cd fix(dashboard): fix NullPointerException in getUserDashboard
- @CurrentUserId resolves to String (JWT userId claim), not User entity
- Change parameter type from User to String, parse to UUID
2026-07-22 08:06:45 +02:00
93aa9fdff3 fix(security): externalize JWT secret via environment variable
- jwt.secret now reads from JWT_SECRET env var
- Falls back to dev default if not set
2026-07-22 07:50:27 +02:00
8546dcc508 test(iam,community): add unit tests for AuthService, AdminIamService, EnergyCommunityService
- AuthServiceTest: register, login, verifyEmail (7 tests)
- AdminIamServiceTest: approve, reject, getPendingUsers (7 tests)
- EnergyCommunityServiceTest: CRUD, member counts, delete guards (9 tests)
2026-07-22 07:42:47 +02:00
cadd5a697e feat(community): add metering point update endpoint and UI
- 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
2026-07-22 07:42:22 +02:00
caf282cb1e fix(mako): fix findPendingWithDetails query and OpenApiGeneratorTest
- 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
2026-07-22 07:41:52 +02:00
b0145f3b30 fix(security): fix critical security and error handling issues
Security:
- Change permitAll() to denyAll() for unlisted routes
- Add @PreAuthorize to membership endpoints
- Add ownership check in requestMembership
- Use AccessDeniedException instead of SecurityException

Error Handling:
- Add proper exception mapping for IllegalArgumentException (400)
- Add proper exception mapping for IllegalStateException (409)
- Add proper exception mapping for AccessDeniedException (403)
- Remove internal error messages from generic exception handler

Tests:
- Update MembershipServiceTest for new method signature
- Update MeteringPointServiceTest for AccessDeniedException
- All 37 tests passing
2026-07-21 16:27:35 +02:00
96bcf57cee feat(community): add metering point deletion with business rules
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
2026-07-21 15:06:48 +02:00
04be9a62ea feat(iam): add complete notification system with email and in-app notifications
Backend:
- Generalize MailService with send() method
- Add Notification entity, repository, service, controller
- Add NotificationListener for 6 domain events
- Add password reset flow (forgot-password, reset-password)
- Add configurable frontend URL in application.yml

Frontend:
- Add notification service and bell-icon component
- Add forgot-password and reset-password pages
- Add routes for new pages

Tests:
- Add NotificationServiceTest with 5 unit tests
- All 27 tests passing
2026-07-21 13:38:15 +02:00
a2025a55e4 fix(dashboard): optimize stats queries and add error handling
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
2026-07-21 13:07:19 +02:00