|
|
CREATE DATABASE IF NOT EXISTS lifanghe_education DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
|
USE lifanghe_education;
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS roles (
|
|
|
role VARCHAR(40) PRIMARY KEY,
|
|
|
name VARCHAR(80) NOT NULL,
|
|
|
permissions JSON NOT NULL
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
|
id VARCHAR(40) PRIMARY KEY,
|
|
|
username VARCHAR(80) NOT NULL UNIQUE,
|
|
|
password_hash CHAR(64) NULL,
|
|
|
role VARCHAR(40) NOT NULL,
|
|
|
role_name VARCHAR(80) NOT NULL,
|
|
|
name VARCHAR(80) NOT NULL,
|
|
|
phone VARCHAR(30) NULL UNIQUE,
|
|
|
wechat_openid VARCHAR(80) NULL UNIQUE,
|
|
|
wechat_unionid VARCHAR(80) NULL UNIQUE,
|
|
|
wechat_nickname VARCHAR(80) NULL,
|
|
|
wechat_avatar VARCHAR(500) NULL,
|
|
|
login_provider VARCHAR(30) NOT NULL DEFAULT 'password',
|
|
|
phone_bound TINYINT(1) NOT NULL DEFAULT 1,
|
|
|
phone_bound_at VARCHAR(32) NULL,
|
|
|
wechat_bound_at VARCHAR(32) NULL,
|
|
|
status VARCHAR(20) NOT NULL DEFAULT 'active',
|
|
|
last_login_at VARCHAR(32) NULL,
|
|
|
inviter_code VARCHAR(40) NULL UNIQUE,
|
|
|
child_id VARCHAR(40) NULL,
|
|
|
child_name VARCHAR(80) NULL,
|
|
|
child_grade VARCHAR(40) NULL,
|
|
|
child_focus VARCHAR(80) NULL,
|
|
|
trial_booking_limit INT NOT NULL DEFAULT 1,
|
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
INDEX idx_users_role (role),
|
|
|
INDEX idx_users_phone (phone),
|
|
|
INDEX idx_users_login_provider (login_provider),
|
|
|
CONSTRAINT fk_users_role FOREIGN KEY (role) REFERENCES roles(role)
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS point_accounts (
|
|
|
user_id VARCHAR(40) PRIMARY KEY,
|
|
|
available INT NOT NULL DEFAULT 0,
|
|
|
pending INT NOT NULL DEFAULT 0,
|
|
|
frozen INT NOT NULL DEFAULT 0,
|
|
|
expiring INT NOT NULL DEFAULT 0,
|
|
|
CONSTRAINT fk_point_accounts_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS point_transactions (
|
|
|
id VARCHAR(40) PRIMARY KEY,
|
|
|
user_id VARCHAR(40) NOT NULL,
|
|
|
title VARCHAR(200) NOT NULL,
|
|
|
amount INT NOT NULL,
|
|
|
status VARCHAR(30) NOT NULL,
|
|
|
reference_type VARCHAR(40) NULL,
|
|
|
reference_id VARCHAR(60) NULL,
|
|
|
created_at VARCHAR(32) NOT NULL,
|
|
|
INDEX idx_point_transactions_user (user_id),
|
|
|
INDEX idx_point_transactions_reference (reference_type, reference_id),
|
|
|
CONSTRAINT fk_point_transactions_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS point_expiry_rule (
|
|
|
id INT PRIMARY KEY DEFAULT 1,
|
|
|
title VARCHAR(100) NOT NULL,
|
|
|
valid_days INT NOT NULL,
|
|
|
description VARCHAR(500) NOT NULL,
|
|
|
reminder VARCHAR(500) NOT NULL
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS point_expiry_schedules (
|
|
|
id VARCHAR(40) PRIMARY KEY,
|
|
|
user_id VARCHAR(40) NOT NULL,
|
|
|
points INT NOT NULL,
|
|
|
expire_at VARCHAR(32) NOT NULL,
|
|
|
source VARCHAR(200) NOT NULL,
|
|
|
INDEX idx_point_expiry_user (user_id),
|
|
|
CONSTRAINT fk_point_expiry_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS referral_rules (
|
|
|
event VARCHAR(40) PRIMARY KEY,
|
|
|
title VARCHAR(100) NOT NULL,
|
|
|
inviter INT NOT NULL,
|
|
|
invitee INT NOT NULL,
|
|
|
sort_order INT NOT NULL
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS referrals (
|
|
|
id VARCHAR(40) PRIMARY KEY,
|
|
|
inviter_id VARCHAR(40) NOT NULL,
|
|
|
invitee_id VARCHAR(40) NULL,
|
|
|
name VARCHAR(80) NOT NULL,
|
|
|
phone VARCHAR(30) NOT NULL,
|
|
|
child_grade VARCHAR(40) NOT NULL,
|
|
|
status VARCHAR(40) NOT NULL,
|
|
|
reward INT NOT NULL DEFAULT 0,
|
|
|
channel VARCHAR(80) NOT NULL,
|
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
INDEX idx_referrals_inviter (inviter_id),
|
|
|
CONSTRAINT fk_referrals_inviter FOREIGN KEY (inviter_id) REFERENCES users(id) ON DELETE CASCADE
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS courses (
|
|
|
id VARCHAR(40) PRIMARY KEY,
|
|
|
name VARCHAR(120) NOT NULL,
|
|
|
tags JSON NOT NULL,
|
|
|
next_time VARCHAR(32) NOT NULL,
|
|
|
points_back INT NOT NULL DEFAULT 0,
|
|
|
seats INT NOT NULL DEFAULT 0,
|
|
|
campus VARCHAR(80) NOT NULL,
|
|
|
teacher VARCHAR(80) NOT NULL,
|
|
|
trial_minutes INT NOT NULL DEFAULT 45,
|
|
|
status VARCHAR(30) NOT NULL DEFAULT 'active',
|
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS appointments (
|
|
|
id VARCHAR(40) PRIMARY KEY,
|
|
|
user_id VARCHAR(40) NOT NULL,
|
|
|
child_id VARCHAR(40) NULL,
|
|
|
course_id VARCHAR(40) NOT NULL,
|
|
|
status VARCHAR(30) NOT NULL,
|
|
|
created_at VARCHAR(40) NOT NULL,
|
|
|
INDEX idx_appointments_user (user_id),
|
|
|
INDEX idx_appointments_course (course_id),
|
|
|
CONSTRAINT fk_appointments_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
|
CONSTRAINT fk_appointments_course FOREIGN KEY (course_id) REFERENCES courses(id) ON DELETE CASCADE
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS rewards (
|
|
|
id VARCHAR(40) PRIMARY KEY,
|
|
|
name VARCHAR(120) NOT NULL,
|
|
|
cost INT NOT NULL,
|
|
|
type VARCHAR(60) NOT NULL,
|
|
|
stock INT NOT NULL DEFAULT 0,
|
|
|
description VARCHAR(500) NOT NULL DEFAULT ''
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS redemption_orders (
|
|
|
id VARCHAR(40) PRIMARY KEY,
|
|
|
user_id VARCHAR(40) NOT NULL,
|
|
|
item_id VARCHAR(40) NOT NULL,
|
|
|
status VARCHAR(40) NOT NULL,
|
|
|
cost_points INT NOT NULL DEFAULT 0,
|
|
|
voucher_code VARCHAR(60) NULL UNIQUE,
|
|
|
voucher_status VARCHAR(40) NOT NULL DEFAULT 'not_issued',
|
|
|
created_at VARCHAR(40) NOT NULL,
|
|
|
reviewed_by VARCHAR(40) NULL,
|
|
|
reviewed_at VARCHAR(40) NULL,
|
|
|
rejected_reason VARCHAR(255) NULL,
|
|
|
expire_at VARCHAR(40) NULL,
|
|
|
used_at VARCHAR(40) NULL,
|
|
|
used_by VARCHAR(40) NULL,
|
|
|
verify_note VARCHAR(255) NULL,
|
|
|
INDEX idx_redemption_user (user_id),
|
|
|
INDEX idx_redemption_status (status),
|
|
|
INDEX idx_redemption_voucher (voucher_code),
|
|
|
CONSTRAINT fk_redemption_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
|
CONSTRAINT fk_redemption_reward FOREIGN KEY (item_id) REFERENCES rewards(id) ON DELETE CASCADE
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS leads (
|
|
|
id VARCHAR(40) PRIMARY KEY,
|
|
|
referral_id VARCHAR(40) NULL,
|
|
|
invitee_id VARCHAR(40) NULL,
|
|
|
parent VARCHAR(80) NOT NULL,
|
|
|
source VARCHAR(100) NOT NULL,
|
|
|
stage VARCHAR(40) NOT NULL,
|
|
|
advisor VARCHAR(80) NOT NULL,
|
|
|
risk VARCHAR(40) NOT NULL DEFAULT '正常',
|
|
|
channel VARCHAR(80) NOT NULL,
|
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
|
INDEX idx_leads_referral (referral_id),
|
|
|
INDEX idx_leads_invitee (invitee_id)
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS channel_stats (
|
|
|
channel VARCHAR(80) PRIMARY KEY,
|
|
|
leads INT NOT NULL DEFAULT 0,
|
|
|
attended INT NOT NULL DEFAULT 0,
|
|
|
purchased INT NOT NULL DEFAULT 0
|
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
|
|
INSERT INTO roles (role, name, permissions) VALUES
|
|
|
('parent', '家长', JSON_ARRAY()),
|
|
|
('super_admin', '超级管理员', JSON_ARRAY('*:*:*')),
|
|
|
('campus_admin', '校区管理员', JSON_ARRAY('dashboard:overview:view', 'system:user:view', 'system:role:view', 'leads:referral:view', 'leads:referral:advance', 'points:account:view', 'points:rule:edit', 'points:redemption:view', 'points:redemption:review', 'points:voucher:verify', 'courses:trial:view', 'courses:trial:add', 'courses:trial:edit', 'statistics:channel:view')),
|
|
|
('advisor', '课程顾问', JSON_ARRAY('dashboard:overview:view', 'leads:referral:view', 'leads:referral:advance', 'courses:trial:view', 'points:account:view', 'points:redemption:view')),
|
|
|
('teacher', '老师', JSON_ARRAY('dashboard:overview:view', 'leads:referral:view', 'courses:trial:view')),
|
|
|
('finance', '财务', JSON_ARRAY('dashboard:overview:view', 'points:account:view', 'points:account:adjust', 'points:rule:edit', 'points:reward:edit', 'points:redemption:view', 'points:redemption:review', 'points:voucher:verify', 'statistics:channel:view'))
|
|
|
ON DUPLICATE KEY UPDATE name = VALUES(name), permissions = VALUES(permissions);
|
|
|
|
|
|
INSERT INTO users (
|
|
|
id, username, password_hash, role, role_name, name, phone,
|
|
|
wechat_openid, wechat_unionid, wechat_nickname, wechat_avatar,
|
|
|
login_provider, phone_bound, phone_bound_at, wechat_bound_at,
|
|
|
status, last_login_at, inviter_code, child_id, child_name, child_grade, child_focus
|
|
|
) VALUES
|
|
|
('admin_001', 'admin', '240be518fabd2724ddb6f04eeb1da5967448d7e831c08c8fa822809f74c720a9', 'super_admin', '超级管理员', '系统管理员', '13800009999', NULL, NULL, NULL, NULL, 'password', 1, NULL, NULL, 'active', NULL, NULL, NULL, NULL, NULL, NULL)
|
|
|
ON DUPLICATE KEY UPDATE username = VALUES(username), password_hash = VALUES(password_hash), role = VALUES(role), role_name = VALUES(role_name), name = VALUES(name), phone = VALUES(phone), login_provider = VALUES(login_provider), phone_bound = VALUES(phone_bound), status = VALUES(status);
|
|
|
|
|
|
INSERT INTO point_expiry_rule (id, title, valid_days, description, reminder) VALUES
|
|
|
(1, '积分有效期说明', 180, '积分自实际到账日起 180 天内有效,仅可兑换课程、测评和学习服务权益,不可提现或转赠。', '系统会在到期前 30 天进入“将过期”口径,运营可通过积分管理页提醒家长尽快兑换。')
|
|
|
ON DUPLICATE KEY UPDATE title = VALUES(title), valid_days = VALUES(valid_days), description = VALUES(description), reminder = VALUES(reminder);
|
|
|
|
|
|
INSERT INTO referral_rules (event, title, inviter, invitee, sort_order) VALUES
|
|
|
('registered', '新家长注册', 20, 20, 1),
|
|
|
('booked', '预约试听', 50, 50, 2),
|
|
|
('attended', '确认到课', 150, 100, 3),
|
|
|
('purchased', '报名正价课', 800, 500, 4)
|
|
|
ON DUPLICATE KEY UPDATE title = VALUES(title), inviter = VALUES(inviter), invitee = VALUES(invitee), sort_order = VALUES(sort_order);
|
|
|
|
|
|
INSERT INTO rewards (id, name, cost, type, stock, description) VALUES
|
|
|
('reward_001', '精品体验课 1 次', 800, '课程权益', 30, '适用于校区公开试听课,审核通过后生成课程券码,30 天内到店核销。'),
|
|
|
('reward_002', '学习规划咨询', 500, '服务权益', 50, '由课程顾问提供一次学习规划沟通,适合新生测评后使用。'),
|
|
|
('reward_003', '正价课抵扣券 100 元', 1000, '抵扣券', 20, '报名正价课程时抵扣 100 元,不可叠加现金活动使用。'),
|
|
|
('reward_004', '阶段测评报告', 300, '测评', 80, '兑换后安排一次阶段测评报告解读,帮助家长了解学习状态。')
|
|
|
ON DUPLICATE KEY UPDATE name = VALUES(name), cost = VALUES(cost), type = VALUES(type), stock = VALUES(stock), description = VALUES(description);
|