-- 新增 dws.biz_date() 函数：将 timestamptz 按营业日分割点归属到对应日期
-- 原因：全系统统计时间口径从自然日切换为营业日（默认 08:00 分割），
--       数据库层需要与 Python 侧 business_date() 等价的 SQL 函数，
--       供物化视图和直接查询使用。
-- 影响：物化视图 mv_dws_finance_daily_summary_l1..l4、
--       mv_dws_assistant_daily_detail_l1..l4 的时间过滤条件将依赖此函数
-- 关联需求：Requirements 9.2, 9.4

CREATE OR REPLACE FUNCTION dws.biz_date(
    ts timestamptz,
    cutoff_hour int DEFAULT 8
)
RETURNS date
LANGUAGE sql
IMMUTABLE
PARALLEL SAFE
AS $$
    SELECT (ts - make_interval(hours => cutoff_hour))::date;
$$;

COMMENT ON FUNCTION dws.biz_date(timestamptz, int) IS
    '营业日归属函数：将时间戳减去 cutoff_hour 小时后取日期。'
    '默认 cutoff_hour=8，即 08:00 前的时间戳归属前一天。'
    '等价于 Python 侧 neozqyy_shared.datetime_utils.business_date()。';

-- 验证 SQL：
-- SELECT dws.biz_date('2026-01-15 07:59:59+08'::timestamptz);        -- 预期：2026-01-14
-- SELECT dws.biz_date('2026-01-15 08:00:00+08'::timestamptz);        -- 预期：2026-01-15
-- SELECT dws.biz_date('2026-01-15 23:59:59+08'::timestamptz);        -- 预期：2026-01-15
-- SELECT dws.biz_date('2026-02-01 07:00:00+08'::timestamptz, 8);     -- 预期：2026-01-31（月末边界）
-- SELECT dws.biz_date(NOW());                                         -- 预期：当前营业日

-- 回滚：
-- DROP FUNCTION IF EXISTS dws.biz_date(timestamptz, int);
