Initial commit: TenderPilot MVP

This commit is contained in:
Peter Foster
2026-02-14 07:43:48 +00:00
commit 61593ea94e
1534 changed files with 202152 additions and 0 deletions

101
init-db.js Executable file
View File

@@ -0,0 +1,101 @@
import pg from 'pg';
import dotenv from 'dotenv';
dotenv.config();
async function setupDatabase() {
try {
// First connect as postgres to create tables
const adminClient = new pg.Client({
host: 'localhost',
port: 5432,
database: 'tenderpilot',
user: 'tenderpilot',
password: 'tenderpilot123'
});
await adminClient.connect();
console.log('Connected to tenderpilot database');
// Create tables
await adminClient.query(`
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
company_name VARCHAR(255),
tier VARCHAR(50) DEFAULT 'free',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
verified BOOLEAN DEFAULT false
);
`);
console.log('Created users table');
await adminClient.query(`
CREATE TABLE IF NOT EXISTS tenders (
id SERIAL PRIMARY KEY,
source VARCHAR(100) NOT NULL,
source_id VARCHAR(255) UNIQUE NOT NULL,
title VARCHAR(500) NOT NULL,
description TEXT,
summary TEXT,
cpv_codes TEXT[],
value_low DECIMAL(15,2),
value_high DECIMAL(15,2),
currency VARCHAR(3) DEFAULT 'GBP',
published_date TIMESTAMP,
deadline TIMESTAMP,
authority_name VARCHAR(255),
authority_type VARCHAR(100),
location VARCHAR(255),
documents_url TEXT,
notice_url TEXT,
status VARCHAR(50) DEFAULT 'open',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
`);
console.log('Created tenders table');
await adminClient.query(`
CREATE TABLE IF NOT EXISTS profiles (
id SERIAL PRIMARY KEY,
user_id INTEGER UNIQUE REFERENCES users(id) ON DELETE CASCADE,
sectors TEXT[],
keywords TEXT[],
min_value DECIMAL(15,2),
max_value DECIMAL(15,2),
locations TEXT[],
authority_types TEXT[],
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
`);
console.log('Created profiles table');
await adminClient.query(`
CREATE TABLE IF NOT EXISTS matches (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
tender_id INTEGER REFERENCES tenders(id) ON DELETE CASCADE,
sent BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(user_id, tender_id)
);
`);
console.log('Created matches table');
// Create indexes
await adminClient.query('CREATE INDEX IF NOT EXISTS idx_tenders_source_id ON tenders(source_id);');
await adminClient.query('CREATE INDEX IF NOT EXISTS idx_tenders_deadline ON tenders(deadline);');
await adminClient.query('CREATE INDEX IF NOT EXISTS idx_matches_user_id ON matches(user_id);');
console.log('Created indexes');
await adminClient.end();
console.log('Database setup complete!');
} catch (error) {
console.error('Error setting up database:', error.message);
process.exit(1);
}
}
setupDatabase();