diff --git a/backup-restore.js b/backup-restore.js index 125d9c5..65da24a 100644 --- a/backup-restore.js +++ b/backup-restore.js @@ -8,12 +8,13 @@ const BACKUP_TABLES = [ 'group_photos', 'entry_photos', 'modules', 'student_photos', 'share_links', 'photo_jobs', 'lesson_reports', 'lesson_report_versions', 'audit_log', 'notifications', 'notification_reads', 'banned_ips', 'chat_threads', 'chat_messages', 'chat_attachments', + 'short_messages', ]; const BACKUP_SEQUENCE_TABLES = [ 'groups', 'students', 'entries', 'project_files', 'branches', 'users', 'group_photos', 'entry_photos', 'modules', 'student_photos', 'share_links', 'photo_jobs', 'lesson_reports', 'lesson_report_versions', 'audit_log', 'notifications', 'chat_threads', 'chat_messages', - 'chat_attachments', + 'chat_attachments', 'short_messages', ]; function isSupportedBackupVersion(data) { @@ -500,7 +501,21 @@ function normalizeRestoreData(data) { size: optInt(x.size, 0, 2147483647) ?? 0, created_at: optTs(x.created_at), })); - return { groups, students, entries, project_files, settings, branches, users, user_branches, entry_photos, student_photos, group_photos, share_links, modules, photo_jobs, lesson_reports, lesson_report_versions, audit_log, notifications, notification_reads, banned_ips, chat_threads, chat_messages, chat_attachments }; + const short_messages = (data.short_messages || []).map(x => ({ + id: reqInt(x.id), + resident: reqStr(x.resident, 200), + lesson_date: reqDate(x.lesson_date), + topic: optStr(x.topic, 500), + message: reqStr(x.message, 10000), + used: !!x.used, + used_at: optDate(x.used_at), + author_id: optInt(x.author_id, 0, 2147483647), + deleted_at: optTs(x.deleted_at), + purge_at: optTs(x.purge_at), + created_at: optTs(x.created_at), + updated_at: optTs(x.updated_at), + })); + return { groups, students, entries, project_files, settings, branches, users, user_branches, entry_photos, student_photos, group_photos, share_links, modules, photo_jobs, lesson_reports, lesson_report_versions, audit_log, notifications, notification_reads, banned_ips, chat_threads, chat_messages, chat_attachments, short_messages }; } module.exports = { diff --git a/backup.selftest.js b/backup.selftest.js index 04c4d52..4488cad 100644 --- a/backup.selftest.js +++ b/backup.selftest.js @@ -79,6 +79,26 @@ const ch = normalizeRestoreData({ ok('chat_threads нормализуются', ch.chat_threads[0].tutor_id === 1 && ch.chat_threads[0].tutor_unread === 2, ch.chat_threads[0]); ok('chat_messages нормализуются', ch.chat_messages[0].thread_id === 3 && ch.chat_messages[0].body === 'привет', ch.chat_messages[0]); ok('chat_attachments нормализуются', ch.chat_attachments[0].name === 'photo.png' && ch.chat_attachments[0].size === 1234, ch.chat_attachments[0]); +const sm = normalizeRestoreData({ + ...base, + short_messages: [{ id: 1, resident: 'Иванов И.И.', lesson_date: '2026-05-05', topic: 'T', message: 'текст', used: true, used_at: '2026-05-06', author_id: 1, deleted_at: '2026-05-07T00:00:00.000Z', purge_at: '2027-05-07T00:00:00.000Z' }], +}); +ok('short_messages нормализуются', sm.short_messages[0].resident === 'Иванов И.И.' && sm.short_messages[0].used === true && sm.short_messages[0].used_at === '2026-05-06', sm.short_messages[0]); +ok('short_messages сохраняет purge_at', sm.short_messages[0].deleted_at === '2026-05-07T00:00:00.000Z' && sm.short_messages[0].purge_at === '2027-05-07T00:00:00.000Z', sm.short_messages[0]); +let smBadDate = false; +try { + normalizeRestoreData({ ...base, short_messages: [{ id: 1, resident: 'X', lesson_date: '05.05.2026', message: 't' }] }); +} catch (e) { + smBadDate = true; +} +ok('кривая дата занятия в short_messages отклоняется', smBadDate); +let smNoResident = false; +try { + normalizeRestoreData({ ...base, short_messages: [{ id: 1, resident: '', lesson_date: '2026-05-05', message: 't' }] }); +} catch (e) { + smNoResident = true; +} +ok('пустой резидент в short_messages отклоняется', smNoResident); const chEdits = normalizeRestoreData({ ...base, chat_messages: [ diff --git a/db/init.sql b/db/init.sql index b3ab257..19839d8 100644 --- a/db/init.sql +++ b/db/init.sql @@ -476,3 +476,5 @@ CREATE TABLE IF NOT EXISTS short_messages ( CREATE INDEX IF NOT EXISTS idx_short_messages_date ON short_messages(lesson_date DESC); CREATE INDEX IF NOT EXISTS idx_short_messages_deleted ON short_messages(deleted_at); + +INSERT INTO settings (key, value) VALUES ('short_messages_retention_days', '365') ON CONFLICT (key) DO NOTHING; diff --git a/public/js/shorts.js b/public/js/shorts.js index 8e03844..cbc974a 100644 --- a/public/js/shorts.js +++ b/public/js/shorts.js @@ -58,21 +58,20 @@ async function loadShorts() { const dateStr = r.lesson_date ? fmtDateOnlyIso(r.lesson_date) : ''; const usedDateStr = r.used_at ? fmtDateOnlyIso(r.used_at) : '—'; const author = r.author_name || r.author_username || '—'; - const canEdit = true; return ` -