-- ============================================================
-- 数据库变更记录 (changeSql.sql)
-- 规则:每次表结构/基础数据变更,在文件【末尾追加】一个新块,
--       不要修改或删除历史块。执行时按从上到下顺序依次执行新增部分。
-- 数据库: PostgreSQL (park_bike)
-- ============================================================


-- ------------------------------------------------------------
-- 2026-06-22  v3.0.1  接入抖音券核销 —— 新增抖音商品表
-- 作者: rk
-- 说明: 用于落地抖音「查询商品线上数据列表」接口同步过来的团购商品
-- ------------------------------------------------------------

-- 抖音商品主表
CREATE TABLE "douyin_product" (
  "id"             varchar(64)   NOT NULL,
  "product_id"     varchar(64)   NOT NULL,
  "out_id"         varchar(128),
  "product_name"   varchar(255),
  "category"       varchar(64),
  "product_type"   smallint,
  "online_status"  smallint      DEFAULT 1,
  "account_id"     varchar(64),
  "sync_date"      timestamp,
  "raw_content"    text,
  "create_date"    timestamp     DEFAULT CURRENT_TIMESTAMP,
  "creator"        varchar(64),
  "edit_date"      timestamp,
  "editor"         varchar(64),
  "isdeleted"      smallint      DEFAULT 0,
  PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX uk_douyin_product_product_id ON "douyin_product" ("product_id") WHERE "isdeleted" = 0;
COMMENT ON TABLE  "douyin_product" IS '抖音商品(团购)线上数据';
COMMENT ON COLUMN "douyin_product"."product_id"    IS '抖音商品ID(业务唯一键,用于upsert)';
COMMENT ON COLUMN "douyin_product"."out_id"        IS '外部商品ID';
COMMENT ON COLUMN "douyin_product"."online_status" IS '在线状态 1在线 2下线 3封禁';
COMMENT ON COLUMN "douyin_product"."account_id"    IS '来客商户根账户ID';
COMMENT ON COLUMN "douyin_product"."sync_date"     IS '最近同步时间';
COMMENT ON COLUMN "douyin_product"."raw_content"   IS '抖音原始响应快照(便于追溯)';
COMMENT ON COLUMN "douyin_product"."isdeleted"     IS '是否已删除 0未删除 1已删除';

-- 抖音商品 SKU 子表
CREATE TABLE "douyin_product_sku" (
  "id"             varchar(64)   NOT NULL,
  "product_id"     varchar(64)   NOT NULL,
  "sku_id"         varchar(64),
  "title"          varchar(255),
  "third_sku_id"   varchar(128),
  "sku_out_id"     varchar(128),
  "market_price"   bigint,
  "groupon_type"   smallint,
  "voucher_type"   smallint,
  "create_date"    timestamp     DEFAULT CURRENT_TIMESTAMP,
  "edit_date"      timestamp,
  "isdeleted"      smallint      DEFAULT 0,
  PRIMARY KEY ("id")
);
CREATE INDEX idx_douyin_product_sku_pid ON "douyin_product_sku" ("product_id");
COMMENT ON TABLE  "douyin_product_sku" IS '抖音商品SKU';
COMMENT ON COLUMN "douyin_product_sku"."product_id"   IS '关联 douyin_product.product_id(抖音商品ID)';
COMMENT ON COLUMN "douyin_product_sku"."market_price" IS '市场价(分)';
COMMENT ON COLUMN "douyin_product_sku"."isdeleted"    IS '是否已删除 0未删除 1已删除';


-- ------------------------------------------------------------
-- 2026-06-22  v3.0.1  接入抖音券核销 —— 新增抖音券核销记录表
-- 作者: rk
-- 说明: 记录抖音团购券的验券(核销)/撤销流水,撤销核销与对账依赖本表
-- ------------------------------------------------------------

CREATE TABLE "douyin_verify_record" (
  "id"              varchar(64)   NOT NULL,
  "verify_id"       varchar(64),
  "certificate_id"  varchar(64),
  "order_id"        varchar(64),
  "origin_code"     varchar(128),
  "encrypted_code"  varchar(255),
  "poi_id"          varchar(64),
  "account_id"      varchar(64),
  "product_id"      varchar(64),
  "product_name"    varchar(255),
  "pay_amount"      bigint,
  "verify_status"   smallint      DEFAULT 1,
  "verify_time"     timestamp,
  "verify_user_id"  varchar(64),
  "verify_msg"      varchar(255),
  "cancel_status"   smallint      DEFAULT 0,
  "cancel_time"     timestamp,
  "cancel_user_id"  varchar(64),
  "cancel_msg"      varchar(255),
  "raw_request"     text,
  "raw_response"    text,
  "create_date"     timestamp     DEFAULT CURRENT_TIMESTAMP,
  "creator"         varchar(64),
  "edit_date"       timestamp,
  "editor"          varchar(64),
  "isdeleted"       smallint      DEFAULT 0,
  PRIMARY KEY ("id")
);
CREATE INDEX idx_dvr_verify_id  ON "douyin_verify_record" ("verify_id");
CREATE INDEX idx_dvr_cert_id    ON "douyin_verify_record" ("certificate_id");
CREATE INDEX idx_dvr_order_id   ON "douyin_verify_record" ("order_id");
COMMENT ON TABLE  "douyin_verify_record" IS '抖音券核销记录';
COMMENT ON COLUMN "douyin_verify_record"."verify_id"      IS '验券返回的一次核销唯一标识,撤销必用';
COMMENT ON COLUMN "douyin_verify_record"."certificate_id" IS '券标识,撤销必用';
COMMENT ON COLUMN "douyin_verify_record"."encrypted_code" IS '加密券码(prepare返回,verify入参)';
COMMENT ON COLUMN "douyin_verify_record"."pay_amount"     IS '实付金额(分)';
COMMENT ON COLUMN "douyin_verify_record"."verify_status"  IS '核销结果 0成功 1失败';
COMMENT ON COLUMN "douyin_verify_record"."cancel_status"  IS '撤销状态 0未撤销 1已撤销';
COMMENT ON COLUMN "douyin_verify_record"."raw_request"    IS '请求快照(便于追溯)';
COMMENT ON COLUMN "douyin_verify_record"."raw_response"   IS '响应快照(便于追溯)';
COMMENT ON COLUMN "douyin_verify_record"."isdeleted"      IS '是否已删除 0未删除 1已删除';


-- ------------------------------------------------------------
-- 2026-06-25  v3.0.1  抖音商品 out_id 语义变更 —— 改由管理端绑定本地套餐
-- 作者: rk
-- 说明: out_id 不再由抖音同步写入,改为管理端绑定本地套餐主键(discount.id)。
--       字段结构不变,仅更新列注释(覆盖旧注释,幂等可重复执行);
--       同步逻辑 upsertProduct 已停止用抖音返回的 out_id 覆盖本地值。
-- ------------------------------------------------------------

COMMENT ON COLUMN "douyin_product"."out_id" IS '绑定本地套餐ID(discount.id,管理端维护,抖音同步不写入)';


-- ------------------------------------------------------------
-- 2026-06-25  v3.0.1  抖音验券操作日志表 —— web 端接口操作流水
-- 作者: rk
-- 说明: 记录 web 端 prepare/verify/cancel 每次调用的操作流水(谁/何时/结果/耗时/IP)。
--       完整审计:含请求入参与抖音响应原文;核销业务数据仍由 douyin_verify_record 承载。
-- ------------------------------------------------------------

CREATE TABLE "douyin_verify_log" (
  "id"               varchar(64)   NOT NULL,
  "operate_type"     smallint,
  "api_path"         varchar(64),
  "member_id"        varchar(64),
  "verify_record_id" varchar(64),
  "poi_id"           varchar(64),
  "origin_code"      varchar(128),
  "result"           smallint,
  "error_msg"        varchar(500),
  "raw_request"      text,
  "raw_response"     text,
  "ip"               varchar(64),
  "cost_ms"          integer,
  "create_date"      timestamp     DEFAULT CURRENT_TIMESTAMP,
  "isdeleted"        smallint      DEFAULT 0,
  PRIMARY KEY ("id")
);
CREATE INDEX idx_dvl_member ON "douyin_verify_log" ("member_id");
CREATE INDEX idx_dvl_record ON "douyin_verify_log" ("verify_record_id");
COMMENT ON TABLE  "douyin_verify_log" IS '抖音验券操作日志(web端接口操作流水)';
COMMENT ON COLUMN "douyin_verify_log"."operate_type"     IS '操作类型 0验券准备 1核销 2撤销核销';
COMMENT ON COLUMN "douyin_verify_log"."api_path"         IS '接口路径';
COMMENT ON COLUMN "douyin_verify_log"."member_id"        IS '操作人会员ID';
COMMENT ON COLUMN "douyin_verify_log"."verify_record_id" IS '关联核销记录 douyin_verify_record.id';
COMMENT ON COLUMN "douyin_verify_log"."poi_id"           IS '核销门店';
COMMENT ON COLUMN "douyin_verify_log"."origin_code"      IS '券码快照';
COMMENT ON COLUMN "douyin_verify_log"."result"           IS '操作结果 0成功 1失败';
COMMENT ON COLUMN "douyin_verify_log"."error_msg"        IS '失败描述';
COMMENT ON COLUMN "douyin_verify_log"."raw_request"      IS '请求入参快照(JSON)';
COMMENT ON COLUMN "douyin_verify_log"."raw_response"     IS '抖音响应原文快照';
COMMENT ON COLUMN "douyin_verify_log"."ip"               IS '请求IP';
COMMENT ON COLUMN "douyin_verify_log"."cost_ms"          IS '耗时(毫秒)';
COMMENT ON COLUMN "douyin_verify_log"."isdeleted"        IS '是否已删除 0未删除 1已删除';


-- ------------------------------------------------------------
-- 2026-06-25  v3.0.1  抖音核销开套餐 —— 核销记录加套餐卡ID列
-- 作者: rk
-- 说明: 核销成功开通 discount_member 后,回填套餐卡ID到核销记录,便于追溯。
-- 注意: goodsorder.payWay 新增取值 2=抖音券核销,前端支付方式展示需配合(若存在字典表则同步新增)。
-- ------------------------------------------------------------

ALTER TABLE "douyin_verify_record" ADD COLUMN IF NOT EXISTS "discount_member_id" varchar(64);
COMMENT ON COLUMN "douyin_verify_record"."discount_member_id" IS '核销成功开通的套餐卡ID(discount_member.id)';


-- ------------------------------------------------------------
-- 2026-06-25  v3.0.1  抖音核销配置入字典 —— 改后台维护、免重启
-- 作者: rk
-- 说明: client_key / client_secret / account_id / poi_id 从 yml 迁到字典
--       (system_dict + system_dict_data);门店ID等变动时,后台 /system/dictData 改即可,无需重启。
-- 执行前:把 4 处「待填」替换为真实值(client_secret 勿提交真值到仓库)。
-- 环境:PostgreSQL 13+ 内置 gen_random_uuid();低版本需先 CREATE EXTENSION pgcrypto。
-- 创建人/更新人:固定 system_user.id = 722ecd1e-e903-45b1-a839-c591c0af0d7e。
-- ------------------------------------------------------------

-- 父:抖音核销配置字典(已存在则跳过,幂等)
INSERT INTO system_dict (code, name, remark, create_user, update_user, create_time, update_time, deleted)
SELECT 'DOUYIN_CONFIG', '抖音核销配置',
       '抖音生活服务团购核销配置(client_key/client_secret/account_id/poi_id)',
       '722ecd1e-e903-45b1-a839-c591c0af0d7e', '722ecd1e-e903-45b1-a839-c591c0af0d7e',
       CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 0
WHERE NOT EXISTS (SELECT 1 FROM system_dict WHERE code = 'DOUYIN_CONFIG' AND deleted = 0);

-- 子:四项配置(label 全大写,与 Java 常量 Constants.DOUYIN_* 对应;code 字段存「值」)
INSERT INTO system_dict_data (id, dict_id, code, label, sort, disabled, info, create_user, update_user, create_time, update_time, deleted)
SELECT gen_random_uuid()::text, d.id, '待填', 'CLIENT_KEY', 1, 0, '抖音应用 client_key',
       '722ecd1e-e903-45b1-a839-c591c0af0d7e', '722ecd1e-e903-45b1-a839-c591c0af0d7e',
       CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 0
FROM system_dict d WHERE d.code = 'DOUYIN_CONFIG' AND d.deleted = 0
  AND NOT EXISTS (SELECT 1 FROM system_dict_data WHERE dict_id = d.id AND label = 'CLIENT_KEY' AND deleted = 0);

INSERT INTO system_dict_data (id, dict_id, code, label, sort, disabled, info, create_user, update_user, create_time, update_time, deleted)
SELECT gen_random_uuid()::text, d.id, '待填', 'CLIENT_SECRET', 2, 0, '抖音应用 client_secret',
       '722ecd1e-e903-45b1-a839-c591c0af0d7e', '722ecd1e-e903-45b1-a839-c591c0af0d7e',
       CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 0
FROM system_dict d WHERE d.code = 'DOUYIN_CONFIG' AND d.deleted = 0
  AND NOT EXISTS (SELECT 1 FROM system_dict_data WHERE dict_id = d.id AND label = 'CLIENT_SECRET' AND deleted = 0);

INSERT INTO system_dict_data (id, dict_id, code, label, sort, disabled, info, create_user, update_user, create_time, update_time, deleted)
SELECT gen_random_uuid()::text, d.id, '待填', 'ACCOUNT_ID', 3, 0, '来客商户根账户ID',
       '722ecd1e-e903-45b1-a839-c591c0af0d7e', '722ecd1e-e903-45b1-a839-c591c0af0d7e',
       CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 0
FROM system_dict d WHERE d.code = 'DOUYIN_CONFIG' AND d.deleted = 0
  AND NOT EXISTS (SELECT 1 FROM system_dict_data WHERE dict_id = d.id AND label = 'ACCOUNT_ID' AND deleted = 0);

INSERT INTO system_dict_data (id, dict_id, code, label, sort, disabled, info, create_user, update_user, create_time, update_time, deleted)
SELECT gen_random_uuid()::text, d.id, '待填', 'POI_ID', 4, 0, '核销门店ID(单门店)',
       '722ecd1e-e903-45b1-a839-c591c0af0d7e', '722ecd1e-e903-45b1-a839-c591c0af0d7e',
       CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 0
FROM system_dict d WHERE d.code = 'DOUYIN_CONFIG' AND d.deleted = 0
  AND NOT EXISTS (SELECT 1 FROM system_dict_data WHERE dict_id = d.id AND label = 'POI_ID' AND deleted = 0);


-- ------------------------------------------------------------
-- 2026-06-25  v3.0.1  订单轨迹 —— 新增电车骑行轨迹表
-- 作者: rk
-- 说明: 仅电车(type=1,走 JT/T 808)骑行中产生实时轨迹;自行车(type=0)走 MQTT 无 GPS 上报,不产生。
--       写入点唯一:Jtt808Service.updateBikesInfo(0200 位置报文 for 循环内)。
--       订单关联经 Redis 缓存(ride:active:{bikeCode})获取,避免秒级上报高频查 member_rides。
--       关联字段说明:rides_id=骑行订单 member_rides.id;order_id=支付订单 member_rides.ordre_id→goodsorder.id(开锁时未绑定则为空)。
-- ------------------------------------------------------------

CREATE TABLE "member_rides_track" (
  "id"           varchar(64)   NOT NULL,
  "rides_id"     varchar(64),
  "order_id"     varchar(64),
  "bike_id"      varchar(64),
  "bike_code"    varchar(64),
  "longitude"    numeric(10,7),
  "latitude"     numeric(10,7),
  "report_time"  timestamp,
  "create_date"  timestamp     DEFAULT CURRENT_TIMESTAMP,
  "isdeleted"    smallint      DEFAULT 0,
  PRIMARY KEY ("id")
);
CREATE INDEX idx_mrt_rides_time ON "member_rides_track" ("rides_id", "report_time");
CREATE INDEX idx_mrt_order      ON "member_rides_track" ("order_id");
CREATE INDEX idx_mrt_bike       ON "member_rides_track" ("bike_id");
COMMENT ON TABLE  "member_rides_track" IS '电车骑行轨迹(JT/T 808 位置上报)';
COMMENT ON COLUMN "member_rides_track"."rides_id"    IS '骑行订单主键① member_rides.id';
COMMENT ON COLUMN "member_rides_track"."order_id"    IS '支付订单主键② member_rides.ordre_id → goodsorder.id(可能为空)';
COMMENT ON COLUMN "member_rides_track"."bike_id"     IS '车辆主键 bikes.id';
COMMENT ON COLUMN "member_rides_track"."bike_code"   IS '车辆编码 bikes.code';
COMMENT ON COLUMN "member_rides_track"."longitude"   IS '经度(高德 GCJ02,WGS84 转换后)';
COMMENT ON COLUMN "member_rides_track"."latitude"    IS '纬度(高德 GCJ02,WGS84 转换后)';
COMMENT ON COLUMN "member_rides_track"."report_time" IS '设备上报时间 deviceTime';
COMMENT ON COLUMN "member_rides_track"."isdeleted"   IS '是否已删除 0未删除 1已删除';


-- ------------------------------------------------------------
-- 2026-06-26  v3.0.1  小程序首页增加「抖音券兑换说明」字典项
-- 作者: rk
-- 说明: 归入既有 MINI_PROGRAMME 字典(与 STOP_SERVE_TIPS 同源);
--       小程序首页 /web/home/home 读取后下发,展示抖音券兑换规则说明。
--       label 全大写,与 Java 常量 Constants.DOUYIN_EXCHANGE_TIPS 对应;
--       code 字段存「值」(说明文案),执行前可先置默认文案。
-- 环境:PostgreSQL 13+ 内置 gen_random_uuid();低版本需先 CREATE EXTENSION pgcrypto。
-- ------------------------------------------------------------

INSERT INTO system_dict_data (id, dict_id, code, label, sort, disabled, info, create_user, update_user, create_time, update_time, deleted)
SELECT gen_random_uuid()::text, d.id,
       '抖音券兑换规则说明请咨询门店', 'DOUYIN_EXCHANGE_TIPS', 99, 0, '抖音券兑换说明(小程序首页展示)',
       '722ecd1e-e903-45b1-a839-c591c0af0d7e', '722ecd1e-e903-45b1-a839-c591c0af0d7e',
       CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 0
FROM system_dict d WHERE d.code = 'MINI_PROGRAMME' AND d.deleted = 0
  AND NOT EXISTS (SELECT 1 FROM system_dict_data WHERE dict_id = d.id AND label = 'DOUYIN_EXCHANGE_TIPS' AND deleted = 0);
