Files
K12Study/init/pg/achievement/10_create_achievement_tables.sql
2026-04-16 11:30:30 +08:00

408 lines
27 KiB
SQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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);