f211f45cb2
test: export and PDF regression for Fee Type without start_date
...
continuous-integration/drone/push Build was killed
Add test for CSV export with only first_name and membership_fee_type.
Add test for PDF export with same field set (status and content-type).
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 09:15:41 +01:00
83264325f1
fix: include Fee Type in export when Start Date not in fields
...
Append membership_fee_type to column list when it is visible but
membership_fee_start_date was not in the selection (MemberExport,
export_column_order, build_export_member_fields_list).
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 09:15:08 +01:00
3b6c0b9fc9
fix: sort Fee Type by name in LiveView and exports
...
Use Ash related-field sort (membership_fee_type.name) instead of
membership_fee_type_id so column order is alphabetical. Load
membership_fee_type when sorting by it even if column is hidden.
In-memory re-sort (Build) uses loaded fee type name.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-24 09:15:04 +01:00
d41d13d122
fix(members): restore column visibility from URL on reload
...
continuous-integration/drone/push Build is passing
Read 'fields' from URI when conn.params has no query (e.g. full page load).
When ?fields=... is present use URL-only selection so columns are not
merged with global settings. Fall back to session+global when URL has
only invalid field names.
2026-02-24 01:06:46 +01:00
e86c78a0dc
feat(export): include Fee Type and groups in PDF export
...
MemberExport allowlist and insert_fee_type; Build load/sort/cell_value;
MemberPdfExportController allow membership_fee_type and groups.
2026-02-24 00:20:29 +01:00
8db24405fa
test: fee type column visibility, CSV export, export controller
...
FieldVisibility pseudo fields and visible selection; MembersCSV fee type
column; export accepts membership_fee_type and returns Fee Type column.
2026-02-23 23:55:13 +01:00
f3b213ecec
feat(export): include Fee Type in CSV export
...
Payload and column_order when visible; allowlist, load, sort;
MembersCSV cell for :membership_fee_type.
2026-02-23 23:55:08 +01:00
68ceaced0c
feat(members): show and sort by Fee Type in member overview
...
Load membership_fee_type when column visible; sort by membership_fee_type_id;
add table column with SortHeader and fee type name.
2026-02-23 23:55:03 +01:00
b7ef69813b
feat(members): add Fee Type label and gettext strings
...
MemberFields.label(:membership_fee_type), DE: Beitragsart.
2026-02-23 23:54:59 +01:00
5715a22b0c
feat(members): add membership_fee_type to overview pseudo fields
...
Allow Fee Type as selectable column in member overview dropdown.
2026-02-23 23:54:50 +01:00
0f51bc89c3
Merge pull request 'Configurable member field "required" flag and Vereinfacht-required fields closes #440 ' ( #441 ) from fix/required_fields into main
...
continuous-integration/drone/push Build is passing
Reviewed-on: #441
2026-02-23 23:28:34 +01:00
b3b8b31c0f
Member: skip required custom fields validation for set_vereinfacht_contact_id
...
continuous-integration/drone/push Build is passing
continuous-integration/drone/promote/production Build is passing
Validation runs only for create_member and update_member so Vereinfacht
sync (which only sets vereinfacht_contact_id) no longer fails with
Required custom fields missing.
2026-02-23 23:07:38 +01:00
e9ed61a8fd
Tests: restore settings in on_exit to avoid leftover state
...
Setup + on_exit save/restore member_field_visibility and
member_field_required in member, setting, index_component and
form_error_handling tests.
2026-02-23 22:51:18 +01:00
50c4ab049d
core_components: set aria-required for required inputs (WCAG)
...
ensure_aria_required_for_input/1 adds aria-required when required
in rest; applied to select, textarea and default input.
2026-02-23 22:51:13 +01:00
717b8f5676
UpdateSingleMemberField: error attribution, updated_at, snapshot newline
...
Attach errors to :field, :show_in_overview, :member_field_required.
Set updated_at in SQL UPDATE. Add trailing newline to snapshot JSON.
2026-02-23 22:50:51 +01:00
0d1b776e78
Member: enforce email + Vereinfacht-required when get_settings fails
...
Compute vereinfacht_required? outside case; on error log and validate
only base required (email + Vereinfacht fields), not full settings.
2026-02-23 22:50:43 +01:00
cca2ca4632
FormComponent: persist vereinfacht_required_field? in socket
...
Assign in assign_form so validate/save enforce server-side without
relying on render assigns; use socket.assigns.vereinfacht_required_field?
2026-02-23 22:50:34 +01:00
bbededf3b9
CODE_GUIDELINES: document member_field_required and Vereinfacht required fields
continuous-integration/drone/push Build is passing
2026-02-23 22:13:58 +01:00
d44c5bdf94
Tests: member required fields, setting, member field live, sync_contact
...
Add tests for required validation, update_single_member_field, form
required map. Add street/postal_code/city to sync_contact when Vereinfacht configured.
2026-02-23 22:13:53 +01:00
27b9cbe814
Member form: required per field from settings and Vereinfacht
...
Load settings, build member_field_required_map and pass required to
inputs for asterisk, tooltip and validation.
2026-02-23 22:13:46 +01:00
8933ad9d14
Member field settings: required checkbox, line break, toggle fix
...
Index/Form use member_field_required; Required disabled for email and
Vereinfacht-required fields with tooltip. Rebuild form with to_form
on validate to fix checkbox toggle. Add mt-4 block before Required.
2026-02-23 22:13:31 +01:00
17fd5e13d5
Member: validate configurable and Vereinfacht-required fields
...
Add validation for required member fields from settings and for
Vereinfacht-required fields when integration is configured.
2026-02-23 22:13:26 +01:00
fec2f7b6f6
Constants: add vereinfacht_required_member_fields
...
Defines first_name, last_name, street, postal_code, city as required
when Vereinfacht integration is active.
2026-02-23 22:13:16 +01:00
c86781c32b
Setting: add member_field_required and update_single_member_field
...
Add JSONB attribute member_field_required, migration, Change and
Membership code interface for atomic per-field required flag.
2026-02-23 22:13:08 +01:00
a1684f485c
Merge pull request 'Vereinfacht accounting software API closes #431 ' ( #432 ) from feature/vereinfacht_api into main
...
continuous-integration/drone/push Build is passing
Reviewed-on: #432
2026-02-23 21:18:44 +01:00
0f20e459e9
Gettext: Vereinfacht strings in du-form (i18n guidelines)
continuous-integration/drone/push Build is passing
continuous-integration/drone/promote/production Build is passing
2026-02-23 20:49:38 +01:00
d9491dea9c
Member show: present? check for vereinfacht_contact_id in UI
...
Use vereinfacht_contact_present assign so empty string is not treated as present.
2026-02-23 20:49:34 +01:00
daaa4dc345
Vereinfacht: filter blank vereinfacht_contact_id in sync_members
...
Include members with empty string; use expr with ref for Ash filter.
2026-02-23 20:49:30 +01:00
8ffd842c38
Vereinfacht client: receipt allowlist, find_contact pagination, flatten nesting
...
- Receipt attrs: allowlist only (no String.to_atom on API input / DoS)
- find_contact_by_email: paginate through all pages (page[size]=100)
- Extract helpers to satisfy Credo max nesting depth
2026-02-23 20:49:19 +01:00
1f21afeb72
Setting: vereinfacht_api_key public? false
...
Reduce exposure of API key; keep sensitive? true.
2026-02-23 20:49:12 +01:00
3cdaa75fc1
Member: remove system-actor fallback in extract_existing_values
...
Per guidelines: actor must come from context. When nil, skip load and return empty map.
2026-02-23 20:49:00 +01:00
482a335d36
Fix config test: clear vereinfacht_app_url from settings so derived URL is used
2026-02-23 20:48:57 +01:00
68e6c74a67
Gettext: add DE translations for Vereinfacht receipts and app URL
2026-02-23 19:54:44 +01:00
b60ab3f392
Member show: Vereinfacht link only, receipts table from API
...
- Show only 'Kontakt in Vereinfacht anzeigen' link (no Contact ID / Debug)
- Button loads receipts via get_contact_with_receipts, table with formatted columns
2026-02-23 19:54:44 +01:00
ede3df12ef
SyncFlash: document :public ETS table option
2026-02-23 19:54:44 +01:00
6c22d889a1
Vereinfacht client: receipts API, fetch_contact refactor, isExternal
...
- get_contact_with_receipts(contact_id) with ?include=receipts
- fetch_contact/2, build_url_with_params, extract_receipts_from_response
- Filter external contacts by isExternal in find_contact_id_by_email
- Send isExternal: true in create/update payloads
2026-02-23 19:54:44 +01:00
140e4a9054
SyncContact: only run when relevant attributes changed
...
- Sync on create; on update only when synced attrs changed or no contact_id yet
- Reduces unnecessary API calls on unrelated member updates
2026-02-23 19:54:43 +01:00
1188320844
Restrict set_vereinfacht_contact_id to system actor
...
- Add ActorIsSystemUser policy check
- Member set_vereinfacht_contact_id only allowed for system user
2026-02-23 19:54:43 +01:00
9d3c72acff
Add Vereinfacht app URL setting and contact view URL
...
- Setting attribute vereinfacht_app_url, migration, .env.example
- Config: vereinfacht_app_url() from env/setting or derived from API URL
- Contact view URL uses app URL with /en/admin/finances/contacts/{id}
- Global settings: App URL field, read-only when VEREINFACHT_APP_URL set
- Tests: update contact view URL expectations
2026-02-23 19:54:43 +01:00
7db609deec
Gettext: translate Vereinfacht API validation messages to German
2026-02-23 19:54:42 +01:00
02245e6684
Clear Vereinfacht ENV in test_helper so tests never hit real API
2026-02-23 19:54:42 +01:00
124857cc9c
Vereinfacht: update existing contact when found by email
...
Before saving contact_id to member, sync current data to the
existing contact so Vereinfacht stays up to date.
2026-02-23 19:54:42 +01:00
bc2d91f9e7
Vereinfacht client: find by email in response, no retries in test
...
API does not allow filter[email]; fetch list and match client-side.
Disable Req retries in test for fast failure and less log noise.
2026-02-23 19:54:42 +01:00
c33199465c
Gettext: new Vereinfacht UI strings and German translations
...
(set), Leave blank to keep current, env hint; DE msgstr added.
2026-02-23 19:54:42 +01:00
e1e0469e41
Global settings: API key redaction and per-field ENV
...
Never put API key in form/DOM; show (set) badge, drop blank on save.
Per-field disabled when ENV set; save button only when not all from ENV.
2026-02-23 19:54:41 +01:00
f2bcf68da2
Config: per-field Vereinfacht ENV helpers
...
vereinfacht_api_url_env_set?, vereinfacht_api_key_env_set?,
vereinfacht_club_id_env_set? for read-only Settings fields when set.
2026-02-23 19:54:41 +01:00
17488a6f42
Add Vereinfacht ENV vars to .env.example
...
VEREINFACHT_API_URL, VEREINFACHT_API_KEY, VEREINFACHT_CLUB_ID
with short comment that they override Settings when set.
2026-02-23 19:54:41 +01:00
a94c0c0b14
Vereinfacht: sync linked member only when email or member changed
...
Run SyncLinkedMemberAfterUserChange only when email or member
relationship changed to avoid unnecessary API calls.
2026-02-23 19:54:41 +01:00
a23f999eee
fix(a11y): WCAG 2 AA contrast and keyboard access
2026-02-23 19:54:36 +01:00
e4e6cfdd47
test(vereinfacht): add tests and scope README
...
- Config, Client, SyncContact, Vereinfacht module tests (no real API)
- vereinfacht_test_README: document test scope
2026-02-23 19:53:20 +01:00