Files
tilbudgivern/analyze_api_data_formats.js
T
alex 10473e8a32 feat: Add complete data import and incremental update scripts for Ordrestyring
- 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.
2025-09-19 15:06:03 +02:00

253 lines
7.9 KiB
JavaScript

#!/usr/bin/env node
const axios = require('axios');
const fs = require('fs');
// Load environment
require('dotenv').config({ path: '.env.ordrestyring' });
const API_BASE = 'https://v2.api.ordrestyring.dk';
const TOKEN = process.env.ORDRESTYRING_TOKEN;
if (!TOKEN) {
console.error('❌ ORDRESTYRING_TOKEN not found in environment');
process.exit(1);
}
// API endpoints to analyze
const endpoints = [
'/cases',
'/case-materials',
'/hours',
'/debtors',
'/debtor-invoices',
'/users',
'/departments',
'/case-types',
'/case-statuses',
'/employee-types'
];
async function makeRequest(endpoint, params = {}) {
try {
const config = {
method: 'GET',
url: `${API_BASE}${endpoint}`,
auth: {
username: TOKEN,
password: 'x'
},
params: {
pagesize: 5, // Just get 5 samples to analyze format
...params
}
};
console.log(`🌐 Making request to: ${config.url}`);
console.log(`🔑 Auth: ${TOKEN.substring(0, 8)}***`);
const response = await axios(config);
console.log(`📦 Response status: ${response.status}`);
console.log(`📊 Response data structure:`, {
hasData: !!response.data,
dataType: typeof response.data,
dataKeys: response.data ? Object.keys(response.data) : [],
totalProperty: response.data?.total,
dataLength: response.data?.data?.length
});
return response.data;
} catch (error) {
console.error(`❌ Error fetching ${endpoint}:`, {
status: error.response?.status,
statusText: error.response?.statusText,
message: error.message,
responseData: error.response?.data
});
return null;
}
}
async function analyzeDataFormats() {
console.log('🔍 Analyzing Ordrestyring API Data Formats');
console.log('==========================================');
const analysis = {
timestamp: new Date().toISOString(),
endpoints: {}
};
for (const endpoint of endpoints) {
console.log(`\n📊 Analyzing ${endpoint}...`);
const data = await makeRequest(endpoint);
if (data && typeof data === 'object') {
// Check if response is an array-like object with numeric keys
const dataKeys = Object.keys(data);
const isArrayLike = dataKeys.length > 0 && dataKeys.every(key => !isNaN(key));
let records = [];
let totalCount = 0;
if (isArrayLike) {
// Convert object with numeric keys to array
records = Object.values(data);
totalCount = records.length;
} else if (data.data && Array.isArray(data.data)) {
// Standard API response format
records = data.data;
totalCount = data.total || records.length;
} else if (Array.isArray(data)) {
// Direct array response
records = data;
totalCount = records.length;
}
if (records.length > 0) {
const sampleRecord = records[0];
const recordStructure = analyzeRecordStructure(sampleRecord);
analysis.endpoints[endpoint] = {
available: true,
totalRecords: totalCount,
sampleRecord: sampleRecord,
structure: recordStructure,
suggestedTableName: endpoint.replace('/', '').replace('-', '_'),
sqlSchema: generateSQLSchema(endpoint.replace('/', '').replace('-', '_'), recordStructure)
};
console.log(`✅ ${endpoint}: ${totalCount} records available`);
console.log(` Structure: ${Object.keys(recordStructure).length} fields`);
console.log(` Key fields: ${Object.keys(recordStructure).slice(0, 5).join(', ')}`);
console.log(` Sample ID: ${sampleRecord.id || 'N/A'}`);
} else {
analysis.endpoints[endpoint] = {
available: false,
error: 'No records in response'
};
console.log(`❌ ${endpoint}: No records found`);
}
} else {
analysis.endpoints[endpoint] = {
available: false,
error: 'No data or empty response'
};
console.log(`❌ ${endpoint}: No data available`);
}
// Small delay to be respectful to API
await new Promise(resolve => setTimeout(resolve, 200));
}
// Save analysis
fs.writeFileSync('api_data_formats_analysis.json', JSON.stringify(analysis, null, 2));
console.log('\n💾 Analysis saved to api_data_formats_analysis.json');
// Generate combined SQL schema
generateCombinedSchema(analysis);
return analysis;
}
function analyzeRecordStructure(record) {
const structure = {};
for (const [key, value] of Object.entries(record)) {
let type = typeof value;
let sqlType = 'TEXT';
let maxLength = null;
if (value === null) {
type = 'null';
sqlType = 'TEXT NULL';
} else if (type === 'string') {
maxLength = value.length;
if (maxLength <= 255) {
sqlType = `VARCHAR(${Math.max(255, maxLength * 2)})`;
} else {
sqlType = 'TEXT';
}
// Check if it's a date
if (isDateString(value)) {
type = 'date';
sqlType = 'DATETIME';
}
} else if (type === 'number') {
if (Number.isInteger(value)) {
sqlType = 'INT';
} else {
sqlType = 'DECIMAL(10,2)';
}
} else if (type === 'boolean') {
sqlType = 'BOOLEAN';
} else if (type === 'object') {
sqlType = 'JSON';
}
structure[key] = {
type,
sqlType,
maxLength,
sampleValue: value
};
}
return structure;
}
function isDateString(str) {
if (typeof str !== 'string') return false;
const date = new Date(str);
return !isNaN(date.getTime()) && (str.includes('T') || str.includes('-'));
}
function generateSQLSchema(tableName, structure) {
const fields = [];
// Add primary key
if (structure.id) {
fields.push(`id ${structure.id.sqlType} PRIMARY KEY`);
} else {
fields.push(`id INT AUTO_INCREMENT PRIMARY KEY`);
}
// Add other fields
for (const [fieldName, fieldInfo] of Object.entries(structure)) {
if (fieldName !== 'id') {
const nullable = fieldInfo.type === 'null' ? '' : ' NULL';
fields.push(`${fieldName} ${fieldInfo.sqlType}${nullable}`);
}
}
return `CREATE TABLE IF NOT EXISTS ${tableName} (
${fields.join(',\n ')}
);`;
}
function generateCombinedSchema(analysis) {
let combinedSchema = `-- Ordrestyring API Database Schema
-- Generated: ${new Date().toISOString()}
--
-- This schema supports all data types from Ordrestyring API
USE ordrestyring_local;
`;
for (const [endpoint, data] of Object.entries(analysis.endpoints)) {
if (data.available && data.sqlSchema) {
combinedSchema += `-- Table for ${endpoint}\n`;
combinedSchema += data.sqlSchema + '\n\n';
}
}
fs.writeFileSync('ordrestyring_complete_schema.sql', combinedSchema);
console.log('📝 Complete SQL schema saved to ordrestyring_complete_schema.sql');
}
// Run analysis
analyzeDataFormats().catch(console.error);