refactor: remove obsolete member management API module
Some checks failed
Workflow / ʦ TypeScript (pull_request) Failing after 5m57s
Workflow / ⚫️ Test (pull_request) Has been skipped

This commit is contained in:
T. Zehetbauer
2026-04-03 14:08:31 +02:00
parent 124c6a632a
commit 5c5aaabae5
132 changed files with 10107 additions and 3442 deletions

View File

@@ -0,0 +1,109 @@
-- =====================================================
-- Atomic Course Enrollment
--
-- Problem: Enrolling a participant in a course requires
-- multiple queries (check capacity, count enrolled, insert).
-- Race conditions can over-enroll a course.
--
-- Fix: Single transactional PG function that locks the
-- course row, validates capacity, and inserts with the
-- correct status (enrolled vs waitlisted).
-- =====================================================
CREATE OR REPLACE FUNCTION public.enroll_course_participant(
p_course_id uuid,
p_member_id uuid DEFAULT NULL,
p_first_name text DEFAULT NULL,
p_last_name text DEFAULT NULL,
p_email text DEFAULT NULL,
p_phone text DEFAULT NULL
)
RETURNS jsonb
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = ''
AS $$
DECLARE
v_course record;
v_enrolled_count bigint;
v_status public.enrollment_status;
v_waitlist_position bigint;
v_participant_id uuid;
BEGIN
-- 1. Lock the course row to prevent concurrent enrollment races
SELECT * INTO v_course
FROM public.courses
WHERE id = p_course_id
FOR UPDATE;
IF v_course IS NULL THEN
RAISE EXCEPTION 'Course % not found', p_course_id
USING ERRCODE = 'P0002';
END IF;
-- 2. Validate course status is open for enrollment
IF v_course.status != 'open' THEN
RAISE EXCEPTION 'Course is not open for enrollment (current status: %)', v_course.status
USING ERRCODE = 'P0001';
END IF;
-- 3. Check registration deadline hasn't passed
IF v_course.registration_deadline IS NOT NULL AND v_course.registration_deadline < current_date THEN
RAISE EXCEPTION 'Registration deadline (%) has passed', v_course.registration_deadline
USING ERRCODE = 'P0001';
END IF;
-- 4. Count currently enrolled participants
SELECT count(*) INTO v_enrolled_count
FROM public.course_participants
WHERE course_id = p_course_id
AND status = 'enrolled';
-- 5. Determine status based on capacity
IF v_enrolled_count >= v_course.capacity THEN
v_status := 'waitlisted';
ELSE
v_status := 'enrolled';
END IF;
-- 6. Insert the participant
INSERT INTO public.course_participants (
course_id,
member_id,
first_name,
last_name,
email,
phone,
status,
enrolled_at
) VALUES (
p_course_id,
p_member_id,
p_first_name,
p_last_name,
p_email,
p_phone,
v_status,
now()
)
RETURNING id INTO v_participant_id;
-- 7. Calculate waitlist position if waitlisted
IF v_status = 'waitlisted' THEN
SELECT count(*) INTO v_waitlist_position
FROM public.course_participants
WHERE course_id = p_course_id
AND status = 'waitlisted';
END IF;
-- 8. Return result
RETURN jsonb_build_object(
'participant_id', v_participant_id,
'status', v_status::text,
'waitlist_position', CASE WHEN v_status = 'waitlisted' THEN v_waitlist_position ELSE NULL END
);
END;
$$;
GRANT EXECUTE ON FUNCTION public.enroll_course_participant(uuid, uuid, text, text, text, text) TO authenticated;
GRANT EXECUTE ON FUNCTION public.enroll_course_participant(uuid, uuid, text, text, text, text) TO service_role;