- Implemented setup_ordrestyring_import.sh for initial database setup and data import from API. - Created sync_ordrestyring_data.sh for incremental updates to the local database. - Developed test_ordrestyring_import.js to validate API data import functionality. - Added test_enhanced_quote_demo.js to demonstrate the enhanced quote system using hybrid data sources. - Introduced test_ordrestyring_system.sh for comprehensive testing of the database system and API functionality. - Enhanced logging and error handling across scripts for better traceability. - Included analysis script creation for post-import data analysis.
231 lines
7.8 KiB
JavaScript
231 lines
7.8 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
const axios = require('axios');
|
|
const mysql = require('mysql2/promise');
|
|
|
|
// Load environment
|
|
require('dotenv').config({ path: '.env.ordrestyring' });
|
|
|
|
const API_BASE = 'https://v2.api.ordrestyring.dk';
|
|
const TOKEN = process.env.ORDRESTYRING_TOKEN;
|
|
|
|
// Database configuration
|
|
const DB_CONFIG = {
|
|
host: process.env.DB_HOST,
|
|
port: parseInt(process.env.DB_PORT) || 3306,
|
|
database: process.env.DB_NAME,
|
|
user: process.env.DB_USER,
|
|
password: process.env.DB_PASSWORD
|
|
};
|
|
|
|
// Start with smaller test sets
|
|
const TEST_ENDPOINTS = [
|
|
{ endpoint: '/case-types', table: 'case_types', limit: 2 },
|
|
{ endpoint: '/case-statuses', table: 'case_statuses', limit: 6 },
|
|
{ endpoint: '/employee-types', table: 'employee_types', limit: 10 },
|
|
{ endpoint: '/users', table: 'users', limit: 10 },
|
|
{ endpoint: '/cases', table: 'cases', limit: 10 },
|
|
{ endpoint: '/case-materials', table: 'case_materials', limit: 10 },
|
|
{ endpoint: '/hours', table: 'hours', limit: 10 }
|
|
];
|
|
|
|
async function makeAPIRequest(endpoint, limit) {
|
|
try {
|
|
const config = {
|
|
method: 'GET',
|
|
url: `${API_BASE}${endpoint}`,
|
|
auth: {
|
|
username: TOKEN,
|
|
password: 'x'
|
|
},
|
|
params: {
|
|
pagesize: limit
|
|
}
|
|
};
|
|
|
|
const response = await axios(config);
|
|
|
|
// Convert object with numeric keys to array
|
|
const dataKeys = Object.keys(response.data);
|
|
const isArrayLike = dataKeys.length > 0 && dataKeys.every(key => !isNaN(key));
|
|
|
|
if (isArrayLike) {
|
|
return Object.values(response.data);
|
|
} else if (response.data.data && Array.isArray(response.data.data)) {
|
|
return response.data.data;
|
|
} else if (Array.isArray(response.data)) {
|
|
return response.data;
|
|
}
|
|
|
|
return [];
|
|
} catch (error) {
|
|
console.error(`❌ Error fetching ${endpoint}:`, error.message);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
async function insertRecords(connection, tableName, records) {
|
|
if (records.length === 0) {
|
|
console.log(`⚠️ No records to insert for ${tableName}`);
|
|
return 0;
|
|
}
|
|
|
|
// Get table structure
|
|
const [columns] = await connection.execute(`SHOW COLUMNS FROM ${tableName}`);
|
|
const columnNames = columns.map(col => col.Field).filter(name => {
|
|
// Include 'id' for tables that have it as primary key from API
|
|
const hasApiId = ['case_materials', 'hours', 'users', 'case_types', 'case_statuses', 'employee_types'].includes(tableName);
|
|
return name !== 'id' || hasApiId;
|
|
});
|
|
|
|
let insertedCount = 0;
|
|
let errorCount = 0;
|
|
|
|
for (const record of records) {
|
|
try {
|
|
// Prepare values for insertion
|
|
const values = columnNames.map(col => {
|
|
let value = record[col];
|
|
|
|
// Handle null values
|
|
if (value === null || value === undefined) {
|
|
return null;
|
|
}
|
|
|
|
// Handle arrays - convert to JSON string
|
|
if (Array.isArray(value)) {
|
|
return JSON.stringify(value);
|
|
}
|
|
|
|
// Handle boolean conversion
|
|
if (typeof value === 'boolean') {
|
|
return value;
|
|
}
|
|
|
|
// Handle numbers - keep as numbers
|
|
if (typeof value === 'number') {
|
|
return value;
|
|
}
|
|
|
|
// Convert empty strings to null
|
|
if (value === '') {
|
|
return null;
|
|
}
|
|
|
|
// Convert everything else to string
|
|
return String(value);
|
|
});
|
|
|
|
// Build INSERT query with proper ON DUPLICATE KEY handling
|
|
const placeholders = columnNames.map(() => '?').join(', ');
|
|
const updatePart = columnNames.filter(col => col !== 'id').map(col => `${col} = VALUES(${col})`).join(', ');
|
|
|
|
let query;
|
|
if (updatePart) {
|
|
query = `INSERT INTO ${tableName} (${columnNames.join(', ')}) VALUES (${placeholders})
|
|
ON DUPLICATE KEY UPDATE ${updatePart}`;
|
|
} else {
|
|
query = `INSERT IGNORE INTO ${tableName} (${columnNames.join(', ')}) VALUES (${placeholders})`;
|
|
}
|
|
|
|
await connection.execute(query, values);
|
|
insertedCount++;
|
|
|
|
} catch (error) {
|
|
errorCount++;
|
|
if (errorCount <= 3) { // Only show first 3 errors to avoid spam
|
|
console.error(`❌ Error inserting record into ${tableName}:`, error.message);
|
|
if (errorCount === 1) {
|
|
console.log('Sample problematic record:', JSON.stringify(record, null, 2));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (errorCount > 3) {
|
|
console.log(` ... and ${errorCount - 3} more errors`);
|
|
}
|
|
|
|
return insertedCount;
|
|
}
|
|
|
|
async function quickTest() {
|
|
console.log('🧪 Quick Ordrestyring API Test - Small Datasets');
|
|
console.log('===============================================');
|
|
|
|
let connection;
|
|
|
|
try {
|
|
// Connect to database
|
|
connection = await mysql.createConnection(DB_CONFIG);
|
|
console.log('✅ Database connection established');
|
|
|
|
const results = {};
|
|
|
|
for (const { endpoint, table, limit } of TEST_ENDPOINTS) {
|
|
console.log(`\n📊 Testing: ${endpoint} -> ${table} (limit: ${limit})`);
|
|
|
|
// Fetch data from API
|
|
const records = await makeAPIRequest(endpoint, limit);
|
|
console.log(`📥 Fetched ${records.length} records`);
|
|
|
|
if (records.length > 0) {
|
|
// Insert records into database
|
|
const insertedCount = await insertRecords(connection, table, records);
|
|
console.log(`✅ Successfully inserted ${insertedCount}/${records.length} records`);
|
|
|
|
results[endpoint] = {
|
|
table: table,
|
|
fetched: records.length,
|
|
inserted: insertedCount,
|
|
success: insertedCount > 0
|
|
};
|
|
} else {
|
|
results[endpoint] = {
|
|
table: table,
|
|
fetched: 0,
|
|
inserted: 0,
|
|
success: false
|
|
};
|
|
}
|
|
|
|
// Small delay
|
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
}
|
|
|
|
console.log('\n🎉 Quick Test Complete!');
|
|
console.log('\n📊 Results Summary:');
|
|
|
|
let totalSuccess = 0;
|
|
for (const [endpoint, result] of Object.entries(results)) {
|
|
const status = result.success ? '✅' : '❌';
|
|
console.log(` ${status} ${endpoint}: ${result.inserted}/${result.fetched} imported`);
|
|
if (result.success) totalSuccess++;
|
|
}
|
|
|
|
console.log(`\n🎯 Overall: ${totalSuccess}/${Object.keys(results).length} endpoints working`);
|
|
|
|
// Show what's in database now
|
|
console.log('\n📊 Database content:');
|
|
for (const { table } of TEST_ENDPOINTS) {
|
|
const [rows] = await connection.execute(`SELECT COUNT(*) as count FROM ${table}`);
|
|
console.log(` ${table}: ${rows[0].count} records`);
|
|
}
|
|
|
|
} catch (error) {
|
|
console.error('❌ Test failed:', error);
|
|
} finally {
|
|
if (connection) {
|
|
await connection.end();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Run test
|
|
if (!TOKEN) {
|
|
console.error('❌ ORDRESTYRING_TOKEN not found in environment');
|
|
process.exit(1);
|
|
}
|
|
|
|
quickTest().catch(console.error);
|