Files
medical-mall/mall_sql/migrations/20260522_hss_service_mvp_p0.sql

274 lines
12 KiB
PL/PgSQL

BEGIN;
ALTER TABLE public.ml_user_addresses
ADD COLUMN IF NOT EXISTS latitude DOUBLE PRECISION,
ADD COLUMN IF NOT EXISTS longitude DOUBLE PRECISION,
ADD COLUMN IF NOT EXISTS coordinate_type TEXT NOT NULL DEFAULT 'gcj02';
CREATE TABLE IF NOT EXISTS public.hss_service_orders (
id TEXT PRIMARY KEY,
order_no TEXT NOT NULL UNIQUE,
user_id UUID NOT NULL,
service_id TEXT NOT NULL,
service_name TEXT NOT NULL,
service_snapshot_json JSONB NOT NULL DEFAULT '{}'::jsonb,
service_address_id UUID,
address_snapshot_json JSONB NOT NULL DEFAULT '{}'::jsonb,
recipient_name TEXT NOT NULL DEFAULT '',
recipient_phone TEXT NOT NULL DEFAULT '',
contact_name TEXT NOT NULL DEFAULT '',
contact_phone TEXT NOT NULL DEFAULT '',
appointment_time TIMESTAMPTZ,
remark TEXT NOT NULL DEFAULT '',
status TEXT NOT NULL DEFAULT 'created',
current_assignment_id TEXT NOT NULL DEFAULT '',
current_staff_id UUID,
accepted_at TIMESTAMPTZ,
departed_at TIMESTAMPTZ,
arrived_at TIMESTAMPTZ,
service_started_at TIMESTAMPTZ,
completed_at TIMESTAMPTZ,
pending_acceptance_at TIMESTAMPTZ,
accepted_by_user_at TIMESTAMPTZ,
reviewed_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
deleted_at TIMESTAMPTZ,
deleted_by UUID,
CONSTRAINT chk_hss_service_orders_status CHECK (
status IN (
'created', 'paid', 'assigned', 'accepted', 'rejected', 'departed', 'arrived',
'in_service', 'completed', 'pending_acceptance', 'accepted_by_user',
'reviewed', 'settled', 'cancelled', 'exception'
)
)
);
CREATE TABLE IF NOT EXISTS public.hss_service_assignments (
id TEXT PRIMARY KEY,
order_id TEXT NOT NULL REFERENCES public.hss_service_orders(id) ON DELETE CASCADE,
staff_id UUID NOT NULL REFERENCES public.ml_delivery_staff(id) ON DELETE RESTRICT,
station_id UUID REFERENCES public.ml_delivery_stations(id) ON DELETE SET NULL,
status TEXT NOT NULL DEFAULT 'assigned',
assigned_at TIMESTAMPTZ NOT NULL DEFAULT now(),
accepted_at TIMESTAMPTZ,
rejected_at TIMESTAMPTZ,
reject_reason TEXT NOT NULL DEFAULT '',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CONSTRAINT chk_hss_service_assignments_status CHECK (
status IN ('assigned', 'accepted', 'rejected', 'departed', 'arrived', 'in_service', 'pending_acceptance', 'completed', 'cancelled', 'exception')
)
);
CREATE TABLE IF NOT EXISTS public.hss_service_execution_records (
id TEXT PRIMARY KEY,
order_id TEXT NOT NULL REFERENCES public.hss_service_orders(id) ON DELETE CASCADE,
assignment_id TEXT NOT NULL REFERENCES public.hss_service_assignments(id) ON DELETE CASCADE,
checkin_time TIMESTAMPTZ,
checkin_latitude DOUBLE PRECISION,
checkin_longitude DOUBLE PRECISION,
checkin_address TEXT NOT NULL DEFAULT '',
service_started_at TIMESTAMPTZ,
service_finished_at TIMESTAMPTZ,
actual_duration_minutes INTEGER NOT NULL DEFAULT 0,
service_items_json JSONB NOT NULL DEFAULT '[]'::jsonb,
summary TEXT NOT NULL DEFAULT '',
remark TEXT NOT NULL DEFAULT '',
track_points_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.hss_service_evidence_files (
id TEXT PRIMARY KEY,
order_id TEXT NOT NULL REFERENCES public.hss_service_orders(id) ON DELETE CASCADE,
execution_record_id TEXT REFERENCES public.hss_service_execution_records(id) ON DELETE CASCADE,
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 TABLE IF NOT EXISTS public.hss_service_order_status_logs (
id TEXT PRIMARY KEY,
order_id TEXT NOT NULL REFERENCES public.hss_service_orders(id) ON DELETE CASCADE,
from_status TEXT NOT NULL DEFAULT '',
to_status TEXT NOT NULL,
operator_id UUID,
operator_role TEXT NOT NULL DEFAULT '',
remark TEXT NOT NULL DEFAULT '',
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS public.hss_service_reviews (
id TEXT PRIMARY KEY,
order_id TEXT NOT NULL REFERENCES public.hss_service_orders(id) ON DELETE CASCADE,
user_id UUID NOT NULL,
rating INTEGER NOT NULL DEFAULT 5,
tags_json JSONB NOT NULL DEFAULT '[]'::jsonb,
content TEXT NOT NULL DEFAULT '',
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_hss_service_orders_user_status
ON public.hss_service_orders(user_id, status)
WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_hss_service_orders_staff_status
ON public.hss_service_orders(current_staff_id, status)
WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_hss_service_assignments_staff_status
ON public.hss_service_assignments(staff_id, status);
CREATE INDEX IF NOT EXISTS idx_hss_service_execution_records_order
ON public.hss_service_execution_records(order_id);
CREATE INDEX IF NOT EXISTS idx_hss_service_evidence_files_order
ON public.hss_service_evidence_files(order_id);
CREATE INDEX IF NOT EXISTS idx_hss_service_logs_order_created
ON public.hss_service_order_status_logs(order_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_hss_service_reviews_order
ON public.hss_service_reviews(order_id);
CREATE OR REPLACE FUNCTION public.tg_hss_set_updated_at()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
NEW.updated_at = now();
RETURN NEW;
END;
$$;
DROP TRIGGER IF EXISTS trg_hss_service_orders_updated_at ON public.hss_service_orders;
CREATE TRIGGER trg_hss_service_orders_updated_at
BEFORE UPDATE ON public.hss_service_orders
FOR EACH ROW
EXECUTE FUNCTION public.tg_hss_set_updated_at();
DROP TRIGGER IF EXISTS trg_hss_service_assignments_updated_at ON public.hss_service_assignments;
CREATE TRIGGER trg_hss_service_assignments_updated_at
BEFORE UPDATE ON public.hss_service_assignments
FOR EACH ROW
EXECUTE FUNCTION public.tg_hss_set_updated_at();
DROP TRIGGER IF EXISTS trg_hss_service_execution_records_updated_at ON public.hss_service_execution_records;
CREATE TRIGGER trg_hss_service_execution_records_updated_at
BEFORE UPDATE ON public.hss_service_execution_records
FOR EACH ROW
EXECUTE FUNCTION public.tg_hss_set_updated_at();
ALTER TABLE public.hss_service_orders ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.hss_service_assignments ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.hss_service_execution_records ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.hss_service_evidence_files ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.hss_service_order_status_logs ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.hss_service_reviews ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS hss_service_orders_user_select ON public.hss_service_orders;
CREATE POLICY hss_service_orders_user_select
ON public.hss_service_orders
FOR SELECT
TO authenticated
USING (
deleted_at IS NULL AND (
user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
OR current_staff_id IN (SELECT id FROM public.ml_delivery_staff WHERE uid IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid()) AND deleted_at IS NULL)
)
);
DROP POLICY IF EXISTS hss_service_orders_user_insert ON public.hss_service_orders;
CREATE POLICY hss_service_orders_user_insert
ON public.hss_service_orders
FOR INSERT
TO authenticated
WITH CHECK (user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid()));
DROP POLICY IF EXISTS hss_service_orders_user_update ON public.hss_service_orders;
CREATE POLICY hss_service_orders_user_update
ON public.hss_service_orders
FOR UPDATE
TO authenticated
USING (
deleted_at IS NULL AND (
user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
OR current_staff_id IN (SELECT id FROM public.ml_delivery_staff WHERE uid IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid()) AND deleted_at IS NULL)
)
)
WITH CHECK (
deleted_at IS NULL AND (
user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
OR current_staff_id IN (SELECT id FROM public.ml_delivery_staff WHERE uid IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid()) AND deleted_at IS NULL)
)
);
DROP POLICY IF EXISTS hss_service_assignments_staff_select ON public.hss_service_assignments;
CREATE POLICY hss_service_assignments_staff_select
ON public.hss_service_assignments
FOR SELECT
TO authenticated
USING (staff_id IN (SELECT id FROM public.ml_delivery_staff WHERE uid IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid()) AND deleted_at IS NULL));
DROP POLICY IF EXISTS hss_service_assignments_staff_update ON public.hss_service_assignments;
CREATE POLICY hss_service_assignments_staff_update
ON public.hss_service_assignments
FOR UPDATE
TO authenticated
USING (staff_id IN (SELECT id FROM public.ml_delivery_staff WHERE uid IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid()) AND deleted_at IS NULL))
WITH CHECK (staff_id IN (SELECT id FROM public.ml_delivery_staff WHERE uid IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid()) AND deleted_at IS NULL));
DROP POLICY IF EXISTS hss_service_assignments_staff_insert ON public.hss_service_assignments;
CREATE POLICY hss_service_assignments_staff_insert
ON public.hss_service_assignments
FOR INSERT
TO authenticated
WITH CHECK (staff_id IN (SELECT id FROM public.ml_delivery_staff WHERE uid IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid()) AND deleted_at IS NULL));
DROP POLICY IF EXISTS hss_service_execution_records_order_access ON public.hss_service_execution_records;
CREATE POLICY hss_service_execution_records_order_access
ON public.hss_service_execution_records
FOR ALL
TO authenticated
USING (order_id IN (SELECT id FROM public.hss_service_orders WHERE deleted_at IS NULL))
WITH CHECK (order_id IN (SELECT id FROM public.hss_service_orders WHERE deleted_at IS NULL));
DROP POLICY IF EXISTS hss_service_evidence_files_order_access ON public.hss_service_evidence_files;
CREATE POLICY hss_service_evidence_files_order_access
ON public.hss_service_evidence_files
FOR ALL
TO authenticated
USING (order_id IN (SELECT id FROM public.hss_service_orders WHERE deleted_at IS NULL))
WITH CHECK (order_id IN (SELECT id FROM public.hss_service_orders WHERE deleted_at IS NULL));
DROP POLICY IF EXISTS hss_service_order_status_logs_order_access ON public.hss_service_order_status_logs;
CREATE POLICY hss_service_order_status_logs_order_access
ON public.hss_service_order_status_logs
FOR ALL
TO authenticated
USING (order_id IN (SELECT id FROM public.hss_service_orders WHERE deleted_at IS NULL))
WITH CHECK (order_id IN (SELECT id FROM public.hss_service_orders WHERE deleted_at IS NULL));
DROP POLICY IF EXISTS hss_service_reviews_order_access ON public.hss_service_reviews;
CREATE POLICY hss_service_reviews_order_access
ON public.hss_service_reviews
FOR ALL
TO authenticated
USING (order_id IN (SELECT id FROM public.hss_service_orders WHERE deleted_at IS NULL))
WITH CHECK (order_id IN (SELECT id FROM public.hss_service_orders WHERE deleted_at IS NULL));
COMMENT ON TABLE public.hss_service_orders IS '居家上门服务订单主表';
COMMENT ON TABLE public.hss_service_assignments IS '居家上门服务派单表';
COMMENT ON TABLE public.hss_service_execution_records IS '居家上门服务执行记录表';
COMMENT ON TABLE public.hss_service_evidence_files IS '居家上门服务证据文件表';
COMMENT ON TABLE public.hss_service_order_status_logs IS '居家上门服务状态日志表';
COMMENT ON TABLE public.hss_service_reviews IS '居家上门服务评价表';
COMMIT;