179 lines
3.9 KiB
Elixir
179 lines
3.9 KiB
Elixir
defmodule Mv.Membership.Member do
|
|
use Ash.Resource,
|
|
domain: Mv.Membership,
|
|
data_layer: AshPostgres.DataLayer
|
|
|
|
postgres do
|
|
table "members"
|
|
repo Mv.Repo
|
|
end
|
|
|
|
actions do
|
|
defaults [:read, :destroy]
|
|
|
|
create :create_member do
|
|
primary? true
|
|
argument :properties, {:array, :map}
|
|
|
|
accept [
|
|
:first_name,
|
|
:last_name,
|
|
:email,
|
|
:birth_date,
|
|
:paid,
|
|
:phone_number,
|
|
:join_date,
|
|
:exit_date,
|
|
:notes,
|
|
:city,
|
|
:street,
|
|
:house_number,
|
|
:postal_code
|
|
]
|
|
|
|
change manage_relationship(:properties, type: :create)
|
|
end
|
|
|
|
update :update_member do
|
|
primary? true
|
|
require_atomic? false
|
|
argument :properties, {:array, :map}
|
|
|
|
accept [
|
|
:first_name,
|
|
:last_name,
|
|
:email,
|
|
:birth_date,
|
|
:paid,
|
|
:phone_number,
|
|
:join_date,
|
|
:exit_date,
|
|
:notes,
|
|
:city,
|
|
:street,
|
|
:house_number,
|
|
:postal_code
|
|
]
|
|
|
|
change manage_relationship(:properties, on_match: :update, on_no_match: :create)
|
|
end
|
|
end
|
|
|
|
validations do
|
|
# Required fields are covered by allow_nil? false
|
|
|
|
# First name and last name must not be empty
|
|
validate present(:first_name)
|
|
validate present(:last_name)
|
|
validate present(:email)
|
|
|
|
# Birth date not in the future
|
|
validate compare(:birth_date, less_than_or_equal_to: &Date.utc_today/0),
|
|
where: [present(:birth_date)],
|
|
message: "cannot be in the future"
|
|
|
|
# Join date not in the future
|
|
validate compare(:join_date, less_than_or_equal_to: &Date.utc_today/0),
|
|
where: [present(:join_date)],
|
|
message: "cannot be in the future"
|
|
|
|
# Exit date not before join date
|
|
validate compare(:exit_date, greater_than: :join_date),
|
|
where: [present([:join_date, :exit_date])],
|
|
message: "cannot be before join date"
|
|
|
|
# Phone number format (only if set)
|
|
validate match(:phone_number, ~r/^\+?[0-9\- ]{6,20}$/),
|
|
where: [present(:phone_number)],
|
|
message: "is not a valid phone number"
|
|
|
|
# Postal code format (only if set)
|
|
validate match(:postal_code, ~r/^\d{5}$/),
|
|
where: [present(:postal_code)],
|
|
message: "must consist of 5 digits"
|
|
|
|
# Email validation with EctoCommons.EmailValidator
|
|
validate fn changeset, _ ->
|
|
email = Ash.Changeset.get_attribute(changeset, :email)
|
|
|
|
changeset2 =
|
|
{%{}, %{email: :string}}
|
|
|> Ecto.Changeset.cast(%{email: email}, [:email])
|
|
|> EctoCommons.EmailValidator.validate_email(:email, checks: [:html_input, :pow])
|
|
|
|
if changeset2.valid? do
|
|
:ok
|
|
else
|
|
{:error, field: :email, message: "is not a valid email"}
|
|
end
|
|
end
|
|
end
|
|
|
|
attributes do
|
|
uuid_v7_primary_key :id
|
|
|
|
attribute :first_name, :string do
|
|
allow_nil? false
|
|
constraints min_length: 1
|
|
end
|
|
|
|
attribute :last_name, :string do
|
|
allow_nil? false
|
|
constraints min_length: 1
|
|
end
|
|
|
|
attribute :email, :string do
|
|
allow_nil? false
|
|
constraints min_length: 5, max_length: 254
|
|
end
|
|
|
|
attribute :birth_date, :date do
|
|
allow_nil? true
|
|
end
|
|
|
|
attribute :paid, :boolean do
|
|
allow_nil? true
|
|
end
|
|
|
|
attribute :phone_number, :string do
|
|
allow_nil? true
|
|
end
|
|
|
|
attribute :join_date, :date do
|
|
allow_nil? true
|
|
end
|
|
|
|
attribute :exit_date, :date do
|
|
allow_nil? true
|
|
end
|
|
|
|
attribute :notes, :string do
|
|
allow_nil? true
|
|
end
|
|
|
|
attribute :city, :string do
|
|
allow_nil? true
|
|
end
|
|
|
|
attribute :street, :string do
|
|
allow_nil? true
|
|
end
|
|
|
|
attribute :house_number, :string do
|
|
allow_nil? true
|
|
end
|
|
|
|
attribute :postal_code, :string do
|
|
allow_nil? true
|
|
end
|
|
|
|
attribute :search_vector, AshPostgres.Tsvector,
|
|
writable?: false,
|
|
public?: false,
|
|
select_by_default?: false
|
|
end
|
|
|
|
relationships do
|
|
has_many :properties, Mv.Membership.Property
|
|
end
|
|
end
|