248 lines
8.5 KiB
Bash
Executable File
248 lines
8.5 KiB
Bash
Executable File
#!/bin/bash
|
||
#
|
||
# COMPREHENSIVE Ordrestyring Data Sync Script
|
||
# Imports ALL data from Ordrestyring API v2 for advanced tilbudsberegning
|
||
# Includes: Cases, Materials, Hours, Calendar, Employees, Financial data
|
||
# Suitable for running as hourly cron job for fresh data
|
||
#
|
||
|
||
set -e
|
||
|
||
# Colors for output
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
PURPLE='\033[0;35m'
|
||
CYAN='\033[0;36m'
|
||
NC='\033[0m'
|
||
|
||
# Configuration
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
LOG_FILE="$SCRIPT_DIR/ordrestyring_comprehensive_sync.log"
|
||
LOCK_FILE="$SCRIPT_DIR/ordrestyring_comprehensive_sync.lock"
|
||
|
||
# Function to log with timestamp
|
||
log() {
|
||
echo -e "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
|
||
}
|
||
|
||
# Function to cleanup on exit
|
||
cleanup() {
|
||
if [ -f "$LOCK_FILE" ]; then
|
||
rm -f "$LOCK_FILE"
|
||
fi
|
||
}
|
||
trap cleanup EXIT
|
||
|
||
# Check if another sync is already running
|
||
if [ -f "$LOCK_FILE" ]; then
|
||
log "${RED}❌ Another comprehensive sync process is already running (lock file exists)${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
# Create lock file
|
||
echo $$ > "$LOCK_FILE"
|
||
|
||
log "${CYAN}� Starting COMPREHENSIVE Ordrestyring sync for Tilbudsberegning${NC}"
|
||
log "${BLUE}📊 Importing: Cases, Materials, Hours, Calendar, Employees, Financial Data${NC}"
|
||
|
||
# Export API token (using the working v2 API key)
|
||
export ORDRESTYRING_TOKEN="cRD7xfeoiGh1OhzV"
|
||
|
||
# Change to script directory
|
||
cd "$SCRIPT_DIR"
|
||
|
||
# Check if comprehensive import script exists
|
||
if [ ! -f "comprehensive_ordrestyring_import.js" ]; then
|
||
log "${RED}❌ Comprehensive import script not found: comprehensive_ordrestyring_import.js${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
# Check database connection
|
||
log "${YELLOW}� Checking database connection...${NC}"
|
||
if ! command -v mysql &> /dev/null; then
|
||
log "${RED}❌ MySQL client not found${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
# Test database connection
|
||
if ! mysql -u ordrestyring_user -psecure_password123 -h localhost ordrestyring_local -e "SELECT 1;" &> /dev/null; then
|
||
log "${RED}❌ Database connection failed${NC}"
|
||
exit 1
|
||
fi
|
||
log "${GREEN}✅ Database connection verified${NC}"
|
||
|
||
# Run comprehensive sync
|
||
log "${PURPLE}📥 Running comprehensive Ordrestyring data sync...${NC}"
|
||
log "${CYAN} - All Cases with historical data${NC}"
|
||
log "${CYAN} - Customer database (Debtors)${NC}"
|
||
log "${CYAN} - Employee data and types${NC}"
|
||
log "${CYAN} - Time tracking (Hours)${NC}"
|
||
log "${CYAN} - Materials and cost data${NC}"
|
||
log "${CYAN} - Calendar/planning data${NC}"
|
||
log "${CYAN} - Financial data (Invoices)${NC}"
|
||
log "${CYAN} - Analytics generation${NC}"
|
||
#!/usr/bin/env node
|
||
/**
|
||
* Incremental Ordrestyring API Data Import
|
||
* Only imports records modified in the last 24 hours
|
||
*/
|
||
|
||
const OrdrestyringImporter = require('./ordrestyring_full_import');
|
||
const mysql = require('mysql2/promise');
|
||
|
||
class IncrementalImporter extends OrdrestyringImporter {
|
||
constructor() {
|
||
super();
|
||
|
||
// Get timestamp for 24 hours ago
|
||
this.since = Math.floor((Date.now() - (24 * 60 * 60 * 1000)) / 1000);
|
||
console.log(`🕐 Importing records updated since: ${new Date(this.since * 1000).toISOString()}`);
|
||
}
|
||
|
||
async makeApiRequest(endpoint, params = {}) {
|
||
// Add since parameter for incremental updates
|
||
const incrementalParams = {
|
||
...params,
|
||
since: this.since
|
||
};
|
||
|
||
return super.makeApiRequest(endpoint, incrementalParams);
|
||
}
|
||
|
||
async runIncrementalImport() {
|
||
console.log('🔄 Starting incremental Ordrestyring API import...');
|
||
console.log(`📅 Start time: ${this.startTime.toISOString()}`);
|
||
|
||
try {
|
||
// Import in dependency order
|
||
await this.importWithPagination('/debtors', this.importDebtors.bind(this), 'debtors');
|
||
await this.importWithPagination('/users', this.importUsers.bind(this), 'users');
|
||
await this.importWithPagination('/cases', this.importCases.bind(this), 'cases');
|
||
await this.importWithPagination('/case-materials', this.importCaseMaterials.bind(this), 'materials');
|
||
await this.importWithPagination('/hours', this.importHours.bind(this), 'hours');
|
||
await this.importWithPagination('/debtor-invoices', this.importDebtorInvoices.bind(this), 'invoices');
|
||
|
||
// Summary
|
||
const endTime = new Date();
|
||
const duration = Math.round((endTime - this.startTime) / 1000);
|
||
|
||
console.log('\n🎉 Incremental import completed!');
|
||
console.log(`⏱️ Duration: ${duration} seconds`);
|
||
|
||
// Check if any data was actually updated
|
||
const totalUpdated = Object.values(this.importStats).reduce((sum, stats) =>
|
||
sum + stats.imported + stats.updated, 0
|
||
);
|
||
|
||
if (totalUpdated === 0) {
|
||
console.log('ℹ️ No new or updated records found');
|
||
} else {
|
||
console.log(`📊 ${totalUpdated} records processed`);
|
||
}
|
||
|
||
return { success: true, duration, totalUpdated, stats: this.importStats };
|
||
|
||
} catch (error) {
|
||
console.error('❌ Incremental import failed:', error.message);
|
||
return { success: false, error: error.message };
|
||
}
|
||
}
|
||
}
|
||
|
||
// Main execution
|
||
async function main() {
|
||
const importer = new IncrementalImporter();
|
||
|
||
try {
|
||
await importer.connect();
|
||
const result = await importer.runIncrementalImport();
|
||
|
||
if (result.success) {
|
||
process.exit(0);
|
||
} else {
|
||
process.exit(1);
|
||
}
|
||
} catch (error) {
|
||
console.error('❌ Application error:', error.message);
|
||
process.exit(1);
|
||
} finally {
|
||
await importer.disconnect();
|
||
}
|
||
}
|
||
|
||
if (require.main === module) {
|
||
main();
|
||
}
|
||
EOF
|
||
|
||
# Run the comprehensive import
|
||
START_TIME=$(date +%s)
|
||
node comprehensive_ordrestyring_import.js 2>&1 | tee -a "$LOG_FILE"
|
||
|
||
# Check exit status
|
||
IMPORT_EXIT_CODE=${PIPESTATUS[0]}
|
||
END_TIME=$(date +%s)
|
||
DURATION=$((END_TIME - START_TIME))
|
||
|
||
if [ $IMPORT_EXIT_CODE -eq 0 ]; then
|
||
log "${GREEN}✅ Comprehensive sync completed successfully in ${DURATION} seconds${NC}"
|
||
|
||
# Log success metrics
|
||
TOTAL_RECORDS=$(mysql -u ordrestyring_user -psecure_password123 -h localhost ordrestyring_local -se "
|
||
SELECT
|
||
(SELECT COUNT(*) FROM ordrestyring_cases) +
|
||
(SELECT COUNT(*) FROM ordrestyring_debtors) +
|
||
(SELECT COUNT(*) FROM ordrestyring_users) +
|
||
(SELECT COUNT(*) FROM ordrestyring_hours) +
|
||
(SELECT COUNT(*) FROM ordrestyring_case_materials) +
|
||
(SELECT COUNT(*) FROM ordrestyring_calendar) as total_records
|
||
" 2>/dev/null || echo "0")
|
||
|
||
log "${GREEN}📊 Total records in local database: ${TOTAL_RECORDS}${NC}"
|
||
|
||
# Check for active employees
|
||
ACTIVE_EMPLOYEES=$(mysql -u ordrestyring_user -psecure_password123 -h localhost ordrestyring_local -se "
|
||
SELECT COUNT(*) FROM ordrestyring_users WHERE full_name IS NOT NULL AND email IS NOT NULL
|
||
" 2>/dev/null || echo "0")
|
||
|
||
log "${GREEN}👥 Active employees found: ${ACTIVE_EMPLOYEES}${NC}"
|
||
|
||
# Check calendar entries for planning
|
||
CALENDAR_ENTRIES=$(mysql -u ordrestyring_user -psecure_password123 -h localhost ordrestyring_local -se "
|
||
SELECT COUNT(*) FROM ordrestyring_calendar
|
||
WHERE start_time > UNIX_TIMESTAMP(CURDATE())
|
||
AND start_time < UNIX_TIMESTAMP(DATE_ADD(CURDATE(), INTERVAL 7 DAY))
|
||
" 2>/dev/null || echo "0")
|
||
|
||
log "${GREEN}📅 Calendar entries for next 7 days: ${CALENDAR_ENTRIES}${NC}"
|
||
|
||
# Update sync status for tilbudsberegning app
|
||
echo "{
|
||
\"last_sync\": \"$(date -Iseconds)\",
|
||
\"status\": \"success\",
|
||
\"duration_seconds\": $DURATION,
|
||
\"total_records\": $TOTAL_RECORDS,
|
||
\"active_employees\": $ACTIVE_EMPLOYEES,
|
||
\"calendar_entries_next_7_days\": $CALENDAR_ENTRIES
|
||
}" > "$SCRIPT_DIR/last_sync_status.json"
|
||
|
||
else
|
||
log "${RED}❌ Comprehensive sync failed with exit code: $IMPORT_EXIT_CODE${NC}"
|
||
|
||
# Update error status
|
||
echo "{
|
||
\"last_sync\": \"$(date -Iseconds)\",
|
||
\"status\": \"failed\",
|
||
\"error_code\": $IMPORT_EXIT_CODE,
|
||
\"duration_seconds\": $DURATION
|
||
}" > "$SCRIPT_DIR/last_sync_status.json"
|
||
|
||
exit 1
|
||
fi
|
||
|
||
log "${PURPLE}🎉 COMPREHENSIVE Ordrestyring sync completed successfully${NC}"
|
||
log "${BLUE}💡 Data is now ready for advanced tilbudsberegning with historical analysis${NC}"
|
||
log "${CYAN}📋 Calendar data available for tilbudsbereger.alw.dk planning integration${NC}"
|