完善服务模块缺少付款页的bug

This commit is contained in:
2026-06-02 11:35:31 +08:00
parent c3324d459a
commit 881262940c
35 changed files with 29069 additions and 557 deletions

View File

@@ -0,0 +1,29 @@
BEGIN;
-- =====================================================================================
-- Fix: hss_service_assignments INSERT RLS
-- Problem: consumers cannot insert assignments when auto-dispatching on order creation
-- because hss_service_assignments_staff_insert only allows the staff themselves.
-- Solution: allow the order owner (consumer) to insert assignments for their own orders.
-- =====================================================================================
DROP POLICY IF EXISTS hss_service_assignments_order_owner_insert ON public.hss_service_assignments;
CREATE POLICY hss_service_assignments_order_owner_insert
ON public.hss_service_assignments
FOR INSERT
TO authenticated
WITH CHECK (
EXISTS (
SELECT 1
FROM public.hss_service_orders o
WHERE o.id = order_id
AND o.user_id IN (SELECT id FROM public.ak_users WHERE auth_id = auth.uid())
AND o.deleted_at IS NULL
)
);
COMMENT ON POLICY hss_service_assignments_order_owner_insert
ON public.hss_service_assignments IS '允许订单所有者(消费者)在下单时为其订单写入自动派单记录';
COMMIT;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,116 @@
BEGIN;
CREATE TABLE IF NOT EXISTS public.hss_service_packages (
id TEXT PRIMARY KEY,
service_id TEXT NOT NULL REFERENCES public.hss_service_catalog(id) ON DELETE RESTRICT,
package_name TEXT NOT NULL,
package_desc TEXT NOT NULL DEFAULT '',
duration_minutes INTEGER NOT NULL DEFAULT 0,
duration_text TEXT NOT NULL DEFAULT '',
price NUMERIC(10, 2) NOT NULL DEFAULT 0,
list_price NUMERIC(10, 2) NOT NULL DEFAULT 0,
is_default BOOLEAN NOT NULL DEFAULT false,
sort_no INTEGER NOT NULL DEFAULT 0,
status SMALLINT NOT NULL DEFAULT 1,
effective_at TIMESTAMPTZ,
expires_at TIMESTAMPTZ,
data_source TEXT NOT NULL DEFAULT 'manual',
seed_batch_no TEXT NOT NULL DEFAULT '',
remark TEXT NOT NULL DEFAULT '',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
deleted_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_hss_service_packages_service_status_sort
ON public.hss_service_packages(service_id, status, sort_no)
WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_hss_service_packages_effective_window
ON public.hss_service_packages(effective_at, expires_at)
WHERE deleted_at IS NULL;
CREATE OR REPLACE FUNCTION public.tg_hss_service_packages_updated_at()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
NEW.updated_at = now();
RETURN NEW;
END;
$$;
DROP TRIGGER IF EXISTS trg_hss_service_packages_updated_at ON public.hss_service_packages;
CREATE TRIGGER trg_hss_service_packages_updated_at
BEFORE UPDATE ON public.hss_service_packages
FOR EACH ROW
EXECUTE FUNCTION public.tg_hss_service_packages_updated_at();
ALTER TABLE public.hss_service_packages ENABLE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS hss_service_packages_public_select_active ON public.hss_service_packages;
CREATE POLICY hss_service_packages_public_select_active
ON public.hss_service_packages
FOR SELECT
USING (
deleted_at IS NULL
AND status = 1
AND (effective_at IS NULL OR effective_at <= now())
AND (expires_at IS NULL OR expires_at > now())
);
ALTER TABLE public.hss_service_orders
ADD COLUMN IF NOT EXISTS service_package_id TEXT REFERENCES public.hss_service_packages(id) ON DELETE SET NULL,
ADD COLUMN IF NOT EXISTS pricing_snapshot_json JSONB NOT NULL DEFAULT '{}'::jsonb,
ADD COLUMN IF NOT EXISTS original_amount NUMERIC(10, 2) NOT NULL DEFAULT 0,
ADD COLUMN IF NOT EXISTS payable_amount NUMERIC(10, 2) NOT NULL DEFAULT 0,
ADD COLUMN IF NOT EXISTS total_amount NUMERIC(10, 2) NOT NULL DEFAULT 0;
CREATE INDEX IF NOT EXISTS idx_hss_service_orders_service_package_id
ON public.hss_service_orders(service_package_id)
WHERE deleted_at IS NULL;
UPDATE public.hss_service_orders
SET
pricing_snapshot_json = CASE
WHEN pricing_snapshot_json = '{}'::jsonb THEN jsonb_build_object(
'service_id', service_id,
'service_name', service_name,
'package_id', NULL,
'package_name', service_name,
'price', COALESCE((service_snapshot_json ->> 'price')::NUMERIC, 0),
'data_source', 'legacy_service_snapshot',
'remark', '历史订单由 service_snapshot_json.price 回填'
)
ELSE pricing_snapshot_json
END,
original_amount = CASE
WHEN original_amount <= 0 THEN COALESCE((service_snapshot_json ->> 'price')::NUMERIC, 0)
ELSE original_amount
END,
payable_amount = CASE
WHEN payable_amount <= 0 THEN COALESCE((service_snapshot_json ->> 'price')::NUMERIC, 0)
ELSE payable_amount
END,
total_amount = CASE
WHEN total_amount <= 0 THEN COALESCE((service_snapshot_json ->> 'price')::NUMERIC, 0)
ELSE total_amount
END,
updated_at = now()
WHERE deleted_at IS NULL
AND (
pricing_snapshot_json = '{}'::jsonb
OR original_amount <= 0
OR payable_amount <= 0
OR total_amount <= 0
);
COMMENT ON TABLE public.hss_service_packages IS '居家服务正式套餐/报价表';
COMMENT ON COLUMN public.hss_service_packages.data_source IS 'manual/dev_seed/prod_import 等数据来源标识';
COMMENT ON COLUMN public.hss_service_packages.seed_batch_no IS '测试种子批次号,便于上线前清理';
COMMENT ON COLUMN public.hss_service_orders.service_package_id IS '下单时冻结的正式套餐 ID';
COMMENT ON COLUMN public.hss_service_orders.pricing_snapshot_json IS '订单创建时冻结的套餐/报价快照';
COMMENT ON COLUMN public.hss_service_orders.payable_amount IS '订单应付金额快照';
COMMENT ON COLUMN public.hss_service_orders.total_amount IS '服务订单总金额快照';
COMMIT;