feat(membership-fees): add database schema and Ash domain structure
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
3710d70024
commit
b37c312b15
14 changed files with 1405 additions and 7 deletions
99
lib/membership_fees/membership_fee_cycle.ex
Normal file
99
lib/membership_fees/membership_fee_cycle.ex
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
defmodule Mv.MembershipFees.MembershipFeeCycle do
|
||||
@moduledoc """
|
||||
Ash resource representing an individual membership fee cycle for a member.
|
||||
|
||||
## Overview
|
||||
MembershipFeeCycle represents a single billing cycle for a member. Each cycle
|
||||
tracks the payment status and amount for a specific time period.
|
||||
|
||||
## Attributes
|
||||
- `cycle_start` - Start date of the billing cycle (aligned to calendar boundaries)
|
||||
- `amount` - The fee amount for this cycle (stored for audit trail)
|
||||
- `status` - Payment status: unpaid, paid, or suspended
|
||||
- `notes` - Optional notes for this cycle
|
||||
|
||||
## Design Decisions
|
||||
- **No cycle_end field**: Calculated from cycle_start + interval (from fee type)
|
||||
- **Amount stored per cycle**: Preserves historical amounts when fee type changes
|
||||
- **Calendar-aligned cycles**: All cycles start on calendar boundaries
|
||||
|
||||
## Relationships
|
||||
- `belongs_to :member` - The member this cycle belongs to
|
||||
- `belongs_to :membership_fee_type` - The fee type for this cycle
|
||||
|
||||
## Constraints
|
||||
- Unique constraint on (member_id, cycle_start) - one cycle per period per member
|
||||
- CASCADE delete when member is deleted
|
||||
- RESTRICT delete on membership_fee_type if cycles exist
|
||||
"""
|
||||
use Ash.Resource,
|
||||
domain: Mv.MembershipFees,
|
||||
data_layer: AshPostgres.DataLayer
|
||||
|
||||
postgres do
|
||||
table "membership_fee_cycles"
|
||||
repo Mv.Repo
|
||||
end
|
||||
|
||||
resource do
|
||||
description "Individual membership fee cycle for a member"
|
||||
end
|
||||
|
||||
actions do
|
||||
defaults [:read, :destroy]
|
||||
|
||||
create :create do
|
||||
primary? true
|
||||
accept [:cycle_start, :amount, :status, :notes, :member_id, :membership_fee_type_id]
|
||||
end
|
||||
|
||||
update :update do
|
||||
primary? true
|
||||
accept [:status, :notes]
|
||||
end
|
||||
end
|
||||
|
||||
attributes do
|
||||
uuid_v7_primary_key :id
|
||||
|
||||
attribute :cycle_start, :date do
|
||||
allow_nil? false
|
||||
public? true
|
||||
description "Start date of the billing cycle"
|
||||
end
|
||||
|
||||
attribute :amount, :decimal do
|
||||
allow_nil? false
|
||||
public? true
|
||||
description "Fee amount for this cycle (stored for audit trail)"
|
||||
end
|
||||
|
||||
attribute :status, :atom do
|
||||
allow_nil? false
|
||||
public? true
|
||||
default :unpaid
|
||||
description "Payment status of this cycle"
|
||||
constraints one_of: [:unpaid, :paid, :suspended]
|
||||
end
|
||||
|
||||
attribute :notes, :string do
|
||||
allow_nil? true
|
||||
public? true
|
||||
description "Optional notes for this cycle"
|
||||
end
|
||||
end
|
||||
|
||||
relationships do
|
||||
belongs_to :member, Mv.Membership.Member do
|
||||
allow_nil? false
|
||||
end
|
||||
|
||||
belongs_to :membership_fee_type, Mv.MembershipFees.MembershipFeeType do
|
||||
allow_nil? false
|
||||
end
|
||||
end
|
||||
|
||||
identities do
|
||||
identity :unique_cycle_per_member, [:member_id, :cycle_start]
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue