Uusi TODO-moduuli: Tehtävät + Kehitysehdotukset + Ajanseuranta
Talon sisäinen tehtävienhallinta kahdella alatabilla: Tehtävät (admin luo): - Prioriteetti (normaali/tärkeä/kiireellinen), status, deadline - Vastuuhenkilö-osoitus, inline-muokkaus lukunäkymässä - Aikakirjaukset: pvm, tunnit, kuvaus - kaikki voivat kirjata - Myöhästyneet = punainen reunus, lähestyvät = keltainen - Kommentointi kaikille käyttäjille Kehitysehdotukset (kaikki voivat luoda): - Status: ehdotettu → harkinnassa → toteutettu/hylätty (admin muuttaa) - Kommentointi kaikille - Ehdottaja voi muokata omia Tietokanta: 3 taulua (todos, todo_comments, todo_time_entries) API: 10 endpointtia oikeustarkistuksineen Frontend: Sub-tab navigointi, kortti-grid, 3-näkymämalli per alatabi Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
138
db.php
138
db.php
@@ -445,6 +445,50 @@ function initDatabase(): void {
|
||||
INDEX idx_company (company_id),
|
||||
INDEX idx_category (category_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS todos (
|
||||
id VARCHAR(20) PRIMARY KEY,
|
||||
company_id VARCHAR(50) NOT NULL,
|
||||
type VARCHAR(20) NOT NULL DEFAULT 'task',
|
||||
title VARCHAR(500) NOT NULL,
|
||||
description TEXT,
|
||||
status VARCHAR(30) NOT NULL DEFAULT 'avoin',
|
||||
priority VARCHAR(20) DEFAULT 'normaali',
|
||||
assigned_to VARCHAR(100) DEFAULT '',
|
||||
created_by VARCHAR(100) NOT NULL DEFAULT '',
|
||||
deadline DATE DEFAULT NULL,
|
||||
luotu DATETIME,
|
||||
muokattu DATETIME NULL,
|
||||
muokkaaja VARCHAR(100) DEFAULT '',
|
||||
FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE,
|
||||
INDEX idx_company (company_id),
|
||||
INDEX idx_type (type),
|
||||
INDEX idx_status (status),
|
||||
INDEX idx_deadline (deadline)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS todo_comments (
|
||||
id VARCHAR(20) PRIMARY KEY,
|
||||
todo_id VARCHAR(20) NOT NULL,
|
||||
author VARCHAR(100) NOT NULL,
|
||||
body TEXT NOT NULL,
|
||||
luotu DATETIME,
|
||||
FOREIGN KEY (todo_id) REFERENCES todos(id) ON DELETE CASCADE,
|
||||
INDEX idx_todo (todo_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
|
||||
|
||||
"CREATE TABLE IF NOT EXISTS todo_time_entries (
|
||||
id VARCHAR(20) PRIMARY KEY,
|
||||
todo_id VARCHAR(20) NOT NULL,
|
||||
user VARCHAR(100) NOT NULL,
|
||||
hours DECIMAL(6,2) NOT NULL,
|
||||
description VARCHAR(500) DEFAULT '',
|
||||
work_date DATE NOT NULL,
|
||||
luotu DATETIME,
|
||||
FOREIGN KEY (todo_id) REFERENCES todos(id) ON DELETE CASCADE,
|
||||
INDEX idx_todo (todo_id),
|
||||
INDEX idx_user (user)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
|
||||
];
|
||||
|
||||
foreach ($tables as $i => $sql) {
|
||||
@@ -1442,3 +1486,97 @@ function dbIsPriorityEmail(string $companyId, string $email): bool {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ==================== TEHTÄVÄT (TODOS) ====================
|
||||
|
||||
function dbLoadTodos(string $companyId): array {
|
||||
$rows = _dbFetchAll("
|
||||
SELECT t.*,
|
||||
COALESCE((SELECT SUM(te.hours) FROM todo_time_entries te WHERE te.todo_id = t.id), 0) AS total_hours,
|
||||
(SELECT COUNT(*) FROM todo_comments tc WHERE tc.todo_id = t.id) AS comment_count
|
||||
FROM todos t
|
||||
WHERE t.company_id = ?
|
||||
ORDER BY
|
||||
CASE t.priority WHEN 'kiireellinen' THEN 0 WHEN 'tarkea' THEN 1 ELSE 2 END,
|
||||
t.deadline IS NULL, t.deadline ASC,
|
||||
t.luotu DESC
|
||||
", [$companyId]);
|
||||
foreach ($rows as &$r) {
|
||||
$r['total_hours'] = floatval($r['total_hours']);
|
||||
$r['comment_count'] = intval($r['comment_count']);
|
||||
unset($r['company_id']);
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
|
||||
function dbLoadTodo(string $todoId): ?array {
|
||||
$row = _dbFetchAll("SELECT * FROM todos WHERE id = ?", [$todoId]);
|
||||
if (empty($row)) return null;
|
||||
$todo = $row[0];
|
||||
$todo['comments'] = _dbFetchAll("SELECT * FROM todo_comments WHERE todo_id = ? ORDER BY luotu", [$todoId]);
|
||||
$todo['time_entries'] = _dbFetchAll("SELECT * FROM todo_time_entries WHERE todo_id = ? ORDER BY work_date DESC, luotu DESC", [$todoId]);
|
||||
foreach ($todo['time_entries'] as &$te) {
|
||||
$te['hours'] = floatval($te['hours']);
|
||||
}
|
||||
$todo['total_hours'] = array_sum(array_column($todo['time_entries'], 'hours'));
|
||||
return $todo;
|
||||
}
|
||||
|
||||
function dbSaveTodo(string $companyId, array $todo): void {
|
||||
_dbExecute("
|
||||
INSERT INTO todos (id, company_id, type, title, description, status, priority, assigned_to, created_by, deadline, luotu, muokattu, muokkaaja)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
title = VALUES(title), description = VALUES(description),
|
||||
status = VALUES(status), priority = VALUES(priority),
|
||||
assigned_to = VALUES(assigned_to), deadline = VALUES(deadline),
|
||||
muokattu = VALUES(muokattu), muokkaaja = VALUES(muokkaaja)
|
||||
", [
|
||||
$todo['id'], $companyId,
|
||||
$todo['type'] ?? 'task',
|
||||
$todo['title'] ?? '',
|
||||
$todo['description'] ?? '',
|
||||
$todo['status'] ?? 'avoin',
|
||||
$todo['priority'] ?? 'normaali',
|
||||
$todo['assigned_to'] ?? '',
|
||||
$todo['created_by'] ?? '',
|
||||
!empty($todo['deadline']) ? $todo['deadline'] : null,
|
||||
$todo['luotu'] ?? date('Y-m-d H:i:s'),
|
||||
date('Y-m-d H:i:s'),
|
||||
$todo['muokkaaja'] ?? ''
|
||||
]);
|
||||
}
|
||||
|
||||
function dbDeleteTodo(string $todoId): void {
|
||||
_dbExecute("DELETE FROM todos WHERE id = ?", [$todoId]);
|
||||
}
|
||||
|
||||
function dbAddTodoComment(string $todoId, array $comment): void {
|
||||
_dbExecute("INSERT INTO todo_comments (id, todo_id, author, body, luotu) VALUES (?, ?, ?, ?, ?)", [
|
||||
$comment['id'] ?? generateId(),
|
||||
$todoId,
|
||||
$comment['author'] ?? '',
|
||||
$comment['body'] ?? '',
|
||||
$comment['luotu'] ?? date('Y-m-d H:i:s')
|
||||
]);
|
||||
}
|
||||
|
||||
function dbDeleteTodoComment(string $commentId): void {
|
||||
_dbExecute("DELETE FROM todo_comments WHERE id = ?", [$commentId]);
|
||||
}
|
||||
|
||||
function dbAddTodoTimeEntry(string $todoId, array $entry): void {
|
||||
_dbExecute("INSERT INTO todo_time_entries (id, todo_id, user, hours, description, work_date, luotu) VALUES (?, ?, ?, ?, ?, ?, ?)", [
|
||||
$entry['id'] ?? generateId(),
|
||||
$todoId,
|
||||
$entry['user'] ?? '',
|
||||
$entry['hours'] ?? 0,
|
||||
$entry['description'] ?? '',
|
||||
$entry['work_date'] ?? date('Y-m-d'),
|
||||
$entry['luotu'] ?? date('Y-m-d H:i:s')
|
||||
]);
|
||||
}
|
||||
|
||||
function dbDeleteTodoTimeEntry(string $entryId): void {
|
||||
_dbExecute("DELETE FROM todo_time_entries WHERE id = ?", [$entryId]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user