Tech4biz_verify-india-api/src/database/setup.js
2025-12-18 12:41:06 +05:30

245 lines
7.1 KiB
JavaScript

/**
* Database Schema Setup Script
* Run this script once to create all required tables
* Usage: npm run db:setup
*/
require('dotenv').config();
const { pool } = require('./connection');
// SQL statements to create tables (matching Developer Guide Part 2)
const createTablesSQL = `
-- ============================================
-- TABLE: users
-- ============================================
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),
phone VARCHAR(20),
email_verified BOOLEAN DEFAULT FALSE,
verification_token VARCHAR(255),
plan VARCHAR(50) DEFAULT 'free',
plan_started_at TIMESTAMP,
plan_expires_at TIMESTAMP,
monthly_quota INTEGER DEFAULT 100,
calls_this_month INTEGER DEFAULT 0,
quota_reset_date DATE,
razorpay_customer_id VARCHAR(100),
razorpay_subscription_id VARCHAR(100),
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
last_login_at TIMESTAMP,
is_active BOOLEAN DEFAULT TRUE
);
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
-- ============================================
-- TABLE: api_keys
-- ============================================
CREATE TABLE IF NOT EXISTS api_keys (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
key_prefix VARCHAR(20) NOT NULL,
key_hash VARCHAR(255) NOT NULL,
key_hint VARCHAR(10),
name VARCHAR(100) DEFAULT 'Default',
is_test_key BOOLEAN DEFAULT FALSE,
is_active BOOLEAN DEFAULT TRUE,
last_used_at TIMESTAMP,
total_calls INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW(),
expires_at TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_api_keys_user ON api_keys(user_id);
CREATE INDEX IF NOT EXISTS idx_api_keys_hash ON api_keys(key_hash);
-- ============================================
-- TABLE: api_calls
-- ============================================
CREATE TABLE IF NOT EXISTS api_calls (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
api_key_id INTEGER REFERENCES api_keys(id),
endpoint VARCHAR(100) NOT NULL,
method VARCHAR(10) NOT NULL,
request_params JSONB,
response_status INTEGER,
response_time_ms INTEGER,
success BOOLEAN,
error_message VARCHAR(500),
credits_used INTEGER DEFAULT 1,
is_billable BOOLEAN DEFAULT TRUE,
ip_address VARCHAR(45),
user_agent VARCHAR(500),
called_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_api_calls_user ON api_calls(user_id);
CREATE INDEX IF NOT EXISTS idx_api_calls_date ON api_calls(called_at);
CREATE INDEX IF NOT EXISTS idx_api_calls_endpoint ON api_calls(endpoint);
-- ============================================
-- TABLE: ifsc_codes
-- ============================================
CREATE TABLE IF NOT EXISTS ifsc_codes (
id SERIAL PRIMARY KEY,
ifsc VARCHAR(11) UNIQUE NOT NULL,
bank_name VARCHAR(255) NOT NULL,
branch VARCHAR(255),
address TEXT,
city VARCHAR(100),
district VARCHAR(100),
state VARCHAR(100),
contact VARCHAR(100),
upi_enabled BOOLEAN DEFAULT FALSE,
rtgs_enabled BOOLEAN DEFAULT TRUE,
neft_enabled BOOLEAN DEFAULT TRUE,
imps_enabled BOOLEAN DEFAULT TRUE,
micr_code VARCHAR(20),
swift_code VARCHAR(20),
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_ifsc ON ifsc_codes(ifsc);
-- ============================================
-- TABLE: pincodes
-- ============================================
CREATE TABLE IF NOT EXISTS pincodes (
id SERIAL PRIMARY KEY,
pincode VARCHAR(6) NOT NULL,
office_name VARCHAR(255),
office_type VARCHAR(50),
district VARCHAR(100),
division VARCHAR(100),
region VARCHAR(100),
state VARCHAR(100),
latitude DECIMAL(10, 8),
longitude DECIMAL(11, 8),
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_pincode ON pincodes(pincode);
-- ============================================
-- TABLE: pan_data
-- ============================================
CREATE TABLE IF NOT EXISTS pan_data (
pan_number VARCHAR(10) PRIMARY KEY,
full_name VARCHAR(255),
father_name VARCHAR(255),
date_of_birth DATE,
gender VARCHAR(10),
category VARCHAR(50),
status VARCHAR(50),
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_pan_number ON pan_data(pan_number);
-- ============================================
-- TABLE: subscriptions
-- ============================================
CREATE TABLE IF NOT EXISTS subscriptions (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
razorpay_subscription_id VARCHAR(100),
razorpay_payment_id VARCHAR(100),
razorpay_plan_id VARCHAR(100),
plan_name VARCHAR(50),
amount DECIMAL(10, 2),
currency VARCHAR(3) DEFAULT 'INR',
status VARCHAR(50),
current_period_start TIMESTAMP,
current_period_end TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW(),
cancelled_at TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_subscriptions_user ON subscriptions(user_id);
-- ============================================
-- TABLE: invoices
-- ============================================
CREATE TABLE IF NOT EXISTS invoices (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
subscription_id INTEGER REFERENCES subscriptions(id),
invoice_number VARCHAR(50) UNIQUE,
amount DECIMAL(10, 2),
tax_amount DECIMAL(10, 2),
total_amount DECIMAL(10, 2),
currency VARCHAR(3) DEFAULT 'INR',
status VARCHAR(50),
razorpay_invoice_id VARCHAR(100),
razorpay_payment_id VARCHAR(100),
invoice_date DATE,
due_date DATE,
paid_at TIMESTAMP,
pdf_url VARCHAR(500),
created_at TIMESTAMP DEFAULT NOW()
);
`;
/**
* Run database setup
*/
const setupDatabase = async () => {
console.log('🚀 Starting database setup...\n');
const client = await pool.connect();
try {
// Start transaction
await client.query('BEGIN');
// Create tables
console.log('📦 Creating tables...');
await client.query(createTablesSQL);
console.log('✅ Tables created successfully\n');
// Commit transaction
await client.query('COMMIT');
// Display created tables
const tablesResult = await client.query(`
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'public'
AND table_type = 'BASE TABLE'
ORDER BY table_name;
`);
console.log('📋 Created tables:');
tablesResult.rows.forEach((row, index) => {
console.log(` ${index + 1}. ${row.table_name}`);
});
console.log('\n✅ Database setup completed successfully!');
} catch (error) {
// Rollback on error
await client.query('ROLLBACK');
console.error('\n❌ Database setup failed:', error.message);
console.error('🔄 Transaction rolled back');
throw error;
} finally {
client.release();
}
};
// Run setup
setupDatabase()
.then(() => {
console.log('\n👋 Exiting...');
process.exit(0);
})
.catch((error) => {
console.error('\n💥 Fatal error:', error);
process.exit(1);
});