-- 019_rock_purchase_logs.sql -- 采购流水:每一次进入采购流程的尝试(含降级、跳过、失败)都留一条主记录, -- 每个上游接口调用在阶段表里保留原始请求/响应,便于对账与排障。 -- 注意:只记录请求体,不记录任何请求头,避免 Bearer Token 落库。 CREATE TABLE IF NOT EXISTS rock_purchase_logs ( id BIGSERIAL PRIMARY KEY, trigger_type VARCHAR(16) NOT NULL DEFAULT 'auto', -- auto / manual status VARCHAR(16) NOT NULL DEFAULT 'running',-- running / success / partial / failed / skipped requested_count INTEGER NOT NULL DEFAULT 0, -- 原计划(批次值或手动输入) planned_count INTEGER NOT NULL DEFAULT 0, -- 降级后的实际计划数 claimed_count INTEGER NOT NULL DEFAULT 0, -- 上游实际返回数 imported_count INTEGER NOT NULL DEFAULT 0, -- 本地实际入库数 upstream_available INTEGER NOT NULL DEFAULT 0, -- 采购时上游可用库存 points_before NUMERIC(12,2) NOT NULL DEFAULT 0.00, -- 采购前积分 unit_cost NUMERIC(12,2) NOT NULL DEFAULT 0.00, -- 采购单价 max_by_points INTEGER NOT NULL DEFAULT 0, -- 积分可买上限 max_by_stock INTEGER NOT NULL DEFAULT 0, -- 上游库存可买上限 limit_reason VARCHAR(32) NOT NULL DEFAULT '', -- points / upstream_stock / points_and_stock points_source VARCHAR(16) NOT NULL DEFAULT '', -- live / snapshot stage VARCHAR(32) NOT NULL DEFAULT '', -- me / dashboard / claim / package / detail / import error_message TEXT NOT NULL DEFAULT '', package_id BIGINT, share_code VARCHAR(64) NOT NULL DEFAULT '', duration_ms INTEGER NOT NULL DEFAULT 0, started_at TIMESTAMPTZ NOT NULL DEFAULT now(), finished_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS idx_rock_purchase_logs_created_at ON rock_purchase_logs (created_at DESC); CREATE INDEX IF NOT EXISTS idx_rock_purchase_logs_trigger_status ON rock_purchase_logs (trigger_type, status); CREATE TABLE IF NOT EXISTS rock_purchase_stages ( id BIGSERIAL PRIMARY KEY, log_id BIGINT NOT NULL REFERENCES rock_purchase_logs(id) ON DELETE CASCADE, seq INTEGER NOT NULL DEFAULT 0, stage VARCHAR(32) NOT NULL, method VARCHAR(8) NOT NULL DEFAULT '', url TEXT NOT NULL DEFAULT '', request_body TEXT NOT NULL DEFAULT '', http_status INTEGER NOT NULL DEFAULT 0, response_body TEXT NOT NULL DEFAULT '', truncated BOOLEAN NOT NULL DEFAULT false, duration_ms INTEGER NOT NULL DEFAULT 0, error_message TEXT NOT NULL DEFAULT '', created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS idx_rock_purchase_stages_log_id ON rock_purchase_stages (log_id, seq);