Migrations
This commit is contained in:
@@ -0,0 +1,260 @@
|
||||
-- =============================================================================
|
||||
-- IT Service Request Module
|
||||
-- =============================================================================
|
||||
|
||||
-- 1. Main table
|
||||
CREATE TABLE IF NOT EXISTS it_service_requests (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
request_number text UNIQUE,
|
||||
|
||||
-- Services (checkboxes from the form)
|
||||
services text[] NOT NULL DEFAULT '{}',
|
||||
services_other text,
|
||||
|
||||
-- Event/Activity Details (Quill Delta JSON)
|
||||
event_name text NOT NULL,
|
||||
event_details text, -- Quill delta JSON
|
||||
|
||||
-- Scheduling
|
||||
event_date timestamptz,
|
||||
event_end_date timestamptz,
|
||||
dry_run_date timestamptz,
|
||||
dry_run_end_date timestamptz,
|
||||
|
||||
-- Contact
|
||||
contact_person text,
|
||||
contact_number text,
|
||||
|
||||
-- Remarks (Quill Delta JSON)
|
||||
remarks text,
|
||||
|
||||
-- Office (Department in the form)
|
||||
office_id uuid REFERENCES offices(id) ON DELETE SET NULL,
|
||||
|
||||
-- Signatories
|
||||
requested_by text, -- Name of requester (default: standard user who created)
|
||||
requested_by_user_id uuid REFERENCES auth.users(id) ON DELETE SET NULL,
|
||||
approved_by text, -- Name of approver (admin only)
|
||||
approved_by_user_id uuid REFERENCES auth.users(id) ON DELETE SET NULL,
|
||||
approved_at timestamptz,
|
||||
|
||||
-- Status lifecycle: draft → pending_approval → scheduled → in_progress_dry_run → in_progress → completed → cancelled
|
||||
status text NOT NULL DEFAULT 'draft' CHECK (
|
||||
status IN ('draft', 'pending_approval', 'scheduled', 'in_progress_dry_run', 'in_progress', 'completed', 'cancelled')
|
||||
),
|
||||
|
||||
-- Geofence override: allow IT staff to check in/out outside CRMC premise
|
||||
outside_premise_allowed boolean NOT NULL DEFAULT false,
|
||||
|
||||
-- Cancellation
|
||||
cancellation_reason text,
|
||||
cancelled_at timestamptz,
|
||||
|
||||
-- Metadata
|
||||
creator_id uuid REFERENCES auth.users(id) ON DELETE SET NULL,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now(),
|
||||
completed_at timestamptz,
|
||||
|
||||
-- Date/Time Received/Checked from the form
|
||||
date_time_received timestamptz,
|
||||
date_time_checked timestamptz
|
||||
);
|
||||
|
||||
-- Auto-update updated_at
|
||||
CREATE OR REPLACE FUNCTION update_it_service_requests_updated_at()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = now();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER it_service_requests_updated_at_trigger
|
||||
BEFORE UPDATE ON it_service_requests
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_it_service_requests_updated_at();
|
||||
|
||||
-- 2. IT Service Request Assignments (IT Staff assigned to the request)
|
||||
CREATE TABLE IF NOT EXISTS it_service_request_assignments (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
request_id uuid NOT NULL REFERENCES it_service_requests(id) ON DELETE CASCADE,
|
||||
user_id uuid NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
UNIQUE(request_id, user_id)
|
||||
);
|
||||
|
||||
-- 3. Activity Logs for audit trail
|
||||
CREATE TABLE IF NOT EXISTS it_service_request_activity_logs (
|
||||
id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
||||
request_id uuid NOT NULL REFERENCES it_service_requests(id) ON DELETE CASCADE,
|
||||
actor_id uuid REFERENCES auth.users(id) ON DELETE SET NULL,
|
||||
action_type text NOT NULL,
|
||||
meta jsonb,
|
||||
created_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- 4. Action Taken (separate table with evidence attachments)
|
||||
CREATE TABLE IF NOT EXISTS it_service_request_actions (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
request_id uuid NOT NULL REFERENCES it_service_requests(id) ON DELETE CASCADE,
|
||||
user_id uuid NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
||||
action_taken text, -- Quill Delta JSON
|
||||
created_at timestamptz NOT NULL DEFAULT now(),
|
||||
updated_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- Auto-update updated_at for actions
|
||||
CREATE TRIGGER it_service_request_actions_updated_at_trigger
|
||||
BEFORE UPDATE ON it_service_request_actions
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION update_it_service_requests_updated_at();
|
||||
|
||||
-- 5. Evidence Attachments (images only, for action taken)
|
||||
CREATE TABLE IF NOT EXISTS it_service_request_evidence (
|
||||
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
request_id uuid NOT NULL REFERENCES it_service_requests(id) ON DELETE CASCADE,
|
||||
action_id uuid REFERENCES it_service_request_actions(id) ON DELETE CASCADE,
|
||||
user_id uuid NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
||||
file_path text NOT NULL,
|
||||
file_name text NOT NULL,
|
||||
taken_at timestamptz, -- Extracted from image EXIF metadata
|
||||
created_at timestamptz NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- 6. Request Number Generation RPC
|
||||
CREATE OR REPLACE FUNCTION insert_it_service_request_with_number(
|
||||
p_event_name text,
|
||||
p_services text[],
|
||||
p_creator_id uuid,
|
||||
p_office_id uuid DEFAULT NULL,
|
||||
p_requested_by text DEFAULT NULL,
|
||||
p_requested_by_user_id uuid DEFAULT NULL,
|
||||
p_status text DEFAULT 'draft'
|
||||
)
|
||||
RETURNS TABLE(id uuid, request_number text) AS $$
|
||||
DECLARE
|
||||
v_seq int;
|
||||
v_id uuid;
|
||||
v_number text;
|
||||
BEGIN
|
||||
-- Get next sequence number for the current year
|
||||
SELECT COALESCE(MAX(
|
||||
CAST(NULLIF(regexp_replace(r.request_number, '^ISR-\d{4}-', ''), '') AS int)
|
||||
), 0) + 1
|
||||
INTO v_seq
|
||||
FROM it_service_requests r
|
||||
WHERE r.request_number LIKE 'ISR-' || EXTRACT(YEAR FROM now())::text || '-%';
|
||||
|
||||
v_number := 'ISR-' || EXTRACT(YEAR FROM now())::text || '-' || LPAD(v_seq::text, 4, '0');
|
||||
v_id := gen_random_uuid();
|
||||
|
||||
INSERT INTO it_service_requests (id, request_number, event_name, services, creator_id, office_id, requested_by, requested_by_user_id, status)
|
||||
VALUES (v_id, v_number, p_event_name, p_services, p_creator_id, p_office_id, p_requested_by, p_requested_by_user_id, p_status);
|
||||
|
||||
RETURN QUERY SELECT v_id, v_number;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- 7. Indexes
|
||||
CREATE INDEX idx_it_service_requests_status ON it_service_requests(status);
|
||||
CREATE INDEX idx_it_service_requests_office_id ON it_service_requests(office_id);
|
||||
CREATE INDEX idx_it_service_requests_creator_id ON it_service_requests(creator_id);
|
||||
CREATE INDEX idx_it_service_requests_event_date ON it_service_requests(event_date);
|
||||
CREATE INDEX idx_it_service_request_assignments_request_id ON it_service_request_assignments(request_id);
|
||||
CREATE INDEX idx_it_service_request_assignments_user_id ON it_service_request_assignments(user_id);
|
||||
CREATE INDEX idx_it_service_request_activity_logs_request_id ON it_service_request_activity_logs(request_id);
|
||||
CREATE INDEX idx_it_service_request_actions_request_id ON it_service_request_actions(request_id);
|
||||
CREATE INDEX idx_it_service_request_evidence_request_id ON it_service_request_evidence(request_id);
|
||||
|
||||
-- 8. Enable RLS
|
||||
ALTER TABLE it_service_requests ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE it_service_request_assignments ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE it_service_request_activity_logs ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE it_service_request_actions ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE it_service_request_evidence ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- 9. RLS Policies
|
||||
|
||||
-- IT Service Requests: authenticated can read all, insert own, update depending on role
|
||||
CREATE POLICY "Authenticated users can read it_service_requests"
|
||||
ON it_service_requests FOR SELECT TO authenticated USING (true);
|
||||
|
||||
CREATE POLICY "Authenticated users can insert it_service_requests"
|
||||
ON it_service_requests FOR INSERT TO authenticated
|
||||
WITH CHECK (auth.uid() = creator_id);
|
||||
|
||||
CREATE POLICY "Authenticated users can update it_service_requests"
|
||||
ON it_service_requests FOR UPDATE TO authenticated
|
||||
USING (true);
|
||||
|
||||
-- Assignments
|
||||
CREATE POLICY "Authenticated users can read it_service_request_assignments"
|
||||
ON it_service_request_assignments FOR SELECT TO authenticated USING (true);
|
||||
|
||||
CREATE POLICY "Authenticated users can insert it_service_request_assignments"
|
||||
ON it_service_request_assignments FOR INSERT TO authenticated
|
||||
WITH CHECK (true);
|
||||
|
||||
CREATE POLICY "Authenticated users can delete it_service_request_assignments"
|
||||
ON it_service_request_assignments FOR DELETE TO authenticated
|
||||
USING (true);
|
||||
|
||||
-- Activity Logs
|
||||
CREATE POLICY "Authenticated users can read it_service_request_activity_logs"
|
||||
ON it_service_request_activity_logs FOR SELECT TO authenticated USING (true);
|
||||
|
||||
CREATE POLICY "Authenticated users can insert it_service_request_activity_logs"
|
||||
ON it_service_request_activity_logs FOR INSERT TO authenticated
|
||||
WITH CHECK (true);
|
||||
|
||||
-- Actions
|
||||
CREATE POLICY "Authenticated users can read it_service_request_actions"
|
||||
ON it_service_request_actions FOR SELECT TO authenticated USING (true);
|
||||
|
||||
CREATE POLICY "Authenticated users can insert it_service_request_actions"
|
||||
ON it_service_request_actions FOR INSERT TO authenticated
|
||||
WITH CHECK (auth.uid() = user_id);
|
||||
|
||||
CREATE POLICY "Authenticated users can update it_service_request_actions"
|
||||
ON it_service_request_actions FOR UPDATE TO authenticated
|
||||
USING (auth.uid() = user_id);
|
||||
|
||||
-- Evidence
|
||||
CREATE POLICY "Authenticated users can read it_service_request_evidence"
|
||||
ON it_service_request_evidence FOR SELECT TO authenticated USING (true);
|
||||
|
||||
CREATE POLICY "Authenticated users can insert it_service_request_evidence"
|
||||
ON it_service_request_evidence FOR INSERT TO authenticated
|
||||
WITH CHECK (auth.uid() = user_id);
|
||||
|
||||
CREATE POLICY "Authenticated users can delete it_service_request_evidence"
|
||||
ON it_service_request_evidence FOR DELETE TO authenticated
|
||||
USING (auth.uid() = user_id);
|
||||
|
||||
-- 10. Add it_service_request_id to notifications table
|
||||
ALTER TABLE notifications ADD COLUMN IF NOT EXISTS it_service_request_id uuid REFERENCES it_service_requests(id) ON DELETE CASCADE;
|
||||
|
||||
-- 11. Storage bucket for IT service request files
|
||||
INSERT INTO storage.buckets (id, name, public, file_size_limit)
|
||||
VALUES ('it_service_attachments', 'it_service_attachments', true, 26214400)
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
-- Storage policies
|
||||
CREATE POLICY "Authenticated users can upload it_service_attachments"
|
||||
ON storage.objects FOR INSERT TO authenticated
|
||||
WITH CHECK (bucket_id = 'it_service_attachments');
|
||||
|
||||
CREATE POLICY "Authenticated users can read it_service_attachments"
|
||||
ON storage.objects FOR SELECT TO authenticated
|
||||
USING (bucket_id = 'it_service_attachments');
|
||||
|
||||
CREATE POLICY "Authenticated users can delete it_service_attachments"
|
||||
ON storage.objects FOR DELETE TO authenticated
|
||||
USING (bucket_id = 'it_service_attachments');
|
||||
|
||||
-- 12. Realtime publication
|
||||
ALTER PUBLICATION supabase_realtime ADD TABLE it_service_requests;
|
||||
ALTER PUBLICATION supabase_realtime ADD TABLE it_service_request_assignments;
|
||||
ALTER PUBLICATION supabase_realtime ADD TABLE it_service_request_activity_logs;
|
||||
ALTER PUBLICATION supabase_realtime ADD TABLE it_service_request_actions;
|
||||
Reference in New Issue
Block a user