Files
affiliate_dash/backend/internal/database/migrations/012_rock_fulfillment.sql
T
yml2213 ef7f67dd0c feat(fulfillment): 接入Rock发货平台(0666.pro)代理履约、通用库存池与UID强一致风控
1. 数据库新增 012_rock_fulfillment 迁移,创建 rock_configs 配置表与 rock_tokens 通用库存表,补齐黑色ROCK长袖T恤与蓝色运动服上衣商品目录;
2. 封装 RockClient 与 RockService,实现 0666.pro 平台 Bearer Token 极简连通校验、批量采购50个入库、水位监控巡检与自动补货;
3. 新增 RockProvider 实现标准履约路由,引入 Anti-Ghost 旧绑定基线比对与 UID 强一致门禁,扫错号硬阻断并记录为 mismatch 状态;
4. 针对黑色ROCK与蓝色运动服实现动态发货(绑定后发货前动态选择 skin),并提取腾讯官方发货流水号 fulfillId 对账;
5. 新增全局自动发货总开关(Kill Switch),支持一键软熔断降级转人工接单处理;
6. 前端新增 PlatformRock 管理大屏,提供总开关切换、Token配置与连通测试、库存监控、一键补货及错单解冻重置。
2026-10-05 14:56:11 +08:00

111 lines
4.5 KiB
SQL

-- ============================================================================
-- 012_rock_fulfillment.sql: Rock 发货平台 (0666.pro) 代理接入与库存风控数据表与商品目录
-- ============================================================================
-- 1) Rock 平台系统配置表
CREATE TABLE IF NOT EXISTS rock_configs (
id BIGINT PRIMARY KEY DEFAULT 1,
auto_delivery_enabled BOOLEAN NOT NULL DEFAULT true,
base_url VARCHAR(255) NOT NULL DEFAULT 'https://0666.pro',
bearer_token TEXT NOT NULL DEFAULT '',
username VARCHAR(128) NOT NULL DEFAULT '',
points NUMERIC(12, 2) NOT NULL DEFAULT 0.00,
min_points_warning NUMERIC(12, 2) NOT NULL DEFAULT 1050.00,
token_warning_stock INT NOT NULL DEFAULT 10,
auto_purchase_enabled BOOLEAN NOT NULL DEFAULT false,
auto_purchase_count INT NOT NULL DEFAULT 50,
purchase_cooldown_minutes INT NOT NULL DEFAULT 10,
last_purchased_at TIMESTAMPTZ,
last_heartbeat_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- 初始化默认配置行(固定 ID=1)
INSERT INTO rock_configs (id, auto_delivery_enabled, base_url, bearer_token, min_points_warning, token_warning_stock, auto_purchase_enabled, auto_purchase_count)
VALUES (1, true, 'https://0666.pro', '', 1050.00, 10, false, 50)
ON CONFLICT (id) DO NOTHING;
-- 2) Rock 通用 Token 本地库存池表
CREATE TABLE IF NOT EXISTS rock_tokens (
id BIGSERIAL PRIMARY KEY,
upstream_token_id VARCHAR(64) NOT NULL DEFAULT '',
token TEXT NOT NULL,
redeem_code VARCHAR(64) NOT NULL,
color VARCHAR(32) NOT NULL DEFAULT 'black',
region VARCHAR(64) NOT NULL DEFAULT 'Q/V可用',
status VARCHAR(32) NOT NULL DEFAULT 'available',
assigned_order_no VARCHAR(128),
expected_uid VARCHAR(64),
actual_role_name VARCHAR(128),
actual_role_id VARCHAR(64),
actual_channel VARCHAR(64),
initial_bound_snapshot TEXT,
upstream_fulfill_id BIGINT,
target_skin VARCHAR(128),
target_currency VARCHAR(64) NOT NULL DEFAULT '幸运币',
target_currency_quantity INT NOT NULL DEFAULT 0,
mismatch_at TIMESTAMPTZ,
mismatch_reason VARCHAR(255),
claimed_at TIMESTAMPTZ,
bound_at TIMESTAMPTZ,
redeemed_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_rock_tokens_status_color ON rock_tokens (status, color);
CREATE INDEX IF NOT EXISTS idx_rock_tokens_assigned_order ON rock_tokens (assigned_order_no);
CREATE INDEX IF NOT EXISTS idx_rock_tokens_redeem_code ON rock_tokens (redeem_code);
CREATE INDEX IF NOT EXISTS idx_rock_tokens_mismatch ON rock_tokens (status, mismatch_at);
-- 3) 插入 Rock 皮肤到商品目录 (products 表与自营 merchant_products 表)
WITH rock_products(sku, name, category, default_price, fulfillment_config) AS (
VALUES
('rock_black_tshirt', '黑色ROCK长袖T恤', '服饰', 2500, '{"routing_mode":"rock","priority":["rock"],"delivery_type":"LINK_BINDING"}'),
('rock_blue_sportswear', '蓝色运动服上衣', '服饰', 2500, '{"routing_mode":"rock","priority":["rock"],"delivery_type":"LINK_BINDING"}')
)
INSERT INTO products (code, name, category, status)
SELECT p.sku, p.name, p.category, 'active'
FROM rock_products p
ON CONFLICT (code) DO UPDATE
SET
name = EXCLUDED.name,
category = EXCLUDED.category,
status = 'active';
WITH rock_products(sku, name, category, default_price, fulfillment_config) AS (
VALUES
('rock_black_tshirt', '黑色ROCK长袖T恤', '服饰', 2500, '{"routing_mode":"rock","priority":["rock"],"delivery_type":"LINK_BINDING"}'),
('rock_blue_sportswear', '蓝色运动服上衣', '服饰', 2500, '{"routing_mode":"rock","priority":["rock"],"delivery_type":"LINK_BINDING"}')
),
self_merchant AS (
SELECT id FROM merchants WHERE code = 'self-operated' LIMIT 1
)
INSERT INTO merchant_products (
merchant_id, product_id, sku, display_name,
price_amount, cost_amount, currency, stock, status, fulfillment_config
)
SELECT
sm.id,
p.id,
rp.sku,
rp.name,
rp.default_price,
rp.default_price,
'POINT',
-1,
'active',
rp.fulfillment_config
FROM rock_products rp
JOIN products p ON p.code = rp.sku
CROSS JOIN self_merchant sm
ON CONFLICT (merchant_id, sku) DO UPDATE
SET
display_name = EXCLUDED.display_name,
price_amount = EXCLUDED.price_amount,
cost_amount = EXCLUDED.cost_amount,
fulfillment_config = EXCLUDED.fulfillment_config,
status = 'active',
deleted_at = NULL;