feat: Add organization member support with memberType field

Implements support for both individual persons and organizations as members.

Changes:
- Added MemberType enum (INDIVIDUAL, ORGANIZATION) to distinguish member types
- Added member_type column to database (defaults to INDIVIDUAL for backward compatibility)
- Added company_name field for organizations
- Made first_name nullable (required for individuals, optional for organizations)
- Implemented conditional validation:
  - INDIVIDUAL members require first_name
  - ORGANIZATION members require company_name
- Updated GraphQL schema with new memberType and companyName fields
- Updated all resolvers to handle new fields and validation
- Added comprehensive unit tests for validation logic
- Updated existing tests to work with new fields
- All 53 tests passing

Technical notes:
- Using memberType instead of 'kind' to avoid GraphQL introspection conflicts
- Using native_enum=False for SQLite compatibility
- Using batch_alter_table for SQLite ALTER COLUMN compatibility
- Backward compatible: existing members automatically become INDIVIDUAL type

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-12-04 12:15:55 +01:00
co-authored by Claude
parent 630af11403
commit 5053b80998
12 changed files with 375 additions and 40 deletions
+2 -2
View File
@@ -80,5 +80,5 @@ class TestMemberModel:
repr_str = repr(member)
assert "Member" in repr_str
assert f"id={member.id}" in repr_str
assert "first_name='David'" in repr_str
assert "last_name='Smith'" in repr_str
assert "type=INDIVIDUAL" in repr_str
assert "name='David Smith'" in repr_str
+1 -1
View File
@@ -86,7 +86,7 @@ class TestCreateMemberMutation:
mutation = Mutation()
input_data = CreateMemberInput(first_name="")
with pytest.raises(ValidationError, match="firstName cannot be empty"):
with pytest.raises(ValidationError, match="firstName is required for individual members"):
await mutation.create_member(input=input_data)