Migrations
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
-- Allow multiple check-in/out within a single duty schedule.
|
||||
-- Preserves first check-in time & arrival/late status on subsequent re-check-ins.
|
||||
|
||||
CREATE OR REPLACE FUNCTION public.attendance_check_in(
|
||||
p_duty_id uuid,
|
||||
p_lat double precision,
|
||||
p_lng double precision
|
||||
) RETURNS uuid
|
||||
LANGUAGE plpgsql SECURITY DEFINER
|
||||
AS $$
|
||||
DECLARE
|
||||
v_schedule duty_schedules%ROWTYPE;
|
||||
v_log_id uuid;
|
||||
v_now timestamptz := now();
|
||||
v_status text;
|
||||
BEGIN
|
||||
SELECT * INTO v_schedule FROM duty_schedules WHERE id = p_duty_id;
|
||||
IF NOT FOUND THEN
|
||||
RAISE EXCEPTION 'Duty schedule not found';
|
||||
END IF;
|
||||
IF v_schedule.user_id != auth.uid() THEN
|
||||
RAISE EXCEPTION 'Not your duty schedule';
|
||||
END IF;
|
||||
|
||||
IF v_now < (v_schedule.start_time - interval '2 hours') THEN
|
||||
RAISE EXCEPTION 'Too early to check in (2-hour window)';
|
||||
END IF;
|
||||
IF v_now > v_schedule.end_time THEN
|
||||
RAISE EXCEPTION 'Duty has already ended';
|
||||
END IF;
|
||||
|
||||
-- Determine status (used only when first check-in)
|
||||
IF v_now <= v_schedule.start_time THEN
|
||||
v_status := 'arrival';
|
||||
ELSE
|
||||
v_status := 'late';
|
||||
END IF;
|
||||
|
||||
-- Insert a new attendance log row for each check-in
|
||||
INSERT INTO attendance_logs (user_id, duty_schedule_id, check_in_at, check_in_lat, check_in_lng)
|
||||
VALUES (auth.uid(), p_duty_id, v_now, p_lat, p_lng)
|
||||
RETURNING id INTO v_log_id;
|
||||
|
||||
-- Only update duty schedule on first check-in (preserve original arrival status)
|
||||
UPDATE duty_schedules
|
||||
SET check_in_at = COALESCE(check_in_at, v_now),
|
||||
check_in_location = ST_SetSRID(ST_MakePoint(p_lng, p_lat), 4326)::geography,
|
||||
status = CASE
|
||||
WHEN check_in_at IS NULL THEN v_status::duty_status
|
||||
ELSE status
|
||||
END
|
||||
WHERE id = p_duty_id;
|
||||
|
||||
RETURN v_log_id;
|
||||
END;
|
||||
$$;
|
||||
|
||||
-- Also update duty_check_in for consistency
|
||||
CREATE OR REPLACE FUNCTION public.duty_check_in(
|
||||
p_duty_id uuid,
|
||||
p_lat double precision,
|
||||
p_lng double precision
|
||||
) RETURNS text
|
||||
LANGUAGE plpgsql SECURITY DEFINER
|
||||
AS $$
|
||||
DECLARE
|
||||
v_schedule duty_schedules%ROWTYPE;
|
||||
v_now timestamptz := now();
|
||||
v_status text;
|
||||
BEGIN
|
||||
SELECT * INTO v_schedule FROM duty_schedules WHERE id = p_duty_id;
|
||||
IF NOT FOUND THEN
|
||||
RAISE EXCEPTION 'Duty schedule not found';
|
||||
END IF;
|
||||
IF v_schedule.user_id != auth.uid() THEN
|
||||
RAISE EXCEPTION 'Not your duty schedule';
|
||||
END IF;
|
||||
|
||||
IF v_now <= v_schedule.start_time THEN
|
||||
v_status := 'arrival';
|
||||
ELSE
|
||||
v_status := 'late';
|
||||
END IF;
|
||||
|
||||
UPDATE duty_schedules
|
||||
SET check_in_at = COALESCE(check_in_at, v_now),
|
||||
check_in_location = ST_SetSRID(ST_MakePoint(p_lng, p_lat), 4326)::geography,
|
||||
status = CASE
|
||||
WHEN check_in_at IS NULL THEN v_status::duty_status
|
||||
ELSE status
|
||||
END
|
||||
WHERE id = p_duty_id;
|
||||
|
||||
-- Create attendance log entry
|
||||
INSERT INTO attendance_logs (user_id, duty_schedule_id, check_in_at, check_in_lat, check_in_lng)
|
||||
VALUES (auth.uid(), p_duty_id, v_now, p_lat, p_lng);
|
||||
|
||||
RETURN v_status;
|
||||
END;
|
||||
$$;
|
||||
Reference in New Issue
Block a user