Dokumentit: kokousmuistiot, kansiorakenne, sub-tabit, asiakaslinkkaus

- Uusi dokumenttityyppi "kokousmuistio" jolla inline tekstieditori (ei tiedostopohjainen)
- document_versions.content -sarake kokousmuistioiden tekstin tallennukseen
- Sub-tabit Dokumentit-välilehdelle (Kaikki / Kokoukset) Tekniikka-mallin mukaan
- Kansiorakenne: document_folders-taulu, kansionavigaatio breadcrumbsilla
- Uudet API-endpointit: document_folders, document_folder_save/delete, document_content_save, document_move
- Asiakasprofiilin Dokumentit-osio: näyttää linkitetyt dokumentit + pikanapit luontiin
- Asiakasprofiilista voi avata dokumentin suoraan tai luoda uuden linkitettynä asiakkaaseen

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 23:19:05 +02:00
parent 150c774bb3
commit f40b387383
5 changed files with 549 additions and 38 deletions

63
db.php
View File

@@ -542,6 +542,18 @@ function initDatabase(): void {
INDEX idx_document (document_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
"CREATE TABLE IF NOT EXISTS document_folders (
id VARCHAR(20) PRIMARY KEY,
company_id VARCHAR(50) NOT NULL,
name VARCHAR(255) NOT NULL,
parent_id VARCHAR(20) DEFAULT NULL,
created_by VARCHAR(100) DEFAULT '',
luotu DATETIME,
FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE,
INDEX idx_company (company_id),
INDEX idx_parent (parent_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
"CREATE TABLE IF NOT EXISTS laitetilat (
id VARCHAR(20) PRIMARY KEY,
company_id VARCHAR(50) NOT NULL,
@@ -599,6 +611,8 @@ function initDatabase(): void {
"ALTER TABLE companies ADD COLUMN allowed_ips TEXT DEFAULT '' AFTER enabled_modules",
"ALTER TABLE todos ADD COLUMN category VARCHAR(30) DEFAULT '' AFTER priority",
"ALTER TABLE user_companies ADD COLUMN role VARCHAR(20) DEFAULT 'user' AFTER company_id",
"ALTER TABLE documents ADD COLUMN folder_id VARCHAR(20) DEFAULT NULL AFTER customer_id",
"ALTER TABLE document_versions ADD COLUMN content MEDIUMTEXT DEFAULT NULL AFTER mime_type",
];
foreach ($alters as $sql) {
try { $db->query($sql); } catch (\Throwable $e) { /* sarake on jo olemassa / jo ajettu */ }
@@ -1736,6 +1750,43 @@ function dbDeleteTodoSubtask(string $subtaskId): void {
_dbExecute("DELETE FROM todo_subtasks WHERE id = ?", [$subtaskId]);
}
// ==================== DOKUMENTTIKANSIOT ====================
function dbLoadFolders(string $companyId): array {
return _dbFetchAll("SELECT * FROM document_folders WHERE company_id = ? ORDER BY name", [$companyId]);
}
function dbSaveFolder(string $companyId, array $folder): string {
$id = $folder['id'] ?? generateId();
$now = date('Y-m-d H:i:s');
_dbExecute("
INSERT INTO document_folders (id, company_id, name, parent_id, created_by, luotu)
VALUES (:id, :companyId, :name, :parentId, :createdBy, :luotu)
ON DUPLICATE KEY UPDATE name = VALUES(name), parent_id = VALUES(parent_id)
", [
'id' => $id,
'companyId' => $companyId,
'name' => $folder['name'] ?? '',
'parentId' => !empty($folder['parent_id']) ? $folder['parent_id'] : null,
'createdBy' => $folder['created_by'] ?? '',
'luotu' => $folder['luotu'] ?? $now
]);
return $id;
}
function dbDeleteFolder(string $companyId, string $folderId): bool {
$folder = _dbFetchOne("SELECT parent_id FROM document_folders WHERE id = ? AND company_id = ?", [$folderId, $companyId]);
if (!$folder) return false;
// Siirrä kansion dokumentit ylätasolle
_dbExecute("UPDATE documents SET folder_id = ? WHERE folder_id = ? AND company_id = ?",
[$folder['parent_id'], $folderId, $companyId]);
// Siirrä alikansiot ylätasolle
_dbExecute("UPDATE document_folders SET parent_id = ? WHERE parent_id = ? AND company_id = ?",
[$folder['parent_id'], $folderId, $companyId]);
_dbExecute("DELETE FROM document_folders WHERE id = ? AND company_id = ?", [$folderId, $companyId]);
return true;
}
// ==================== DOKUMENTIT ====================
function dbLoadDocuments(string $companyId, ?string $customerId = null): array {
@@ -1767,19 +1818,21 @@ function dbSaveDocument(string $companyId, array $doc): string {
$id = $doc['id'] ?? generateId();
$now = date('Y-m-d H:i:s');
_dbExecute("
INSERT INTO documents (id, company_id, customer_id, title, description, category, current_version, created_by, luotu, muokattu, muokkaaja)
VALUES (:id, :companyId, :customerId, :title, :description, :category, :currentVersion, :createdBy, :luotu, :muokattu, :muokkaaja)
INSERT INTO documents (id, company_id, customer_id, folder_id, title, description, category, current_version, created_by, luotu, muokattu, muokkaaja)
VALUES (:id, :companyId, :customerId, :folderId, :title, :description, :category, :currentVersion, :createdBy, :luotu, :muokattu, :muokkaaja)
ON DUPLICATE KEY UPDATE
title = VALUES(title),
description = VALUES(description),
category = VALUES(category),
customer_id = VALUES(customer_id),
folder_id = VALUES(folder_id),
muokattu = VALUES(muokattu),
muokkaaja = VALUES(muokkaaja)
", [
'id' => $id,
'companyId' => $companyId,
'customerId' => !empty($doc['customer_id']) ? $doc['customer_id'] : null,
'folderId' => !empty($doc['folder_id']) ? $doc['folder_id'] : null,
'title' => $doc['title'] ?? '',
'description' => $doc['description'] ?? '',
'category' => $doc['category'] ?? 'muu',
@@ -1807,7 +1860,7 @@ function dbAddDocumentVersion(string $documentId, array $version): void {
$maxVersion = _dbFetchScalar("SELECT COALESCE(MAX(version_number), 0) FROM document_versions WHERE document_id = ?", [$documentId]);
$nextVersion = (int)$maxVersion + 1;
_dbExecute("INSERT INTO document_versions (id, document_id, version_number, filename, original_name, file_size, mime_type, change_notes, created_by, luotu) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [
_dbExecute("INSERT INTO document_versions (id, document_id, version_number, filename, original_name, file_size, mime_type, content, change_notes, created_by, luotu) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [
$version['id'] ?? generateId(),
$documentId,
$nextVersion,
@@ -1815,6 +1868,7 @@ function dbAddDocumentVersion(string $documentId, array $version): void {
$version['original_name'] ?? '',
$version['file_size'] ?? 0,
$version['mime_type'] ?? '',
$version['content'] ?? null,
$version['change_notes'] ?? '',
$version['created_by'] ?? '',
$now
@@ -1836,7 +1890,7 @@ function dbRestoreDocumentVersion(string $documentId, string $versionId, string
$nextVersion = (int)$maxVersion + 1;
$newId = generateId();
_dbExecute("INSERT INTO document_versions (id, document_id, version_number, filename, original_name, file_size, mime_type, change_notes, created_by, luotu) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [
_dbExecute("INSERT INTO document_versions (id, document_id, version_number, filename, original_name, file_size, mime_type, content, change_notes, created_by, luotu) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [
$newId,
$documentId,
$nextVersion,
@@ -1844,6 +1898,7 @@ function dbRestoreDocumentVersion(string $documentId, string $versionId, string
$oldVersion['original_name'],
$oldVersion['file_size'],
$oldVersion['mime_type'],
$oldVersion['content'] ?? null,
'Palautettu versiosta ' . $oldVersion['version_number'],
$user,
$now