领养是信息服务:没有金额字段,文案里出现收费话术或短期内连续送养都会转人工, 送出时按 30/90 天建好回访任务。配种同样只做信息展示,且默认关闭。 代喂是这个模块里唯一动钱的部分,顺序是它的安全边界:先付款再进大厅,选定 之后才解密门牌与电话,每次上门按到达/喂食/离开留照片,主人确认或超时自动确认 后才结算。结算只走账本,(user, biz_type, biz_id) 唯一键让重复结算付不出第二次; 申诉会冻结自动确认,由客服裁定全付、部分付或全退。 提现按方案默认关闭:收益先只记账,等分账通道与资质到位再在管理端开闸。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
247 lines
12 KiB
SQL
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);
|