refactor: remove obsolete member management API module
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
-- =====================================================
|
||||
-- Atomic Application Workflow
|
||||
-- Replaces multi-query approve/reject in api.ts with
|
||||
-- single transactional PG functions.
|
||||
-- =====================================================
|
||||
|
||||
-- approve_application: atomically creates a member from an application
|
||||
CREATE OR REPLACE FUNCTION public.approve_application(
|
||||
p_application_id uuid,
|
||||
p_user_id uuid
|
||||
)
|
||||
RETURNS uuid
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER
|
||||
SET search_path = ''
|
||||
AS $$
|
||||
DECLARE
|
||||
v_app record;
|
||||
v_member_id uuid;
|
||||
v_member_number text;
|
||||
BEGIN
|
||||
-- 1. Fetch and lock the application
|
||||
SELECT * INTO v_app
|
||||
FROM public.membership_applications
|
||||
WHERE id = p_application_id
|
||||
FOR UPDATE;
|
||||
|
||||
IF v_app IS NULL THEN
|
||||
RAISE EXCEPTION 'Application % not found', p_application_id
|
||||
USING ERRCODE = 'P0002';
|
||||
END IF;
|
||||
|
||||
-- Authorization: caller must have write permission on this account
|
||||
IF NOT public.has_permission(auth.uid(), v_app.account_id, 'members.write'::public.app_permissions) THEN
|
||||
RAISE EXCEPTION 'Access denied to account %', v_app.account_id
|
||||
USING ERRCODE = '42501';
|
||||
END IF;
|
||||
|
||||
IF v_app.status NOT IN ('submitted', 'review') THEN
|
||||
RAISE EXCEPTION 'Application is not in a reviewable state (current: %)', v_app.status
|
||||
USING ERRCODE = 'P0001';
|
||||
END IF;
|
||||
|
||||
-- 2. Generate next member number
|
||||
SELECT LPAD(
|
||||
(COALESCE(
|
||||
MAX(CASE WHEN member_number ~ '^\d+$' THEN member_number::integer ELSE 0 END),
|
||||
0
|
||||
) + 1)::text,
|
||||
4, '0'
|
||||
) INTO v_member_number
|
||||
FROM public.members
|
||||
WHERE account_id = v_app.account_id;
|
||||
|
||||
-- 3. Create the member
|
||||
INSERT INTO public.members (
|
||||
account_id,
|
||||
member_number,
|
||||
first_name,
|
||||
last_name,
|
||||
email,
|
||||
phone,
|
||||
street,
|
||||
postal_code,
|
||||
city,
|
||||
date_of_birth,
|
||||
status,
|
||||
entry_date,
|
||||
created_by,
|
||||
updated_by
|
||||
) VALUES (
|
||||
v_app.account_id,
|
||||
v_member_number,
|
||||
v_app.first_name,
|
||||
v_app.last_name,
|
||||
v_app.email,
|
||||
v_app.phone,
|
||||
v_app.street,
|
||||
v_app.postal_code,
|
||||
v_app.city,
|
||||
v_app.date_of_birth,
|
||||
'active'::public.membership_status,
|
||||
current_date,
|
||||
auth.uid(),
|
||||
auth.uid()
|
||||
)
|
||||
RETURNING id INTO v_member_id;
|
||||
|
||||
-- 4. Mark application as approved
|
||||
UPDATE public.membership_applications
|
||||
SET
|
||||
status = 'approved'::public.application_status,
|
||||
reviewed_by = auth.uid(),
|
||||
reviewed_at = now(),
|
||||
member_id = v_member_id,
|
||||
updated_at = now()
|
||||
WHERE id = p_application_id;
|
||||
|
||||
RETURN v_member_id;
|
||||
END;
|
||||
$$;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION public.approve_application(uuid, uuid) TO authenticated;
|
||||
GRANT EXECUTE ON FUNCTION public.approve_application(uuid, uuid) TO service_role;
|
||||
|
||||
-- reject_application: atomically rejects an application with notes
|
||||
CREATE OR REPLACE FUNCTION public.reject_application(
|
||||
p_application_id uuid,
|
||||
p_user_id uuid,
|
||||
p_review_notes text DEFAULT NULL
|
||||
)
|
||||
RETURNS void
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER
|
||||
SET search_path = ''
|
||||
AS $$
|
||||
DECLARE
|
||||
v_app record;
|
||||
BEGIN
|
||||
-- Fetch and lock the application
|
||||
SELECT * INTO v_app
|
||||
FROM public.membership_applications
|
||||
WHERE id = p_application_id
|
||||
FOR UPDATE;
|
||||
|
||||
IF v_app IS NULL THEN
|
||||
RAISE EXCEPTION 'Application % not found', p_application_id
|
||||
USING ERRCODE = 'P0002';
|
||||
END IF;
|
||||
|
||||
-- Authorization: caller must have write permission on this account
|
||||
IF NOT public.has_permission(auth.uid(), v_app.account_id, 'members.write'::public.app_permissions) THEN
|
||||
RAISE EXCEPTION 'Access denied to account %', v_app.account_id
|
||||
USING ERRCODE = '42501';
|
||||
END IF;
|
||||
|
||||
IF v_app.status NOT IN ('submitted', 'review') THEN
|
||||
RAISE EXCEPTION 'Application is not in a reviewable state (current: %)', v_app.status
|
||||
USING ERRCODE = 'P0001';
|
||||
END IF;
|
||||
|
||||
UPDATE public.membership_applications
|
||||
SET
|
||||
status = 'rejected'::public.application_status,
|
||||
reviewed_by = auth.uid(),
|
||||
reviewed_at = now(),
|
||||
review_notes = p_review_notes,
|
||||
updated_at = now()
|
||||
WHERE id = p_application_id;
|
||||
END;
|
||||
$$;
|
||||
|
||||
GRANT EXECUTE ON FUNCTION public.reject_application(uuid, uuid, text) TO authenticated;
|
||||
GRANT EXECUTE ON FUNCTION public.reject_application(uuid, uuid, text) TO service_role;
|
||||
Reference in New Issue
Block a user