Backend: - schema.js: add document_templates, template_versions, document_versions tables; migrate documents with template_id/template_version_id columns; auto-seed Version 1 for all 190 existing documents - templateController.js (NEW): full CRUD + file upload/download for templates and template versions - templates.js route (NEW): /api/templates endpoints - documentController.js: add getDocumentVersions, uploadDocumentVersion, downloadDocumentVersion; uploadDocument now seeds Version 1 on creation - documents.js: wire GET /:id/versions, POST /:id/upload-version - backupController.js: upgrade backup to ZIP archive (DB + student files + template files + SHA-256 manifest); restore handles ZIP and legacy .db; safety backup taken before every restore - package.json: add archiver + unzipper dependencies Frontend: - template_model.dart (NEW): DocumentTemplateModel + TemplateVersionModel entities - document_version_model.dart (NEW): DocumentVersionModel entity - template_repository.dart (NEW): Dio-based template API client - document_repository.dart: add getDocumentVersions, uploadDocumentVersion, downloadDocumentVersion methods - document_preview_modal.dart: add Open / Open With (Windows rundll32 OpenAs_RunDLL / Android chooser) / Edit (download-temp -> open -> upload prompt) / Upload New Version (FilePicker) / Version History actions - document_version_history_sheet.dart (NEW): draggable bottom sheet listing all document versions with per-version Preview + Download - file_folder_card.dart: add Open With, Edit, Upload New Version, Version History items to context menu - documents_screen.dart: wire open_with, edit, upload_version, version_history, restore action cases; import version history sheet Bugfix: - student_profile_modal.dart: remove enrollment.status access that caused NoSuchMethodError (enrollments table has no status column)
113 lines
4.3 KiB
JavaScript
113 lines
4.3 KiB
JavaScript
process.env.TZ = 'Asia/Manila';
|
|
const express = require('express');
|
|
const cors = require('cors');
|
|
const morgan = require('morgan');
|
|
const path = require('path');
|
|
require('dotenv').config({ path: path.join(__dirname, '.env'), override: true });
|
|
require('dotenv').config({ path: path.join(__dirname, '..', '.env'), override: true });
|
|
|
|
// ==========================================
|
|
// CROSS-PLATFORM SYSTEM SETUP (Ghostscript, Tesseract)
|
|
// ==========================================
|
|
const { setupSystemEnvironment } = require('./src/config/systemSetup');
|
|
setupSystemEnvironment();
|
|
|
|
|
|
const { initSchema } = require('./src/models/schema');
|
|
const authRoutes = require('./src/routes/auth');
|
|
const studentRoutes = require('./src/routes/students');
|
|
const documentRoutes = require('./src/routes/documents');
|
|
const dashboardRoutes = require('./src/routes/dashboard');
|
|
const setupRoutes = require('./src/routes/setup');
|
|
const userRoutes = require('./src/routes/users');
|
|
const reportsRoutes = require('./src/routes/reports');
|
|
const archivesRoutes = require('./src/routes/archives');
|
|
const folderRoutes = require('./src/routes/folders');
|
|
const requirementRoutes = require('./src/routes/requirements');
|
|
const ocrRoutes = require('./src/routes/ocr.routes.js');
|
|
const notificationRoutes = require('./src/routes/notifications');
|
|
const backupRoutes = require('./src/routes/backup');
|
|
const serverRoutes = require('./src/routes/server.routes');
|
|
const settingsRoutes = require('./src/routes/settings');
|
|
const templateRoutes = require('./src/routes/templates');
|
|
|
|
const app = express();
|
|
const PORT = process.env.PORT || 18484;
|
|
|
|
// Initialize Database
|
|
initSchema();
|
|
|
|
// Middleware
|
|
app.use(cors());
|
|
app.use(express.json());
|
|
app.use(express.urlencoded({ extended: true }));
|
|
app.use(morgan('dev'));
|
|
app.use('/uploads', express.static(path.join(__dirname, 'uploads')));
|
|
|
|
// Routes
|
|
app.use('/api/auth', authRoutes);
|
|
app.use('/api/students', studentRoutes);
|
|
app.use('/api/documents', documentRoutes);
|
|
app.use('/api/dashboard', dashboardRoutes);
|
|
app.use('/api/setup', setupRoutes);
|
|
app.use('/api/users', userRoutes);
|
|
app.use('/api/reports', reportsRoutes);
|
|
app.use('/api/archives', archivesRoutes);
|
|
app.use('/api/folders', folderRoutes);
|
|
app.use('/api/requirements', requirementRoutes);
|
|
app.use('/api/ocr', ocrRoutes);
|
|
app.use('/api/notifications', notificationRoutes);
|
|
app.use('/api/backup', backupRoutes);
|
|
app.use('/api/server', serverRoutes);
|
|
app.use('/api/settings', settingsRoutes);
|
|
app.use('/api/templates', templateRoutes);
|
|
|
|
app.get(['/', '/api'], (req, res) => {
|
|
res.set('X-TIS-RMS', 'true');
|
|
res.json({ message: 'TIS RMS API is running' });
|
|
});
|
|
|
|
app.listen(PORT, '0.0.0.0', () => {
|
|
console.log(`Server running on port ${PORT} (0.0.0.0)`);
|
|
// Run auto-graduation check on startup and daily
|
|
try {
|
|
const { checkAndRunAutoGraduation } = require('./src/services/autoGraduationService');
|
|
checkAndRunAutoGraduation(1);
|
|
setInterval(() => checkAndRunAutoGraduation(1), 24 * 60 * 60 * 1000);
|
|
} catch (err) {
|
|
console.error('Failed to start auto-graduation schedule:', err.message);
|
|
}
|
|
|
|
// Run auto-archiving check on startup and daily (for Enrolled students without active enrollment past grace period)
|
|
try {
|
|
const { checkAndRunAutoArchive } = require('./src/services/autoArchiveService');
|
|
checkAndRunAutoArchive(1);
|
|
setInterval(() => checkAndRunAutoArchive(1), 24 * 60 * 60 * 1000);
|
|
} catch (err) {
|
|
console.error('Failed to start auto-archiving schedule:', err.message);
|
|
}
|
|
|
|
// Initialize Auto Cloudflare Tunnel activation when internet is connected
|
|
try {
|
|
const { startAutoTunnel } = require('./src/services/tunnelService');
|
|
startAutoTunnel();
|
|
} catch (err) {
|
|
console.error('Failed to start auto tunnel service:', err.message);
|
|
}
|
|
|
|
// Initialize Password Reset Link Expiration Monitor
|
|
try {
|
|
const { startResetLinkMonitor } = require('./src/services/passwordResetMonitor');
|
|
startResetLinkMonitor();
|
|
} catch (err) {
|
|
console.error('Failed to start password reset link monitor:', err.message);
|
|
}
|
|
|
|
// Initialize Firebase Cloud Messaging for Push Notifications
|
|
try {
|
|
require('./src/services/fcmService').init();
|
|
} catch (err) {
|
|
console.error('Failed to initialize FCM service:', err.message);
|
|
}
|
|
});
|