mitgliederverwaltung/lib/membership/custom_field.ex

118 lines
3.3 KiB
Elixir

defmodule Mv.Membership.CustomField do
@moduledoc """
Ash resource defining the schema for custom member fields.
## Overview
CustomFields define the "schema" for custom fields in the membership system.
Each CustomField specifies the name, data type, and behavior of a custom field
that can be attached to members via CustomFieldValue resources.
## Attributes
- `name` - Unique identifier for the custom field (e.g., "phone_mobile", "birthday")
- `slug` - URL-friendly, immutable identifier automatically generated from name (e.g., "phone-mobile")
- `value_type` - Data type constraint (`:string`, `:integer`, `:boolean`, `:date`, `:email`)
- `description` - Optional human-readable description
- `immutable` - If true, custom field values cannot be changed after creation
- `required` - If true, all members must have this custom field (future feature)
## Supported Value Types
- `:string` - Text data (max 10,000 characters)
- `:integer` - Numeric data (64-bit integers)
- `:boolean` - True/false flags
- `:date` - Date values (no time component)
- `:email` - Validated email addresses (max 254 characters)
## Relationships
- `has_many :custom_field_values` - All custom field values of this type
## Constraints
- Name must be unique across all custom fields
- Name maximum length: 100 characters
- Cannot delete a custom field that has existing custom field values (RESTRICT)
## Examples
# Create a new custom field
CustomField.create!(%{
name: "phone_mobile",
value_type: :string,
description: "Mobile phone number"
})
# Create a required custom field
CustomField.create!(%{
name: "emergency_contact",
value_type: :string,
required: true
})
"""
use Ash.Resource,
domain: Mv.Membership,
data_layer: AshPostgres.DataLayer
postgres do
table "custom_fields"
repo Mv.Repo
end
actions do
defaults [:read, :update, :destroy]
default_accept [:name, :value_type, :description, :immutable, :required]
create :create do
accept [:name, :value_type, :description, :immutable, :required]
change Mv.Membership.CustomField.Changes.GenerateSlug
validate string_length(:slug, min: 1)
end
end
attributes do
uuid_primary_key :id
attribute :name, :string,
allow_nil?: false,
public?: true,
constraints: [
max_length: 100,
trim?: true
]
attribute :slug, :string,
allow_nil?: false,
public?: true,
writable?: false,
constraints: [
max_length: 100,
trim?: true
]
attribute :value_type, :atom,
constraints: [one_of: [:string, :integer, :boolean, :date, :email]],
allow_nil?: false,
description: "Defines the datatype `CustomFieldValue.value` is interpreted as"
attribute :description, :string,
allow_nil?: true,
public?: true,
constraints: [
max_length: 500,
trim?: true
]
attribute :immutable, :boolean,
default: false,
allow_nil?: false
attribute :required, :boolean,
default: false,
allow_nil?: false
end
relationships do
has_many :custom_field_values, Mv.Membership.CustomFieldValue
end
identities do
identity :unique_name, [:name]
identity :unique_slug, [:slug]
end
end