Files
kefu/im/backend/migrations/038_pet_feed_wallet.sql
T
Your NameandClaude Opus 5 46a60ffac3 宠物板块二到四期:领养、配种、上门代喂与收益账户
领养是信息服务:没有金额字段,文案里出现收费话术或短期内连续送养都会转人工,
送出时按 30/90 天建好回访任务。配种同样只做信息展示,且默认关闭。

代喂是这个模块里唯一动钱的部分,顺序是它的安全边界:先付款再进大厅,选定
之后才解密门牌与电话,每次上门按到达/喂食/离开留照片,主人确认或超时自动确认
后才结算。结算只走账本,(user, biz_type, biz_id) 唯一键让重复结算付不出第二次;
申诉会冻结自动确认,由客服裁定全付、部分付或全退。

提现按方案默认关闭:收益先只记账,等分账通道与资质到位再在管理端开闸。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 08:14:19 +08:00

247 lines
12 KiB
SQL

SET NAMES utf8mb4;
-- 服务地址。发布时只展示城市与街道,门牌与联系方式加密存储,
-- 选定喂养者之后才解密下发;任务结束后由清理任务抹掉明文。
CREATE TABLE IF NOT EXISTS pet_addresses (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
user_id BIGINT UNSIGNED NOT NULL,
city_code VARCHAR(20) NOT NULL DEFAULT '',
city_name VARCHAR(50) NOT NULL DEFAULT '',
area_text VARCHAR(100) NOT NULL DEFAULT '' COMMENT '公开展示的粗略位置',
detail_cipher VARBINARY(1024) NOT NULL COMMENT '门牌与门锁说明,AES-GCM',
contact_cipher VARBINARY(512) NOT NULL COMMENT '联系人与电话,AES-GCM',
latitude DECIMAL(10,7) NULL,
longitude DECIMAL(10,7) NULL,
purge_at DATETIME(3) NULL COMMENT '到期清除明文',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (id),
KEY idx_pet_addresses_user (user_id, id),
KEY idx_pet_addresses_purge (purge_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 喂养者资料。保证金是接单的前提,也是赔付的第一道来源。
CREATE TABLE IF NOT EXISTS pet_sitters (
user_id BIGINT UNSIGNED NOT NULL,
city_code VARCHAR(20) NOT NULL DEFAULT '',
city_name VARCHAR(50) NOT NULL DEFAULT '',
radius_m INT UNSIGNED NOT NULL DEFAULT 5000,
intro VARCHAR(500) NOT NULL DEFAULT '',
certs_json TEXT NULL,
deposit_cent INT UNSIGNED NOT NULL DEFAULT 0,
rating_total INT UNSIGNED NOT NULL DEFAULT 0,
rating_count INT UNSIGNED NOT NULL DEFAULT 0,
completed_count INT UNSIGNED NOT NULL DEFAULT 0,
cancelled_count INT UNSIGNED NOT NULL DEFAULT 0,
status TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '0 待审核 1 可接单 2 已驳回 3 已停用',
status_note VARCHAR(255) NOT NULL DEFAULT '',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (user_id),
KEY idx_sitters_city (status, city_code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 代喂任务。金额四段拆分,是为了对接分账与代征通道时不用再改结构。
CREATE TABLE IF NOT EXISTS pet_feed_tasks (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
owner_user_id BIGINT UNSIGNED NOT NULL,
pet_id BIGINT UNSIGNED NOT NULL,
address_id BIGINT UNSIGNED NOT NULL,
city_code VARCHAR(20) NOT NULL DEFAULT '',
start_date DATE NOT NULL,
end_date DATE NOT NULL,
visits_per_day TINYINT UNSIGNED NOT NULL DEFAULT 1,
min_minutes SMALLINT UNSIGNED NOT NULL DEFAULT 20,
price_cent INT UNSIGNED NOT NULL COMMENT '单次报酬',
gross_cent INT UNSIGNED NOT NULL COMMENT '主人支付总额',
platform_fee_cent INT UNSIGNED NOT NULL DEFAULT 0,
tax_cent INT UNSIGNED NOT NULL DEFAULT 0,
payout_cent INT UNSIGNED NOT NULL DEFAULT 0,
note VARCHAR(500) NOT NULL DEFAULT '',
status VARCHAR(20) NOT NULL DEFAULT 'CREATED' COMMENT 'CREATED/ESCROWED/ASSIGNED/SERVING/COMPLETED/SETTLED/CANCELLED/DISPUTED/ARBITRATED/REFUNDED',
sitter_user_id BIGINT UNSIGNED NULL,
order_id BIGINT UNSIGNED NULL,
conversation_id BIGINT UNSIGNED NULL,
insurance_no VARCHAR(60) NOT NULL DEFAULT '',
applications_count INT UNSIGNED NOT NULL DEFAULT 0,
completed_visits INT UNSIGNED NOT NULL DEFAULT 0,
total_visits INT UNSIGNED NOT NULL DEFAULT 0,
confirm_due_at DATETIME(3) NULL COMMENT '自动确认时间',
settled_at DATETIME(3) NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (id),
KEY idx_feed_tasks_hall (status, city_code, id),
KEY idx_feed_tasks_owner (owner_user_id, id),
KEY idx_feed_tasks_sitter (sitter_user_id, id),
KEY idx_feed_tasks_confirm (status, confirm_due_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS pet_feed_task_items (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
task_id BIGINT UNSIGNED NOT NULL,
kind VARCHAR(20) NOT NULL COMMENT 'feed/water/litter/walk/medicine',
amount_text VARCHAR(100) NOT NULL DEFAULT '',
PRIMARY KEY (id),
KEY idx_feed_items_task (task_id, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS pet_feed_applications (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
task_id BIGINT UNSIGNED NOT NULL,
sitter_user_id BIGINT UNSIGNED NOT NULL,
message VARCHAR(300) NOT NULL DEFAULT '',
status TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '0 待选定 1 已选定 2 未选中 3 已撤回',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
PRIMARY KEY (id),
UNIQUE KEY uk_feed_application (task_id, sitter_user_id),
KEY idx_feed_applications_sitter (sitter_user_id, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS pet_feed_visits (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
task_id BIGINT UNSIGNED NOT NULL,
visit_date DATE NOT NULL,
sequence TINYINT UNSIGNED NOT NULL DEFAULT 1,
started_at DATETIME(3) NULL,
finished_at DATETIME(3) NULL,
status TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '0 待上门 1 进行中 2 已完成 3 已跳过',
abnormal TINYINT(1) NOT NULL DEFAULT 0,
abnormal_note VARCHAR(255) NOT NULL DEFAULT '',
PRIMARY KEY (id),
UNIQUE KEY uk_feed_visit (task_id, visit_date, sequence),
KEY idx_feed_visits_task (task_id, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 打卡是履约的唯一证据。distance_m 与 verdict 让"是否真的到过"可复核。
CREATE TABLE IF NOT EXISTS pet_feed_checkins (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
visit_id BIGINT UNSIGNED NOT NULL,
task_id BIGINT UNSIGNED NOT NULL,
step VARCHAR(20) NOT NULL COMMENT 'arrive/feed/water/litter/leave',
media_url VARCHAR(500) NOT NULL,
latitude DECIMAL(10,7) NULL,
longitude DECIMAL(10,7) NULL,
distance_m INT UNSIGNED NULL,
captured_at DATETIME(3) NOT NULL,
verdict VARCHAR(20) NOT NULL DEFAULT 'ok' COMMENT 'ok/far/stale/duplicate',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
PRIMARY KEY (id),
UNIQUE KEY uk_checkin_step (visit_id, step),
KEY idx_checkins_task (task_id, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS pet_feed_reviews (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
task_id BIGINT UNSIGNED NOT NULL,
from_user_id BIGINT UNSIGNED NOT NULL,
to_user_id BIGINT UNSIGNED NOT NULL,
punctual TINYINT UNSIGNED NOT NULL DEFAULT 5,
accurate TINYINT UNSIGNED NOT NULL DEFAULT 5,
communication TINYINT UNSIGNED NOT NULL DEFAULT 5,
content VARCHAR(500) NOT NULL DEFAULT '',
visible_at DATETIME(3) NULL COMMENT '双盲:双方都提交或到期后才公开',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
PRIMARY KEY (id),
UNIQUE KEY uk_feed_review (task_id, from_user_id),
KEY idx_feed_reviews_target (to_user_id, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS pet_feed_disputes (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
task_id BIGINT UNSIGNED NOT NULL,
raised_by BIGINT UNSIGNED NOT NULL,
reason VARCHAR(500) NOT NULL,
evidence_json TEXT NULL,
status TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '0 待处理 1 已裁定',
verdict VARCHAR(20) NOT NULL DEFAULT '' COMMENT 'payout/refund/split',
refund_cent INT UNSIGNED NOT NULL DEFAULT 0,
payout_cent INT UNSIGNED NOT NULL DEFAULT 0,
handled_by BIGINT UNSIGNED NULL,
handled_note VARCHAR(500) NOT NULL DEFAULT '',
handled_at DATETIME(3) NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
PRIMARY KEY (id),
UNIQUE KEY uk_dispute_task (task_id),
KEY idx_disputes_status (status, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 收益账户。与"充值消费"严格分离:这里的余额只能提现,不能反向变成消费额度。
CREATE TABLE IF NOT EXISTS wallet_accounts (
user_id BIGINT UNSIGNED NOT NULL,
available_cent BIGINT NOT NULL DEFAULT 0,
frozen_cent BIGINT NOT NULL DEFAULT 0,
total_income_cent BIGINT NOT NULL DEFAULT 0,
total_withdraw_cent BIGINT NOT NULL DEFAULT 0,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 账本:任何余额变动都必须有一条流水,任何时刻余额等于流水累加。
CREATE TABLE IF NOT EXISTS wallet_transactions (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
user_id BIGINT UNSIGNED NOT NULL,
biz_type VARCHAR(30) NOT NULL COMMENT 'feed_settle/withdraw/withdraw_refund/adjust',
biz_id BIGINT UNSIGNED NOT NULL DEFAULT 0,
direction TINYINT NOT NULL COMMENT '1 入账 -1 出账',
amount_cent BIGINT NOT NULL,
balance_after_cent BIGINT NOT NULL,
memo VARCHAR(255) NOT NULL DEFAULT '',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
PRIMARY KEY (id),
UNIQUE KEY uk_wallet_biz (user_id, biz_type, biz_id),
KEY idx_wallet_tx_user (user_id, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS payout_accounts (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
user_id BIGINT UNSIGNED NOT NULL,
kind VARCHAR(20) NOT NULL COMMENT 'alipay/bank',
account_cipher VARBINARY(512) NOT NULL,
account_mask VARCHAR(60) NOT NULL DEFAULT '',
holder_name VARCHAR(50) NOT NULL,
bank_name VARCHAR(100) NOT NULL DEFAULT '',
status TINYINT UNSIGNED NOT NULL DEFAULT 1,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
PRIMARY KEY (id),
KEY idx_payout_user (user_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS withdrawals (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
user_id BIGINT UNSIGNED NOT NULL,
account_id BIGINT UNSIGNED NOT NULL,
amount_cent BIGINT NOT NULL COMMENT '申请金额',
fee_cent BIGINT NOT NULL DEFAULT 0,
tax_cent BIGINT NOT NULL DEFAULT 0,
payout_cent BIGINT NOT NULL DEFAULT 0 COMMENT '实际到账',
status VARCHAR(20) NOT NULL DEFAULT 'PENDING' COMMENT 'PENDING/APPROVED/PAID/REJECTED/FAILED',
provider VARCHAR(30) NOT NULL DEFAULT '',
provider_order_no VARCHAR(80) NOT NULL DEFAULT '',
failed_reason VARCHAR(255) NOT NULL DEFAULT '',
handled_by BIGINT UNSIGNED NULL,
handled_at DATETIME(3) NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
PRIMARY KEY (id),
KEY idx_withdrawals_status (status, id),
KEY idx_withdrawals_user (user_id, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO system_configs(config_key,config_value,value_type,description) VALUES
('pet.feed_enabled','true','boolean','是否开放上门代喂'),
('pet.feed_platform_fee_percent','15','integer','平台服务费比例(百分比)'),
('pet.feed_min_price_cent','2000','integer','单次代喂最低报酬(分)'),
('pet.feed_max_price_cent','50000','integer','单次代喂最高报酬(分)'),
('pet.feed_max_days','14','integer','单个任务最长服务天数'),
('pet.feed_confirm_hours','24','integer','服务完成后自动确认的小时数'),
('pet.feed_checkin_max_distance_m','300','integer','打卡定位与地址的最大偏差(米)'),
('pet.feed_checkin_max_delay_min','5','integer','照片拍摄与提交的最大间隔(分钟)'),
('pet.sitter_deposit_cent','20000','integer','喂养者保证金(分)'),
('pet.withdraw_enabled','false','boolean','是否开放提现;接入分账/代征通道并完成对账后再开启'),
('pet.withdraw_min_cent','1000','integer','单笔提现最低金额(分)'),
('pet.withdraw_daily_limit_cent','500000','integer','单日提现上限(分)'),
('pet.withdraw_fee_percent','0','integer','提现手续费比例(百分比)')
ON DUPLICATE KEY UPDATE description=VALUES(description);