126 lines
5.0 KiB
MySQL
126 lines
5.0 KiB
MySQL
|
|
-- 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
|
||
|
|
);
|