This commit is contained in:
parent
f7f25ad69a
commit
55401eda3a
19 changed files with 732 additions and 499 deletions
|
|
@ -6,8 +6,8 @@
|
|||
// - https://dbdocs.io
|
||||
// - VS Code Extensions: "DBML Language" or "dbdiagram.io"
|
||||
//
|
||||
// Version: 1.3
|
||||
// Last Updated: 2025-12-11
|
||||
// Version: 1.4
|
||||
// Last Updated: 2026-01-13
|
||||
|
||||
Project mila_membership_management {
|
||||
database_type: 'PostgreSQL'
|
||||
|
|
@ -28,6 +28,7 @@ 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)
|
||||
|
|
@ -500,3 +501,138 @@ 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).
|
||||
'''
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue