docs: add @moduledoc to core membership resources

Add comprehensive module documentation to Member, Property, PropertyType, and Email.
Improves code discoverability and enables ExDoc generation.
This commit is contained in:
Moritz 2025-11-10 16:22:43 +01:00
parent 20af015da6
commit 409bc7bf2f
Signed by: moritz
GPG key ID: 1020A035E5DD0824
4 changed files with 141 additions and 0 deletions

View file

@ -1,4 +1,37 @@
defmodule Mv.Membership.Email do
@moduledoc """
Custom Ash type for validated email addresses.
## Overview
This type extends `:string` with email-specific validation constraints.
It ensures that email values stored in Property resources are valid email
addresses according to a standard regex pattern.
## Validation Rules
- Minimum length: 5 characters
- Maximum length: 254 characters (RFC 5321 maximum)
- Pattern: Standard email format (username@domain.tld)
- Automatic trimming of leading/trailing whitespace
## Usage
This type is used in the Property union type for properties with
`value_type: :email` in PropertyType definitions.
## Example
# In a property type definition
PropertyType.create!(%{
name: "work_email",
value_type: :email
})
# Valid values
"user@example.com"
"first.last@company.co.uk"
# Invalid values
"not-an-email" # Missing @ and domain
"a@b" # Too short
"""
@match_pattern ~S/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$/
@match_regex Regex.compile!(@match_pattern)
@min_length 5

View file

@ -1,4 +1,36 @@
defmodule Mv.Membership.Member do
@moduledoc """
Ash resource representing a club member.
## Overview
Members are the core entity in the membership management system. Each member
can have:
- Personal information (name, email, phone, address)
- Optional link to a User account (1:1 relationship)
- Dynamic custom properties via PropertyType system
- Full-text searchable profile
## Email Synchronization
When a member is linked to a user account, emails are automatically synchronized
bidirectionally. User.email is the source of truth on initial link.
See `Mv.EmailSync` for details.
## Relationships
- `has_many :properties` - Dynamic custom fields
- `has_one :user` - Optional authentication account link
## Validations
- Required: first_name, last_name, email
- Email format validation (using EctoCommons.EmailValidator)
- Phone number format: international format with 6-20 digits
- Postal code format: exactly 5 digits (German format)
- Date validations: birth_date and join_date not in future, exit_date after join_date
- Email uniqueness: prevents conflicts with unlinked users
## Full-Text Search
Members have a `search_vector` attribute (tsvector) that is automatically
updated via database trigger. Search includes name, email, notes, and contact fields.
"""
use Ash.Resource,
domain: Mv.Membership,
data_layer: AshPostgres.DataLayer

View file

@ -1,4 +1,36 @@
defmodule Mv.Membership.Property do
@moduledoc """
Ash resource representing a custom property value for a member.
## Overview
Properties implement the Entity-Attribute-Value (EAV) pattern, allowing
dynamic custom fields to be attached to members. Each property links a
member to a property type and stores the actual value.
## Value Storage
Values are stored using Ash's union type with JSONB storage format:
```json
{
"type": "string",
"value": "example"
}
```
## Supported Types
- `:string` - Text data
- `:integer` - Numeric data
- `:boolean` - True/false flags
- `:date` - Date values
- `:email` - Validated email addresses (custom type)
## Relationships
- `belongs_to :member` - The member this property belongs to (CASCADE delete)
- `belongs_to :property_type` - The property type definition
## Constraints
- Each member can have only one property per property type (unique composite index)
- Properties are deleted when the associated member is deleted (CASCADE)
"""
use Ash.Resource,
domain: Mv.Membership,
data_layer: AshPostgres.DataLayer

View file

@ -1,4 +1,48 @@
defmodule Mv.Membership.PropertyType do
@moduledoc """
Ash resource defining the schema for custom member properties.
## Overview
PropertyTypes define the "schema" for custom fields in the membership system.
Each PropertyType specifies the name, data type, and behavior of a custom field
that can be attached to members via Property resources.
## Attributes
- `name` - Unique identifier for the property (e.g., "phone_mobile", "birthday")
- `value_type` - Data type constraint (`:string`, `:integer`, `:boolean`, `:date`, `:email`)
- `description` - Optional human-readable description
- `immutable` - If true, property values cannot be changed after creation
- `required` - If true, all members must have this property (future feature)
## Supported Value Types
- `:string` - Text data (unlimited length)
- `:integer` - Numeric data (64-bit integers)
- `:boolean` - True/false flags
- `:date` - Date values (no time component)
- `:email` - Validated email addresses
## Relationships
- `has_many :properties` - All property values of this type
## Constraints
- Name must be unique across all property types
- Cannot delete a property type that has existing property values (RESTRICT)
## Examples
# Create a new property type
PropertyType.create!(%{
name: "phone_mobile",
value_type: :string,
description: "Mobile phone number"
})
# Create a required property type
PropertyType.create!(%{
name: "emergency_contact",
value_type: :string,
required: true
})
"""
use Ash.Resource,
domain: Mv.Membership,
data_layer: AshPostgres.DataLayer