CREATE TABLE thread ( id INTEGER NOT NULL PRIMARY KEY, original_poster TEXT NOT NULL, coordinator TEXT NULL, -- NULL - proposal closed_by TEXT NULL, -- who closed or rejected the thread private BOOLEAN NOT NULL DEFAULT 0, -- 0 - public, 1 - private lock BOOLEAN NOT NULL DEFAULT 0, -- 0 - unlocked, 1 - locked type TEXT NOT NULL DEFAULT 'issue', -- issue, project state TEXT NOT NULL DEFAULT 'proposal', -- proposal,opened,done,closed,rejected create_date TEXT NOT NULL, -- ISO8601 last_activity_date TEXT NOT NULL, -- ISO8601 last_modification_date TEXT NOT NULL, -- ISO8601 close_date TEXT, -- ISO8601 title TEXT NOT NULL, content TEXT NOT NULL, content_html TEXT NOT NULL, task_count INTEGER NOT NULL DEFAULT 0, task_count_closed INTEGER NOT NULL DEFAULT 0, task_sum_cost REAL ); CREATE INDEX thread_ix_last_activity_date ON thread (last_activity_date); -- to speedup order by CREATE TABLE thread_participant ( thread_id INTEGER NOT NULL REFERENCES thread (id), user_id TEXT NOT NULL, original_poster BOOLEAN NOT NULL DEFAULT 0, coordinator BOOLEAN NOT NULL DEFAULT 0, commentator BOOLEAN NOT NULL DEFAULT 0, task_assignee BOOLEAN NOT NULL DEFAULT 0, subscribent BOOLEAN NOT NULL DEFAULT 0, added_by TEXT NOT NULL, -- user who added the participant. Equals user_id when user subscribed himself added_date TEXT NOT NULL, -- ISO8601 PRIMARY KEY (thread_id, user_id) ); CREATE TABLE thread_comment ( id INTEGER NOT NULL PRIMARY KEY, thread_id INTEGER NOT NULL REFERENCES thread (id), type TEXT NOT NULL DEFAULT 'comment', -- comment, cause_real, cause_potential -- will be: comment, cause, risk author TEXT NOT NULL, create_date TEXT NOT NULL, -- ISO8601 last_modification_date TEXT NOT NULL, -- ISO8601 content TEXT NOT NULL, content_html TEXT NOT NULL, task_count INTEGER NOT NULL DEFAULT 0 ); CREATE VIEW thread_comment_view AS SELECT thread_comment.*, thread.coordinator AS coordinator FROM thread_comment JOIN thread ON thread_comment.thread_id = thread.id; CREATE INDEX thread_comment_ix_thread_id ON thread_comment (thread_id); CREATE TABLE label ( id INTEGER NOT NULL PRIMARY KEY, name TEXT UNIQUE NOT NULL, color TEXT NULL, -- color of the label, hex RGB: xxxxxx count INTEGER NOT NULL DEFAULT 0, added_by TEXT NOT NULL, -- user who added the label added_date TEXT NOT NULL -- ISO8601 ); CREATE INDEX label_ix_name ON label (name); CREATE TABLE thread_label ( thread_id INTEGER NOT NULL, label_id INTEGER NOT NULL, PRIMARY KEY (thread_id, label_id) ); CREATE TRIGGER thread_label_tr_insert INSERT ON thread_label BEGIN UPDATE label SET count = count + 1 WHERE id = new.label_id; END; CREATE TRIGGER thread_label_tr_delete DELETE ON thread_label BEGIN UPDATE label SET count = count - 1 WHERE id = old.label_id; END; CREATE TRIGGER thread_label_tr_update_label_id UPDATE OF label_id ON thread_label BEGIN UPDATE label SET count = count - 1 WHERE id = old.label_id; UPDATE label SET count = count + 1 WHERE id = new.label_id; END; CREATE TABLE task_program ( id INTEGER NOT NULL PRIMARY KEY, name TEXT UNIQUE NOT NULL, count INTEGER NOT NULL DEFAULT 0, added_by TEXT NOT NULL, -- user who added the label added_date TEXT NOT NULL -- ISO8601 ); -- we cannot delete tasks (so not triggers provided) CREATE TABLE task ( id INTEGER NOT NULL PRIMARY KEY, original_poster TEXT NOT NULL, assignee TEXT NOT NULL, closed_by TEXT NULL, -- who closed the task private BOOLEAN NOT NULL DEFAULT 0, -- 0 - public, 1 - private lock BOOLEAN NOT NULL DEFAULT 0, -- 0 - unlocked, 1 - locked state TEXT NOT NULL DEFAULT 'opened', -- opened, done type TEXT NOT NULL DEFAULT 'correction', -- correction, corrective, preventive, program create_date TEXT NOT NULL, -- ISO8601 last_activity_date TEXT NOT NULL, -- -- ISO8601 last_modification_date TEXT NOT NULL, -- ISO8601 close_date TEXT, -- ISO8601 cost REAL, plan_date TEXT NOT NULL, -- -- ISO8601 all_day_event INTEGER NOT NULL DEFAULT 0, -- 0 - false, 1 - true start_time TEXT NULL, -- HH:MM finish_time TEXT NULL, -- HH:MM content TEXT NOT NULL, content_html TEXT NOT NULL, thread_id INTEGER REFERENCES thread (id), --may be null thread_comment_id INTEGER REFERENCES thread_comment (id), --may be null task_program_id INTEGER REFERENCES task_program (id) --may be null ); CREATE INDEX task_ix_thread_id_thread_comment_id ON task (thread_id, thread_comment_id); CREATE INDEX task_ix_task_program_id ON task(task_program_id); CREATE TRIGGER task_tr_insert_task_count INSERT ON task WHEN new.thread_id IS NOT NULL BEGIN UPDATE thread SET task_count = task_count + 1 WHERE id = new.thread_id; END; CREATE TRIGGER task_tr_insert_task_sum_cost INSERT ON task WHEN new.thread_id IS NOT NULL AND new.cost IS NOT NULL BEGIN UPDATE thread SET task_sum_cost = coalesce(task_sum_cost, 0) + new.cost WHERE id = new.thread_id; END; CREATE TRIGGER task_tr_update_task_count UPDATE OF thread_id ON task BEGIN UPDATE thread SET task_count = task_count - 1 WHERE id = old.thread_id; UPDATE thread SET task_count = task_count + 1 WHERE id = new.thread_id; END; CREATE TRIGGER task_tr_update_task_sum_cost_old_cost_not_null UPDATE OF thread_id, cost ON task WHEN old.cost IS NOT NULL BEGIN UPDATE thread SET task_sum_cost = task_sum_cost - old.cost WHERE id = old.thread_id; END; CREATE TRIGGER task_tr_update_task_sum_cost_new_cost_not_null UPDATE OF thread_id, cost ON task WHEN new.cost IS NOT NULL BEGIN UPDATE thread SET task_sum_cost = coalesce(task_sum_cost, 0) + new.cost WHERE id = new.thread_id; END; CREATE TRIGGER task_tr_update_state_opened_closed UPDATE OF thread_id, state ON task WHEN old.state = 'opened' AND new.state = 'done' BEGIN UPDATE thread SET task_count_closed = task_count_closed + 1 WHERE id = new.thread_id; END; CREATE TRIGGER task_tr_update_state_closed_opened UPDATE OF thread_id, state ON task WHEN old.state = 'done' AND new.state = 'opened' BEGIN UPDATE thread SET task_count_closed = task_count_closed - 1 WHERE id = old.thread_id; END; CREATE TRIGGER task_tr_update_state_closed_closed UPDATE OF thread_id, state ON task WHEN old.state = 'done' AND new.state = 'done' BEGIN UPDATE thread SET task_count_closed = task_count_closed - 1 WHERE id = old.thread_id; UPDATE thread SET task_count_closed = task_count_closed + 1 WHERE id = new.thread_id; END; -- thread_comment triggers CREATE TRIGGER thread_comment_tr_insert INSERT ON task BEGIN UPDATE thread_comment SET task_count = task_count + 1 WHERE id = new.thread_comment_id; END; CREATE TRIGGER thread_comment_tr_thread_comment_id UPDATE OF thread_comment_id ON task BEGIN UPDATE thread_comment SET task_count = task_count - 1 WHERE id = old.thread_comment_id; UPDATE thread_comment SET task_count = task_count + 1 WHERE id = new.thread_comment_id; END; -- end of thread_comment triggers -- task_program triggers CREATE TRIGGER task_program_tr_insert INSERT ON task BEGIN UPDATE task_program SET count = count + 1 WHERE id = new.task_program_id; END; CREATE TRIGGER task_program_tr_delete DELETE ON task BEGIN UPDATE task_program SET count = count - 1 WHERE id = old.task_program_id; END; CREATE TRIGGER task_program_tr_update_task_program_id UPDATE OF task_program_id ON task BEGIN UPDATE task_program SET count = count - 1 WHERE id = old.task_program_id; UPDATE task_program SET count = count + 1 WHERE id = new.task_program_id; END; -- end of task_program triggres CREATE TABLE task_participant ( task_id INTEGER NOT NULL REFERENCES thread (id), user_id TEXT NOT NULL, original_poster BOOLEAN NOT NULL DEFAULT 0, assignee BOOLEAN NOT NULL DEFAULT 0, commentator BOOLEAN NOT NULL DEFAULT 0, subscribent BOOLEAN NOT NULL DEFAULT 0, added_by TEXT NOT NULL, -- user who added the participant. Equals user_id when user subscribed himself added_date TEXT NOT NULL, -- ISO8601 PRIMARY KEY (task_id, user_id) ); CREATE TABLE task_comment ( id INTEGER NOT NULL PRIMARY KEY, task_id INTEGER NOT NULL REFERENCES task (id), author TEXT NOT NULL, create_date TEXT NOT NULL, -- ISO8601 last_modification_date TEXT NOT NULL, -- ISO8601 content TEXT NOT NULL, content_html TEXT NOT NULL ); CREATE TABLE authentication_token ( page_id TEXT NOT NULL, token TEXT NOT NULL, generated_by TEXT NOT NULL, generation_date TEXT NOT NULL, expire_date TEXT, PRIMARY KEY (page_id, token) ); CREATE VIEW task_view AS SELECT task.*, task_program.name AS task_program_name, thread.coordinator AS coordinator, CASE WHEN task.state = 'done' THEN NULL WHEN task.plan_date >= date('now', '+1 month') THEN '2' WHEN task.plan_date >= date('now') THEN '1' ELSE '0' END AS priority FROM task LEFT JOIN task_program ON task.task_program_id = task_program.id LEFT JOIN thread ON task.thread_id = thread.id; CREATE VIEW thread_view AS SELECT thread.id, thread.original_poster, thread.coordinator, thread.closed_by, thread.private, thread.lock, thread.type, thread.create_date, thread.last_activity_date, thread.last_modification_date, thread.close_date, thread.title, thread.content, thread.content_html, thread.task_count, thread.task_count_closed, thread.task_sum_cost, label.id AS label_id, label.name AS label_name, (SELECT MIN(priority) FROM task_view WHERE task_view.thread_id = thread.id) AS priority, CASE WHEN thread.state = 'opened' AND thread.task_count > 0 AND thread.task_count = thread.task_count_closed THEN 'done' ELSE thread.state END AS state FROM thread LEFT JOIN thread_label ON thread.id = thread_label.thread_id LEFT JOIN label ON label.id = thread_label.label_id;