706a6e257b
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
505 lines
14 KiB
Markdown
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
|
|
|
|
---
|