336 lines
12 KiB
PL/PgSQL
336 lines
12 KiB
PL/PgSQL
BEGIN;
|
|
|
|
-- 与 delivery 侧保持同版,供 consumer/delivery 双端使用同一套 homecare foundation schema。
|
|
|
|
CREATE TABLE IF NOT EXISTS public.ec_service_requests (
|
|
id UUID PRIMARY KEY,
|
|
user_id UUID NOT NULL,
|
|
service_catalog_id TEXT NOT NULL DEFAULT '',
|
|
service_name TEXT NOT NULL DEFAULT '',
|
|
service_category TEXT NOT NULL DEFAULT '',
|
|
elder_name TEXT NOT NULL DEFAULT '',
|
|
elder_phone TEXT NOT NULL DEFAULT '',
|
|
contact_name TEXT NOT NULL DEFAULT '',
|
|
contact_phone TEXT NOT NULL DEFAULT '',
|
|
address_snapshot JSONB,
|
|
address_snapshot_json JSONB,
|
|
scheduled_at TIMESTAMPTZ,
|
|
remark TEXT NOT NULL DEFAULT '',
|
|
status TEXT NOT NULL DEFAULT 'ORDER_CREATED',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS public.ec_care_tasks (
|
|
id UUID PRIMARY KEY,
|
|
task_no TEXT NOT NULL UNIQUE,
|
|
request_id UUID REFERENCES public.ec_service_requests(id) ON DELETE SET NULL,
|
|
user_id UUID NOT NULL,
|
|
assigned_to UUID,
|
|
service_catalog_id TEXT NOT NULL DEFAULT '',
|
|
service_name TEXT NOT NULL DEFAULT '',
|
|
service_category TEXT NOT NULL DEFAULT '',
|
|
service_snapshot_json JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
elder_name TEXT NOT NULL DEFAULT '',
|
|
elder_phone TEXT NOT NULL DEFAULT '',
|
|
contact_name TEXT NOT NULL DEFAULT '',
|
|
contact_phone TEXT NOT NULL DEFAULT '',
|
|
address_snapshot JSONB,
|
|
address_snapshot_json JSONB,
|
|
scheduled_at TIMESTAMPTZ,
|
|
appointment_time TIMESTAMPTZ,
|
|
remark TEXT NOT NULL DEFAULT '',
|
|
status TEXT NOT NULL DEFAULT 'ORDER_CREATED',
|
|
reject_reason TEXT NOT NULL DEFAULT '',
|
|
accepted_at TIMESTAMPTZ,
|
|
departed_at TIMESTAMPTZ,
|
|
checked_in_at TIMESTAMPTZ,
|
|
service_started_at TIMESTAMPTZ,
|
|
service_completed_at TIMESTAMPTZ,
|
|
acceptance_pending_at TIMESTAMPTZ,
|
|
accepted_by_family_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS public.ec_care_records (
|
|
id TEXT PRIMARY KEY,
|
|
task_id UUID NOT NULL REFERENCES public.ec_care_tasks(id) ON DELETE CASCADE,
|
|
record_type TEXT NOT NULL DEFAULT 'service_record',
|
|
care_record_type TEXT,
|
|
created_by UUID,
|
|
started_at TIMESTAMPTZ,
|
|
finished_at TIMESTAMPTZ,
|
|
checked_in_at TIMESTAMPTZ,
|
|
checkin_time TIMESTAMPTZ,
|
|
latitude DOUBLE PRECISION,
|
|
longitude DOUBLE PRECISION,
|
|
location_text TEXT NOT NULL DEFAULT '',
|
|
duration_minutes INTEGER NOT NULL DEFAULT 0,
|
|
actual_duration_minutes INTEGER NOT NULL DEFAULT 0,
|
|
service_items_json JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
service_content_json JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
service_summary TEXT NOT NULL DEFAULT '',
|
|
process_note TEXT NOT NULL DEFAULT '',
|
|
summary TEXT NOT NULL DEFAULT '',
|
|
content TEXT NOT NULL DEFAULT '',
|
|
remark TEXT NOT NULL DEFAULT '',
|
|
elder_status TEXT NOT NULL DEFAULT '',
|
|
health_metrics_json JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
materials_used TEXT NOT NULL DEFAULT '',
|
|
abnormal_note TEXT NOT NULL DEFAULT '',
|
|
photos_json JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
staff_remark TEXT NOT NULL DEFAULT '',
|
|
family_confirmation_json JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
rating INTEGER,
|
|
tags_json JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS public.hc_work_order_events (
|
|
id TEXT PRIMARY KEY,
|
|
task_id UUID NOT NULL REFERENCES public.ec_care_tasks(id) ON DELETE CASCADE,
|
|
from_status TEXT,
|
|
to_status TEXT NOT NULL DEFAULT '',
|
|
actor_id UUID,
|
|
actor_role TEXT NOT NULL DEFAULT '',
|
|
action TEXT NOT NULL DEFAULT '',
|
|
remark TEXT NOT NULL DEFAULT '',
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS public.hc_work_order_exceptions (
|
|
id TEXT PRIMARY KEY,
|
|
task_id UUID NOT NULL REFERENCES public.ec_care_tasks(id) ON DELETE CASCADE,
|
|
exception_type TEXT NOT NULL DEFAULT 'other',
|
|
description TEXT NOT NULL DEFAULT '',
|
|
occurred_at TIMESTAMPTZ,
|
|
location_text TEXT NOT NULL DEFAULT '',
|
|
images_json JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
need_platform_intervention BOOLEAN NOT NULL DEFAULT false,
|
|
request_cancel_order BOOLEAN NOT NULL DEFAULT false,
|
|
request_reschedule BOOLEAN NOT NULL DEFAULT false,
|
|
created_by UUID,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS public.hc_evidence_files (
|
|
id TEXT PRIMARY KEY,
|
|
task_id UUID NOT NULL REFERENCES public.ec_care_tasks(id) ON DELETE CASCADE,
|
|
care_record_id TEXT,
|
|
phase TEXT NOT NULL DEFAULT 'service',
|
|
file_type TEXT NOT NULL DEFAULT 'image',
|
|
storage_path TEXT NOT NULL DEFAULT '',
|
|
file_url TEXT NOT NULL DEFAULT '',
|
|
latitude DOUBLE PRECISION,
|
|
longitude DOUBLE PRECISION,
|
|
captured_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_ec_service_requests_user_created
|
|
ON public.ec_service_requests(user_id, created_at DESC);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_ec_care_tasks_user_created
|
|
ON public.ec_care_tasks(user_id, created_at DESC);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_ec_care_tasks_assigned_status
|
|
ON public.ec_care_tasks(assigned_to, status, created_at DESC);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_ec_care_records_task_created
|
|
ON public.ec_care_records(task_id, created_at DESC);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_hc_work_order_events_task_created
|
|
ON public.hc_work_order_events(task_id, created_at DESC);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_hc_work_order_exceptions_task_created
|
|
ON public.hc_work_order_exceptions(task_id, created_at DESC);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_hc_evidence_files_task_created
|
|
ON public.hc_evidence_files(task_id, created_at DESC);
|
|
|
|
CREATE OR REPLACE FUNCTION public.tg_ec_set_updated_at()
|
|
RETURNS trigger
|
|
LANGUAGE plpgsql
|
|
AS $$
|
|
BEGIN
|
|
NEW.updated_at = now();
|
|
RETURN NEW;
|
|
END;
|
|
$$;
|
|
|
|
DROP TRIGGER IF EXISTS trg_ec_service_requests_updated_at ON public.ec_service_requests;
|
|
CREATE TRIGGER trg_ec_service_requests_updated_at
|
|
BEFORE UPDATE ON public.ec_service_requests
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION public.tg_ec_set_updated_at();
|
|
|
|
DROP TRIGGER IF EXISTS trg_ec_care_tasks_updated_at ON public.ec_care_tasks;
|
|
CREATE TRIGGER trg_ec_care_tasks_updated_at
|
|
BEFORE UPDATE ON public.ec_care_tasks
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION public.tg_ec_set_updated_at();
|
|
|
|
DROP TRIGGER IF EXISTS trg_ec_care_records_updated_at ON public.ec_care_records;
|
|
CREATE TRIGGER trg_ec_care_records_updated_at
|
|
BEFORE UPDATE ON public.ec_care_records
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION public.tg_ec_set_updated_at();
|
|
|
|
DROP TRIGGER IF EXISTS trg_hc_work_order_exceptions_updated_at ON public.hc_work_order_exceptions;
|
|
CREATE TRIGGER trg_hc_work_order_exceptions_updated_at
|
|
BEFORE UPDATE ON public.hc_work_order_exceptions
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION public.tg_ec_set_updated_at();
|
|
|
|
ALTER TABLE public.ec_service_requests ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE public.ec_care_tasks ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE public.ec_care_records ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE public.hc_work_order_events ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE public.hc_work_order_exceptions ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE public.hc_evidence_files ENABLE ROW LEVEL SECURITY;
|
|
|
|
DROP POLICY IF EXISTS ec_service_requests_owner_select ON public.ec_service_requests;
|
|
CREATE POLICY ec_service_requests_owner_select
|
|
ON public.ec_service_requests
|
|
FOR SELECT
|
|
TO authenticated
|
|
USING (user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid()));
|
|
|
|
DROP POLICY IF EXISTS ec_service_requests_owner_insert ON public.ec_service_requests;
|
|
CREATE POLICY ec_service_requests_owner_insert
|
|
ON public.ec_service_requests
|
|
FOR INSERT
|
|
TO authenticated
|
|
WITH CHECK (user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid()));
|
|
|
|
DROP POLICY IF EXISTS ec_service_requests_owner_update ON public.ec_service_requests;
|
|
CREATE POLICY ec_service_requests_owner_update
|
|
ON public.ec_service_requests
|
|
FOR UPDATE
|
|
TO authenticated
|
|
USING (user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid()))
|
|
WITH CHECK (user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid()));
|
|
|
|
DROP POLICY IF EXISTS ec_care_tasks_owner_or_staff_select ON public.ec_care_tasks;
|
|
CREATE POLICY ec_care_tasks_owner_or_staff_select
|
|
ON public.ec_care_tasks
|
|
FOR SELECT
|
|
TO authenticated
|
|
USING (
|
|
user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
OR assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
);
|
|
|
|
DROP POLICY IF EXISTS ec_care_tasks_owner_insert ON public.ec_care_tasks;
|
|
CREATE POLICY ec_care_tasks_owner_insert
|
|
ON public.ec_care_tasks
|
|
FOR INSERT
|
|
TO authenticated
|
|
WITH CHECK (user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid()));
|
|
|
|
DROP POLICY IF EXISTS ec_care_tasks_owner_or_staff_update ON public.ec_care_tasks;
|
|
CREATE POLICY ec_care_tasks_owner_or_staff_update
|
|
ON public.ec_care_tasks
|
|
FOR UPDATE
|
|
TO authenticated
|
|
USING (
|
|
user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
OR assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
)
|
|
WITH CHECK (
|
|
user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
OR assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
);
|
|
|
|
DROP POLICY IF EXISTS ec_care_records_task_access ON public.ec_care_records;
|
|
CREATE POLICY ec_care_records_task_access
|
|
ON public.ec_care_records
|
|
FOR ALL
|
|
TO authenticated
|
|
USING (
|
|
task_id IN (
|
|
SELECT t.id
|
|
FROM public.ec_care_tasks t
|
|
WHERE t.user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
OR t.assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
)
|
|
)
|
|
WITH CHECK (
|
|
task_id IN (
|
|
SELECT t.id
|
|
FROM public.ec_care_tasks t
|
|
WHERE t.user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
OR t.assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
)
|
|
);
|
|
|
|
DROP POLICY IF EXISTS hc_work_order_events_task_access ON public.hc_work_order_events;
|
|
CREATE POLICY hc_work_order_events_task_access
|
|
ON public.hc_work_order_events
|
|
FOR ALL
|
|
TO authenticated
|
|
USING (
|
|
task_id IN (
|
|
SELECT t.id
|
|
FROM public.ec_care_tasks t
|
|
WHERE t.user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
OR t.assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
)
|
|
)
|
|
WITH CHECK (
|
|
task_id IN (
|
|
SELECT t.id
|
|
FROM public.ec_care_tasks t
|
|
WHERE t.user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
OR t.assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
)
|
|
);
|
|
|
|
DROP POLICY IF EXISTS hc_work_order_exceptions_task_access ON public.hc_work_order_exceptions;
|
|
CREATE POLICY hc_work_order_exceptions_task_access
|
|
ON public.hc_work_order_exceptions
|
|
FOR ALL
|
|
TO authenticated
|
|
USING (
|
|
task_id IN (
|
|
SELECT t.id
|
|
FROM public.ec_care_tasks t
|
|
WHERE t.user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
OR t.assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
)
|
|
)
|
|
WITH CHECK (
|
|
task_id IN (
|
|
SELECT t.id
|
|
FROM public.ec_care_tasks t
|
|
WHERE t.user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
OR t.assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
)
|
|
);
|
|
|
|
DROP POLICY IF EXISTS hc_evidence_files_task_access ON public.hc_evidence_files;
|
|
CREATE POLICY hc_evidence_files_task_access
|
|
ON public.hc_evidence_files
|
|
FOR ALL
|
|
TO authenticated
|
|
USING (
|
|
task_id IN (
|
|
SELECT t.id
|
|
FROM public.ec_care_tasks t
|
|
WHERE t.user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
OR t.assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
)
|
|
)
|
|
WITH CHECK (
|
|
task_id IN (
|
|
SELECT t.id
|
|
FROM public.ec_care_tasks t
|
|
WHERE t.user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
OR t.assigned_to IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
|
|
)
|
|
);
|
|
|
|
COMMIT; |