Spaces:
Running
Running
| ```javascript | |
| const express = require('express'); | |
| const sqlite3 = require('sqlite3').verbose(); | |
| const path = require('path'); | |
| const app = express(); | |
| const PORT = process.env.PORT || 3000; | |
| // Initialize database | |
| const db = new sqlite3.Database('./stockfolio.db', (err) => { | |
| if (err) { | |
| console.error('Database connection error:', err.message); | |
| } else { | |
| console.log('Connected to SQLite database'); | |
| initializeDatabase(); | |
| } | |
| }); | |
| function initializeDatabase() { | |
| db.serialize(() => { | |
| // Create tables if they don't exist | |
| db.run(`CREATE TABLE IF NOT EXISTS users ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| name TEXT NOT NULL, | |
| email TEXT UNIQUE NOT NULL, | |
| password TEXT NOT NULL, | |
| uac_verified BOOLEAN DEFAULT 0, | |
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
| )`); | |
| db.run(`CREATE TABLE IF NOT EXISTS companies ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| symbol TEXT UNIQUE NOT NULL, | |
| name TEXT NOT NULL, | |
| sector TEXT NOT NULL, | |
| current_price REAL NOT NULL, | |
| change_percent REAL NOT NULL, | |
| volume INTEGER NOT NULL, | |
| market_cap REAL, | |
| pe_ratio REAL, | |
| dividend_yield REAL, | |
| last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
| )`); | |
| db.run(`CREATE TABLE IF NOT EXISTS sectors ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| name TEXT UNIQUE NOT NULL, | |
| weightage REAL NOT NULL, | |
| change_percent REAL NOT NULL, | |
| top_stock TEXT NOT NULL, | |
| last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
| )`); | |
| db.run(`CREATE TABLE IF NOT EXISTS portfolio ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| user_id INTEGER NOT NULL, | |
| company_id INTEGER NOT NULL, | |
| shares REAL NOT NULL, | |
| avg_price REAL NOT NULL, | |
| FOREIGN KEY (user_id) REFERENCES users (id), | |
| FOREIGN KEY (company_id) REFERENCES companies (id) | |
| )`); | |
| db.run(`CREATE TABLE IF NOT EXISTS transactions ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| user_id INTEGER NOT NULL, | |
| company_id INTEGER NOT NULL, | |
| type TEXT CHECK(type IN ('BUY', 'SELL')) NOT NULL, | |
| shares REAL NOT NULL, | |
| price REAL NOT NULL, | |
| total_amount REAL NOT NULL, | |
| transaction_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | |
| FOREIGN KEY (user_id) REFERENCES users (id), | |
| FOREIGN KEY (company_id) REFERENCES companies (id) | |
| )`); | |
| db.run(`CREATE TABLE IF NOT EXISTS uac_reports ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| user_id INTEGER NOT NULL, | |
| report_type TEXT NOT NULL, | |
| period TEXT NOT NULL, | |
| file_path TEXT NOT NULL, | |
| generated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, | |
| FOREIGN KEY (user_id) REFERENCES users (id) | |
| )`); | |
| // Insert sample data if tables are empty | |
| db.get("SELECT COUNT(*) as count FROM companies", (err, row) => { | |
| if (row.count === 0) { | |
| console.log('Inserting sample company data...'); | |
| const companies = require('./sample-data/companies.json'); | |
| const stmt = db.prepare("INSERT INTO companies (symbol, name, sector, current_price, change_percent, volume) VALUES (?, ?, ?, ?, ?, ?)"); | |
| companies.forEach(company => { | |
| stmt.run(company.symbol, company.name, company.sector, company.current_price, company.change_percent, company.volume); | |
| }); | |
| stmt.finalize(); | |
| } | |
| }); | |
| db.get("SELECT COUNT(*) as count FROM sectors", (err, row) => { | |
| if (row.count === 0) { | |
| console.log('Inserting sample sector data...'); | |
| const sectors = require('./sample-data/sectors.json'); | |
| const stmt = db.prepare("INSERT INTO sectors (name, weightage, change_percent, top_stock) VALUES (?, ?, ?, ?)"); | |
| sectors.forEach(sector => { | |
| stmt.run(sector.name, sector.weightage, sector.change_percent, sector.top_stock); | |
| }); | |
| stmt.finalize(); | |
| } | |
| }); | |
| }); | |
| } | |
| // Middleware | |
| app.use(express.json()); | |
| app.use(express.static(path.join(__dirname, 'public'))); | |
| // API Routes | |
| app.get('/api/companies', (req, res) => { | |
| db.all("SELECT * FROM companies ORDER BY symbol", [], (err, rows) => { | |
| if (err) { | |
| res.status(500).json({ error: err.message }); | |
| return; | |
| } | |
| res.json(rows); | |
| }); | |
| }); | |
| app.get('/api/sectors', (req, res) => { | |
| db.all("SELECT * FROM sectors ORDER BY name", [], (err, rows) => { | |
| if (err) { | |
| res.status(500).json({ error: err.message }); | |
| return; | |
| } | |
| res.json(rows); | |
| }); | |
| }); | |
| app.get('/api/market-summary', (req, res) => { | |
| db.get("SELECT SUM(volume) as total_volume, SUM(current_price * volume) as total_value FROM companies", [], (err, row) => { | |
| if (err) { | |
| res.status(500).json({ error: err.message }); | |
| return; | |
| } | |
| res.json({ | |
| volume: row.total_volume, | |
| value: row.total_value | |
| }); | |
| }); | |
| }); | |
| app.get('/api/uac-reports/:userId', (req, res) => { | |
| db.all("SELECT * FROM uac_reports WHERE user_id = ? ORDER BY generated_at DESC", [req.params.userId], (err, rows) => { | |
| if (err) { | |
| res.status(500).json({ error: err.message }); | |
| return; | |
| } | |
| res.json(rows); | |
| }); | |
| }); | |
| // Serve HTML files | |
| app.get(['/', '/dashboard'], (req, res) => { | |
| res.sendFile(path.join(__dirname, 'public', 'index.html')); | |
| }); | |
| app.get('/psx-companies', (req, res) => { | |
| res.sendFile(path.join(__dirname, 'public', 'psx-companies.html')); | |
| }); | |
| app.get('/sector-analysis', (req, res) => { | |
| res.sendFile(path.join(__dirname, 'public', 'sector-analysis.html')); | |
| }); | |
| app.get('/uac-reports', (req, res) => { | |
| res.sendFile(path.join(__dirname, 'public', 'uac-reports.html')); | |
| }); | |
| // Start server | |
| app.listen(PORT, () => { | |
| console.log(`Server running on port ${PORT}`); | |
| }); | |
| process.on('SIGINT', () => { | |
| db.close(); | |
| process.exit(); | |
| }); | |
| ``` | |
| <<<<<<< PROJECT_NAME_START Stockfolio PKX >>>>>>> PROJECT_NAME_END |