4 * Create "Precise PCs" Tenant in PostgreSQL
6 * This script creates a new tenant for Precise PCs customers
7 * being migrated from WHMCS.
10require('dotenv').config();
11const { Pool } = require('pg');
12const { v4: uuidv4 } = require('uuid');
14// PostgreSQL connection
15const pool = new Pool({
16 host: process.env.DB_HOST,
17 port: process.env.DB_PORT,
18 user: process.env.DB_USER,
19 password: process.env.DB_PASSWORD,
20 database: process.env.DB_NAME,
21 ssl: process.env.DB_HOST.includes('digitalocean') ? { rejectUnauthorized: false } : false
27async function createPrecisePCsTenant() {
28 console.log('========================================');
29 console.log('Creating Precise PCs Tenant');
30 console.log('========================================');
34 // Check if tenant already exists
35 const existingCheck = await pool.query(
36 "SELECT tenant_id, name, subdomain FROM tenants WHERE name ILIKE '%Precise%' OR subdomain ILIKE '%precise%'"
39 if (existingCheck.rows.length > 0) {
40 const existing = existingCheck.rows[0];
41 console.log('⚠️ Tenant already exists:');
42 console.log(` ID: ${existing.tenant_id}`);
43 console.log(` Name: ${existing.name}`);
44 console.log(` Subdomain: ${existing.subdomain || 'N/A'}`);
46 console.log('Using existing tenant for import...');
49 const fs = require('fs');
50 const path = require('path');
51 const exportDir = path.join(__dirname, '..', 'exports');
53 if (!fs.existsSync(exportDir)) {
54 fs.mkdirSync(exportDir, { recursive: true });
58 path.join(exportDir, 'precise_pcs_tenant.json'),
60 tenant_id: existing.tenant_id,
62 subdomain: existing.subdomain
66 return existing.tenant_id;
70 const tenantId = uuidv4();
74 subdomain: 'precisepcs',
77 email_automation: JSON.stringify({
78 migrated_from: 'WHMCS',
79 migration_date: new Date().toISOString(),
80 original_whmcs_url: 'https://clientarea.precisewebhosting.com.au',
81 original_domain: 'precisewebhosting.com.au',
84 support_tickets: true,
85 domain_management: true,
86 wordpress_hosting: true
93 tenant_id, name, subdomain, status, is_msp,
94 email_automation, created_at, updated_at
96 $1, $2, $3, $4, $5, $6, NOW(), NOW()
98 RETURNING tenant_id, name, subdomain, status, is_msp, created_at
101 const result = await pool.query(insertQuery, [
102 tenantData.tenant_id,
104 tenantData.subdomain,
107 tenantData.email_automation
110 const tenant = result.rows[0];
112 console.log('✅ Tenant created successfully!');
114 console.log('Tenant Details:');
115 console.log('─────────────────────────────────────');
116 console.log(`ID: ${tenant.tenant_id}`);
117 console.log(`Name: ${tenant.name}`);
118 console.log(`Subdomain: ${tenant.subdomain}`);
119 console.log(`Status: ${tenant.status}`);
120 console.log(`Is MSP: ${tenant.is_msp}`);
121 console.log(`Created: ${tenant.created_at}`);
122 console.log('─────────────────────────────────────');
125 // Save tenant ID to file for import script
126 const fs = require('fs');
127 const path = require('path');
128 const exportDir = path.join(__dirname, '..', 'exports');
130 if (!fs.existsSync(exportDir)) {
131 fs.mkdirSync(exportDir, { recursive: true });
135 path.join(exportDir, 'precise_pcs_tenant.json'),
137 tenant_id: tenant.tenant_id,
139 subdomain: tenant.subdomain,
140 created_at: tenant.created_at
144 console.log('💾 Tenant ID saved to: exports/precise_pcs_tenant.json');
147 return tenant.tenant_id;
150 console.error('❌ Error creating tenant:', error.message);
157// Run if executed directly
158if (require.main === module) {
159 createPrecisePCsTenant()
161 console.log('✅ Tenant creation complete');
165 console.error('❌ Tenant creation failed:', error);
170module.exports = { createPrecisePCsTenant };