-- =========================================================
-- 测试管理模块数据库初始化脚本（_time 字段版本）
-- 适用数据库：PostgreSQL
-- 说明：
-- 1. 本脚本与当前后端代码字段保持一致
-- 2. 所有时间字段统一使用 *_time 后缀
-- 3. 主表包含 is_delete 逻辑删除字段
-- =========================================================


-- =========================================================
-- 一、项目相关
-- =========================================================

-- -------------------------
-- 1. 项目表
-- -------------------------
CREATE TABLE IF NOT EXISTS project (
    id BIGSERIAL PRIMARY KEY,
    key VARCHAR(32) UNIQUE NOT NULL,
    name VARCHAR(128) NOT NULL,
    description TEXT,
    department VARCHAR(64),
    status SMALLINT DEFAULT 1,
    config JSONB DEFAULT '{}'::jsonb,
    created_by BIGINT,
    is_delete INTEGER DEFAULT 0,
    created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

COMMENT ON TABLE project IS '项目表';
COMMENT ON COLUMN project.id IS '主键ID';
COMMENT ON COLUMN project.key IS '项目唯一标识，如 XP2024';
COMMENT ON COLUMN project.name IS '项目名称';
COMMENT ON COLUMN project.description IS '项目描述';
COMMENT ON COLUMN project.department IS '所属部门';
COMMENT ON COLUMN project.status IS '项目状态：1启用 0禁用';
COMMENT ON COLUMN project.config IS '扩展配置，JSON格式';
COMMENT ON COLUMN project.created_by IS '创建人';
COMMENT ON COLUMN project.is_delete IS '逻辑删除标记：0未删除 1已删除';
COMMENT ON COLUMN project.created_time IS '创建时间';
COMMENT ON COLUMN project.updated_time IS '更新时间';

CREATE INDEX IF NOT EXISTS idx_project_status ON project(status);
CREATE INDEX IF NOT EXISTS idx_project_is_delete ON project(is_delete);


-- -------------------------
-- 2. 项目成员表
-- -------------------------
CREATE TABLE IF NOT EXISTS project_member (
    id BIGSERIAL PRIMARY KEY,
    project_id BIGINT NOT NULL REFERENCES project(id) ON DELETE CASCADE,
    user_id BIGINT NOT NULL,
    role SMALLINT NOT NULL,
    joined_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

COMMENT ON TABLE project_member IS '项目成员表';
COMMENT ON COLUMN project_member.id IS '主键ID';
COMMENT ON COLUMN project_member.project_id IS '项目ID';
COMMENT ON COLUMN project_member.user_id IS '用户ID';
COMMENT ON COLUMN project_member.role IS '角色：1测试经理 2测试工程师 3开发工程师 4访客';
COMMENT ON COLUMN project_member.joined_time IS '加入时间';

CREATE UNIQUE INDEX IF NOT EXISTS uk_project_member ON project_member(project_id, user_id);
CREATE INDEX IF NOT EXISTS idx_member_user ON project_member(user_id);
CREATE INDEX IF NOT EXISTS idx_member_project_id ON project_member(project_id);


-- -------------------------
-- 3. 环境配置表
-- -------------------------
CREATE TABLE IF NOT EXISTS environment (
    id BIGSERIAL PRIMARY KEY,
    project_id BIGINT NOT NULL REFERENCES project(id) ON DELETE CASCADE,
    name VARCHAR(64) NOT NULL,
    variables JSONB NOT NULL,
    is_encrypted BOOLEAN DEFAULT FALSE,
    is_delete INTEGER DEFAULT 0,
    created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

COMMENT ON TABLE environment IS '环境配置表';
COMMENT ON COLUMN environment.id IS '主键ID';
COMMENT ON COLUMN environment.project_id IS '项目ID';
COMMENT ON COLUMN environment.name IS '环境名称，如 dev/test/staging/prod';
COMMENT ON COLUMN environment.variables IS '环境变量配置，JSON格式';
COMMENT ON COLUMN environment.is_encrypted IS '敏感信息是否已加密';
COMMENT ON COLUMN environment.is_delete IS '逻辑删除标记：0未删除 1已删除';
COMMENT ON COLUMN environment.created_time IS '创建时间';

CREATE INDEX IF NOT EXISTS idx_environment_project_id ON environment(project_id);
CREATE INDEX IF NOT EXISTS idx_environment_is_delete ON environment(is_delete);


-- -------------------------
-- 4. 产品表
-- -------------------------
CREATE TABLE IF NOT EXISTS product (
    id BIGSERIAL PRIMARY KEY,
    name VARCHAR(128) NOT NULL,
    code VARCHAR(64) UNIQUE NOT NULL,
    description TEXT,
    status SMALLINT DEFAULT 1,
    is_delete INTEGER DEFAULT 0,
    created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

COMMENT ON TABLE product IS '产品表';
COMMENT ON COLUMN product.id IS '主键ID';
COMMENT ON COLUMN product.name IS '产品名称';
COMMENT ON COLUMN product.code IS '产品编码';
COMMENT ON COLUMN product.description IS '产品描述';
COMMENT ON COLUMN product.status IS '产品状态：1启用 0禁用';
COMMENT ON COLUMN product.is_delete IS '逻辑删除标记：0未删除 1已删除';
COMMENT ON COLUMN product.created_time IS '创建时间';
COMMENT ON COLUMN product.updated_time IS '更新时间';

CREATE INDEX IF NOT EXISTS idx_product_status ON product(status);
CREATE INDEX IF NOT EXISTS idx_product_is_delete ON product(is_delete);


-- =========================================================
-- 二、用例相关
-- =========================================================

-- -------------------------
-- 4. 模块表
-- -------------------------
CREATE TABLE IF NOT EXISTS module (
    id BIGSERIAL PRIMARY KEY,
    project_id BIGINT NOT NULL REFERENCES project(id) ON DELETE CASCADE,
    parent_id BIGINT DEFAULT 0,
    name VARCHAR(128) NOT NULL,
    sort_order INTEGER DEFAULT 0,
    path VARCHAR(512),
    is_delete INTEGER DEFAULT 0
);

COMMENT ON TABLE module IS '模块树表，支持多层级模块结构';
COMMENT ON COLUMN module.id IS '主键ID';
COMMENT ON COLUMN module.project_id IS '项目ID';
COMMENT ON COLUMN module.parent_id IS '父模块ID，0表示根节点';
COMMENT ON COLUMN module.name IS '模块名称';
COMMENT ON COLUMN module.sort_order IS '排序值';
COMMENT ON COLUMN module.path IS '模块路径，如 /1/23/45';
COMMENT ON COLUMN module.is_delete IS '逻辑删除标记：0未删除 1已删除';

CREATE INDEX IF NOT EXISTS idx_module_project ON module(project_id);
CREATE INDEX IF NOT EXISTS idx_module_parent_id ON module(parent_id);
CREATE INDEX IF NOT EXISTS idx_module_is_delete ON module(is_delete);


-- -------------------------
-- 5. 用例表
-- -------------------------
CREATE TABLE IF NOT EXISTS test_case (
    id BIGSERIAL PRIMARY KEY,
    project_id BIGINT NOT NULL REFERENCES project(id) ON DELETE CASCADE,
    module_id BIGINT REFERENCES module(id) ON DELETE SET NULL,
    case_key VARCHAR(64) NOT NULL,
    title VARCHAR(255) NOT NULL,
    preconditions TEXT,
    steps JSONB NOT NULL DEFAULT '[]'::jsonb,
    priority SMALLINT DEFAULT 2,
    case_type SMALLINT DEFAULT 1,
    tags VARCHAR(64)[] DEFAULT '{}'::varchar[],
    status SMALLINT DEFAULT 1,
    created_by BIGINT,
    is_delete INTEGER DEFAULT 0,
    created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

COMMENT ON TABLE test_case IS '测试用例表';
COMMENT ON COLUMN test_case.id IS '主键ID';
COMMENT ON COLUMN test_case.project_id IS '项目ID';
COMMENT ON COLUMN test_case.module_id IS '所属模块ID';
COMMENT ON COLUMN test_case.case_key IS '项目内唯一编号，如 TC-001';
COMMENT ON COLUMN test_case.title IS '用例标题';
COMMENT ON COLUMN test_case.preconditions IS '前置条件';
COMMENT ON COLUMN test_case.steps IS '测试步骤，JSON数组';
COMMENT ON COLUMN test_case.priority IS '优先级：0P0 1P1 2P2 3P3';
COMMENT ON COLUMN test_case.case_type IS '用例类型：1功能 2性能 3安全 4接口';
COMMENT ON COLUMN test_case.tags IS '标签数组';
COMMENT ON COLUMN test_case.status IS '状态：1正常 2已废弃 3评审中';
COMMENT ON COLUMN test_case.created_by IS '创建人';
COMMENT ON COLUMN test_case.is_delete IS '逻辑删除标记：0未删除 1已删除';
COMMENT ON COLUMN test_case.created_time IS '创建时间';
COMMENT ON COLUMN test_case.updated_time IS '更新时间';

CREATE INDEX IF NOT EXISTS idx_case_project ON test_case(project_id);
CREATE INDEX IF NOT EXISTS idx_case_module ON test_case(module_id);
CREATE INDEX IF NOT EXISTS idx_case_priority ON test_case(priority);
CREATE INDEX IF NOT EXISTS idx_case_status ON test_case(status);
CREATE INDEX IF NOT EXISTS idx_case_is_delete ON test_case(is_delete);
CREATE UNIQUE INDEX IF NOT EXISTS uk_test_case_project_case_key ON test_case(project_id, case_key);


-- -------------------------
-- 6. 用例快照表
-- -------------------------
CREATE TABLE IF NOT EXISTS case_snapshot (
    id BIGSERIAL PRIMARY KEY,
    case_id BIGINT NOT NULL REFERENCES test_case(id) ON DELETE CASCADE,
    version INTEGER NOT NULL,
    snapshot JSONB NOT NULL,
    created_by BIGINT,
    created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

COMMENT ON TABLE case_snapshot IS '用例版本快照表';
COMMENT ON COLUMN case_snapshot.id IS '主键ID';
COMMENT ON COLUMN case_snapshot.case_id IS '用例ID';
COMMENT ON COLUMN case_snapshot.version IS '版本号';
COMMENT ON COLUMN case_snapshot.snapshot IS '完整快照内容';
COMMENT ON COLUMN case_snapshot.created_by IS '创建人';
COMMENT ON COLUMN case_snapshot.created_time IS '创建时间';

CREATE INDEX IF NOT EXISTS idx_case_snapshot_case_id ON case_snapshot(case_id);
CREATE UNIQUE INDEX IF NOT EXISTS uk_case_snapshot_case_version ON case_snapshot(case_id, version);


-- -------------------------
-- 7. 用例评审表
-- -------------------------
CREATE TABLE IF NOT EXISTS case_review (
    id BIGSERIAL PRIMARY KEY,
    case_id BIGINT NOT NULL REFERENCES test_case(id) ON DELETE CASCADE,
    reviewer_id BIGINT NOT NULL,
    status SMALLINT DEFAULT 0,
    comments TEXT,
    diff_content TEXT,
    created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    reviewed_time TIMESTAMP
);

COMMENT ON TABLE case_review IS '用例评审表';
COMMENT ON COLUMN case_review.id IS '主键ID';
COMMENT ON COLUMN case_review.case_id IS '用例ID';
COMMENT ON COLUMN case_review.reviewer_id IS '评审人ID';
COMMENT ON COLUMN case_review.status IS '评审状态：0待评审 1通过 2驳回 3建议修改';
COMMENT ON COLUMN case_review.comments IS '评审意见';
COMMENT ON COLUMN case_review.diff_content IS '变更差异内容，通常为JSON diff字符串';
COMMENT ON COLUMN case_review.created_time IS '创建时间';
COMMENT ON COLUMN case_review.reviewed_time IS '评审时间';

CREATE INDEX IF NOT EXISTS idx_case_review_case_id ON case_review(case_id);
CREATE INDEX IF NOT EXISTS idx_case_review_reviewer_id ON case_review(reviewer_id);


-- =========================================================
-- 三、测试计划相关
-- =========================================================

-- -------------------------
-- 8. 测试计划表
-- -------------------------
CREATE TABLE IF NOT EXISTS test_plan (
    id BIGSERIAL PRIMARY KEY,
    project_id BIGINT NOT NULL REFERENCES project(id) ON DELETE CASCADE,
    name VARCHAR(128) NOT NULL,
    version VARCHAR(32),
    description TEXT,
    start_date DATE,
    end_date DATE,
    owner_id BIGINT,
    status SMALLINT DEFAULT 0,
    environment_id BIGINT REFERENCES environment(id),
    is_delete INTEGER DEFAULT 0,
    created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

COMMENT ON TABLE test_plan IS '测试计划表';
COMMENT ON COLUMN test_plan.id IS '主键ID';
COMMENT ON COLUMN test_plan.project_id IS '项目ID';
COMMENT ON COLUMN test_plan.name IS '计划名称';
COMMENT ON COLUMN test_plan.version IS '测试版本号';
COMMENT ON COLUMN test_plan.description IS '计划描述';
COMMENT ON COLUMN test_plan.start_date IS '开始日期';
COMMENT ON COLUMN test_plan.end_date IS '结束日期';
COMMENT ON COLUMN test_plan.owner_id IS '负责人ID';
COMMENT ON COLUMN test_plan.status IS '计划状态：0草稿 1进行中 2已完成 3已归档';
COMMENT ON COLUMN test_plan.environment_id IS '关联环境ID';
COMMENT ON COLUMN test_plan.is_delete IS '逻辑删除标记：0未删除 1已删除';
COMMENT ON COLUMN test_plan.created_time IS '创建时间';
COMMENT ON COLUMN test_plan.updated_time IS '更新时间';

CREATE INDEX IF NOT EXISTS idx_test_plan_project_id ON test_plan(project_id);
CREATE INDEX IF NOT EXISTS idx_test_plan_status ON test_plan(status);
CREATE INDEX IF NOT EXISTS idx_test_plan_is_delete ON test_plan(is_delete);


-- -------------------------
-- 9. 计划用例表
-- -------------------------
CREATE TABLE IF NOT EXISTS plan_case (
    id BIGSERIAL PRIMARY KEY,
    plan_id BIGINT NOT NULL REFERENCES test_plan(id) ON DELETE CASCADE,
    case_id BIGINT NOT NULL REFERENCES test_case(id),
    assignee_id BIGINT,
    round_no INTEGER DEFAULT 1,
    status SMALLINT DEFAULT 0,
    actual_result TEXT,
    defect_links JSONB DEFAULT '[]'::jsonb,
    attachments JSONB DEFAULT '[]'::jsonb,
    executed_time TIMESTAMP,
    execution_duration INTEGER
);

COMMENT ON TABLE plan_case IS '计划与用例关联表，同时存储执行结果';
COMMENT ON COLUMN plan_case.id IS '主键ID';
COMMENT ON COLUMN plan_case.plan_id IS '计划ID';
COMMENT ON COLUMN plan_case.case_id IS '用例ID';
COMMENT ON COLUMN plan_case.assignee_id IS '执行人ID';
COMMENT ON COLUMN plan_case.round_no IS '执行轮次';
COMMENT ON COLUMN plan_case.status IS '执行状态：0未开始 1通过 2失败 3阻塞';
COMMENT ON COLUMN plan_case.actual_result IS '实际执行结果';
COMMENT ON COLUMN plan_case.defect_links IS '缺陷链接数组';
COMMENT ON COLUMN plan_case.attachments IS '附件数组';
COMMENT ON COLUMN plan_case.executed_time IS '执行时间';
COMMENT ON COLUMN plan_case.execution_duration IS '执行耗时，单位秒';

CREATE UNIQUE INDEX IF NOT EXISTS uk_plan_case_round ON plan_case(plan_id, case_id, round_no);
CREATE INDEX IF NOT EXISTS idx_plan_case_plan ON plan_case(plan_id);
CREATE INDEX IF NOT EXISTS idx_plan_case_assignee ON plan_case(assignee_id);
CREATE INDEX IF NOT EXISTS idx_plan_case_status ON plan_case(status);


-- -------------------------
-- 10. 测试轮次表
-- -------------------------
CREATE TABLE IF NOT EXISTS test_round (
    id BIGSERIAL PRIMARY KEY,
    plan_id BIGINT NOT NULL REFERENCES test_plan(id) ON DELETE CASCADE,
    round_no INTEGER NOT NULL,
    name VARCHAR(64),
    start_date DATE,
    end_date DATE
);

COMMENT ON TABLE test_round IS '测试轮次表';
COMMENT ON COLUMN test_round.id IS '主键ID';
COMMENT ON COLUMN test_round.plan_id IS '计划ID';
COMMENT ON COLUMN test_round.round_no IS '轮次编号';
COMMENT ON COLUMN test_round.name IS '轮次名称';
COMMENT ON COLUMN test_round.start_date IS '开始日期';
COMMENT ON COLUMN test_round.end_date IS '结束日期';

CREATE UNIQUE INDEX IF NOT EXISTS uk_test_round_plan_round_no ON test_round(plan_id, round_no);
CREATE INDEX IF NOT EXISTS idx_test_round_plan_id ON test_round(plan_id);


-- =========================================================
-- 四、报告相关
-- =========================================================

-- -------------------------
-- 11. 报告表
-- -------------------------
CREATE TABLE IF NOT EXISTS report (
    id BIGSERIAL PRIMARY KEY,
    plan_id BIGINT NOT NULL REFERENCES test_plan(id) ON DELETE CASCADE,
    name VARCHAR(128) NOT NULL,
    report_type SMALLINT DEFAULT 1,
    summary JSONB,
    content TEXT,
    file_url VARCHAR(512),
    generated_by BIGINT,
    generated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

COMMENT ON TABLE report IS '测试报告表';
COMMENT ON COLUMN report.id IS '主键ID';
COMMENT ON COLUMN report.plan_id IS '计划ID';
COMMENT ON COLUMN report.name IS '报告名称';
COMMENT ON COLUMN report.report_type IS '报告类型：1实时报告 2归档报告';
COMMENT ON COLUMN report.summary IS '报告统计摘要，JSON格式';
COMMENT ON COLUMN report.content IS '报告HTML内容';
COMMENT ON COLUMN report.file_url IS '导出文件地址';
COMMENT ON COLUMN report.generated_by IS '生成人';
COMMENT ON COLUMN report.generated_time IS '生成时间';

CREATE INDEX IF NOT EXISTS idx_report_plan_id ON report(plan_id);
CREATE INDEX IF NOT EXISTS idx_report_generated_time ON report(generated_time);


-- -------------------------
-- 12. 缺陷同步表
-- -------------------------
CREATE TABLE IF NOT EXISTS defect_sync (
    id BIGSERIAL PRIMARY KEY,
    project_id BIGINT NOT NULL REFERENCES project(id),
    external_id VARCHAR(64) NOT NULL,
    external_system VARCHAR(32),
    plan_case_id BIGINT REFERENCES plan_case(id),
    status VARCHAR(32),
    last_sync_time TIMESTAMP
);

COMMENT ON TABLE defect_sync IS '缺陷同步表，用于记录外部缺陷系统关联关系';
COMMENT ON COLUMN defect_sync.id IS '主键ID';
COMMENT ON COLUMN defect_sync.project_id IS '项目ID';
COMMENT ON COLUMN defect_sync.external_id IS '外部缺陷ID，如 JIRA-123';
COMMENT ON COLUMN defect_sync.external_system IS '外部系统，如 jira/tapd/zentao';
COMMENT ON COLUMN defect_sync.plan_case_id IS '计划用例执行ID';
COMMENT ON COLUMN defect_sync.status IS '外部缺陷状态';
COMMENT ON COLUMN defect_sync.last_sync_time IS '最后同步时间';

CREATE INDEX IF NOT EXISTS idx_defect_sync_project_id ON defect_sync(project_id);
CREATE INDEX IF NOT EXISTS idx_defect_sync_plan_case_id ON defect_sync(plan_case_id);
CREATE INDEX IF NOT EXISTS idx_defect_sync_external_id ON defect_sync(external_id);


-- =========================================================
-- 五、造数相关
-- =========================================================

-- -------------------------
-- 13. 造数器表
-- -------------------------
CREATE TABLE IF NOT EXISTS data_builder (
    id BIGSERIAL PRIMARY KEY,
    project_id BIGINT NOT NULL REFERENCES project(id) ON DELETE CASCADE,
    name VARCHAR(128) NOT NULL,
    description TEXT,
    builder_type SMALLINT DEFAULT 1,
    definition JSONB NOT NULL,
    input_schema JSONB,
    output_example JSONB,
    created_by BIGINT,
    is_delete INTEGER DEFAULT 0,
    created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

COMMENT ON TABLE data_builder IS '数据构造器表';
COMMENT ON COLUMN data_builder.id IS '主键ID';
COMMENT ON COLUMN data_builder.project_id IS '项目ID';
COMMENT ON COLUMN data_builder.name IS '造数器名称';
COMMENT ON COLUMN data_builder.description IS '造数器描述';
COMMENT ON COLUMN data_builder.builder_type IS '造数器类型：1流程编排 2SQL 3脚本';
COMMENT ON COLUMN data_builder.definition IS '造数逻辑定义，JSON格式';
COMMENT ON COLUMN data_builder.input_schema IS '输入参数结构定义';
COMMENT ON COLUMN data_builder.output_example IS '输出示例';
COMMENT ON COLUMN data_builder.created_by IS '创建人';
COMMENT ON COLUMN data_builder.is_delete IS '逻辑删除标记：0未删除 1已删除';
COMMENT ON COLUMN data_builder.created_time IS '创建时间';
COMMENT ON COLUMN data_builder.updated_time IS '更新时间';

CREATE INDEX IF NOT EXISTS idx_data_builder_project_id ON data_builder(project_id);
CREATE INDEX IF NOT EXISTS idx_data_builder_is_delete ON data_builder(is_delete);


-- -------------------------
-- 14. 造数任务表
-- -------------------------
CREATE TABLE IF NOT EXISTS data_task (
    id BIGSERIAL PRIMARY KEY,
    builder_id BIGINT NOT NULL REFERENCES data_builder(id),
    project_id BIGINT NOT NULL,
    params JSONB,
    status SMALLINT DEFAULT 0,
    result_data JSONB,
    error_message TEXT,
    created_by BIGINT,
    created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    completed_time TIMESTAMP
);

COMMENT ON TABLE data_task IS '数据生成任务表';
COMMENT ON COLUMN data_task.id IS '主键ID';
COMMENT ON COLUMN data_task.builder_id IS '造数器ID';
COMMENT ON COLUMN data_task.project_id IS '项目ID';
COMMENT ON COLUMN data_task.params IS '任务入参，JSON格式';
COMMENT ON COLUMN data_task.status IS '任务状态：0等待 1执行中 2成功 3失败';
COMMENT ON COLUMN data_task.result_data IS '生成结果数据';
COMMENT ON COLUMN data_task.error_message IS '错误信息';
COMMENT ON COLUMN data_task.created_by IS '创建人';
COMMENT ON COLUMN data_task.created_time IS '创建时间';
COMMENT ON COLUMN data_task.completed_time IS '完成时间';

CREATE INDEX IF NOT EXISTS idx_task_status ON data_task(status);
CREATE INDEX IF NOT EXISTS idx_data_task_builder_id ON data_task(builder_id);
CREATE INDEX IF NOT EXISTS idx_data_task_project_id ON data_task(project_id);


-- =========================================================
-- 六、更新时间自动维护触发器
-- 说明：
-- PostgreSQL 需要借助触发器维护 updated_time
-- =========================================================

CREATE OR REPLACE FUNCTION update_updated_time_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_time = CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

DROP TRIGGER IF EXISTS trg_project_updated_time ON project;
CREATE TRIGGER trg_project_updated_time
BEFORE UPDATE ON project
FOR EACH ROW
EXECUTE FUNCTION update_updated_time_column();

DROP TRIGGER IF EXISTS trg_product_updated_time ON product;
CREATE TRIGGER trg_product_updated_time
BEFORE UPDATE ON product
FOR EACH ROW
EXECUTE FUNCTION update_updated_time_column();

DROP TRIGGER IF EXISTS trg_test_case_updated_time ON test_case;
CREATE TRIGGER trg_test_case_updated_time
BEFORE UPDATE ON test_case
FOR EACH ROW
EXECUTE FUNCTION update_updated_time_column();

DROP TRIGGER IF EXISTS trg_test_plan_updated_time ON test_plan;
CREATE TRIGGER trg_test_plan_updated_time
BEFORE UPDATE ON test_plan
FOR EACH ROW
EXECUTE FUNCTION update_updated_time_column();

DROP TRIGGER IF EXISTS trg_data_builder_updated_time ON data_builder;
CREATE TRIGGER trg_data_builder_updated_time
BEFORE UPDATE ON data_builder
FOR EACH ROW
EXECUTE FUNCTION update_updated_time_column();