Merge branch 'main' into feat/447_concistency
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/promote/production Build is passing

This commit is contained in:
carla 2026-02-25 16:52:33 +01:00
commit c7c082b867
27 changed files with 926 additions and 131 deletions

View file

@ -48,7 +48,7 @@ A **basic CSV member import feature** that allows administrators to upload a CSV
- Upload CSV file via LiveView file upload
- Parse CSV with bilingual header support for core member fields (English/German)
- Auto-detect delimiter (`;` or `,`) using header recognition
- Map CSV columns to core member fields (`first_name`, `last_name`, `email`, `street`, `postal_code`, `city`)
- Map CSV columns to core member fields (`first_name`, `last_name`, `email`, `street`, `postal_code`, `city`, `country`)
- **Import custom field values** - Map CSV columns to existing custom fields by name (unknown custom field columns will be ignored with a warning)
- Validate each row (required field: `email`)
- Create members via Ash resource (one-by-one, **no background jobs**, processed in chunks of 200 rows via LiveView messages)
@ -149,13 +149,26 @@ A **basic CSV member import feature** that allows administrators to upload a CSV
**v1 Supported Fields:**
**Core Member Fields:**
**Core Member Fields (all importable):**
- `email` / `E-Mail` (required)
- `first_name` / `Vorname` (optional)
- `last_name` / `Nachname` (optional)
- `email` / `E-Mail` (required)
- `street` / `Straße` (optional)
- `postal_code` / `PLZ` / `Postleitzahl` (optional)
- `join_date` / `Beitrittsdatum` (optional, ISO-8601 date)
- `exit_date` / `Austrittsdatum` (optional, ISO-8601 date)
- `notes` / `Notizen` (optional)
- `country` / `Land` / `Staat` (optional)
- `city` / `Stadt` (optional)
- `street` / `Straße` (optional)
- `house_number` / `Hausnummer` / `Nr.` (optional)
- `postal_code` / `PLZ` / `Postleitzahl` (optional)
- `membership_fee_start_date` / `Beitragsbeginn` (optional, ISO-8601 date)
Address column order in import/export matches the members overview: country, city, street, house number, postal code.
**Not supported for import (by design):**
- **membership_fee_status** Computed field (from fee cycles). Not stored; export-only.
- **groups** Many-to-many relationship. Would require resolving group names to IDs; not in current scope.
- **membership_fee_type_id** Foreign key; could be added later (e.g. resolve type name to ID).
**Custom Fields:**
- Any custom field column using the custom field's **name** as the header (e.g., `membership_number`, `birth_date`)
@ -176,9 +189,15 @@ A **basic CSV member import feature** that allows administrators to upload a CSV
| `first_name` | `first_name`, `firstname` | `Vorname`, `vorname` |
| `last_name` | `last_name`, `lastname`, `surname` | `Nachname`, `nachname`, `Familienname` |
| `email` | `email`, `e-mail`, `e_mail` | `E-Mail`, `e-mail`, `e_mail` |
| `join_date` | `join date`, `join_date` | `Beitrittsdatum`, `beitritts-datum` |
| `exit_date` | `exit date`, `exit_date` | `Austrittsdatum`, `austritts-datum` |
| `notes` | `notes` | `Notizen`, `bemerkungen` |
| `street` | `street`, `address` | `Straße`, `strasse`, `Strasse` |
| `house_number` | `house number`, `house_number`, `house no` | `Hausnummer`, `Nr`, `Nr.`, `Nummer` |
| `postal_code` | `postal_code`, `zip`, `postcode` | `PLZ`, `plz`, `Postleitzahl`, `postleitzahl` |
| `city` | `city`, `town` | `Stadt`, `stadt`, `Ort` |
| `country` | `country` | `Land`, `land`, `Staat`, `staat` |
| `membership_fee_start_date` | `membership fee start date`, `membership_fee_start_date`, `fee start` | `Beitragsbeginn`, `beitrags-beginn` |
**Header Normalization (used consistently for both input headers AND mapping variants):**
- Trim whitespace

View file

@ -191,7 +191,8 @@ Settings (1) → MembershipFeeType (0..1)
- Join date cannot be in future
- Exit date must be after join date
- Phone: `+?[0-9\- ]{6,20}`
- Postal code: 5 digits
- Postal code: optional (no format validation)
- Country: optional
### CustomFieldValue System
- Maximum one custom field value per custom field per member
@ -240,7 +241,7 @@ Settings (1) → MembershipFeeType (0..1)
### Weighted Fields
- **Weight A (highest):** first_name, last_name
- **Weight B:** email, notes, group names (from member_groups → groups)
- **Weight C:** city, street, house_number, postal_code, custom_field_values
- **Weight C:** city, street, house_number, postal_code, country, custom_field_values
- **Weight D (lowest):** join_date, exit_date
### Group Names in Search

View file

@ -131,6 +131,7 @@ Table members {
street text [null, note: 'Street name']
house_number text [null, note: 'House number']
postal_code text [null, note: '5-digit German postal code']
country text [null, note: 'Country of residence']
search_vector tsvector [null, note: 'Full-text search index (auto-generated)']
membership_fee_type_id uuid [null, note: 'FK to membership_fee_types - assigned fee type']
membership_fee_start_date date [null, note: 'Date from which membership fees should be calculated']
@ -188,7 +189,8 @@ Table members {
- email: 5-254 characters, valid email format (required)
- join_date: cannot be in future
- exit_date: must be after join_date (if both present)
- postal_code: exactly 5 digits (if present)
- postal_code: optional (no format validation)
- country: optional
'''
}