This commit is contained in:
2026-01-27 15:12:27 +05:00
parent d2c530bb3a
commit 9714ac5004
6 changed files with 2499 additions and 20 deletions

View File

@@ -323,7 +323,32 @@ function createSQLiteTables() {
)`);
console.log('✅ Таблицы для групп пользователей созданы');
// Таблица для типов документов (упрощенная версия)
db.run(`CREATE TABLE IF NOT EXISTS simple_document_types (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
description TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)`);
// Таблица для документов (расширенная задача)
db.run(`CREATE TABLE IF NOT EXISTS simple_documents (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task_id INTEGER NOT NULL,
document_type_id INTEGER,
document_number TEXT,
document_date DATE,
pages_count INTEGER,
urgency_level TEXT CHECK(urgency_level IN ('normal', 'urgent', 'very_urgent')),
comment TEXT,
refusal_reason TEXT,
FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE,
FOREIGN KEY (document_type_id) REFERENCES simple_document_types(id)
)`);
console.log('✅ Таблицы для типов документов и документов (расширенные задачи) созданы');
// Запускаем проверку и обновление структуры таблиц
setTimeout(() => {
checkAndUpdateTableStructure();
@@ -431,6 +456,23 @@ function checkAndUpdateTableStructure() {
{ name: 'user_id', type: 'INTEGER NOT NULL' },
{ name: 'group_id', type: 'INTEGER NOT NULL' },
{ name: 'created_at', type: 'DATETIME DEFAULT CURRENT_TIMESTAMP' }
],
simple_document_types: [
{ name: 'id', type: 'INTEGER PRIMARY KEY AUTOINCREMENT' },
{ name: 'name', type: 'TEXT NOT NULL' },
{ name: 'description', type: 'TEXT' },
{ name: 'created_at', type: 'DATETIME DEFAULT CURRENT_TIMESTAMP' }
],
simple_documents: [
{ name: 'id', type: 'INTEGER PRIMARY KEY AUTOINCREMENT' },
{ name: 'task_id', type: 'INTEGER NOT NULL' },
{ name: 'document_type_id', type: 'INTEGER' },
{ name: 'document_number', type: 'TEXT' },
{ name: 'document_date', type: 'DATE' },
{ name: 'pages_count', type: 'INTEGER' },
{ name: 'urgency_level', type: 'TEXT CHECK(urgency_level IN (\'normal\', \'urgent\', \'very_urgent\'))' },
{ name: 'comment', type: 'TEXT' },
{ name: 'refusal_reason', type: 'TEXT' }
]
};
@@ -500,7 +542,9 @@ function checkAndUpdateTableStructure() {
"CREATE INDEX IF NOT EXISTS idx_tasks_approver_group_id ON tasks(approver_group_id)",
"CREATE INDEX IF NOT EXISTS idx_user_groups_can_approve ON user_groups(can_approve_documents)",
"CREATE INDEX IF NOT EXISTS idx_user_group_memberships_user_id ON user_group_memberships(user_id)",
"CREATE INDEX IF NOT EXISTS idx_user_group_memberships_group_id ON user_group_memberships(group_id)"
"CREATE INDEX IF NOT EXISTS idx_user_group_memberships_group_id ON user_group_memberships(group_id)",
"CREATE INDEX IF NOT EXISTS idx_simple_documents_task_id ON simple_documents(task_id)",
"CREATE INDEX IF NOT EXISTS idx_simple_documents_document_number ON simple_documents(document_number)"
];
newIndexes.forEach(indexQuery => {
@@ -896,6 +940,31 @@ async function createPostgresTables() {
)
`);
// Таблица для типов документов (упрощенная версия)
await client.query(`
CREATE TABLE IF NOT EXISTS simple_document_types (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
`);
// Таблица для документов (расширенная задача)
await client.query(`
CREATE TABLE IF NOT EXISTS simple_documents (
id SERIAL PRIMARY KEY,
task_id INTEGER NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
document_type_id INTEGER REFERENCES simple_document_types(id),
document_number VARCHAR(100),
document_date DATE,
pages_count INTEGER,
urgency_level VARCHAR(20) CHECK (urgency_level IN ('normal', 'urgent', 'very_urgent')),
comment TEXT,
refusal_reason TEXT
)
`);
console.log('✅ Все таблицы PostgreSQL созданы/проверены');
// Создаем индексы
@@ -920,7 +989,10 @@ async function createPostgresTables() {
'CREATE INDEX IF NOT EXISTS idx_documents_status ON documents(status)',
'CREATE INDEX IF NOT EXISTS idx_documents_created_by ON documents(created_by)',
'CREATE INDEX IF NOT EXISTS idx_document_approvals_document_id ON document_approvals(document_id)',
'CREATE INDEX IF NOT EXISTS idx_document_approvals_status ON document_approvals(status)'
'CREATE INDEX IF NOT EXISTS idx_document_approvals_status ON document_approvals(status)',
// Индексы для простых документов
'CREATE INDEX IF NOT EXISTS idx_simple_documents_task_id ON simple_documents(task_id)',
'CREATE INDEX IF NOT EXISTS idx_simple_documents_document_number ON simple_documents(document_number)'
];
for (const indexQuery of indexes) {
@@ -983,6 +1055,16 @@ async function checkPostgresTableStructure() {
{ name: 'task_type', type: 'VARCHAR(50) DEFAULT "regular"' },
{ name: 'approver_group_id', type: 'INTEGER' },
{ name: 'document_id', type: 'INTEGER' }
],
simple_documents: [
{ name: 'task_id', type: 'INTEGER NOT NULL REFERENCES tasks(id) ON DELETE CASCADE' },
{ name: 'document_type_id', type: 'INTEGER REFERENCES simple_document_types(id)' },
{ name: 'document_number', type: 'VARCHAR(100)' },
{ name: 'document_date', type: 'DATE' },
{ name: 'pages_count', type: 'INTEGER' },
{ name: 'urgency_level', type: 'VARCHAR(20) CHECK (urgency_level IN (\'normal\', \'urgent\', \'very_urgent\'))' },
{ name: 'comment', type: 'TEXT' },
{ name: 'refusal_reason', type: 'TEXT' }
]
};
@@ -1252,6 +1334,122 @@ function checkOverdueTasks() {
setInterval(checkOverdueTasks, 60000);
// Функции для работы с простыми документами
function createSimpleDocumentType(name, description, callback) {
db.run(
"INSERT INTO simple_document_types (name, description) VALUES (?, ?)",
[name, description],
function(err) {
if (err) {
console.error('❌ Ошибка создания типа документа:', err);
callback(err);
} else {
callback(null, this.lastID);
}
}
);
}
function getSimpleDocumentTypes(callback) {
db.all("SELECT * FROM simple_document_types ORDER BY name", [], (err, types) => {
if (err) {
console.error('❌ Ошибка получения типов документов:', err);
callback(err, []);
} else {
callback(null, types || []);
}
});
}
function createSimpleDocument(taskId, documentData, callback) {
const {
document_type_id,
document_number,
document_date,
pages_count,
urgency_level,
comment,
refusal_reason
} = documentData;
const query = `
INSERT INTO simple_documents (
task_id, document_type_id, document_number, document_date,
pages_count, urgency_level, comment, refusal_reason
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
`;
db.run(query, [
taskId, document_type_id, document_number, document_date,
pages_count, urgency_level, comment, refusal_reason
], function(err) {
if (err) {
console.error('❌ Ошибка создания документа:', err);
callback(err);
} else {
callback(null, this.lastID);
}
});
}
function getTaskDocuments(taskId, callback) {
const query = `
SELECT sd.*, sdt.name as document_type_name
FROM simple_documents sd
LEFT JOIN simple_document_types sdt ON sd.document_type_id = sdt.id
WHERE sd.task_id = ?
ORDER BY sd.document_date DESC, sd.id DESC
`;
db.all(query, [taskId], (err, documents) => {
if (err) {
console.error('❌ Ошибка получения документов задачи:', err);
callback(err, []);
} else {
callback(null, documents || []);
}
});
}
function updateSimpleDocument(documentId, updates, callback) {
const fields = [];
const values = [];
Object.entries(updates).forEach(([key, value]) => {
fields.push(`${key} = ?`);
values.push(value);
});
if (fields.length === 0) {
callback(new Error('Нет полей для обновления'));
return;
}
values.push(documentId);
const query = `UPDATE simple_documents SET ${fields.join(', ')} WHERE id = ?`;
db.run(query, values, function(err) {
if (err) {
console.error('❌ Ошибка обновления документа:', err);
callback(err);
} else {
callback(null, this.changes > 0);
}
});
}
function deleteSimpleDocument(documentId, callback) {
db.run("DELETE FROM simple_documents WHERE id = ?", [documentId], function(err) {
if (err) {
console.error('❌ Ошибка удаления документа:', err);
callback(err);
} else {
callback(null, this.changes > 0);
}
});
}
module.exports = {
initializeDatabase, // Экспортируем функцию инициализации
getDb: () => {
@@ -1270,12 +1468,19 @@ module.exports = {
USE_POSTGRES,
getDatabaseType: () => USE_POSTGRES ? 'PostgreSQL' : 'SQLite',
checkAndUpdateTableStructure, // Экспортируем для ручного запуска
// Новые функции для работы с группами
// Функции для работы с группами
getUserGroups,
getGroupMembers,
getApproverGroups,
addUserToGroup,
removeUserFromGroup
removeUserFromGroup,
// Функции для работы с простыми документами
createSimpleDocumentType,
getSimpleDocumentTypes,
createSimpleDocument,
getTaskDocuments,
updateSimpleDocument,
deleteSimpleDocument
};
// Запускаем инициализацию при экспорте (но она завершится позже)