3 changed files with 28 additions and 6 deletions
|
|
@ -48,7 +48,7 @@ A **basic CSV member import feature** that allows administrators to upload a CSV
|
||||||
- Upload CSV file via LiveView file upload
|
- Upload CSV file via LiveView file upload
|
||||||
- Parse CSV with bilingual header support for core member fields (English/German)
|
- Parse CSV with bilingual header support for core member fields (English/German)
|
||||||
- Auto-detect delimiter (`;` or `,`) using header recognition
|
- 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)
|
- **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`)
|
- 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)
|
- 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:**
|
**v1 Supported Fields:**
|
||||||
|
|
||||||
**Core Member Fields:**
|
**Core Member Fields (all importable):**
|
||||||
|
- `email` / `E-Mail` (required)
|
||||||
- `first_name` / `Vorname` (optional)
|
- `first_name` / `Vorname` (optional)
|
||||||
- `last_name` / `Nachname` (optional)
|
- `last_name` / `Nachname` (optional)
|
||||||
- `email` / `E-Mail` (required)
|
- `join_date` / `Beitrittsdatum` (optional, ISO-8601 date)
|
||||||
- `street` / `Straße` (optional)
|
- `exit_date` / `Austrittsdatum` (optional, ISO-8601 date)
|
||||||
- `postal_code` / `PLZ` / `Postleitzahl` (optional)
|
- `notes` / `Notizen` (optional)
|
||||||
|
- `country` / `Land` / `Staat` (optional)
|
||||||
- `city` / `Stadt` (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:**
|
**Custom Fields:**
|
||||||
- Any custom field column using the custom field's **name** as the header (e.g., `membership_number`, `birth_date`)
|
- 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` |
|
| `first_name` | `first_name`, `firstname` | `Vorname`, `vorname` |
|
||||||
| `last_name` | `last_name`, `lastname`, `surname` | `Nachname`, `nachname`, `Familienname` |
|
| `last_name` | `last_name`, `lastname`, `surname` | `Nachname`, `nachname`, `Familienname` |
|
||||||
| `email` | `email`, `e-mail`, `e_mail` | `E-Mail`, `e-mail`, `e_mail` |
|
| `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` |
|
| `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` |
|
| `postal_code` | `postal_code`, `zip`, `postcode` | `PLZ`, `plz`, `Postleitzahl`, `postleitzahl` |
|
||||||
| `city` | `city`, `town` | `Stadt`, `stadt`, `Ort` |
|
| `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):**
|
**Header Normalization (used consistently for both input headers AND mapping variants):**
|
||||||
- Trim whitespace
|
- Trim whitespace
|
||||||
|
|
|
||||||
|
|
@ -192,6 +192,7 @@ Settings (1) → MembershipFeeType (0..1)
|
||||||
- Exit date must be after join date
|
- Exit date must be after join date
|
||||||
- Phone: `+?[0-9\- ]{6,20}`
|
- Phone: `+?[0-9\- ]{6,20}`
|
||||||
- Postal code: optional (no format validation)
|
- Postal code: optional (no format validation)
|
||||||
|
- Country: optional
|
||||||
|
|
||||||
### CustomFieldValue System
|
### CustomFieldValue System
|
||||||
- Maximum one custom field value per custom field per member
|
- Maximum one custom field value per custom field per member
|
||||||
|
|
@ -240,7 +241,7 @@ Settings (1) → MembershipFeeType (0..1)
|
||||||
### Weighted Fields
|
### Weighted Fields
|
||||||
- **Weight A (highest):** first_name, last_name
|
- **Weight A (highest):** first_name, last_name
|
||||||
- **Weight B:** email, notes, group names (from member_groups → groups)
|
- **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
|
- **Weight D (lowest):** join_date, exit_date
|
||||||
|
|
||||||
### Group Names in Search
|
### Group Names in Search
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,7 @@ Table members {
|
||||||
street text [null, note: 'Street name']
|
street text [null, note: 'Street name']
|
||||||
house_number text [null, note: 'House number']
|
house_number text [null, note: 'House number']
|
||||||
postal_code text [null, note: '5-digit German postal code']
|
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)']
|
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_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']
|
membership_fee_start_date date [null, note: 'Date from which membership fees should be calculated']
|
||||||
|
|
@ -189,6 +190,7 @@ Table members {
|
||||||
- join_date: cannot be in future
|
- join_date: cannot be in future
|
||||||
- exit_date: must be after join_date (if both present)
|
- exit_date: must be after join_date (if both present)
|
||||||
- postal_code: optional (no format validation)
|
- postal_code: optional (no format validation)
|
||||||
|
- country: optional
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue