diff --git a/ApplicationLogger.php b/ApplicationLogger.php new file mode 100644 index 0000000..d9ea300 --- /dev/null +++ b/ApplicationLogger.php @@ -0,0 +1,200 @@ +config = $appConfig; + + // Create logs directory if it doesn't exist + $logsDir = __DIR__ . '/logs'; + if (!file_exists($logsDir)) { + mkdir($logsDir, 0755, true); + } + + $this->logFile = $logsDir . '/application.log'; + } + + /** + * Log action with structured data + */ + public function log($action, $user, $data = [], $status = 'success') { + $logEntry = [ + 'timestamp' => date('Y-m-d H:i:s'), + 'action' => $action, + 'user_email' => $user['email'] ?? 'unknown', + 'user_name' => $user['name'] ?? 'unknown', + 'status' => $status, + 'data' => $data, + 'ip_address' => $_SERVER['REMOTE_ADDR'] ?? 'unknown', + 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'unknown' + ]; + + $logLine = json_encode($logEntry) . "\n"; + + // Append to log file + file_put_contents($this->logFile, $logLine, FILE_APPEND | LOCK_EX); + + // Also log to PHP error log for debugging + error_log('[APP LOG] ' . $action . ' - ' . $status . ' - ' . ($user['email'] ?? 'unknown')); + + return $logEntry; + } + + /** + * Log Master Asset Submission + */ + public function logAssetSubmission($user, $boxId, $masterCampaignNumber, $dates, $status = 'success', $error = null) { + return $this->log('master_asset_submission', $user, [ + 'box_id' => $boxId, + 'master_campaign_number' => $masterCampaignNumber, + 'supply_date' => $dates['supply'] ?? null, + 'live_date' => $dates['live'] ?? null, + 'end_date' => $dates['end'] ?? null, + 'error' => $error + ], $status); + } + + /** + * Log Global to Local Transformation + */ + public function logGlobalToLocal($user, $campaignNumber, $businessUnit, $inputRows, $outputFiles, $status = 'success', $error = null) { + return $this->log('global_to_local_transform', $user, [ + 'campaign_number' => $campaignNumber, + 'business_unit' => $businessUnit, + 'input_rows' => $inputRows, + 'output_file_count' => $outputFiles, + 'total_output_rows' => $inputRows * $outputFiles, + 'error' => $error + ], $status); + } + + /** + * Log Box Upload + */ + public function logBoxUpload($user, $fileCount, $folderId, $status = 'success', $error = null) { + return $this->log('box_upload', $user, [ + 'file_count' => $fileCount, + 'folder_id' => $folderId, + 'error' => $error + ], $status); + } + + /** + * Log OMG API Call + */ + public function logOMGAPICall($user, $campaignNumber, $businessArea, $businessUnit, $status = 'success', $error = null) { + return $this->log('omg_api_lookup', $user, [ + 'campaign_number' => $campaignNumber, + 'business_area' => $businessArea, + 'business_unit' => $businessUnit, + 'error' => $error + ], $status); + } + + /** + * Get recent logs + */ + public function getRecentLogs($limit = 100) { + if (!file_exists($this->logFile)) { + return []; + } + + $lines = file($this->logFile, FILE_IGNORE_NEW_LINES); + $lines = array_reverse($lines); // Most recent first + $lines = array_slice($lines, 0, $limit); + + $logs = []; + foreach ($lines as $line) { + $log = json_decode($line, true); + if ($log) { + $logs[] = $log; + } + } + + return $logs; + } + + /** + * Get logs by action type + */ + public function getLogsByAction($action, $limit = 100) { + $allLogs = $this->getRecentLogs(1000); + + $filtered = array_filter($allLogs, function($log) use ($action) { + return $log['action'] === $action; + }); + + return array_slice(array_values($filtered), 0, $limit); + } + + /** + * Get logs by user + */ + public function getLogsByUser($userEmail, $limit = 100) { + $allLogs = $this->getRecentLogs(1000); + + $filtered = array_filter($allLogs, function($log) use ($userEmail) { + return $log['user_email'] === $userEmail; + }); + + return array_slice(array_values($filtered), 0, $limit); + } + + /** + * Generate report statistics + */ + public function getStatistics($startDate = null, $endDate = null) { + $allLogs = $this->getRecentLogs(10000); + + // Filter by date if provided + if ($startDate || $endDate) { + $allLogs = array_filter($allLogs, function($log) use ($startDate, $endDate) { + $timestamp = strtotime($log['timestamp']); + if ($startDate && $timestamp < strtotime($startDate)) return false; + if ($endDate && $timestamp > strtotime($endDate)) return false; + return true; + }); + } + + $stats = [ + 'total_actions' => count($allLogs), + 'by_action' => [], + 'by_user' => [], + 'by_status' => [], + 'errors' => [] + ]; + + foreach ($allLogs as $log) { + // Count by action + $action = $log['action']; + $stats['by_action'][$action] = ($stats['by_action'][$action] ?? 0) + 1; + + // Count by user + $user = $log['user_email']; + $stats['by_user'][$user] = ($stats['by_user'][$user] ?? 0) + 1; + + // Count by status + $status = $log['status']; + $stats['by_status'][$status] = ($stats['by_status'][$status] ?? 0) + 1; + + // Collect errors + if ($status === 'error') { + $stats['errors'][] = [ + 'timestamp' => $log['timestamp'], + 'action' => $log['action'], + 'user' => $log['user_email'], + 'error' => $log['data']['error'] ?? 'Unknown error' + ]; + } + } + + return $stats; + } +} diff --git a/OMGService.php b/OMGService.php index 38ccab8..ded33e4 100644 --- a/OMGService.php +++ b/OMGService.php @@ -27,6 +27,10 @@ class OMGService { $url = $this->baseUrl . '/getProject'; $url .= '?project_number=' . urlencode($projectNumber); + error_log('===== OMG API CALL START ====='); + error_log('OMG API: Base URL: ' . $this->baseUrl); + error_log('OMG API: Full URL: ' . $url); + error_log('OMG API: API Key (first 20 chars): ' . substr($this->apiKey, 0, 20) . '...'); error_log('OMG API: Requesting project ' . $projectNumber); $ch = curl_init($url); @@ -44,6 +48,10 @@ class OMGService { $curlError = curl_error($ch); curl_close($ch); + error_log('OMG API: Response code ' . $httpCode); + error_log('OMG API: Response body (first 500 chars): ' . substr($response, 0, 500)); + error_log('===== OMG API CALL END ====='); + if ($curlError) { return [ 'success' => false, diff --git a/process-csv.php b/process-csv.php index e0347da..6161bab 100644 --- a/process-csv.php +++ b/process-csv.php @@ -114,8 +114,13 @@ try { // STAGE 4: Call OMG API $progress[] = ['stage' => 'omg_api', 'status' => 'processing', 'message' => 'Looking up campaign in OMG...']; + error_log('=== OMG API LOOKUP ==='); + error_log('Campaign Number: ' . $campaignNumber); + $projectResult = $omgService->getProject($campaignNumber); + error_log('OMG API Result: ' . json_encode($projectResult)); + if (!$projectResult['success']) { echo json_encode([ 'success' => false, @@ -138,6 +143,8 @@ try { $businessArea = $omgService->getBusinessArea($projectData); + error_log('Extracted Business Area: ' . ($businessArea ?? 'NULL')); + if (empty($businessArea)) { echo json_encode([ 'success' => false, @@ -153,6 +160,8 @@ try { $mappingResult = $omgService->mapBusinessUnit($businessArea); + error_log('Business Unit Mapping Result: ' . json_encode($mappingResult)); + if (!$mappingResult['success']) { // Non-fatal warning - continue with "ERROR" value $progress[] = [