Initial state for GitNexus analysis
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* -------------------------------------------------------
|
||||
* Member Management Schema
|
||||
* Phase 4: members, membership_applications, dues_categories, member_cards
|
||||
* -------------------------------------------------------
|
||||
*/
|
||||
|
||||
-- =====================================================
|
||||
-- 1. Enums
|
||||
-- =====================================================
|
||||
create type public.membership_status as enum(
|
||||
'active', 'inactive', 'pending', 'resigned', 'excluded', 'deceased'
|
||||
);
|
||||
|
||||
create type public.sepa_mandate_status as enum(
|
||||
'active', 'pending', 'revoked', 'expired'
|
||||
);
|
||||
|
||||
create type public.application_status as enum(
|
||||
'submitted', 'review', 'approved', 'rejected'
|
||||
);
|
||||
|
||||
-- =====================================================
|
||||
-- 2. members
|
||||
-- =====================================================
|
||||
create table if not exists public.members (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
account_id uuid not null references public.accounts(id) on delete cascade,
|
||||
member_number text,
|
||||
|
||||
-- Personal
|
||||
first_name text not null,
|
||||
last_name text not null,
|
||||
date_of_birth date,
|
||||
gender text check (gender in ('male', 'female', 'diverse', null)),
|
||||
title text, -- Dr., Prof., etc.
|
||||
|
||||
-- Contact
|
||||
email text,
|
||||
phone text,
|
||||
mobile text,
|
||||
|
||||
-- Address
|
||||
street text,
|
||||
house_number text,
|
||||
postal_code text,
|
||||
city text,
|
||||
country text default 'DE',
|
||||
|
||||
-- Membership
|
||||
status public.membership_status not null default 'active',
|
||||
entry_date date not null default current_date,
|
||||
exit_date date,
|
||||
exit_reason text,
|
||||
dues_category_id uuid,
|
||||
|
||||
-- SEPA
|
||||
sepa_mandate_id text,
|
||||
sepa_mandate_date date,
|
||||
sepa_mandate_status public.sepa_mandate_status default 'pending',
|
||||
iban text,
|
||||
bic text,
|
||||
account_holder text,
|
||||
|
||||
-- GDPR
|
||||
gdpr_consent boolean not null default false,
|
||||
gdpr_consent_date timestamptz,
|
||||
gdpr_data_source text,
|
||||
|
||||
-- Meta
|
||||
notes text,
|
||||
custom_data jsonb not null default '{}'::jsonb,
|
||||
created_by uuid references auth.users(id) on delete set null,
|
||||
updated_by uuid references auth.users(id) on delete set null,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now(),
|
||||
|
||||
unique(account_id, member_number)
|
||||
);
|
||||
|
||||
comment on table public.members is 'Club/association members — replaces legacy ve_mitglieder';
|
||||
|
||||
create index ix_members_account on public.members(account_id);
|
||||
create index ix_members_status on public.members(account_id, status);
|
||||
create index ix_members_name on public.members(account_id, last_name, first_name);
|
||||
create index ix_members_email on public.members(account_id, email);
|
||||
|
||||
alter table public.members enable row level security;
|
||||
revoke all on public.members from authenticated, service_role;
|
||||
grant select, insert, update, delete on public.members to authenticated;
|
||||
grant all on public.members to service_role;
|
||||
|
||||
create policy members_select on public.members for select to authenticated
|
||||
using (public.has_role_on_account(account_id));
|
||||
|
||||
create policy members_insert on public.members for insert to authenticated
|
||||
with check (public.has_permission(auth.uid(), account_id, 'members.write'::public.app_permissions));
|
||||
|
||||
create policy members_update on public.members for update to authenticated
|
||||
using (public.has_permission(auth.uid(), account_id, 'members.write'::public.app_permissions));
|
||||
|
||||
create policy members_delete on public.members for delete to authenticated
|
||||
using (public.has_permission(auth.uid(), account_id, 'members.write'::public.app_permissions));
|
||||
|
||||
create trigger trg_members_updated_at
|
||||
before update on public.members
|
||||
for each row execute function public.update_account_settings_timestamp();
|
||||
|
||||
-- =====================================================
|
||||
-- 3. dues_categories — tiered pricing
|
||||
-- =====================================================
|
||||
create table if not exists public.dues_categories (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
account_id uuid not null references public.accounts(id) on delete cascade,
|
||||
name text not null,
|
||||
description text,
|
||||
amount numeric(10,2) not null default 0,
|
||||
interval text not null default 'yearly' check (interval in ('monthly', 'quarterly', 'half_yearly', 'yearly')),
|
||||
is_default boolean not null default false,
|
||||
sort_order integer not null default 0,
|
||||
created_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
comment on table public.dues_categories is 'Membership dues/fee categories';
|
||||
|
||||
create index ix_dues_categories_account on public.dues_categories(account_id);
|
||||
|
||||
alter table public.dues_categories enable row level security;
|
||||
revoke all on public.dues_categories from authenticated, service_role;
|
||||
grant select, insert, update, delete on public.dues_categories to authenticated;
|
||||
grant all on public.dues_categories to service_role;
|
||||
|
||||
create policy dues_categories_select on public.dues_categories for select to authenticated
|
||||
using (public.has_role_on_account(account_id));
|
||||
|
||||
create policy dues_categories_mutate on public.dues_categories for all to authenticated
|
||||
using (public.has_permission(auth.uid(), account_id, 'members.write'::public.app_permissions));
|
||||
|
||||
-- Add FK from members to dues_categories
|
||||
alter table public.members
|
||||
add constraint fk_members_dues_category
|
||||
foreign key (dues_category_id) references public.dues_categories(id) on delete set null;
|
||||
|
||||
-- =====================================================
|
||||
-- 4. membership_applications — workflow
|
||||
-- =====================================================
|
||||
create table if not exists public.membership_applications (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
account_id uuid not null references public.accounts(id) on delete cascade,
|
||||
first_name text not null,
|
||||
last_name text not null,
|
||||
email text,
|
||||
phone text,
|
||||
street text,
|
||||
postal_code text,
|
||||
city text,
|
||||
date_of_birth date,
|
||||
message text,
|
||||
status public.application_status not null default 'submitted',
|
||||
reviewed_by uuid references auth.users(id) on delete set null,
|
||||
reviewed_at timestamptz,
|
||||
review_notes text,
|
||||
member_id uuid references public.members(id) on delete set null,
|
||||
created_at timestamptz not null default now(),
|
||||
updated_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
comment on table public.membership_applications is 'Online membership applications with approval workflow';
|
||||
|
||||
create index ix_applications_account on public.membership_applications(account_id);
|
||||
create index ix_applications_status on public.membership_applications(account_id, status);
|
||||
|
||||
alter table public.membership_applications enable row level security;
|
||||
revoke all on public.membership_applications from authenticated, service_role;
|
||||
grant select, insert, update, delete on public.membership_applications to authenticated;
|
||||
grant all on public.membership_applications to service_role;
|
||||
|
||||
create policy applications_select on public.membership_applications for select to authenticated
|
||||
using (public.has_role_on_account(account_id));
|
||||
|
||||
create policy applications_mutate on public.membership_applications for all to authenticated
|
||||
using (public.has_permission(auth.uid(), account_id, 'members.write'::public.app_permissions));
|
||||
|
||||
-- =====================================================
|
||||
-- 5. member_cards — ID cards
|
||||
-- =====================================================
|
||||
create table if not exists public.member_cards (
|
||||
id uuid primary key default gen_random_uuid(),
|
||||
member_id uuid not null references public.members(id) on delete cascade,
|
||||
account_id uuid not null references public.accounts(id) on delete cascade,
|
||||
card_number text,
|
||||
valid_from date not null default current_date,
|
||||
valid_until date,
|
||||
pdf_storage_path text,
|
||||
created_at timestamptz not null default now()
|
||||
);
|
||||
|
||||
comment on table public.member_cards is 'Member ID cards with generated PDFs';
|
||||
|
||||
create index ix_member_cards_member on public.member_cards(member_id);
|
||||
|
||||
alter table public.member_cards enable row level security;
|
||||
revoke all on public.member_cards from authenticated, service_role;
|
||||
grant select, insert, update, delete on public.member_cards to authenticated;
|
||||
grant all on public.member_cards to service_role;
|
||||
|
||||
create policy member_cards_select on public.member_cards for select to authenticated
|
||||
using (public.has_role_on_account(account_id));
|
||||
|
||||
create policy member_cards_mutate on public.member_cards for all to authenticated
|
||||
using (public.has_permission(auth.uid(), account_id, 'members.write'::public.app_permissions));
|
||||
Reference in New Issue
Block a user