Files
cannamanage/docs/user-stories.md
T
Patrick Plate 706a6e257b feat(sprint7): Phase 1 — notifications enhancement + push infrastructure
Phase 1 (Notification Enhancement):
- Extended NotificationType enum (ADMIN_MESSAGE, INFO_BOARD_POST, FORUM_REPLY, FORUM_MENTION)
- Extended StaffPermission enum (SEND_NOTIFICATIONS, MANAGE_INFO_BOARD, MODERATE_FORUM)
- Extended AuditEventType with Sprint 7 events
- Flyway V11: notification_sends + notification_send_recipients tables
- NotificationSend + NotificationSendRecipient entities
- NotificationSendRepository + NotificationSendRecipientRepository
- Extended NotificationService with sendBroadcast() and sendToSelected()
- NotificationComposeController (POST /compose, GET /sends)
- ComposeNotificationRequest DTO

Phase 1B (Push Infrastructure):
- Flyway V12: device_tokens + notification_preferences tables
- DeviceToken entity + DevicePlatform enum
- NotificationPreference entity + NotificationChannel enum
- DeviceTokenRepository + NotificationPreferenceRepository
- DeviceRegistrationService (register/unregister/list devices, max 10 per user)
- NotificationPreferenceService (get/create defaults, update, IN_APP always on)
- NotificationDispatchService (multi-channel fan-out: WebSocket, Web Push, FCM, Email)
- WebPushSender (VAPID-based, simplified for MVP)
- FcmPushSender (graceful degradation if not configured)
- PushPayload DTO
- DeviceRegistrationController (POST/GET/DELETE /devices, GET /vapid-key)
- NotificationPreferenceController (GET/PUT /preferences)
- ConsentType extended (NOTIFICATION_PUSH, NOTIFICATION_EMAIL)
- TargetType enum (ALL, SELECTED)

Frontend:
- Updated sw.js with push event handler + notification click handler
- push-subscription.ts (subscribeToPush, unsubscribe, permission helpers)
- notification-compose.ts service (compose, sends, devices, preferences APIs)
- i18n keys (de.json + en.json) for compose, preferences, push, devices

Configuration:
- application-docker.properties: VAPID + FCM push config properties
- MemberRepository: added findAllActiveUserIds() for broadcast
2026-06-13 19:25:19 +02:00

505 lines
14 KiB
Markdown

# CannaManage — User Stories
**Version:** 1.0
**Date:** 2026-06-13
**Status:** Complete
---
## Persona: Admin/Staff (Vereinsverwaltung)
### US-A01: Admin Login
**As an** admin,
**I want to** log in with my email and password,
**So that** I can access the management dashboard securely.
**Acceptance Criteria:**
- Login page displays email and password fields
- Form validates email format (Zod schema)
- Empty fields trigger validation errors with `aria-invalid`
- Invalid credentials show localized error message
- Successful login redirects to `/dashboard`
- Password field is masked (type="password")
- Form is keyboard-navigable (Tab + Enter)
---
### US-A02: Dashboard Overview
**As an** admin,
**I want to** see KPI cards on my dashboard,
**So that** I can monitor club status at a glance.
**Acceptance Criteria:**
- Dashboard shows 4 KPI cards: Active Members, Distributions Today, Stock Level, Monthly Quota Used
- Quick actions section provides shortcuts to common tasks
- Recent distributions list shows latest activity
- Stock by strain visualization is present
- Page is responsive (cards stack on mobile)
- Dark/light mode renders correctly
---
### US-A03: Member List Management
**As an** admin,
**I want to** view, search, and paginate through members,
**So that** I can quickly find and manage club members.
**Acceptance Criteria:**
- Member table displays: name, email, status, joined date, member number
- Status badges show Active/Inactive/Suspended with color coding
- Search input filters members by name or email
- Pagination controls navigate between pages
- "Add Member" button navigates to creation form
- Clicking a member navigates to their detail page
---
### US-A04: Add New Member
**As an** admin,
**I want to** register a new member with their details,
**So that** they can start receiving distributions.
**Acceptance Criteria:**
- Form includes: first name, last name, email, date of birth, phone, notes
- All required fields show validation errors when empty
- Date of birth calculates age for KCanG compliance checks
- Email must be unique (backend validation)
- Success redirects to member detail page
- Cancel returns to member list without saving
---
### US-A05: Edit Member Details
**As an** admin,
**I want to** edit an existing member's information,
**So that** I can keep records current.
**Acceptance Criteria:**
- Form pre-fills with existing member data
- All editable fields can be updated
- Status can be changed (Active/Inactive/Suspended)
- Changes are saved with confirmation
- Audit event is logged on status change
---
### US-A06: Distribution List
**As an** admin,
**I want to** view all cannabis distributions with filters,
**So that** I can track dispensing history.
**Acceptance Criteria:**
- Table shows: date, member name, strain, amount (grams), recorded by
- Filter by time period: today, this week, this month, all
- Sort by date (newest first by default)
- "New Distribution" button starts the wizard
- Total distributed amount shown in header
---
### US-A07: Distribution Wizard (4-Step)
**As an** admin,
**I want to** record a distribution through a guided wizard,
**So that** quota limits are enforced before dispensing.
**Acceptance Criteria:**
- **Step 1:** Select member (search by name/number)
- **Step 2:** Quota check shows daily/monthly remaining (25g daily, 50g monthly)
- Under-21 shows 30g monthly limit and 10% THC restriction
- Blocks progression if limits exceeded
- **Step 3:** Select strain + enter amount (grams)
- THC% shown per strain for under-21 verification
- Amount cannot exceed available batch stock
- **Step 4:** Confirmation summary → submit
- Success creates distribution record + audit event
- Back navigation between steps preserves data
---
### US-A08: Stock/Batch Management
**As an** admin,
**I want to** manage cannabis batches in inventory,
**So that** I can track available stock.
**Acceptance Criteria:**
- Batch list shows: strain, THC%, CBD%, available grams, status
- Overview cards: total stock, active batches, low stock alerts
- Filter by strain or batch status
- "Add Batch" button opens creation form
- Stock levels update after distributions
---
### US-A09: Add New Batch
**As an** admin,
**I want to** register a new cannabis batch,
**So that** it becomes available for distribution.
**Acceptance Criteria:**
- Form includes: strain name, THC%, CBD%, total grams, harvest date, notes
- THC% and CBD% are numeric with validation (0-100)
- Total grams must be positive
- Batch gets unique ID and "Available" status
- Can link to a grow entry (traceability)
---
### US-A10: Grow Calendar
**As an** admin,
**I want to** track plant grows through their lifecycle stages,
**So that** I can manage cultivation from seed to harvest.
**Acceptance Criteria:**
- Calendar/list shows all active grows with current stage
- 7 stages: Seedling → Vegetative → Flowering → Harvest → Drying → Curing → Complete
- Stage progression is sequential (can't skip)
- Each grow shows: strain, start date, current stage, days in stage
- Color-coded stage indicators
---
### US-A11: Grow Detail
**As an** admin,
**I want to** manage a specific grow entry in detail,
**So that** I can record sensors, photos, and feeding.
**Acceptance Criteria:**
- Sensor readings displayed: temperature, humidity, CO2, pH, EC
- Photo gallery with upload capability
- Feeding log with date, nutrients, amount
- Timeline showing stage transitions
- "Advance Stage" button with confirmation
- Harvest → links to batch creation (traceability)
---
### US-A12: Reports
**As an** admin,
**I want to** generate compliance reports,
**So that** I can satisfy regulatory requirements.
**Acceptance Criteria:**
- Three report types: Monthly Report, Member List, Recall Report
- Preview mode shows report content in-page
- PDF download generates branded document
- CSV export for data analysis
- Monthly report includes: distributions count, total grams, member activity
- Recall report traces a batch to all distribution recipients
---
### US-A13: Audit Log
**As an** admin,
**I want to** view an immutable audit trail,
**So that** all actions are traceable for compliance.
**Acceptance Criteria:**
- Shows 18+ event types (MEMBER_CREATED, DISTRIBUTION_RECORDED, BATCH_ADDED, etc.)
- Filter by event type, date range, actor
- Each entry shows: timestamp, event type, actor, details
- Tamper-proof indicator (hash chain)
- PDF export of filtered results
- 10-year retention policy displayed
- Log entries cannot be deleted (REVOKE DELETE)
---
### US-A14: Staff Management
**As an** admin,
**I want to** invite and manage staff accounts,
**So that** I can control who has access.
**Acceptance Criteria:**
- Staff list shows: name, email, role, permissions, last active
- "Invite Staff" button opens invitation form (email + role)
- Permission checkboxes for granular access control
- "Revoke Access" button with confirmation dialog
- Prevention officer role limit enforced (max per KCanG)
- Invite sends email with token link
---
### US-A15: Billing & Subscription
**As an** admin,
**I want to** manage my club's subscription plan,
**So that** I can access features appropriate to our size.
**Acceptance Criteria:**
- Current plan displayed with usage stats
- Three tiers: Starter (€19/≤30 members), Pro (€49/≤100 members), Enterprise
- Upgrade/downgrade available
- Payment methods: SEPA, PayPal, Card (via Stripe)
- Billing history with invoices
- 3-month free trial for new clubs
---
### US-A16: Privacy/DSGVO Settings
**As an** admin,
**I want to** handle data privacy requests,
**So that** my club complies with GDPR.
**Acceptance Criteria:**
- Data Export (Art. 15): Generate JSON export of all member data
- Account Deletion (Art. 17): Delete member with confirmation
- Consent management overview
- Data processing agreement reference
- Last export/deletion timestamp shown
---
### US-A17: Protected Route Access Control
**As a** system,
**I want to** redirect unauthenticated users to login,
**So that** admin pages are secured.
**Acceptance Criteria:**
- All admin routes redirect to `/login` when not authenticated
- Redirect preserves `callbackUrl` parameter
- After login, user returns to originally requested page
- Session expiry triggers redirect
---
## Persona: Member (Portal-Nutzer)
### US-M01: Member Portal Login
**As a** member,
**I want to** log in to my personal portal,
**So that** I can view my quota and history.
**Acceptance Criteria:**
- Portal login page at `/portal-login` with email + password
- Separate from admin login (different auth flow)
- Link to admin login ("Staff login")
- Successful login redirects to `/portal/dashboard`
- Invalid credentials show error
---
### US-M02: Portal Dashboard / Quota View
**As a** member,
**I want to** see my daily and monthly quota usage,
**So that** I know how much I can still receive.
**Acceptance Criteria:**
- Daily quota ring: X.Xg / 25g used (visual circle)
- Monthly quota ring: X.Xg / 50g used (visual circle)
- Under-21 shows 30g monthly limit
- Last distribution info: strain, amount, date
- Quick info section with member number and club name
- Navigation links to history and profile
---
### US-M03: Distribution History
**As a** member,
**I want to** view my past distributions,
**So that** I can track what I received.
**Acceptance Criteria:**
- Table showing: date, strain, amount (grams), recorded by
- Sorted by date (newest first)
- Pagination for many entries
- Tamper-proof indicator per entry
- Navbar with portal navigation
- Total received this month displayed
---
### US-M04: Member Profile
**As a** member,
**I want to** view and update my personal information,
**So that** my records stay current.
**Acceptance Criteria:**
- Personal info displayed: name, email, member number, date of birth
- Password change section (current + new + confirm)
- Language preference toggle (DE/EN)
- Theme preference (dark/light/system)
- Save button for changes
- Read-only fields clearly distinguished
---
### US-M05: Portal Navigation
**As a** member,
**I want to** navigate between portal pages easily,
**So that** I can access all self-service features.
**Acceptance Criteria:**
- Top navbar with links: Dashboard, History, Profile
- Active page indicator in navigation
- Footer with legal links
- No sidebar (cleaner portal layout)
- Responsive at all breakpoints
---
## Persona: Visitor (Öffentlicher Zugang)
### US-V01: Pricing Page
**As a** visitor,
**I want to** compare subscription plans,
**So that** I can decide which tier to purchase.
**Acceptance Criteria:**
- Three plan cards: Starter, Pro, Enterprise
- Feature comparison matrix
- Price displayed per plan (€19/€49/Custom)
- FAQ section for common questions
- CTA button per plan ("Get Started" / "Contact Us")
- Responsive layout (cards stack on mobile)
---
### US-V02: Legal Pages (Impressum, Datenschutz, AGB)
**As a** visitor,
**I want to** read legal information,
**So that** I understand the terms.
**Acceptance Criteria:**
- `/impressum` — Legal notice with company info
- `/datenschutz` — Privacy policy (DSGVO-compliant)
- `/agb` — Terms of service
- All pages render text content without authentication
- Proper heading hierarchy
- Footer links accessible from all public pages
---
### US-V03: 404 Not Found
**As a** visitor,
**I want to** see a helpful error page for invalid URLs,
**So that** I can navigate back to valid content.
**Acceptance Criteria:**
- Custom 404 page with branded design
- "Go Home" or navigation links
- Displays on any non-existent route
- Consistent with app theme (dark/light)
---
## Cross-Cutting: Non-Functional User Stories
### US-X01: Responsive Design
**As any** user,
**I want** the app to work on all device sizes,
**So that** I can use it on mobile, tablet, or desktop.
**Acceptance Criteria:**
- Mobile (375px): Single column, hamburger menu, stacked cards
- Tablet (768px): Sidebar collapses, 2-column where appropriate
- Desktop (1280px): Full sidebar, multi-column layouts
- No horizontal scrollbar at any breakpoint
- Touch-friendly tap targets (≥44px)
---
### US-X02: Dark/Light Theme
**As any** user,
**I want** to switch between dark and light themes,
**So that** I can use the app in my preferred color scheme.
**Acceptance Criteria:**
- Theme toggle accessible from settings/header
- Dark mode: dark backgrounds, light text, green accents
- Light mode: white backgrounds, dark text, green accents
- Preference persisted in localStorage
- System preference detection (prefers-color-scheme)
- All pages render correctly in both modes
---
### US-X03: Internationalization (i18n)
**As any** user,
**I want** the app in German or English,
**So that** I can use it in my preferred language.
**Acceptance Criteria:**
- German (de) as default language
- English (en) as alternative
- All UI labels, buttons, messages translated
- Language switcher in settings
- Date/number formatting adapts to locale
- next-intl integration working
---
### US-X04: PWA & Offline Support
**As any** user,
**I want** the app to be installable and work offline,
**So that** I can access it without constant connectivity.
**Acceptance Criteria:**
- Web app manifest with icons (192px, 512px)
- Service worker registered
- Offline page shows when no connectivity
- Install prompt available on supported browsers
- App icon on home screen after install
---
### US-X05: Accessibility (a11y)
**As a** user with disabilities,
**I want** the app to be accessible,
**So that** I can use it with assistive technology.
**Acceptance Criteria:**
- All form inputs have associated labels
- Proper heading hierarchy (h1 → h2 → h3)
- Keyboard navigation works on all interactive elements
- ARIA attributes on dynamic content
- Color contrast meets WCAG 2.1 AA
- Focus visible on interactive elements
- Autocomplete attributes on login fields
---
### US-X06: Notifications
**As an** admin,
**I want to** receive real-time notifications,
**So that** I'm alerted to important events.
**Acceptance Criteria:**
- Bell icon with unread count badge
- Notification dropdown/panel
- WebSocket (STOMP) real-time delivery
- Notification types: low stock, quota warning, new member, system alert
- Mark as read / mark all as read
- Persistent across page navigation
---