408 lines
27 KiB
SQL
408 lines
27 KiB
SQL
DROP SCHEMA IF EXISTS achievement CASCADE;
|
||
CREATE SCHEMA IF NOT EXISTS achievement;
|
||
|
||
DROP TABLE IF EXISTS achievement.ac_achievement CASCADE;
|
||
CREATE TABLE IF NOT EXISTS achievement.ac_achievement (
|
||
achievement_id VARCHAR(64) PRIMARY KEY,
|
||
achievement_code VARCHAR(64) UNIQUE NOT NULL,
|
||
achievement_name VARCHAR(128) NOT NULL,
|
||
achievement_desc TEXT,
|
||
achievement_category VARCHAR(32) NOT NULL DEFAULT 'SCORE',
|
||
trigger_event VARCHAR(32) NOT NULL DEFAULT 'GRADE_PUBLISHED',
|
||
trigger_rule_json JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||
badge_level VARCHAR(16) NOT NULL DEFAULT 'BRONZE',
|
||
badge_icon_url VARCHAR(512),
|
||
status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE',
|
||
tenant_id VARCHAR(64) NOT NULL,
|
||
created_by VARCHAR(64),
|
||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
CONSTRAINT chk_ac_achievement_category
|
||
CHECK (achievement_category IN ('SCORE', 'PROGRESS', 'TEACHING', 'ENGAGEMENT', 'MANUAL')),
|
||
CONSTRAINT chk_ac_achievement_trigger_event
|
||
CHECK (trigger_event IN ('GRADE_PUBLISHED', 'WRONG_QUESTION_MASTERED', 'TASK_COMPLETED', 'REVIEW_COMPLETED', 'MANUAL')),
|
||
CONSTRAINT chk_ac_achievement_badge_level
|
||
CHECK (badge_level IN ('BRONZE', 'SILVER', 'GOLD', 'PLATINUM')),
|
||
CONSTRAINT chk_ac_achievement_status
|
||
CHECK (status IN ('ACTIVE', 'DISABLED')),
|
||
CONSTRAINT chk_ac_achievement_trigger_rule_json
|
||
CHECK (jsonb_typeof(trigger_rule_json) = 'object'),
|
||
CONSTRAINT fk_ac_achievement_created_by
|
||
FOREIGN KEY (created_by) REFERENCES upms.tb_sys_user(user_id)
|
||
);
|
||
COMMENT ON TABLE achievement.ac_achievement IS '成就定义表';
|
||
COMMENT ON COLUMN achievement.ac_achievement.achievement_id IS '成就ID';
|
||
COMMENT ON COLUMN achievement.ac_achievement.achievement_code IS '成就编码';
|
||
COMMENT ON COLUMN achievement.ac_achievement.achievement_name IS '成就名称';
|
||
COMMENT ON COLUMN achievement.ac_achievement.achievement_desc IS '成就描述';
|
||
COMMENT ON COLUMN achievement.ac_achievement.achievement_category IS '成就类别(SCORE/PROGRESS/TEACHING/ENGAGEMENT/MANUAL)';
|
||
COMMENT ON COLUMN achievement.ac_achievement.trigger_event IS '触发事件(GRADE_PUBLISHED/WRONG_QUESTION_MASTERED/TASK_COMPLETED/REVIEW_COMPLETED/MANUAL)';
|
||
COMMENT ON COLUMN achievement.ac_achievement.trigger_rule_json IS '触发规则JSON(可配置成绩阈值、次数阈值等)';
|
||
COMMENT ON COLUMN achievement.ac_achievement.badge_level IS '徽章等级(BRONZE/SILVER/GOLD/PLATINUM)';
|
||
COMMENT ON COLUMN achievement.ac_achievement.badge_icon_url IS '徽章图标URL';
|
||
COMMENT ON COLUMN achievement.ac_achievement.status IS '状态(ACTIVE/DISABLED)';
|
||
COMMENT ON COLUMN achievement.ac_achievement.tenant_id IS '租户ID';
|
||
COMMENT ON COLUMN achievement.ac_achievement.created_by IS '创建人ID';
|
||
COMMENT ON COLUMN achievement.ac_achievement.created_at IS '创建时间';
|
||
COMMENT ON COLUMN achievement.ac_achievement.updated_at IS '更新时间';
|
||
|
||
DROP TABLE IF EXISTS achievement.ac_achievement_role_rel CASCADE;
|
||
CREATE TABLE IF NOT EXISTS achievement.ac_achievement_role_rel (
|
||
achievement_id VARCHAR(64) NOT NULL,
|
||
role_id VARCHAR(64) NOT NULL,
|
||
tenant_id VARCHAR(64) NOT NULL,
|
||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
PRIMARY KEY (achievement_id, role_id),
|
||
CONSTRAINT fk_ac_achievement_role_rel_achievement
|
||
FOREIGN KEY (achievement_id) REFERENCES achievement.ac_achievement(achievement_id) ON DELETE CASCADE,
|
||
CONSTRAINT fk_ac_achievement_role_rel_role
|
||
FOREIGN KEY (role_id) REFERENCES upms.tb_sys_role(role_id)
|
||
);
|
||
COMMENT ON TABLE achievement.ac_achievement_role_rel IS '成就-角色绑定表';
|
||
COMMENT ON COLUMN achievement.ac_achievement_role_rel.achievement_id IS '成就ID';
|
||
COMMENT ON COLUMN achievement.ac_achievement_role_rel.role_id IS '角色ID';
|
||
COMMENT ON COLUMN achievement.ac_achievement_role_rel.tenant_id IS '租户ID';
|
||
COMMENT ON COLUMN achievement.ac_achievement_role_rel.created_at IS '创建时间';
|
||
|
||
DROP TABLE IF EXISTS achievement.ac_user_achievement CASCADE;
|
||
CREATE TABLE IF NOT EXISTS achievement.ac_user_achievement (
|
||
user_achievement_id VARCHAR(64) PRIMARY KEY,
|
||
user_id VARCHAR(64) NOT NULL,
|
||
achievement_id VARCHAR(64) NOT NULL,
|
||
role_id VARCHAR(64) NOT NULL,
|
||
summary_id VARCHAR(64),
|
||
grading_task_id VARCHAR(64),
|
||
score_snapshot NUMERIC(8,2),
|
||
grade_level VARCHAR(8),
|
||
surpass_ratio NUMERIC(5,2),
|
||
used_seconds INTEGER,
|
||
award_source VARCHAR(32) NOT NULL DEFAULT 'RULE_ENGINE',
|
||
award_reason VARCHAR(256),
|
||
evidence_json JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||
achieved_count INTEGER NOT NULL DEFAULT 1,
|
||
first_achieved_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
last_achieved_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
tenant_id VARCHAR(64) NOT NULL,
|
||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
CONSTRAINT uq_ac_user_achievement_user_achievement_role
|
||
UNIQUE (user_id, achievement_id, role_id),
|
||
CONSTRAINT chk_ac_user_achievement_award_source
|
||
CHECK (award_source IN ('RULE_ENGINE', 'MANUAL', 'SYSTEM')),
|
||
CONSTRAINT chk_ac_user_achievement_evidence_json
|
||
CHECK (jsonb_typeof(evidence_json) = 'object'),
|
||
CONSTRAINT chk_ac_user_achievement_achieved_count
|
||
CHECK (achieved_count > 0),
|
||
CONSTRAINT fk_ac_user_achievement_user
|
||
FOREIGN KEY (user_id) REFERENCES upms.tb_sys_user(user_id),
|
||
CONSTRAINT fk_ac_user_achievement_role_binding
|
||
FOREIGN KEY (achievement_id, role_id) REFERENCES achievement.ac_achievement_role_rel(achievement_id, role_id),
|
||
CONSTRAINT fk_ac_user_achievement_summary
|
||
FOREIGN KEY (summary_id) REFERENCES question.gd_score_summary(summary_id),
|
||
CONSTRAINT fk_ac_user_achievement_task
|
||
FOREIGN KEY (grading_task_id) REFERENCES question.gd_grading_task(grading_task_id)
|
||
);
|
||
COMMENT ON TABLE achievement.ac_user_achievement IS '用户成就记录表';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement.user_achievement_id IS '用户成就记录ID';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement.user_id IS '用户ID';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement.achievement_id IS '成就ID';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement.role_id IS '获奖时角色ID';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement.summary_id IS '成绩汇总ID(来源于question.gd_score_summary)';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement.grading_task_id IS '批改任务ID(来源于question.gd_grading_task)';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement.score_snapshot IS '成绩快照分数';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement.grade_level IS '成绩快照等级';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement.surpass_ratio IS '成绩快照超越比例';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement.used_seconds IS '成绩快照耗时(秒)';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement.award_source IS '发放来源(RULE_ENGINE/MANUAL/SYSTEM)';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement.award_reason IS '发放原因';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement.evidence_json IS '发放证据JSON(可存规则命中明细)';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement.achieved_count IS '累计达成次数';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement.first_achieved_at IS '首次达成时间';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement.last_achieved_at IS '最近达成时间';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement.tenant_id IS '租户ID';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement.created_at IS '创建时间';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement.updated_at IS '更新时间';
|
||
DROP TABLE IF EXISTS achievement.ac_user_achievement_progress CASCADE;
|
||
CREATE TABLE IF NOT EXISTS achievement.ac_user_achievement_progress (
|
||
progress_id VARCHAR(64) PRIMARY KEY,
|
||
user_id VARCHAR(64) NOT NULL,
|
||
achievement_id VARCHAR(64) NOT NULL,
|
||
role_id VARCHAR(64) NOT NULL,
|
||
current_value NUMERIC(12,2) NOT NULL DEFAULT 0,
|
||
target_value NUMERIC(12,2) NOT NULL,
|
||
progress_rate NUMERIC(5,2) NOT NULL DEFAULT 0,
|
||
effort_index NUMERIC(6,2) NOT NULL DEFAULT 0,
|
||
improvement_rate NUMERIC(6,2) NOT NULL DEFAULT 0,
|
||
resilience_index NUMERIC(6,2) NOT NULL DEFAULT 0,
|
||
streak_days INTEGER NOT NULL DEFAULT 0,
|
||
last_checkin_date DATE,
|
||
progress_status VARCHAR(16) NOT NULL DEFAULT 'IN_PROGRESS',
|
||
progress_snapshot_json JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||
last_evaluated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
achieved_at TIMESTAMP,
|
||
tenant_id VARCHAR(64) NOT NULL,
|
||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
CONSTRAINT uq_ac_user_achievement_progress_user_achievement_role
|
||
UNIQUE (user_id, achievement_id, role_id),
|
||
CONSTRAINT chk_ac_user_achievement_progress_current
|
||
CHECK (current_value >= 0),
|
||
CONSTRAINT chk_ac_user_achievement_progress_target
|
||
CHECK (target_value > 0),
|
||
CONSTRAINT chk_ac_user_achievement_progress_rate
|
||
CHECK (progress_rate >= 0 AND progress_rate <= 100),
|
||
CONSTRAINT chk_ac_user_achievement_progress_effort_index
|
||
CHECK (effort_index >= 0 AND effort_index <= 100),
|
||
CONSTRAINT chk_ac_user_achievement_progress_improvement_rate
|
||
CHECK (improvement_rate >= -100 AND improvement_rate <= 1000),
|
||
CONSTRAINT chk_ac_user_achievement_progress_resilience_index
|
||
CHECK (resilience_index >= 0 AND resilience_index <= 100),
|
||
CONSTRAINT chk_ac_user_achievement_progress_streak_days
|
||
CHECK (streak_days >= 0),
|
||
CONSTRAINT chk_ac_user_achievement_progress_status
|
||
CHECK (progress_status IN ('IN_PROGRESS', 'ACHIEVED', 'EXPIRED')),
|
||
CONSTRAINT chk_ac_user_achievement_progress_snapshot_json
|
||
CHECK (jsonb_typeof(progress_snapshot_json) = 'object'),
|
||
CONSTRAINT chk_ac_user_achievement_progress_achieved_at
|
||
CHECK (
|
||
(progress_status = 'ACHIEVED' AND achieved_at IS NOT NULL)
|
||
OR (progress_status IN ('IN_PROGRESS', 'EXPIRED') AND achieved_at IS NULL)
|
||
),
|
||
CONSTRAINT fk_ac_user_achievement_progress_user
|
||
FOREIGN KEY (user_id) REFERENCES upms.tb_sys_user(user_id),
|
||
CONSTRAINT fk_ac_user_achievement_progress_role_binding
|
||
FOREIGN KEY (achievement_id, role_id) REFERENCES achievement.ac_achievement_role_rel(achievement_id, role_id)
|
||
);
|
||
COMMENT ON TABLE achievement.ac_user_achievement_progress IS '用户成就进度表(含未达成记录)';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_progress.progress_id IS '成就进度ID';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_progress.user_id IS '用户ID';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_progress.achievement_id IS '成就ID';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_progress.role_id IS '角色ID(学生/教师)';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_progress.current_value IS '当前进度值';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_progress.target_value IS '目标值';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_progress.progress_rate IS '完成率(0-100)';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_progress.effort_index IS '努力指数(0-100)';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_progress.improvement_rate IS '进步率(可为负)';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_progress.resilience_index IS '学习韧性指数(0-100)';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_progress.streak_days IS '连续打卡天数';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_progress.last_checkin_date IS '最近打卡日期';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_progress.progress_status IS '进度状态(IN_PROGRESS/ACHIEVED/EXPIRED)';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_progress.progress_snapshot_json IS '进度快照JSON(可记录最近一次评估明细)';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_progress.last_evaluated_at IS '最近评估时间';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_progress.achieved_at IS '达成时间';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_progress.tenant_id IS '租户ID';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_progress.created_at IS '创建时间';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_progress.updated_at IS '更新时间';
|
||
|
||
DROP TABLE IF EXISTS achievement.ac_user_achievement_daily_fact CASCADE;
|
||
CREATE TABLE IF NOT EXISTS achievement.ac_user_achievement_daily_fact (
|
||
stat_date DATE NOT NULL,
|
||
user_id VARCHAR(64) NOT NULL,
|
||
role_id VARCHAR(64) NOT NULL,
|
||
tenant_id VARCHAR(64) NOT NULL,
|
||
gained_achievement_count INTEGER NOT NULL DEFAULT 0,
|
||
active_achievement_count INTEGER NOT NULL DEFAULT 0,
|
||
progress_delta NUMERIC(10,4) NOT NULL DEFAULT 0,
|
||
effort_index NUMERIC(6,2) NOT NULL DEFAULT 0,
|
||
improvement_rate NUMERIC(6,2) NOT NULL DEFAULT 0,
|
||
resilience_index NUMERIC(6,2) NOT NULL DEFAULT 0,
|
||
streak_days INTEGER NOT NULL DEFAULT 0,
|
||
learning_minutes INTEGER NOT NULL DEFAULT 0,
|
||
checkin_status VARCHAR(16) NOT NULL DEFAULT 'NONE',
|
||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
PRIMARY KEY (stat_date, user_id, role_id),
|
||
CONSTRAINT chk_ac_user_achievement_daily_fact_gained
|
||
CHECK (gained_achievement_count >= 0),
|
||
CONSTRAINT chk_ac_user_achievement_daily_fact_active
|
||
CHECK (active_achievement_count >= 0),
|
||
CONSTRAINT chk_ac_user_achievement_daily_fact_effort
|
||
CHECK (effort_index >= 0 AND effort_index <= 100),
|
||
CONSTRAINT chk_ac_user_achievement_daily_fact_improvement
|
||
CHECK (improvement_rate >= -100 AND improvement_rate <= 1000),
|
||
CONSTRAINT chk_ac_user_achievement_daily_fact_resilience
|
||
CHECK (resilience_index >= 0 AND resilience_index <= 100),
|
||
CONSTRAINT chk_ac_user_achievement_daily_fact_streak
|
||
CHECK (streak_days >= 0),
|
||
CONSTRAINT chk_ac_user_achievement_daily_fact_learning_minutes
|
||
CHECK (learning_minutes >= 0),
|
||
CONSTRAINT chk_ac_user_achievement_daily_fact_checkin
|
||
CHECK (checkin_status IN ('NONE', 'CHECKED_IN', 'BROKEN')),
|
||
CONSTRAINT fk_ac_user_achievement_daily_fact_user
|
||
FOREIGN KEY (user_id) REFERENCES upms.tb_sys_user(user_id),
|
||
CONSTRAINT fk_ac_user_achievement_daily_fact_role
|
||
FOREIGN KEY (role_id) REFERENCES upms.tb_sys_role(role_id)
|
||
);
|
||
COMMENT ON TABLE achievement.ac_user_achievement_daily_fact IS '用户成就激励日事实表(激励数据即成就数据)';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_daily_fact.stat_date IS '统计日期';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_daily_fact.user_id IS '用户ID';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_daily_fact.role_id IS '角色ID';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_daily_fact.tenant_id IS '租户ID';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_daily_fact.gained_achievement_count IS '当日新增成就数';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_daily_fact.active_achievement_count IS '当日活跃成就数';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_daily_fact.progress_delta IS '当日进度变化量';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_daily_fact.effort_index IS '当日努力指数(0-100)';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_daily_fact.improvement_rate IS '当日进步率(可为负)';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_daily_fact.resilience_index IS '当日学习韧性指数(0-100)';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_daily_fact.streak_days IS '当日连续打卡天数';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_daily_fact.learning_minutes IS '当日学习分钟数';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_daily_fact.checkin_status IS '打卡状态';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_daily_fact.created_at IS '创建时间';
|
||
COMMENT ON COLUMN achievement.ac_user_achievement_daily_fact.updated_at IS '更新时间';
|
||
|
||
DROP TABLE IF EXISTS achievement.ac_achievement_rule_template CASCADE;
|
||
DROP TABLE IF EXISTS achievement.ac_achievement_metric_def CASCADE;
|
||
DROP TABLE IF EXISTS achievement.ac_achievement_event_dict CASCADE;
|
||
CREATE TABLE IF NOT EXISTS achievement.ac_achievement_event_dict (
|
||
event_code VARCHAR(64) PRIMARY KEY,
|
||
event_name VARCHAR(128) NOT NULL,
|
||
event_domain VARCHAR(32) NOT NULL DEFAULT 'LEARNING_LOOP',
|
||
event_desc TEXT,
|
||
payload_schema_json JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||
enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||
tenant_id VARCHAR(64) NOT NULL,
|
||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
CONSTRAINT chk_ac_achievement_event_dict_domain
|
||
CHECK (event_domain IN ('LEARNING_LOOP', 'GRADING', 'REVIEW', 'CHECKIN', 'SYSTEM')),
|
||
CONSTRAINT chk_ac_achievement_event_dict_payload_json
|
||
CHECK (jsonb_typeof(payload_schema_json) = 'object')
|
||
);
|
||
COMMENT ON TABLE achievement.ac_achievement_event_dict IS '成就事件字典表(通用触发事件定义)';
|
||
COMMENT ON COLUMN achievement.ac_achievement_event_dict.event_code IS '事件编码';
|
||
COMMENT ON COLUMN achievement.ac_achievement_event_dict.event_name IS '事件名称';
|
||
COMMENT ON COLUMN achievement.ac_achievement_event_dict.event_domain IS '事件域';
|
||
COMMENT ON COLUMN achievement.ac_achievement_event_dict.event_desc IS '事件描述';
|
||
COMMENT ON COLUMN achievement.ac_achievement_event_dict.payload_schema_json IS '事件载荷结构定义JSON';
|
||
COMMENT ON COLUMN achievement.ac_achievement_event_dict.enabled IS '是否启用';
|
||
COMMENT ON COLUMN achievement.ac_achievement_event_dict.tenant_id IS '租户ID';
|
||
COMMENT ON COLUMN achievement.ac_achievement_event_dict.created_at IS '创建时间';
|
||
COMMENT ON COLUMN achievement.ac_achievement_event_dict.updated_at IS '更新时间';
|
||
|
||
CREATE TABLE IF NOT EXISTS achievement.ac_achievement_metric_def (
|
||
metric_id VARCHAR(64) PRIMARY KEY,
|
||
metric_code VARCHAR(64) NOT NULL,
|
||
metric_name VARCHAR(128) NOT NULL,
|
||
metric_type VARCHAR(16) NOT NULL DEFAULT 'NUM',
|
||
metric_unit VARCHAR(32),
|
||
source_domain VARCHAR(32) NOT NULL DEFAULT 'SYSTEM',
|
||
agg_method VARCHAR(16) NOT NULL DEFAULT 'LATEST',
|
||
default_value_num NUMERIC(18,6),
|
||
default_value_text VARCHAR(255),
|
||
expr_json JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||
enabled BOOLEAN NOT NULL DEFAULT TRUE,
|
||
tenant_id VARCHAR(64) NOT NULL,
|
||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
CONSTRAINT uq_ac_achievement_metric_def_tenant_code
|
||
UNIQUE (tenant_id, metric_code),
|
||
CONSTRAINT chk_ac_achievement_metric_def_type
|
||
CHECK (metric_type IN ('NUM', 'BOOL', 'TEXT', 'RATE', 'COUNT')),
|
||
CONSTRAINT chk_ac_achievement_metric_def_source_domain
|
||
CHECK (source_domain IN ('COURSE', 'HOMEWORK', 'GRADING', 'REVIEW', 'RECOMMENDATION', 'ACHIEVEMENT', 'SYSTEM')),
|
||
CONSTRAINT chk_ac_achievement_metric_def_agg_method
|
||
CHECK (agg_method IN ('LATEST', 'SUM', 'AVG', 'MAX', 'MIN', 'COUNT')),
|
||
CONSTRAINT chk_ac_achievement_metric_def_expr_json
|
||
CHECK (jsonb_typeof(expr_json) = 'object')
|
||
);
|
||
COMMENT ON TABLE achievement.ac_achievement_metric_def IS '成就指标定义表(通用指标注册)';
|
||
COMMENT ON COLUMN achievement.ac_achievement_metric_def.metric_id IS '指标ID';
|
||
COMMENT ON COLUMN achievement.ac_achievement_metric_def.metric_code IS '指标编码';
|
||
COMMENT ON COLUMN achievement.ac_achievement_metric_def.metric_name IS '指标名称';
|
||
COMMENT ON COLUMN achievement.ac_achievement_metric_def.metric_type IS '指标类型';
|
||
COMMENT ON COLUMN achievement.ac_achievement_metric_def.metric_unit IS '指标单位';
|
||
COMMENT ON COLUMN achievement.ac_achievement_metric_def.source_domain IS '指标来源域';
|
||
COMMENT ON COLUMN achievement.ac_achievement_metric_def.agg_method IS '聚合方式';
|
||
COMMENT ON COLUMN achievement.ac_achievement_metric_def.default_value_num IS '默认数值';
|
||
COMMENT ON COLUMN achievement.ac_achievement_metric_def.default_value_text IS '默认文本值';
|
||
COMMENT ON COLUMN achievement.ac_achievement_metric_def.expr_json IS '计算表达式JSON';
|
||
COMMENT ON COLUMN achievement.ac_achievement_metric_def.enabled IS '是否启用';
|
||
COMMENT ON COLUMN achievement.ac_achievement_metric_def.tenant_id IS '租户ID';
|
||
COMMENT ON COLUMN achievement.ac_achievement_metric_def.created_at IS '创建时间';
|
||
COMMENT ON COLUMN achievement.ac_achievement_metric_def.updated_at IS '更新时间';
|
||
|
||
CREATE TABLE IF NOT EXISTS achievement.ac_achievement_rule_template (
|
||
template_id VARCHAR(64) PRIMARY KEY,
|
||
template_code VARCHAR(64) NOT NULL,
|
||
template_name VARCHAR(128) NOT NULL,
|
||
event_code VARCHAR(64) NOT NULL,
|
||
role_id VARCHAR(64),
|
||
achievement_category VARCHAR(32) NOT NULL DEFAULT 'PROGRESS',
|
||
rule_condition_json JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||
reward_action_json JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||
priority INTEGER NOT NULL DEFAULT 100,
|
||
template_status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE',
|
||
valid_from TIMESTAMP,
|
||
valid_to TIMESTAMP,
|
||
tenant_id VARCHAR(64) NOT NULL,
|
||
created_by VARCHAR(64),
|
||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
CONSTRAINT uq_ac_achievement_rule_template_tenant_code
|
||
UNIQUE (tenant_id, template_code),
|
||
CONSTRAINT chk_ac_achievement_rule_template_category
|
||
CHECK (achievement_category IN ('SCORE', 'PROGRESS', 'TEACHING', 'ENGAGEMENT', 'MANUAL')),
|
||
CONSTRAINT chk_ac_achievement_rule_template_status
|
||
CHECK (template_status IN ('ACTIVE', 'INACTIVE', 'ARCHIVED')),
|
||
CONSTRAINT chk_ac_achievement_rule_template_condition_json
|
||
CHECK (jsonb_typeof(rule_condition_json) = 'object'),
|
||
CONSTRAINT chk_ac_achievement_rule_template_reward_json
|
||
CHECK (jsonb_typeof(reward_action_json) = 'object'),
|
||
CONSTRAINT chk_ac_achievement_rule_template_valid
|
||
CHECK (valid_to IS NULL OR valid_from IS NULL OR valid_to >= valid_from),
|
||
CONSTRAINT fk_ac_achievement_rule_template_event
|
||
FOREIGN KEY (event_code) REFERENCES achievement.ac_achievement_event_dict(event_code),
|
||
CONSTRAINT fk_ac_achievement_rule_template_role
|
||
FOREIGN KEY (role_id) REFERENCES upms.tb_sys_role(role_id),
|
||
CONSTRAINT fk_ac_achievement_rule_template_created_by
|
||
FOREIGN KEY (created_by) REFERENCES upms.tb_sys_user(user_id)
|
||
);
|
||
COMMENT ON TABLE achievement.ac_achievement_rule_template IS '成就规则模板表(通用配置驱动)';
|
||
COMMENT ON COLUMN achievement.ac_achievement_rule_template.template_id IS '模板ID';
|
||
COMMENT ON COLUMN achievement.ac_achievement_rule_template.template_code IS '模板编码';
|
||
COMMENT ON COLUMN achievement.ac_achievement_rule_template.template_name IS '模板名称';
|
||
COMMENT ON COLUMN achievement.ac_achievement_rule_template.event_code IS '触发事件编码';
|
||
COMMENT ON COLUMN achievement.ac_achievement_rule_template.role_id IS '适用角色ID';
|
||
COMMENT ON COLUMN achievement.ac_achievement_rule_template.achievement_category IS '成就类别';
|
||
COMMENT ON COLUMN achievement.ac_achievement_rule_template.rule_condition_json IS '规则条件JSON';
|
||
COMMENT ON COLUMN achievement.ac_achievement_rule_template.reward_action_json IS '奖励动作JSON';
|
||
COMMENT ON COLUMN achievement.ac_achievement_rule_template.priority IS '优先级';
|
||
COMMENT ON COLUMN achievement.ac_achievement_rule_template.template_status IS '模板状态';
|
||
COMMENT ON COLUMN achievement.ac_achievement_rule_template.valid_from IS '生效开始时间';
|
||
COMMENT ON COLUMN achievement.ac_achievement_rule_template.valid_to IS '生效结束时间';
|
||
COMMENT ON COLUMN achievement.ac_achievement_rule_template.tenant_id IS '租户ID';
|
||
COMMENT ON COLUMN achievement.ac_achievement_rule_template.created_by IS '创建人';
|
||
COMMENT ON COLUMN achievement.ac_achievement_rule_template.created_at IS '创建时间';
|
||
COMMENT ON COLUMN achievement.ac_achievement_rule_template.updated_at IS '更新时间';
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_ac_achievement_tenant_status
|
||
ON achievement.ac_achievement(tenant_id, status, created_at DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_ac_achievement_role_rel_role
|
||
ON achievement.ac_achievement_role_rel(role_id, tenant_id);
|
||
CREATE INDEX IF NOT EXISTS idx_ac_user_achievement_user_role
|
||
ON achievement.ac_user_achievement(user_id, role_id, last_achieved_at DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_ac_user_achievement_tenant_time
|
||
ON achievement.ac_user_achievement(tenant_id, last_achieved_at DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_ac_user_achievement_summary
|
||
ON achievement.ac_user_achievement(summary_id);
|
||
CREATE INDEX IF NOT EXISTS idx_ac_user_achievement_task
|
||
ON achievement.ac_user_achievement(grading_task_id);
|
||
CREATE INDEX IF NOT EXISTS idx_ac_user_achievement_progress_user_status
|
||
ON achievement.ac_user_achievement_progress(user_id, role_id, progress_status, last_evaluated_at DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_ac_user_achievement_progress_tenant_status
|
||
ON achievement.ac_user_achievement_progress(tenant_id, progress_status, last_evaluated_at DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_ac_user_achievement_progress_achievement
|
||
ON achievement.ac_user_achievement_progress(achievement_id, role_id);
|
||
CREATE INDEX IF NOT EXISTS idx_ac_user_achievement_progress_streak
|
||
ON achievement.ac_user_achievement_progress(user_id, role_id, streak_days DESC, last_evaluated_at DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_ac_user_achievement_daily_fact_tenant_date
|
||
ON achievement.ac_user_achievement_daily_fact(tenant_id, stat_date DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_ac_user_achievement_daily_fact_user_date
|
||
ON achievement.ac_user_achievement_daily_fact(user_id, role_id, stat_date DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_ac_achievement_event_dict_tenant_enabled
|
||
ON achievement.ac_achievement_event_dict(tenant_id, enabled, event_domain);
|
||
CREATE INDEX IF NOT EXISTS idx_ac_achievement_metric_def_tenant_enabled
|
||
ON achievement.ac_achievement_metric_def(tenant_id, enabled, source_domain);
|
||
CREATE INDEX IF NOT EXISTS idx_ac_achievement_rule_template_tenant_event
|
||
ON achievement.ac_achievement_rule_template(tenant_id, event_code, template_status, priority);
|