bmc_hub/migrations/183_task_templates_mvp.sql

126 lines
5.0 KiB
MySQL
Raw Permalink Normal View History

-- Task template MVP for case automation
CREATE TABLE IF NOT EXISTS task_templates (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description TEXT,
template_type VARCHAR(20) NOT NULL DEFAULT 'global'
CHECK (template_type IN ('global', 'company', 'internal', 'deactivated')),
customer_id INTEGER REFERENCES customers(id) ON DELETE CASCADE,
category VARCHAR(50) NOT NULL DEFAULT 'andet'
CHECK (category IN ('onboarding', 'offboarding', 'simkort', 'hardwarebestilling', 'brugerandring', 'andet')),
is_active BOOLEAN NOT NULL DEFAULT TRUE,
created_by INTEGER REFERENCES users(user_id) ON DELETE SET NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMP,
CONSTRAINT task_templates_company_type_consistency CHECK (
(template_type = 'company' AND customer_id IS NOT NULL)
OR (template_type IN ('global', 'internal', 'deactivated') AND customer_id IS NULL)
)
);
CREATE TABLE IF NOT EXISTS task_template_items (
id SERIAL PRIMARY KEY,
template_id INTEGER NOT NULL REFERENCES task_templates(id) ON DELETE CASCADE,
title VARCHAR(255) NOT NULL,
description TEXT,
item_type VARCHAR(20) NOT NULL CHECK (item_type IN ('task', 'subcase')),
default_assignee_user_id INTEGER REFERENCES users(user_id) ON DELETE SET NULL,
default_assignee_role_id INTEGER,
days_offset INTEGER DEFAULT 0,
sort_order INTEGER NOT NULL DEFAULT 0,
is_required BOOLEAN NOT NULL DEFAULT TRUE,
is_active BOOLEAN NOT NULL DEFAULT TRUE,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS case_template_runs (
id SERIAL PRIMARY KEY,
case_id INTEGER NOT NULL REFERENCES sag_sager(id) ON DELETE CASCADE,
template_id INTEGER NOT NULL REFERENCES task_templates(id) ON DELETE RESTRICT,
started_by INTEGER REFERENCES users(user_id) ON DELETE SET NULL,
started_at TIMESTAMP NOT NULL DEFAULT NOW(),
status VARCHAR(30) NOT NULL DEFAULT 'running'
CHECK (status IN ('running', 'completed', 'failed')),
error_message TEXT,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS case_template_run_items (
id SERIAL PRIMARY KEY,
template_run_id INTEGER NOT NULL REFERENCES case_template_runs(id) ON DELETE CASCADE,
template_item_id INTEGER REFERENCES task_template_items(id) ON DELETE SET NULL,
created_case_id INTEGER REFERENCES sag_sager(id) ON DELETE SET NULL,
created_task_id INTEGER REFERENCES sag_todo_steps(id) ON DELETE SET NULL,
status VARCHAR(30) NOT NULL DEFAULT 'created'
CHECK (status IN ('created', 'skipped', 'failed')),
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_task_templates_active
ON task_templates (is_active)
WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_task_templates_customer
ON task_templates (customer_id)
WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_task_templates_type
ON task_templates (template_type)
WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_task_template_items_template
ON task_template_items (template_id, sort_order, id)
WHERE is_active = TRUE;
CREATE INDEX IF NOT EXISTS idx_case_template_runs_case
ON case_template_runs (case_id, started_at DESC);
CREATE INDEX IF NOT EXISTS idx_case_template_run_items_run
ON case_template_run_items (template_run_id);
INSERT INTO permissions (code, description, category)
VALUES
('templates.view', 'View task templates', 'templates'),
('templates.create', 'Create task templates', 'templates'),
('templates.edit', 'Edit task templates', 'templates'),
('templates.delete', 'Deactivate task templates', 'templates'),
('templates.run', 'Run task templates on cases', 'templates')
ON CONFLICT (code) DO NOTHING;
INSERT INTO group_permissions (group_id, permission_id)
SELECT g.id, p.id
FROM groups g
JOIN permissions p ON p.code IN (
'templates.view',
'templates.create',
'templates.edit',
'templates.delete',
'templates.run'
)
WHERE g.name = 'Administrators'
ON CONFLICT DO NOTHING;
INSERT INTO tags (name, type, description, color, is_active)
VALUES ('opgave_template', 'workflow', 'Åbner opgave-template modal', '#ff6b35', TRUE)
ON CONFLICT (name, type) DO NOTHING;
INSERT INTO tag_workflows (tag_id, trigger_event, action_type, action_config, is_active)
SELECT t.id, 'on_add', 'open_task_template_modal',
'{"modal":"task_template_selector","default_category":null,"allow_company_templates":true,"allow_global_templates":true}'::jsonb,
TRUE
FROM tags t
WHERE t.name = 'opgave_template' AND t.type = 'workflow'
AND NOT EXISTS (
SELECT 1
FROM tag_workflows tw
WHERE tw.tag_id = t.id
AND tw.trigger_event = 'on_add'
AND tw.action_type = 'open_task_template_modal'
AND tw.is_active = TRUE
);