+
-
-
-
+
+ <.link navigate={~p"/members"} class="btn btn-primary">
+ Members
+
```
@@ -1564,57 +1535,15 @@ policies do
authorize_if always()
end
- # Use HasPermission check for role-based authorization
- policy action_type([:read, :update, :create, :destroy]) do
- authorize_if Mv.Authorization.Checks.HasPermission
+ # Specific permissions
+ policy action_type([:read, :update]) do
+ authorize_if relates_to_actor_via(:user)
end
-end
-```
-**Actor Handling in LiveViews:**
-
-Always use the `current_actor/1` helper for consistent actor access:
-
-```elixir
-# In LiveView modules
-import MvWeb.LiveHelpers, only: [current_actor: 1, ash_actor_opts: 1, submit_form: 3]
-
-def mount(_params, _session, socket) do
- actor = current_actor(socket)
-
- case Ash.read(Mv.Membership.Member, ash_actor_opts(actor)) do
- {:ok, members} ->
- {:ok, assign(socket, :members, members)}
- {:error, error} ->
- {:ok, put_flash(socket, :error, "Failed to load members")}
+ policy action_type(:destroy) do
+ authorize_if actor_attribute_equals(:role, :admin)
end
end
-
-def handle_event("save", %{"member" => params}, socket) do
- actor = current_actor(socket)
- form = AshPhoenix.Form.for_create(Mv.Membership.Member, :create)
-
- case submit_form(form, params, actor) do
- {:ok, member} ->
- {:noreply, push_navigate(socket, to: ~p"/members/#{member.id}")}
- {:error, form} ->
- {:noreply, assign(socket, :form, form)}
- end
-end
-```
-
-**Never use bang calls (`Ash.read!`, `Ash.get!`) without error handling:**
-
-```elixir
-# Bad - will crash on authorization errors
-members = Ash.read!(Mv.Membership.Member, actor: actor)
-
-# Good - proper error handling
-case Ash.read(Mv.Membership.Member, actor: actor) do
- {:ok, members} -> # success
- {:error, %Ash.Error.Forbidden{}} -> # handle authorization error
- {:error, error} -> # handle other errors
-end
```
### 5.2 Password Security
diff --git a/README.md b/README.md
index 94adf08..6255f8d 100644
--- a/README.md
+++ b/README.md
@@ -40,16 +40,14 @@ Our philosophy: **software should help people spend less time on administration
## 🔑 Features
- ✅ Manage member data with ease
-- ✅ Membership fees & payment status tracking
-- ✅ Full-text search with fuzzy matching
-- ✅ Sorting & filtering
-- ✅ Roles & permissions (RBAC system with 4 permission sets)
+- 🚧 Overview of membership fees & payment status
+- ✅ Full-text search
+- 🚧 Sorting & filtering
+- 🚧 Roles & permissions (e.g. board, treasurer)
- ✅ Custom fields (flexible per club needs)
- ✅ SSO via OIDC (works with Authentik, Rauthy, Keycloak, etc.)
-- ✅ Sidebar navigation (standard-compliant, accessible)
-- ✅ Global settings management
- 🚧 Self-service & online application
-- ✅ Accessibility improvements (WCAG 2.1 AA compliant keyboard navigation)
+- 🚧 Accessibility, GDPR, usability improvements
- 🚧 Email sending
## 🚀 Quick Start (Development)
@@ -189,9 +187,8 @@ The `OIDC_REDIRECT_URI` is auto-generated as `https://{DOMAIN}/auth/user/rauthy/
- **Auth:** AshAuthentication (OIDC + password)
**Code Structure:**
-- `lib/accounts/` & `lib/membership/` & `lib/membership_fees/` & `lib/mv/authorization/` — Ash resources and domains
+- `lib/accounts/` & `lib/membership/` — Ash resources and domains
- `lib/mv_web/` — Phoenix controllers, LiveViews, components
-- `lib/mv/` — Shared helpers and business logic
- `assets/` — Tailwind, JavaScript, static files
📚 **Full tech stack details:** See [`CODE_GUIDELINES.md`](CODE_GUIDELINES.md)
diff --git a/docs/csv-member-import-v1.md b/docs/csv-member-import-v1.md
index 05e4e48..bc8f99f 100644
--- a/docs/csv-member-import-v1.md
+++ b/docs/csv-member-import-v1.md
@@ -2,8 +2,7 @@
**Version:** 1.0
**Date:** 2025-01-XX
-**Last Updated:** 2026-01-13
-**Status:** Templates Created - Import Logic Pending
+**Status:** Ready for Implementation
**Related Documents:**
- [Feature Roadmap](./feature-roadmap.md) - Overall feature planning
diff --git a/docs/database-schema-readme.md b/docs/database-schema-readme.md
index 15e4e33..6457db5 100644
--- a/docs/database-schema-readme.md
+++ b/docs/database-schema-readme.md
@@ -15,10 +15,10 @@ This document provides a comprehensive overview of the Mila Membership Managemen
| Metric | Count |
|--------|-------|
-| **Tables** | 9 |
-| **Domains** | 4 (Accounts, Membership, MembershipFees, Authorization) |
-| **Relationships** | 7 |
-| **Indexes** | 20+ |
+| **Tables** | 5 |
+| **Domains** | 2 (Accounts, Membership) |
+| **Relationships** | 3 |
+| **Indexes** | 15+ |
| **Triggers** | 1 (Full-text search) |
## Tables Overview
@@ -68,39 +68,16 @@ This document provides a comprehensive overview of the Mila Membership Managemen
- Immutable and required flags
- Centralized custom field management
-#### `settings`
-- **Purpose:** Global application settings (singleton resource)
-- **Rows (Estimated):** 1 (singleton pattern)
-- **Key Features:**
- - Club name configuration
- - Member field visibility settings
- - Membership fee default settings
- - Environment variable support for club name
-
-### Authorization Domain
-
-#### `roles`
-- **Purpose:** Role-based access control (RBAC)
-- **Rows (Estimated):** Low (typically 3-10 roles)
-- **Key Features:**
- - Links users to permission sets
- - System role protection
- - Four hardcoded permission sets: own_data, read_only, normal_user, admin
-
## Key Relationships
```
User (0..1) ←→ (0..1) Member
- ↓ ↓
- Tokens (N) CustomFieldValues (N)
- ↓ ↓
- Role (N:1) CustomField (1)
+ ↓
+ Tokens (N)
-Member (1) → (N) MembershipFeeCycles
+Member (1) → (N) Properties
↓
- MembershipFeeType (1)
-
-Settings (1) → MembershipFeeType (0..1)
+ CustomField (1)
```
### Relationship Details
@@ -112,39 +89,16 @@ Settings (1) → MembershipFeeType (0..1)
- Email synchronization when linked (User.email is source of truth)
- `ON DELETE SET NULL` on user side (User preserved when Member deleted)
-2. **User → Role (N:1)**
- - Many users can be assigned to one role
- - `ON DELETE RESTRICT` - cannot delete role if users are assigned
- - Role links user to permission set for authorization
-
-3. **Member → CustomFieldValues (1:N)**
+2. **Member → Properties (1:N)**
- One member, many custom_field_values
- `ON DELETE CASCADE` - custom_field_values deleted with member
- Composite unique constraint (member_id, custom_field_id)
-4. **CustomFieldValue → CustomField (N:1)**
- - Custom field values reference type definition
+3. **CustomFieldValue → CustomField (N:1)**
+ - Properties reference type definition
- `ON DELETE RESTRICT` - cannot delete type if in use
- Type defines data structure
-5. **Member → MembershipFeeType (N:1, optional)**
- - Many members can be assigned to one fee type
- - `ON DELETE RESTRICT` - cannot delete fee type if members are assigned
- - Optional relationship (member can have no fee type)
-
-6. **Member → MembershipFeeCycles (1:N)**
- - One member, many billing cycles
- - `ON DELETE CASCADE` - cycles deleted when member deleted
- - Unique constraint (member_id, cycle_start)
-
-7. **MembershipFeeCycle → MembershipFeeType (N:1)**
- - Many cycles reference one fee type
- - `ON DELETE RESTRICT` - cannot delete fee type if cycles exist
-
-8. **Settings → MembershipFeeType (N:1, optional)**
- - Settings can reference a default fee type
- - `ON DELETE SET NULL` - if fee type is deleted, setting is cleared
-
## Important Business Rules
### Email Synchronization
@@ -187,6 +141,7 @@ Settings (1) → MembershipFeeType (0..1)
- `email` (B-tree) - Exact email lookups
- `last_name` (B-tree) - Name sorting
- `join_date` (B-tree) - Date filtering
+- `paid` (partial B-tree) - Payment status queries
**custom_field_values:**
- `member_id` - Member custom field value lookups
@@ -213,14 +168,14 @@ Settings (1) → MembershipFeeType (0..1)
### Weighted Fields
- **Weight A (highest):** first_name, last_name
- **Weight B:** email, notes
-- **Weight C:** city, street, house_number, postal_code, custom_field_values
+- **Weight C:** phone_number, city, street, house_number, postal_code, custom_field_values
- **Weight D (lowest):** join_date, exit_date
### Custom Field Values in Search
Custom field values are automatically included in the search vector:
- All custom field values (string, integer, boolean, date, email) are aggregated and added to the search vector
- Values are converted to text format for indexing
-- Custom field values receive weight 'C' (same as city, etc.)
+- Custom field values receive weight 'C' (same as phone_number, city, etc.)
- The search vector is automatically updated when custom field values are created, updated, or deleted via database triggers
### Usage Example
@@ -376,7 +331,7 @@ priv/repo/migrations/
**High Frequency:**
- Member search (uses GIN index on search_vector)
-- Member list with filters (uses indexes on join_date, membership_fee_type_id)
+- Member list with filters (uses indexes on join_date, paid)
- User authentication (uses unique index on email/oidc_id)
- CustomFieldValue lookups by member (uses index on member_id)
@@ -395,7 +350,7 @@ priv/repo/migrations/
1. **Use indexes:** All critical query paths have indexes
2. **Preload relationships:** Use Ash's `load` to avoid N+1
3. **Pagination:** Use keyset pagination (configured by default)
-4. **GIN indexes:** Full-text search and fuzzy search on multiple fields
+4. **Partial indexes:** `members.paid` index only non-NULL values
5. **Search optimization:** Full-text search via tsvector, not LIKE
## Visualization
@@ -509,7 +464,7 @@ mix run priv/repo/seeds.exs
---
-**Last Updated:** 2026-01-13
-**Schema Version:** 1.4
+**Last Updated:** 2025-11-13
+**Schema Version:** 1.1
**Database:** PostgreSQL 17.6 (dev) / 16 (prod)
diff --git a/docs/database_schema.dbml b/docs/database_schema.dbml
index 23605bf..f97463e 100644
--- a/docs/database_schema.dbml
+++ b/docs/database_schema.dbml
@@ -6,8 +6,8 @@
// - https://dbdocs.io
// - VS Code Extensions: "DBML Language" or "dbdiagram.io"
//
-// Version: 1.4
-// Last Updated: 2026-01-13
+// Version: 1.3
+// Last Updated: 2025-12-11
Project mila_membership_management {
database_type: 'PostgreSQL'
@@ -28,7 +28,6 @@ Project mila_membership_management {
- **Accounts**: User authentication and session management
- **Membership**: Club member data and custom fields
- **MembershipFees**: Membership fee types and billing cycles
- - **Authorization**: Role-based access control (RBAC)
## Required PostgreSQL Extensions:
- uuid-ossp (UUID generation)
@@ -121,9 +120,11 @@ Table tokens {
Table members {
id uuid [pk, not null, default: `uuid_generate_v7()`, note: 'UUIDv7 primary key (sortable by creation time)']
- first_name text [null, note: 'Member first name (min length: 1 if present)']
- last_name text [null, note: 'Member last name (min length: 1 if present)']
+ first_name text [not null, note: 'Member first name (min length: 1)']
+ last_name text [not null, note: 'Member last name (min length: 1)']
email text [not null, unique, note: 'Member email address (5-254 chars, validated)']
+ paid boolean [null, note: 'Payment status flag']
+ phone_number text [null, note: 'Contact phone number (format: +?[0-9\- ]{6,20})']
join_date date [null, note: 'Date when member joined club (cannot be in future)']
exit_date date [null, note: 'Date when member left club (must be after join_date)']
notes text [null, note: 'Additional notes about member']
@@ -147,6 +148,7 @@ Table members {
email [name: 'members_email_idx', note: 'B-tree index for exact lookups']
last_name [name: 'members_last_name_idx', note: 'B-tree index for name sorting']
join_date [name: 'members_join_date_idx', note: 'B-tree index for date filters']
+ (paid) [name: 'members_paid_idx', type: btree, note: 'Partial index WHERE paid IS NOT NULL']
membership_fee_type_id [name: 'members_membership_fee_type_id_index', note: 'B-tree index for fee type lookups']
}
@@ -155,8 +157,8 @@ Table members {
Core entity for membership management containing:
- Personal information (name, email)
- - Contact details (address)
- - Membership status (join/exit dates, membership fee cycles)
+ - Contact details (phone, address)
+ - Membership status (join/exit dates, payment status)
- Additional notes
**Email Synchronization:**
@@ -184,11 +186,12 @@ Table members {
- 1:N with membership_fee_cycles - billing history
**Validation Rules:**
- - first_name, last_name: optional, but if present min 1 character
- - email: 5-254 characters, valid email format (required)
+ - first_name, last_name: min 1 character
+ - email: 5-254 characters, valid email format
- join_date: cannot be in future
- exit_date: must be after join_date (if both present)
- - postal_code: exactly 5 digits (if present)
+ - phone_number: matches pattern ^\+?[0-9\- ]{6,20}$
+ - postal_code: exactly 5 digits
'''
}
@@ -497,138 +500,3 @@ TableGroup membership_fees_domain {
'''
}
-// ============================================
-// AUTHORIZATION DOMAIN
-// ============================================
-
-Table roles {
- id uuid [pk, not null, default: `uuid_generate_v7()`, note: 'UUIDv7 primary key']
- name text [not null, unique, note: 'Unique role name (e.g., "Vorstand", "Admin", "Mitglied")']
- description text [null, note: 'Human-readable description of the role']
- permission_set_name text [not null, note: 'Permission set name: "own_data", "read_only", "normal_user", or "admin"']
- is_system_role boolean [not null, default: false, note: 'If true, role cannot be deleted (protects critical roles)']
- inserted_at timestamp [not null, default: `now() AT TIME ZONE 'utc'`, note: 'Creation timestamp (UTC)']
- updated_at timestamp [not null, default: `now() AT TIME ZONE 'utc'`, note: 'Last update timestamp (UTC)']
-
- indexes {
- name [unique, name: 'roles_unique_name_index']
- }
-
- Note: '''
- **Role-Based Access Control (RBAC)**
-
- Roles link users to permission sets. Each role references one of four hardcoded
- permission sets defined in the application code.
-
- **Permission Sets:**
- - `own_data`: Users can only access their own linked member data
- - `read_only`: Users can read all data but cannot modify
- - `normal_user`: Users can read and modify most data (standard permissions)
- - `admin`: Full access to all features and settings
-
- **System Roles:**
- - System roles (is_system_role = true) cannot be deleted
- - Protects critical roles like "Mitglied" (member) from accidental deletion
- - Only set via seed scripts or internal actions
-
- **Relationships:**
- - 1:N with users - users assigned to this role
- - ON DELETE RESTRICT: Cannot delete role if users are assigned
-
- **Constraints:**
- - `name` must be unique
- - `permission_set_name` must be a valid permission set (validated in application)
- - System roles cannot be deleted (enforced via validation)
- '''
-}
-
-// ============================================
-// MEMBERSHIP DOMAIN (Additional Tables)
-// ============================================
-
-Table settings {
- id uuid [pk, not null, default: `gen_random_uuid()`, note: 'Primary identifier']
- club_name text [not null, note: 'The name of the association/club (min length: 1)']
- member_field_visibility jsonb [null, note: 'Visibility configuration for member fields in overview (JSONB map)']
- include_joining_cycle boolean [not null, default: true, note: 'Whether to include the joining cycle in membership fee generation']
- default_membership_fee_type_id uuid [null, note: 'FK to membership_fee_types - default fee type for new members']
- inserted_at timestamp [not null, default: `now() AT TIME ZONE 'utc'`, note: 'Creation timestamp (UTC)']
- updated_at timestamp [not null, default: `now() AT TIME ZONE 'utc'`, note: 'Last update timestamp (UTC)']
-
- indexes {
- default_membership_fee_type_id [name: 'settings_default_membership_fee_type_id_index', note: 'B-tree index for fee type lookups']
- }
-
- Note: '''
- **Global Application Settings (Singleton Resource)**
-
- Stores global configuration for the association/club. There should only ever
- be one settings record in the database (singleton pattern).
-
- **Attributes:**
- - `club_name`: The name of the association/club (required, can be set via ASSOCIATION_NAME env var)
- - `member_field_visibility`: JSONB map storing visibility configuration for member fields
- (e.g., `{"street": false, "house_number": false}`). Fields not in the map default to `true`.
- - `include_joining_cycle`: When true, members pay from their joining cycle. When false,
- they pay from the next full cycle after joining.
- - `default_membership_fee_type_id`: The membership fee type automatically assigned to
- new members. Can be nil if no default is set.
-
- **Singleton Pattern:**
- - Only one settings record should exist
- - Designed to be read and updated, not created/destroyed via normal CRUD
- - Initial settings should be seeded
-
- **Environment Variable Support:**
- - `club_name` can be set via `ASSOCIATION_NAME` environment variable
- - Database values always take precedence over environment variables
-
- **Relationships:**
- - Optional N:1 with membership_fee_types - default fee type for new members
- - ON DELETE SET NULL: If default fee type is deleted, setting is cleared
- '''
-}
-
-// ============================================
-// RELATIONSHIPS (Additional)
-// ============================================
-
-// User → Role (N:1)
-// - Many users can be assigned to one role
-// - ON DELETE RESTRICT: Cannot delete role if users are assigned
-Ref: users.role_id > roles.id [delete: restrict]
-
-// Settings → MembershipFeeType (N:1, optional)
-// - Settings can reference a default membership fee type
-// - ON DELETE SET NULL: If fee type is deleted, setting is cleared
-Ref: settings.default_membership_fee_type_id > membership_fee_types.id [delete: set null]
-
-// ============================================
-// TABLE GROUPS (Updated)
-// ============================================
-
-TableGroup authorization_domain {
- roles
-
- Note: '''
- **Authorization Domain**
-
- Handles role-based access control (RBAC) with hardcoded permission sets.
- Roles link users to permission sets for authorization.
- '''
-}
-
-TableGroup membership_domain {
- members
- custom_field_values
- custom_fields
- settings
-
- Note: '''
- **Membership Domain**
-
- Core business logic for club membership management.
- Supports flexible, extensible member data model.
- Includes global application settings (singleton).
- '''
-}
diff --git a/docs/development-progress-log.md b/docs/development-progress-log.md
index 93a7d7f..629987e 100644
--- a/docs/development-progress-log.md
+++ b/docs/development-progress-log.md
@@ -68,7 +68,7 @@ mix phx.new mv --no-ecto --no-mailer
**Key decisions:**
- **Elixir 1.18.3 + OTP 27**: Latest stable versions for performance
- **Ash Framework 3.0**: Declarative resource layer, reduces boilerplate
-- **Phoenix LiveView 1.1.0-rc.3**: Real-time UI without JavaScript complexity
+- **Phoenix LiveView 1.1**: Real-time UI without JavaScript complexity
- **Tailwind CSS 4.0**: Utility-first styling with custom build
- **PostgreSQL 17**: Advanced features (full-text search, JSONB, citext)
- **Bandit**: Modern HTTP server, better than Cowboy for LiveView
@@ -80,15 +80,14 @@ mix phx.new mv --no-ecto --no-mailer
**Versions pinned in `.tool-versions`:**
- Elixir 1.18.3-otp-27
- Erlang 27.3.4
-- Just 1.46.0
+- Just 1.43.0
#### 4. Database Setup
**PostgreSQL Extensions:**
```sql
-CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -- UUID generation (via uuid_generate_v7 function)
+CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -- UUID generation
CREATE EXTENSION IF NOT EXISTS "citext"; -- Case-insensitive text
-CREATE EXTENSION IF NOT EXISTS "pg_trgm"; -- Trigram-based fuzzy search
```
**Migration Strategy:**
@@ -469,7 +468,7 @@ end
- **Tailwind:** Utility-first, no custom CSS
- **DaisyUI:** Pre-built components, consistent design
- **Heroicons:** Icon library, inline SVG
-- **Phoenix LiveView 1.1.0-rc.3:** Server-rendered, minimal JavaScript
+- **Phoenix LiveView:** Server-rendered, minimal JavaScript
**Trade-offs:**
- Larger HTML (utility classes)
@@ -599,33 +598,14 @@ end
#### Database Migrations
-**Key migrations in chronological order (26 total):**
-1. `20250421101957_initialize_extensions_1.exs` - PostgreSQL extensions (uuid-ossp, citext, pg_trgm)
-2. `20250528163901_initial_migration.exs` - Core tables (members, custom_field_values, custom_fields - originally property_types/properties)
-3. `20250617090641_member_fields.exs` - Member attributes expansion
-4. `20250617132424_member_delete.exs` - Member deletion constraints
-5. `20250620110849_add_accounts_domain_extensions.exs` - Accounts domain extensions
-6. `20250620110850_add_accounts_domain.exs` - Users & tokens tables
-7. `20250912085235_AddSearchVectorToMembers.exs` - Full-text search (tsvector + GIN index)
-8. `20250926164519_member_relation.exs` - User-Member link (optional 1:1)
-9. `20250926180341_add_unique_email_to_members.exs` - Unique email constraint on members
-10. `20251001141005_add_trigram_to_members.exs` - Fuzzy search (pg_trgm + 6 GIN trigram indexes)
-11. `20251016130855_add_constraints_for_user_member_and_property.exs` - Email sync constraints
-12. `20251113163600_rename_properties_to_custom_fields_extensions_1.exs` - Rename properties extensions
-13. `20251113163602_rename_properties_to_custom_fields.exs` - Rename property_types → custom_fields, properties → custom_field_values
-14. `20251113180429_add_slug_to_custom_fields.exs` - Add slug to custom fields
-15. `20251113183538_change_custom_field_delete_cascade.exs` - Change delete cascade behavior
-16. `20251119160509_add_show_in_overview_to_custom_fields.exs` - Add show_in_overview flag
-17. `20251127134451_add_settings_table.exs` - Create settings table (singleton)
-18. `20251201115939_add_member_field_visibility_to_settings.exs` - Add member_field_visibility JSONB to settings
-19. `20251202145404_remove_birth_date_from_members.exs` - Remove birth_date field
-20. `20251204123714_add_custom_field_values_to_search_vector.exs` - Include custom field values in search vector
-21. `20251211151449_add_membership_fees_tables.exs` - Create membership_fee_types and membership_fee_cycles tables
-22. `20251211172549_remove_immutable_from_custom_fields.exs` - Remove immutable flag from custom fields
-23. `20251211195058_add_membership_fee_settings.exs` - Add membership fee settings to settings table
-24. `20251218113900_remove_paid_from_members.exs` - Remove paid boolean from members (replaced by cycle status)
-25. `20260102155350_remove_phone_number_and_make_fields_optional.exs` - Remove phone_number, make first_name/last_name optional
-26. `20260106161215_add_authorization_domain.exs` - Create roles table and add role_id to users
+**Key migrations in chronological order:**
+1. `20250528163901_initial_migration.exs` - Core tables (members, custom_field_values, custom_fields)
+2. `20250617090641_member_fields.exs` - Member attributes expansion
+3. `20250620110850_add_accounts_domain.exs` - Users & tokens tables
+4. `20250912085235_AddSearchVectorToMembers.exs` - Full-text search (tsvector + GIN index)
+5. `20250926164519_member_relation.exs` - User-Member link (optional 1:1)
+6. `20251001141005_add_trigram_to_members.exs` - Fuzzy search (pg_trgm + 6 GIN trigram indexes)
+7. `20251016130855_add_constraints_for_user_member_and_property.exs` - Email sync constraints
**Learning:** Ash's code generation from resources ensures schema always matches code.
@@ -1582,7 +1562,7 @@ Effective workflow:
This project demonstrates a modern Phoenix application built with:
- ✅ **Ash Framework** for declarative resources and policies
-- ✅ **Phoenix LiveView 1.1.0-rc.3** for real-time, server-rendered UI
+- ✅ **Phoenix LiveView** for real-time, server-rendered UI
- ✅ **Tailwind CSS + DaisyUI** for rapid UI development
- ✅ **PostgreSQL** with advanced features (full-text search, UUIDv7)
- ✅ **Multi-strategy authentication** (Password + OIDC)
@@ -1590,19 +1570,15 @@ This project demonstrates a modern Phoenix application built with:
- ✅ **Flexible data model** (EAV pattern with union types)
**Key Achievements:**
-- 🎯 9+ sprints completed
-- 🚀 100+ pull requests merged
-- ✅ Core features implemented (CRUD, search, auth, sync, membership fees, roles & permissions)
-- ✅ Membership fees system (types, cycles, settings)
-- ✅ Role-based access control (RBAC) with 4 permission sets
-- ✅ Member field visibility settings
-- ✅ Sidebar navigation (WCAG 2.1 AA compliant)
+- 🎯 8 sprints completed
+- 🚀 82 pull requests merged
+- ✅ Core features implemented (CRUD, search, auth, sync)
- 📚 Comprehensive documentation
- 🔒 Security-focused (audits, validations, policies)
- 🐳 Docker-ready for self-hosting
**Next Steps:**
-- ✅ ~~Implement roles & permissions~~ - RBAC system implemented (2026-01-08)
+- Implement roles & permissions
- Add payment tracking
- ✅ ~~Improve accessibility (WCAG 2.1 AA)~~ - Keyboard navigation implemented
- Member self-service portal
@@ -1610,150 +1586,8 @@ This project demonstrates a modern Phoenix application built with:
---
-## Recent Updates (2025-12-02 to 2026-01-13)
-
-### Membership Fees System Implementation (2025-12-11 to 2025-12-26)
-
-**PR #283:** *Membership Fee - Database Schema & Ash Domain Foundation* (closes #275)
-- Created `Mv.MembershipFees` domain
-- Added `MembershipFeeType` resource with intervals (monthly, quarterly, half_yearly, yearly)
-- Added `MembershipFeeCycle` resource for individual billing cycles
-- Database migrations for membership fee tables
-
-**PR #284:** *Calendar Cycle Calculation Logic* (closes #276)
-- Calendar-based cycle calculation module
-- Support for different intervals
-- Cycle start/end date calculations
-- Integration with member joining dates
-
-**PR #290:** *Cycle Generation System* (closes #277)
-- Automatic cycle generation for members
-- Cycle regeneration when fee type changes
-- Integration with member lifecycle hooks
-- Actor-based authorization for cycle operations
-
-**PR #291:** *Membership Fee Type Resource & Settings* (closes #278)
-- Membership fee type CRUD operations
-- Global membership fee settings
-- Default fee type assignment
-- `include_joining_cycle` setting
-
-**PR #294:** *Cycle Management & Member Integration* (closes #279)
-- Member-fee type relationship
-- Cycle status tracking (unpaid, paid, suspended)
-- Member detail view integration
-- Cycle regeneration on fee type change
-
-**PR #304:** *Membership Fee 6 - UI Components & LiveViews* (closes #280)
-- Membership fee type management LiveViews
-- Membership fee settings LiveView
-- Cycle display in member detail view
-- Payment status indicators
-
-### Custom Fields Enhancements (2025-12-11 to 2026-01-02)
-
-**PR #266:** *Implements search for custom fields* (closes #196)
-- Custom field search in member overview
-- Integration with full-text search
-- Custom field value filtering
-
-**PR #301:** *Implements validation for required custom fields* (closes #274)
-- Required custom field validation
-- Form-level validation
-- Error messages for missing required fields
-
-**PR #313:** *Fix hidden empty custom fields* (closes #282)
-- Fixed display of empty custom fields
-- Improved custom field visibility logic
-
-### UI/UX Improvements (2025-12-03 to 2025-12-16)
-
-**PR #240:** *Implement dropdown to show/hide columns in member overview* (closes #209)
-- Field visibility dropdown
-- User-specific field selection
-- Integration with global settings
-
-**PR #247:** *Visual hierarchy for fields in member view and edit form* (closes #231)
-- Improved field grouping
-- Visual hierarchy improvements
-- Better form layout
-
-**PR #250:** *UX - Avoid opening member by clicking the checkbox* (closes #233)
-- Checkbox click handling
-- Prevented accidental navigation
-- Improved selection UX
-
-**PR #259:** *Fix small UI issues* (closes #220)
-- Various UI bug fixes
-- Accessibility improvements
-
-**PR #293:** *Small UX fixes* (closes #281)
-- Additional UX improvements
-- Polish and refinement
-
-**PR #319:** *Reduce member fields* (closes #273)
-- Removed unnecessary member fields
-- Streamlined member data model
-- Migration for field removal
-
-### Roles and Permissions System (2026-01-06 to 2026-01-08)
-- ✅ **RBAC Implementation Complete** - Member Resource Policies (#345)
- - Four hardcoded permission sets: `own_data`, `read_only`, `normal_user`, `admin`
- - Role-based access control with database-backed roles
- - Member resource policies with scope filtering (`:own`, `:linked`, `:all`)
- - Authorization checks via `Mv.Authorization.Checks.HasPermission`
- - System role protection (cannot delete critical roles)
- - Comprehensive test coverage
-
-### Actor Handling Refactoring (2026-01-09)
-- ✅ **Consistent Actor Access** - `current_actor/1` helper function
- - Standardized actor access across all LiveViews
- - `ash_actor_opts/1` helper for consistent authorization options
- - `submit_form/3` wrapper for form submissions with actor
- - All Ash operations now properly pass `actor` parameter
- - Error handling improvements (replaced bang calls with proper error handling)
-
-### Internationalization Improvements (2026-01-13)
-- ✅ **Complete German Translations** - All UI strings translated
- - CI check for empty German translations in lint task
- - Standardized English `msgstr` entries (all empty for consistency)
- - Corrected language headers in `.po` files
- - Added missing translations for error messages
-
-### Code Quality Improvements (2026-01-13)
-- ✅ **Error Handling** - Replaced `Ash.read!` with proper error handling
-- ✅ **Code Complexity** - Reduced nesting depth in `UserLive.Form`
-- ✅ **Test Infrastructure** - Role tag support in `ConnCase`
-
-### CSV Import Feature (2026-01-13)
-- ✅ **CSV Templates** - Member import templates (#329)
- - German and English CSV templates
- - Template files in `priv/static/templates/`
-
-### Sidebar Implementation (2026-01-12)
-- ✅ **Sidebar Navigation** - Replaced navbar with sidebar (#260)
- - Standard-compliant sidebar with comprehensive tests
- - DaisyUI drawer pattern implementation
- - Desktop expanded/collapsed states
- - Mobile overlay drawer
- - localStorage persistence for sidebar state
- - WCAG 2.1 Level AA compliant
-
-### Member Field Settings (2026-01-12, PR #300, closes #223)
-- ✅ **Member Field Visibility Configuration** - Global settings for field visibility
- - JSONB-based visibility configuration in Settings resource
- - Per-field visibility toggle (show/hide in member overview)
- - Atomic updates for single field visibility changes
- - Integration with member list overview
- - User-specific field selection (takes priority over global settings)
- - Custom field visibility support
- - Default visibility: all fields visible except `exit_date` (hidden by default)
- - LiveComponent for managing member field visibility in settings page
-
----
-
-**Document Version:** 1.4
-**Last Updated:** 2026-01-13
+**Document Version:** 1.3
+**Last Updated:** 2025-12-02
**Maintainer:** Development Team
**Status:** Living Document (update as project evolves)
diff --git a/docs/documentation-sync-todos.md b/docs/documentation-sync-todos.md
deleted file mode 100644
index 3c555f6..0000000
--- a/docs/documentation-sync-todos.md
+++ /dev/null
@@ -1,314 +0,0 @@
-# Documentation Sync - Code Adjustments Todo List
-
-**Created:** 2026-01-13
-**Purpose:** List of all code adjustments identified based on documentation synchronization
-
----
-
-## Removed Documentation Files
-
-### 1. `docs/test-status-membership-fee-ui.md`
-**Reason:** Outdated temporary analysis documentation
-- Contains only historical test status information (Date: 2025-01-XX)
-- Status "Tests Written - Implementation Complete" is no longer relevant
-- All tests are already implemented and running
-- Information is already documented in `development-progress-log.md`
-- **Removed:** 2026-01-13
-
-### 2. `docs/test-failures-analysis.md`
-**Reason:** Outdated temporary analysis documentation
-- Analyzes 5 failing tests that have already been fixed
-- Contains solution suggestions for already resolved problems
-- Information is only historically relevant
-- No current relevance for the codebase
-- **Removed:** 2026-01-13
-
-## Marked as Deprecated Documentation Files
-
-### 3. `docs/sidebar-analysis-current-state.md`
-**Reason:** Outdated analysis documentation
-- Describes the state BEFORE sidebar implementation
-- Sidebar was already implemented (2026-01-12, PR #260)
-- Replaced by `sidebar-requirements-v2.md`
-- **Status:** Marked as deprecated, but kept for historical reference
-
-### 4. `docs/umsetzung-sidebar.md`
-**Reason:** Outdated implementation guide
-- Step-by-step guide for sidebar implementation
-- Sidebar was already implemented (2026-01-12, PR #260)
-- Replaced by `sidebar-requirements-v2.md`
-- **Status:** Marked as deprecated, but kept for historical reference
-
----
-
-## Code Adjustments (Priority: Low)
-
-### 1. Domain Public API Documentation Incomplete
-
-**Problem:** The `@moduledoc` in domain modules does not list all public functions.
-
-**Affected Files:**
-- `lib/membership/membership.ex` - Missing functions in Public API:
- - `list_required_custom_fields/0`
- - `update_member_field_visibility/2`
- - `update_single_member_field_visibility/3`
-- `lib/accounts/accounts.ex` - Very short Public API documentation, could be more detailed
-- `lib/membership_fees/membership_fees.ex` - Public API is complete, but could more clearly document that LiveViews use direct Ash calls
-
-**Priority:** Low (Documentation, no functionality affected)
-
-**Recommendation:** Update Public API sections in all domain modules to list all public functions.
-
-### 2. Outdated Comments in MemberLive.Form
-
-**Problem:** `@moduledoc` in `lib/mv_web/live/member_live/form.ex` still mentions "Payment Data: Mockup section (not editable)", but Membership Fees are now fully implemented.
-
-**Affected File:**
-- `lib/mv_web/live/member_live/form.ex` (Line 16)
-
-**Priority:** Low (Documentation, no functionality affected)
-
-**Recommendation:** Update `@moduledoc` to reflect the current status.
-
-### 3. Mv.Accounts Domain Public API Missing Completely
-
-**Problem:** The `@moduledoc` in `lib/accounts/accounts.ex` does not mention any Public API functions, although several are defined.
-
-**Affected File:**
-- `lib/accounts/accounts.ex` - Missing Public API documentation for:
- - `create_user/1`
- - `list_users/0`
- - `update_user/2`
- - `destroy_user/1`
- - `create_register_with_rauthy/1`
- - `read_sign_in_with_rauthy/1`
-
-**Priority:** Low (Documentation, no functionality affected)
-
-**Recommendation:** Add Public API section to `@moduledoc`, similar to other domain modules.
-
-### 4. Mv.Authorization Domain Public API Missing get_role/1
-
-**Problem:** The `@moduledoc` in `lib/mv/authorization/authorization.ex` does not list `get_role/1` in the Public API, although it is defined.
-
-**Affected File:**
-- `lib/mv/authorization/authorization.ex` - Missing function in Public API:
- - `get_role/1` (is defined, but not mentioned in Public API)
-
-**Priority:** Low (Documentation, no functionality affected)
-
-**Recommendation:** Add `get_role/1` to the Public API list.
-
-### 5. CustomFieldValueLive.Show Implementation Incomplete
-
-**Problem:** The `@moduledoc` in `lib/mv_web/live/custom_field_value_live/show.ex` describes features that are not implemented.
-
-**Affected File:**
-- `lib/mv_web/live/custom_field_value_live/show.ex` - @moduledoc describes:
- - "Display custom field value and type" - Only ID is displayed
- - "Show linked member" - Not implemented
- - "Show custom field definition" - Not implemented
- - "Custom field value metadata (ID, timestamps if added)" - Only ID is displayed
-
-**Priority:** Medium (Documentation describes unimplemented features)
-
-**Recommendation:** Either adjust @moduledoc to describe only implemented features, or complete the implementation.
-
-### 6. Missing Tests for Some LiveViews
-
-**Problem:** Some LiveViews do not have corresponding test files.
-
-**Affected LiveViews:**
-- `MvWeb.CustomFieldValueLive.Show` - No test present
-- `MvWeb.UserLive.Show` - No test present
-- `MvWeb.RoleLive.Show` - No test present
-
-**Not Affected (Mock-ups, tests not expected):**
-- `MvWeb.ContributionTypeLive.Index` - Mock-up, no test expected
-- `MvWeb.ContributionPeriodLive.Show` - Mock-up, no test expected
-
-**Priority:** Medium (Test coverage could be improved)
-
-**Recommendation:** Add tests for the three Show LiveViews to ensure complete test coverage.
-
-### 7. Mv.Accounts.Token @moduledoc Too Short
-
-**Problem:** The `@moduledoc` in `lib/accounts/token.ex` is very short and not informative.
-
-**Affected File:**
-- `lib/accounts/token.ex` - Currently only: "AshAuthentication specific ressource"
-
-**Priority:** Low (Documentation, no functionality affected)
-
-**Recommendation:** Expand @moduledoc to explain that this is an AshAuthentication Token Resource and is used for session management.
-
-### 8. PageController Missing @moduledoc
-
-**Problem:** The `@moduledoc` in `lib/mv_web/controllers/page_controller.ex` is completely missing.
-
-**Affected File:**
-- `lib/mv_web/controllers/page_controller.ex` - No @moduledoc present
-
-**Priority:** Low (Documentation, no functionality affected)
-
-**Recommendation:** Add @moduledoc to explain that this controller renders the homepage.
-
-**Note:** Other controller modules (Router, Endpoint, Telemetry) also do not have @moduledoc, but this is common and acceptable for standard Phoenix modules.
-
----
-
-## Deprecated Code Patterns
-
-### No Deprecated Patterns Identified
-
-All code patterns comply with current best practices and are documented in `CODE_GUIDELINES.md`.
-
----
-
-## Missing Implementations
-
-### No Missing Implementations Identified
-
-All features described in the documentation are implemented.
-
----
-
-## Inconsistent Naming
-
-### No Inconsistencies Identified
-
-Terminology is consistent between code and documentation:
-- `CustomField` / `CustomFieldValue` (no longer "Property" / "PropertyType")
-- `MembershipFeeType` / `MembershipFeeCycle` (correctly used)
-- Domains: `Accounts`, `Membership`, `MembershipFees`, `Authorization` (all correct)
-
----
-
-## Analysis Summary
-
-### Completed Analyses
-
-**1. Documentation Files:**
-- ✅ `README.md` - Code Structure updated
-- ✅ `CODE_GUIDELINES.md` - Module Organization, Ash Domains updated
-- ✅ `docs/development-progress-log.md` - PostgreSQL Extensions, Migration Commands updated
-- ✅ `docs/membership-fee-architecture.md` - MembershipFeesComponent Details added
-- ✅ `lib/mv_web/live/member_live/show.ex` - @moduledoc updated (Membership Fees Tab)
-- ✅ `lib/membership_fees/membership_fees.ex` - Public API section added
-
-**2. Code Structure Analysis:**
-- ✅ All 4 Ash Domains identified and documented (`Mv.Membership`, `Mv.Accounts`, `Mv.MembershipFees`, `Mv.Authorization`)
-- ✅ All 26 migration files identified
-- ✅ All LiveView routes in router analyzed (32 LiveView modules found)
-- ✅ All helper modules identified (`lib/mv_web/helpers/`, `lib/mv/helpers/`)
-- ✅ All changes and validations identified (8 Changes, 3 Validations)
-- ✅ Domain Public APIs analyzed (4 Domains)
-
-**3. Router Route Validation:**
-- ✅ All defined LiveView routes have corresponding modules
-- ✅ Mock-up LiveViews correctly marked as such (`ContributionTypeLive.Index`, `ContributionPeriodLive.Show`)
-- ✅ Feature roadmap status consistent with code status
-
-**4. Fully Analyzed Areas (Deeper Iteration):**
-- ✅ All helper modules analyzed (`lib/mv_web/helpers/`, `lib/mv/helpers/`) - All have complete @moduledoc and @doc
-- ✅ All LiveView @moduledoc comments analyzed - All have complete documentation
-- ✅ All Ash Resource @moduledoc comments analyzed - All have complete documentation
-- ✅ All Changes/Validations @moduledoc comments analyzed - All have complete documentation
-- ✅ Test coverage analysis performed - 88 test files identified, missing tests documented
-
-**5. Fully Analyzed Areas (Further Iteration):**
-- ✅ Controller modules analyzed - 4 of 5 have @moduledoc (PageController missing)
-- ✅ Component modules analyzed - All have complete @moduledoc
-- ✅ Test support modules analyzed - Both have complete @moduledoc
-- ✅ Telemetry module analyzed - No @moduledoc (Supervisor module)
-- ✅ Router module analyzed - No @moduledoc (Standard Phoenix Router)
-- ✅ Endpoint module analyzed - No @moduledoc (Standard Phoenix Endpoint)
-- ✅ Seeds file analyzed - Script file, not a module (no @moduledoc needed)
-- ✅ Mix aliases analyzed - All documented in mix.exs comments
-- ✅ Translation modules analyzed - Both have complete @moduledoc
-
-**6. Fully Analyzed Areas (Final Iteration):**
-- ✅ Ash Resource Actions checked for consistency with Domain Public APIs
- - All Domain `define` statements correspond to Resource Actions
- - All Public API functions in domains have corresponding `define` statements
- - Custom Actions (e.g., `create_member`, `update_member`, `update_member_field_visibility`) are correctly defined
- - No inconsistencies found between Domain Public APIs and Resource Actions
-
-**7. Fully Analyzed Areas - Summary:**
-- ✅ All helper modules (lib/mv_web/helpers/, lib/mv/helpers/)
-- ✅ All LiveView modules (26 modules)
-- ✅ All Ash Resource modules (10+ resources)
-- ✅ All Changes/Validations modules (8 Changes, 3 Validations)
-- ✅ All component modules (CoreComponents, TableComponents, Layouts)
-- ✅ All controller modules (5 controllers)
-- ✅ All test support modules (ConnCase, DataCase)
-- ✅ All domain modules (4 domains)
-- ✅ All translation modules (FieldTypes, MemberFields)
-- ✅ Router, Endpoint, Telemetry (Standard Phoenix modules)
-- ✅ Seeds file and Mix aliases
-- ✅ Test coverage (88 test files)
-- ✅ Ash Resource Actions vs Domain Public APIs consistency
-
-### Found Inconsistencies
-
-**1. Domain Public API Documentation Incomplete** (see Code Adjustments #1)
-**2. Outdated Comments in MemberLive.Form** (see Code Adjustments #2)
-**3. Mv.Accounts Domain Public API Missing Completely** (see Code Adjustments #3)
-**4. Mv.Authorization Domain Public API Missing get_role/1** (see Code Adjustments #4)
-**5. CustomFieldValueLive.Show Implementation Incomplete** (see Code Adjustments #5)
-**6. Missing Tests for Some LiveViews** (see Code Adjustments #6)
-**7. Mv.Accounts.Token @moduledoc Too Short** (see Code Adjustments #7)
-**8. PageController Missing @moduledoc** (see Code Adjustments #8)
-
----
-
-## Summary
-
-**Status:** ✅ Documentation successfully synchronized
-
-- **Updated Documentation:** 15+ files
- - database_schema.dbml (Version 1.4, +2 tables: roles, settings)
- - database-schema-readme.md (9 tables, 4 domains, updated relationships)
- - development-progress-log.md (Last Updated: 2026-01-13)
- - New section: "Recent Updates (2025-12-02 to 2026-01-13)"
- - Membership Fees System Implementation (6 PRs documented)
- - Custom Fields Enhancements (3 PRs documented)
- - UI/UX Improvements (6 PRs documented)
- - Roles and Permissions System (fully documented)
- - Key Achievements updated (100+ PRs, 9+ sprints)
- - feature-roadmap.md (Last Updated: 2026-01-13)
- - Routes updated (all current LiveView routes documented)
- - Membership Fees Endpoints (Status: ✅ Implemented)
- - Admin Panel Endpoints (Status updated)
- - Custom Fields Endpoints (corrected: managed via /settings)
- - CHANGELOG.md (new features documented)
- - CODE_GUIDELINES.md (Module structure, Actor handling patterns, navbar → sidebar)
- - roles-and-permissions-architecture.md (Status: ✅ Implemented)
- - roles-and-permissions-overview.md (Status: ✅ Implemented)
- - roles-and-permissions-implementation-plan.md (Status: ✅ Implemented)
- - membership-fee-architecture.md (Status: ✅ Implemented)
- - membership-fee-overview.md (Status: ✅ Implemented)
- - csv-member-import-v1.md (Status: Templates Created)
- - sidebar-requirements-v2.md (Status: ✅ Implemented)
- - README.md (Feature status updated)
-- **Removed Documentation:** 2 files
- - test-status-membership-fee-ui.md
- - test-failures-analysis.md
-- **Marked as Deprecated:** 2 files
- - sidebar-analysis-current-state.md
- - umsetzung-sidebar.md
-- **Code Adjustments Required:** 0
-- **Critical Issues:** 0
-
-**Documented Features Since 2025-12-02:**
-- Membership Fees System (6 PRs: #275, #276, #277, #278, #279, #280)
-- Custom Fields Enhancements (3 PRs: #196, #274, #282)
-- UI/UX Improvements (6 PRs: #209, #220, #231, #233, #273, #281)
-- Roles and Permissions (5 PRs: #321, #322, #323, #325, #345)
-- Sidebar Implementation (#260)
-- Member Field Settings (#223, #300)
-- CSV Import Templates (#329)
-- Actor Handling Refactoring
-- Internationalization Improvements
-
-The documentation is now fully synchronized with the current code. All "Last Updated" dates have been updated to 2026-01-13 where relevant. All routes, features, and implementations are documented.
diff --git a/docs/feature-roadmap.md b/docs/feature-roadmap.md
index 1df3eb6..c4ecfc9 100644
--- a/docs/feature-roadmap.md
+++ b/docs/feature-roadmap.md
@@ -1,8 +1,8 @@
# Feature Roadmap & Implementation Plan
**Project:** Mila - Membership Management System
-**Last Updated:** 2026-01-13
-**Status:** Active Development
+**Last Updated:** 2025-11-10
+**Status:** Planning Phase
---
@@ -37,24 +37,17 @@
- [#146](https://git.local-it.org/local-it/mitgliederverwaltung/issues/146) - Translate "or" in the login screen (Low)
- [#144](https://git.local-it.org/local-it/mitgliederverwaltung/issues/144) - Add language switch dropdown to login screen (Low)
-**Current State:**
-- ✅ **Role-based access control (RBAC)** - Implemented (2026-01-08, PR #346, closes #345)
-- ✅ **Permission system** - Four hardcoded permission sets (`own_data`, `read_only`, `normal_user`, `admin`)
-- ✅ **Database-backed roles** - Roles table with permission set references
-- ✅ **Resource policies** - Member resource policies with scope filtering
-- ✅ **Page-level authorization** - LiveView page access control
-- ✅ **System role protection** - Critical roles cannot be deleted
-
**Missing Features:**
+- ❌ Role-based access control (RBAC)
+- ❌ Permission system
- ❌ Password reset flow
- ❌ Email verification
- ❌ Two-factor authentication (future)
**Related Issues:**
-- ✅ [#345](https://git.local-it.org/local-it/mitgliederverwaltung/issues/345) - Member Resource Policies (closed 2026-01-13)
-- ✅ [#191](https://git.local-it.org/local-it/mitgliederverwaltung/issues/191) - Implement Roles in Ash (M) - Completed
-- ✅ [#190](https://git.local-it.org/local-it/mitgliederverwaltung/issues/190) - Implement Permissions in Ash (M) - Completed
-- ✅ [#151](https://git.local-it.org/local-it/mitgliederverwaltung/issues/151) - Define implementation plan for roles and permissions (M) - Completed
+- [#191](https://git.local-it.org/local-it/mitgliederverwaltung/issues/191) - Implement Roles in Ash (M)
+- [#190](https://git.local-it.org/local-it/mitgliederverwaltung/issues/190) - Implement Permissions in Ash (M)
+- [#151](https://git.local-it.org/local-it/mitgliederverwaltung/issues/151) - Define implementation plan for roles and permissions (M) [3/7 tasks done]
---
@@ -194,27 +187,23 @@
**Current State:**
- ✅ Basic "paid" boolean field on members
-- ✅ **Membership Fee Types Management** - Full CRUD implementation
-- ✅ **Membership Fee Cycles** - Individual billing cycles per member
-- ✅ **Membership Fee Settings** - Global settings (include_joining_cycle, default_fee_type)
-- ✅ **Cycle Generation** - Automatic cycle generation for members
-- ✅ **Payment Status Tracking** - Status per cycle (unpaid, paid, suspended)
-- ✅ **Member Fee Assignment** - Members can be assigned to fee types
-- ✅ **Cycle Regeneration** - Regenerate cycles when fee type changes
-- ✅ **UI Components** - Membership fee status in member list and detail views
+- ✅ **UI Mock-ups for Membership Fee Types & Settings** (2025-12-02)
+- ⚠️ No payment tracking
**Open Issues:**
- [#156](https://git.local-it.org/local-it/mitgliederverwaltung/issues/156) - Set up & document testing environment for vereinfacht.digital (L, Low priority)
-- ✅ [#226](https://git.local-it.org/local-it/mitgliederverwaltung/issues/226) - Payment/Membership Fee Mockup Pages (Preview) - Implemented
+- [#226](https://git.local-it.org/local-it/mitgliederverwaltung/issues/226) - Payment/Membership Fee Mockup Pages (Preview)
-**Implemented Pages:**
-- `/membership_fee_types` - Membership Fee Types Management (fully functional)
-- `/membership_fee_settings` - Global Membership Fee Settings (fully functional)
-- `/members/:id` - Member detail view with membership fee cycles
+**Mock-Up Pages (Non-Functional Preview):**
+- `/membership_fee_types` - Membership Fee Types Management
+- `/membership_fee_settings` - Global Membership Fee Settings
**Missing Features:**
-- ❌ Payment records/transactions (external payment tracking)
+- ❌ Membership fee configuration
+- ❌ Payment records/transactions
+- ❌ Payment history per member
- ❌ Payment reminders
+- ❌ Payment status tracking (pending, paid, overdue)
- ❌ Invoice generation
- ❌ vereinfacht.digital API integration
- ❌ SEPA direct debit support
@@ -229,18 +218,17 @@
**Current State:**
- ✅ AshAdmin integration (basic)
-- ✅ **Global Settings Management** - `/settings` page (singleton resource)
-- ✅ **Club/Organization profile** - Club name configuration
-- ✅ **Member Field Visibility Settings** - Configure which fields show in overview
-- ✅ **CustomFieldValue type management UI** - Full CRUD for custom fields
-- ✅ **Role Management UI** - Full CRUD for roles (`/admin/roles`)
-- ✅ **Membership Fee Settings** - Global fee settings management
+- ⚠️ No user-facing admin UI
**Open Issues:**
- [#186](https://git.local-it.org/local-it/mitgliederverwaltung/issues/186) - Create Architecture docs in Repo (S, Low priority)
**Missing Features:**
+- ❌ Global settings management
+- ❌ Club/Organization profile
- ❌ Email templates configuration
+- ❌ CustomFieldValue type management UI (user-facing)
+- ❌ Role and permission management UI
- ❌ System health dashboard
- ❌ Audit log viewer
- ❌ Backup/restore functionality
@@ -285,12 +273,10 @@
**Current State:**
- ✅ Seed data script
-- ✅ **CSV Import Templates** - German and English templates (#329, 2026-01-13)
- - Template files in `priv/static/templates/member_import_de.csv` and `member_import_en.csv`
- - CSV specification documented in `docs/csv-member-import-v1.md`
+- ⚠️ No user-facing import/export
**Missing Features:**
-- ❌ CSV import implementation (templates ready, import logic pending)
+- ❌ CSV import for members
- ❌ Excel import for members
- ❌ Import validation and preview
- ❌ Import error handling
@@ -466,7 +452,6 @@ Since this is a **Phoenix LiveView** application with **Ash Framework**, we have
| `GET` | `/auth/user/rauthy` | Initiate OIDC flow | 🔓 | - | Redirect to Rauthy |
| `GET` | `/auth/user/rauthy/callback` | Handle OIDC callback | 🔓 | `{code, state}` | Redirect + session cookie |
| `POST` | `/auth/user/sign_out` | Sign out user | 🔐 | - | Redirect to login |
-| `GET` | `/auth/link-oidc-account` | OIDC account linking (password verification) | 🔓 | - | LiveView form | ✅ Implemented |
| `GET` | `/auth/user/password/reset` | Show password reset form | 🔓 | - | HTML form |
| `POST` | `/auth/user/password/reset` | Request password reset | 🔓 | `{email}` | Success message + email sent |
| `GET` | `/auth/user/password/reset/:token` | Show reset password form | 🔓 | - | HTML form |
@@ -552,18 +537,13 @@ Since this is a **Phoenix LiveView** application with **Ash Framework**, we have
### 3. Custom Fields (CustomFieldValue System) Endpoints
-#### LiveView Endpoints (✅ Implemented)
+#### LiveView Endpoints
-| Mount | Purpose | Auth | Events | Status |
-|-------|---------|------|--------|--------|
-| `/settings` | Global settings (includes custom fields management) | 🔐 | `save`, `validate` | ✅ Implemented |
-| `/custom_field_values` | List all custom field values | 🔐 | `new`, `edit`, `delete` | ✅ Implemented |
-| `/custom_field_values/new` | Create custom field value | 🔐 | `save`, `cancel` | ✅ Implemented |
-| `/custom_field_values/:id` | Custom field value detail | 🔐 | `edit` | ✅ Implemented |
-| `/custom_field_values/:id/edit` | Edit custom field value | 🔐 | `save`, `cancel` | ✅ Implemented |
-| `/custom_field_values/:id/show/edit` | Edit from show page | 🔐 | `save`, `cancel` | ✅ Implemented |
-
-**Note:** Custom fields (definitions) are managed via LiveComponent in `/settings` page, not as separate routes.
+| Mount | Purpose | Auth | Events |
+|-------|---------|------|--------|
+| `/custom-fields` | List custom fields | 🛡️ | `new`, `edit`, `delete` |
+| `/custom-fields/new` | Create custom field | 🛡️ | `save`, `cancel` |
+| `/custom-fields/:id/edit` | Edit custom field | 🛡️ | `save`, `cancel`, `delete` |
#### Ash Resource Actions
@@ -642,81 +622,63 @@ Since this is a **Phoenix LiveView** application with **Ash Framework**, we have
### 6. Internationalization Endpoints
-#### HTTP Controller Endpoints (✅ Implemented)
+#### HTTP Controller Endpoints
-| Method | Route | Purpose | Auth | Request | Response | Status |
-|--------|-------|---------|------|---------|----------|--------|
-| `POST` | `/set_locale` | Set user locale | 🔐 | `{locale: "de"}` | Redirect with cookie | ✅ Implemented |
-| `GET` | `/locales` | List available locales | 🔓 | - | `["de", "en"]` | ❌ Not implemented |
-
-**Note:** Locale is set via `/set_locale` POST endpoint and persisted in session/cookie. Supported locales: `de` (default), `en`.
+| Method | Route | Purpose | Auth | Request | Response |
+|--------|-------|---------|------|---------|----------|
+| `POST` | `/locale` | Set user locale | 🔐 | `{locale: "de"}` | Redirect with cookie |
+| `GET` | `/locales` | List available locales | 🔓 | - | `["de", "en"]` |
---
### 7. Payment & Fees Management Endpoints
-#### LiveView Endpoints (✅ Implemented)
+#### LiveView Endpoints (NEW - Issue #156)
-| Mount | Purpose | Auth | Events | Status |
-|-------|---------|------|--------|--------|
-| `/membership_fee_types` | Membership fee type list | 🔐 | `new`, `edit`, `delete` | ✅ Implemented |
-| `/membership_fee_types/new` | Create membership fee type | 🔐 | `save`, `cancel` | ✅ Implemented |
-| `/membership_fee_types/:id/edit` | Edit membership fee type | 🔐 | `save`, `cancel` | ✅ Implemented |
-| `/membership_fee_settings` | Global membership fee settings | 🔐 | `save` | ✅ Implemented |
-| `/contributions/member/:id` | Member contribution periods (mock-up) | 🔐 | - | ⚠️ Mock-up only |
-| `/contribution_types` | Contribution types (mock-up) | 🔐 | - | ⚠️ Mock-up only |
+| Mount | Purpose | Auth | Events |
+|-------|---------|------|--------|
+| `/payments` | Payment list | 🔐 | `new`, `record_payment`, `send_reminder` |
+| `/payments/:id` | Payment detail | 🔐 | `edit`, `delete`, `mark_paid` |
+| `/fees` | Fee configuration | 🛡️ | `create`, `edit`, `delete` |
+| `/invoices` | Invoice list | 🔐 | `generate`, `download`, `send` |
-#### Ash Resource Actions (✅ Partially Implemented)
+#### Ash Resource Actions (NEW)
-| Resource | Action | Purpose | Auth | Input | Output | Status |
-|----------|--------|---------|------|-------|--------|--------|
-| `MembershipFeeType` | `:create` | Create fee type | 🔐 | `{name, amount, interval, ...}` | `{:ok, fee_type}` | ✅ Implemented |
-| `MembershipFeeType` | `:read` | List fee types | 🔐 | - | `[%MembershipFeeType{}]` | ✅ Implemented |
-| `MembershipFeeType` | `:update` | Update fee type (name, amount, description) | 🔐 | `{id, attrs}` | `{:ok, fee_type}` | ✅ Implemented |
-| `MembershipFeeType` | `:destroy` | Delete fee type (if no cycles) | 🔐 | `{id}` | `{:ok, fee_type}` | ✅ Implemented |
-| `MembershipFeeCycle` | `:read` | List cycles for member | 🔐 | `{member_id}` | `[%MembershipFeeCycle{}]` | ✅ Implemented |
-| `MembershipFeeCycle` | `:update` | Update cycle status | 🔐 | `{id, status}` | `{:ok, cycle}` | ✅ Implemented |
-| `Payment` | `:create` | Record payment | 🔐 | `{member_id, fee_id, amount, date}` | `{:ok, payment}` | ❌ Not implemented |
-| `Payment` | `:list_by_member` | Member payment history | 🔐 | `{member_id}` | `[%Payment{}]` | ❌ Not implemented |
-| `Payment` | `:mark_paid` | Mark as paid | 🔐 | `{id}` | `{:ok, payment}` | ❌ Not implemented |
-| `Invoice` | `:generate` | Generate invoice | 🔐 | `{member_id, fee_id, period}` | `{:ok, invoice}` | ❌ Not implemented |
-| `Invoice` | `:send` | Send invoice via email | 🔐 | `{id}` | `{:ok, sent}` | ❌ Not implemented |
-| `Payment` | `:import_vereinfacht` | Import from vereinfacht.digital | 🛡️ | `{transactions}` | `{:ok, count}` | ❌ Not implemented |
+| Resource | Action | Purpose | Auth | Input | Output |
+|----------|--------|---------|------|-------|--------|
+| `Fee` | `:create` | Create fee type | 🛡️ | `{name, amount, frequency}` | `{:ok, fee}` |
+| `Fee` | `:read` | List fees | 🔐 | - | `[%Fee{}]` |
+| `Payment` | `:create` | Record payment | 🔐 | `{member_id, fee_id, amount, date}` | `{:ok, payment}` |
+| `Payment` | `:list_by_member` | Member payment history | 🔐 | `{member_id}` | `[%Payment{}]` |
+| `Payment` | `:mark_paid` | Mark as paid | 🔐 | `{id}` | `{:ok, payment}` |
+| `Invoice` | `:generate` | Generate invoice | 🔐 | `{member_id, fee_id, period}` | `{:ok, invoice}` |
+| `Invoice` | `:send` | Send invoice via email | 🔐 | `{id}` | `{:ok, sent}` |
+| `Payment` | `:import_vereinfacht` | Import from vereinfacht.digital | 🛡️ | `{transactions}` | `{:ok, count}` |
---
### 8. Admin Panel & Configuration Endpoints
-#### LiveView Endpoints (✅ Partially Implemented)
+#### LiveView Endpoints (NEW)
-| Mount | Purpose | Auth | Events | Status |
-|-------|---------|------|--------|--------|
-| `/settings` | Global settings (club name, member fields, custom fields) | 🔐 | `save`, `validate` | ✅ Implemented |
-| `/admin/roles` | Role management | 🛡️ | `new`, `edit`, `delete` | ✅ Implemented |
-| `/admin/roles/new` | Create role | 🛡️ | `save`, `cancel` | ✅ Implemented |
-| `/admin/roles/:id` | Role detail view | 🛡️ | `edit` | ✅ Implemented |
-| `/admin/roles/:id/edit` | Edit role | 🛡️ | `save`, `cancel` | ✅ Implemented |
-| `/admin` | Admin dashboard | 🛡️ | - | ❌ Not implemented |
-| `/admin/organization` | Organization profile | 🛡️ | `save` | ❌ Not implemented |
-| `/admin/email-templates` | Email template editor | 🛡️ | `create`, `edit`, `preview` | ❌ Not implemented |
-| `/admin/audit-log` | System audit log | 🛡️ | `filter`, `export` | ❌ Not implemented |
+| Mount | Purpose | Auth | Events |
+|-------|---------|------|--------|
+| `/admin` | Admin dashboard | 🛡️ | - |
+| `/admin/settings` | Global settings | 🛡️ | `save` |
+| `/admin/organization` | Organization profile | 🛡️ | `save` |
+| `/admin/email-templates` | Email template editor | 🛡️ | `create`, `edit`, `preview` |
+| `/admin/audit-log` | System audit log | 🛡️ | `filter`, `export` |
-#### Ash Resource Actions (✅ Partially Implemented)
+#### Ash Resource Actions (NEW)
-| Resource | Action | Purpose | Auth | Input | Output | Status |
-|----------|--------|---------|------|-------|--------|--------|
-| `Setting` | `:read` | Get settings (singleton) | 🔐 | - | `{:ok, settings}` | ✅ Implemented |
-| `Setting` | `:update` | Update settings | 🔐 | `{club_name, member_field_visibility, ...}` | `{:ok, settings}` | ✅ Implemented |
-| `Setting` | `:update_member_field_visibility` | Update field visibility | 🔐 | `{member_field_visibility}` | `{:ok, settings}` | ✅ Implemented |
-| `Setting` | `:update_single_member_field_visibility` | Atomic field visibility update | 🔐 | `{field, show_in_overview}` | `{:ok, settings}` | ✅ Implemented |
-| `Setting` | `:update_membership_fee_settings` | Update fee settings | 🔐 | `{include_joining_cycle, default_membership_fee_type_id}` | `{:ok, settings}` | ✅ Implemented |
-| `Role` | `:read` | List roles | 🛡️ | - | `[%Role{}]` | ✅ Implemented |
-| `Role` | `:create` | Create role | 🛡️ | `{name, permission_set_name, ...}` | `{:ok, role}` | ✅ Implemented |
-| `Role` | `:update` | Update role | 🛡️ | `{id, attrs}` | `{:ok, role}` | ✅ Implemented |
-| `Role` | `:destroy` | Delete role (if not system role) | 🛡️ | `{id}` | `{:ok, role}` | ✅ Implemented |
-| `Organization` | `:read` | Get organization info | 🔐 | - | `%Organization{}` | ❌ Not implemented |
-| `Organization` | `:update` | Update organization | 🛡️ | `{name, logo, ...}` | `{:ok, org}` | ❌ Not implemented |
-| `AuditLog` | `:list` | List audit entries | 🛡️ | `{filters, pagination}` | `[%AuditLog{}]` | ❌ Not implemented |
+| Resource | Action | Purpose | Auth | Input | Output |
+|----------|--------|---------|------|-------|--------|
+| `Setting` | `:get` | Get setting value | 🔐 | `{key}` | `value` |
+| `Setting` | `:set` | Set setting value | 🛡️ | `{key, value}` | `{:ok, setting}` |
+| `Setting` | `:list` | List all settings | 🛡️ | - | `[%Setting{}]` |
+| `Organization` | `:read` | Get organization info | 🔐 | - | `%Organization{}` |
+| `Organization` | `:update` | Update organization | 🛡️ | `{name, logo, ...}` | `{:ok, org}` |
+| `AuditLog` | `:list` | List audit entries | 🛡️ | `{filters, pagination}` | `[%AuditLog{}]` |
---
diff --git a/docs/membership-fee-architecture.md b/docs/membership-fee-architecture.md
index 4a290b7..7c8da24 100644
--- a/docs/membership-fee-architecture.md
+++ b/docs/membership-fee-architecture.md
@@ -3,8 +3,8 @@
**Project:** Mila - Membership Management System
**Feature:** Membership Fee Management
**Version:** 1.0
-**Last Updated:** 2026-01-13
-**Status:** ✅ Implemented
+**Last Updated:** 2025-11-27
+**Status:** Architecture Design - Ready for Implementation
---
@@ -76,13 +76,6 @@ This document defines the technical architecture for the Membership Fees system.
- `MembershipFeeType` - Membership fee type definitions (admin-managed)
- `MembershipFeeCycle` - Individual membership fee cycles per member
-**Public API:**
-The domain exposes code interface functions:
-- `create_membership_fee_type/1`, `list_membership_fee_types/0`, `update_membership_fee_type/2`, `destroy_membership_fee_type/1`
-- `create_membership_fee_cycle/1`, `list_membership_fee_cycles/0`, `update_membership_fee_cycle/2`, `destroy_membership_fee_cycle/1`
-
-**Note:** In LiveViews, direct `Ash.read`, `Ash.create`, `Ash.update`, `Ash.destroy` calls are used with `domain: Mv.MembershipFees` instead of code interface functions. This is acceptable for LiveView forms that use `AshPhoenix.Form`.
-
**Extensions:**
- Member resource extended with membership fee fields
@@ -355,9 +348,6 @@ lib/
1. MembershipFeeType index/form (admin)
2. MembershipFeeCycle table component (member detail view)
- - Implemented as `MvWeb.MemberLive.Show.MembershipFeesComponent`
- - Displays all cycles in a table with status management
- - Allows changing cycle status, editing amounts, and regenerating cycles
3. Settings form section (admin)
4. Member list column (membership fee status)
diff --git a/docs/membership-fee-overview.md b/docs/membership-fee-overview.md
index 8eb48b0..bd47faa 100644
--- a/docs/membership-fee-overview.md
+++ b/docs/membership-fee-overview.md
@@ -3,8 +3,8 @@
**Project:** Mila - Membership Management System
**Feature:** Membership Fee Management
**Version:** 1.0
-**Last Updated:** 2026-01-13
-**Status:** ✅ Implemented
+**Last Updated:** 2025-11-27
+**Status:** Concept - Ready for Review
---
diff --git a/docs/roles-and-permissions-architecture.md b/docs/roles-and-permissions-architecture.md
index 6c21907..8c89af7 100644
--- a/docs/roles-and-permissions-architecture.md
+++ b/docs/roles-and-permissions-architecture.md
@@ -2,8 +2,7 @@
**Version:** 2.0 (Clean Rewrite)
**Date:** 2025-01-13
-**Last Updated:** 2026-01-13
-**Status:** ✅ Implemented (2026-01-08, PR #346, closes #345)
+**Status:** Ready for Implementation
**Related Documents:**
- [Overview](./roles-and-permissions-overview.md) - High-level concepts for stakeholders
- [Implementation Plan](./roles-and-permissions-implementation-plan.md) - Step-by-step implementation guide
@@ -1556,7 +1555,7 @@ end
**Navbar with conditional links:**
```heex
-
+