PHASE 6: Communication & Events

Trigger: "Execute Phase 6 as per masterplan."

Goal: Email and push notification system, event/tournament management, and homepage generation for entities.

Prerequisite: Phase 5 is completed.

Step 6.0 — Technical Conception

Create doc/developer/conception/phase-6-conception.md.

(reference: Chapter 11 — Data Model, Chapter 12 — Integration)

Content: - Scope: membership-communication, membership-event (event part), homepage builder - Email Architecture: SMTP + Thymeleaf templates, per-entity branding, i18n (recipient locale) - Push Architecture: FCM (Android) + APNs (iOS), device token management - Homepage SSR: Thymeleaf server-side rendering, template schema, SEO - Design Chapter References: Ch11, Ch12

Result: Technical conception for Phase 6.


Step 6.1 — Communication Module

Create the membership-communication module.

(reference: Chapter 11 — Data Model, Chapter 12 — Integration)

Approach:

  1. Create JPA entities: - Communication fields:
Field Type Constraints Description
id Long PK
entityId Long FK NOT NULL Organization
memberId Long FK nullable Recipient member (null for broadcast)
templateId Long FK nullable Source template
channelCd String(20) NOT NULL EMAIL, PUSH, IN_APP, SMS
statusCd String(20) default 'PENDING' PENDING / SENT / DELIVERED / FAILED / BOUNCED
subject String(500) NOT NULL Rendered subject
body String NOT NULL Rendered body (HTML for email, plain for push)
recipientEmail String(255) nullable Email address
recipientDeviceToken String(500) nullable FCM/APNs token
sentAt Instant nullable When sent
deliveredAt Instant nullable When delivered (bounce tracking)
errorMessage String(500) nullable Delivery error
createdAt Instant auto
version Long @Version
  • CommunicationTemplate fields:
Field Type Constraints Description
id Long PK
entityId Long FK nullable null = system-wide template
name String(200) NOT NULL Internal name, e.g., "welcome_email"
typeCd String(50) NOT NULL WELCOME, VERIFICATION, PASSWORD_RESET, PAYMENT_RECEIPT, PAYMENT_FAILURE, CONTRACT_RENEWAL, COURSE_CANCELLATION, CUSTOM, SUPPORT_MACRO, HOMEPAGE
channelCd String(20) NOT NULL EMAIL, PUSH, IN_APP
locale String(10) NOT NULL e.g., 'de', 'en', 'ar'
subject String(500) NOT NULL Subject with {{variables}}
body String NOT NULL Thymeleaf template body
variables JSONB default '[]' Available variables: [{name, description, example}]
active boolean default true
createdAt Instant auto
updatedAt Instant auto
version Long @Version
  1. Create services: - NotificationService: send via channel (email/push/in-app), resolve template + variables, select locale from recipient User.locale - TemplateService: CRUD, variable substitution (Thymeleaf), per-entity branding (logo, colors, footer from Organization.settings), locale fallback chain (member locale → entity locale → 'en') - BulkMessageService: send to filtered member list (all, active contracts, specific template, custom filter), RabbitMQ queue notification.send for async processing, rate limiting (max 100/min per entity) - EmailSender: SMTP integration (Spring JavaMailSender), HTML rendering, per-entity SMTP config (or shared default), bounce tracking - PushSender: FCM (Android), APNs (iOS), device token management per member
  2. Create controller: - POST /api/communications/send — Send notification (single or bulk) - GET /api/communications — History (paginated, filterable by channel/status/member) - GET /api/communication-templates — List templates - POST /api/communication-templates — Create template - PUT /api/communication-templates/{id} — Update template - POST /api/communication-templates/{id}/preview — Preview with sample data
  3. Flyway: V600__create_communication.sql - Indexes: (entityId, channelCd, statusCd), (memberId), (templateId)
  4. Automated triggers (via RabbitMQ event listeners): - Member registration → welcome email - Email verification → verification link - Password reset → reset link - Payment received → payment receipt - Payment failed → payment failure notification - Contract renewal approaching → renewal reminder (30 days before) - Course cancelled → cancellation notification to all registrants
  5. Tests: NotificationServiceTest, TemplateServiceTest, BulkMessageServiceTest

Result: Multi-channel notifications with templates, automation, branding, and i18n.


Step 6.2 — Event and Tournament Management

(reference: Chapter 11 — Data Model, Chapter 08 — User Journeys)

Approach:

  1. Create JPA entity: Event - Event fields:
Field Type Constraints Description
id Long PK
entityId Long FK NOT NULL Organization
title String(255) NOT NULL Event title
description String(4000) Rich text description
typeCd String(50) NOT NULL TOURNAMENT, WORKSHOP, SOCIAL, CAMP, COMPETITION, OPEN_DAY
statusCd String(50) default 'DRAFT' DRAFT / PUBLISHED / CANCELLED / COMPLETED
startDateTime Instant NOT NULL Event start
endDateTime Instant NOT NULL Event end
registrationDeadline Instant nullable Registration closes
resourceId Long FK nullable Booked resource/room
maxParticipants Integer nullable Capacity (null = unlimited)
currentParticipants Integer default 0 Current count
waitListEnabled boolean default false Enable wait list
entryFee BigDecimal(19,4) nullable Entry fee (null = free)
currency String(3) default 'EUR'
isPublic boolean default true Visible to non-members
imageUrl String(500) nullable Event image
organizerUserId Long FK nullable Responsible staff
customAttributes JSONB default '{}' Category-specific fields
createdAt Instant auto
updatedAt Instant auto
version Long @Version
  • EventRegistration: id, eventId, memberId, status (REGISTERED/WAIT_LIST/CANCELLED), transactionId (FK nullable, if paid), registeredAt
  1. Create EventService: - CRUD with status transitions (DRAFT → PUBLISHED → COMPLETED) - Registration: validate capacity, move to wait list if full, generate Transaction if entryFee > 0 - Wait list: auto-promote when spot opens (notify via RabbitMQ) - Cancel registration: refund if paid (create storno transaction) - Cancel event: notify all registrants, refund all paid registrations - Upcoming events: public endpoint for published events, sorted by date - Resource booking: auto-book resource for event duration (conflict detection)
  2. Create controller: - POST /api/events — Create event (CLUB_ADMIN) - GET /api/events — List events (admin: all; member: published only) - GET /api/events/upcoming/{entityId} — Public upcoming events (no auth) - GET /api/events/{id} — Event detail with participant list (admin) - PUT /api/events/{id} — Update event - POST /api/events/{id}/register — Register for event (member) - DELETE /api/events/{id}/register — Cancel registration (member) - POST /api/events/{id}/cancel — Cancel event (admin)
  3. Member app: event list (card layout with image, date, title, spots remaining), event detail, register button
  4. Admin app: event management (DataTable), create/edit form, participant list with export
  5. Flyway: V601__create_event.sql, V602__create_event_registration.sql
  6. Tests: EventServiceTest — registration, capacity, wait list promotion, fee transaction, cancellation refund

Result: Event management with registration, capacity, wait list, payment, and resource booking.


Step 6.3 — Homepage Generation

Create entity-specific landing pages for member acquisition.

(reference: Chapter 09 — Frontend Strategy)

Approach:

  1. Server-Side Rendering (Thymeleaf): - Each entity gets a public page at /p/{entity-slug} - Thymeleaf template loaded from CommunicationTemplate (type: HOMEPAGE) - Data sources: organization settings, membership templates, course schedule, upcoming events
  2. Template Schema: - HomepageConfig JSONB in Organization entity: json { "heroTitle": "Welcome to FitClub Berlin", "heroSubtitle": "Your fitness journey starts here", "showPricing": true, "showSchedule": true, "showEvents": true, "accentColor": "#FF5722", "contactEmail": "info@fitclub-berlin.de" } - Admin UI: visual editor for homepage config fields
  3. SEO: - <meta> tags: title, description, og:image from organization logo - Structured data: LocalBusiness schema.org JSON-LD - Sitemap.xml generated from all active entity slugs
  4. Subdomain Support (optional): - Custom domain mapping: fitclub-berlin.membership-one.com or www.fitclub-berlin.de - DNS CNAME verification - TLS via Let's Encrypt wildcard or per-domain
  5. Cache: - Redis cache (5 min TTL) for rendered pages - Cache bust on organization settings update

Result: Each organization has a public-facing, SEO-optimized landing page.


Step 6.4 — Phase 6 Documentation

Update all doc files with communication, event, homepage features.


Step 6.5 — Update Intranet

Run python doc/intranet/build.py.


Phase 6 — Quality Gate

# Check Target
1 Conception exists
2 Compilation + tests 0 errors, 0 failures
3 Coverage >= 65%
4 Email notification sent to member, received
5 Event create -> register -> capacity tracking
6 Homepage /p/{slug} renders with organization data
7 SEO meta tags, structured data, sitemap
8 Documentation + intranet updated
9 CLAUDE.md updated

Report: "Phase 6 completed."

---