exec($sql); return true; } catch (PDOException $e) { if (strpos($e->getMessage(), 'already exists') === false) { error_log("SQL Execution Error: " . $e->getMessage()); } return false; } } $project = null; $versions = []; $allocations = []; $roster_for_search = []; $db_error = null; function get_months($startDate, $endDate) { $start = new DateTime($startDate); $end = new DateTime($endDate); $interval = new DateInterval('P1M'); $period = new DatePeriod($start, $interval, $end->modify('+1 month')); $months = []; foreach ($period as $dt) { $months[] = $dt->format('Y-m-01'); } return $months; } try { $pdo = db(); // Apply all migrations $migration_files = glob(__DIR__ . '/db/migrations/*.sql'); sort($migration_files); foreach ($migration_files as $file) { execute_sql_from_file($pdo, $file); } // Fetch project details $stmt = $pdo->prepare("SELECT * FROM projects WHERE id = :projectId"); $stmt->execute([':projectId' => $projectId]); $project = $stmt->fetch(PDO::FETCH_ASSOC); if (!$project) { die("Project not found."); } // Fetch forecasting versions $stmt = $pdo->prepare("SELECT * FROM forecasting WHERE projectId = :projectId ORDER BY versionNumber DESC"); $stmt->execute([':projectId' => $projectId]); $versions = $stmt->fetchAll(PDO::FETCH_ASSOC); if (empty($versionNumber) && !empty($versions)) { $versionNumber = $versions[0]['versionNumber']; } $selected_version = null; if ($versionNumber) { foreach($versions as $v) { if ($v['versionNumber'] == $versionNumber) { $selected_version = $v; break; } } } // Fetch allocations for the selected version if ($selected_version) { $months = get_months($project['startDate'], $project['endDate']); $sql = "SELECT fa.rosterId, fa.resourceName, fa.level, GROUP_CONCAT(fa.month, '|', fa.allocatedDays ORDER BY fa.month) as monthly_allocations FROM forecastAllocation fa WHERE fa.forecastingId = :forecastingId GROUP BY fa.rosterId, fa.resourceName, fa.level ORDER BY fa.resourceName"; $stmt = $pdo->prepare($sql); $stmt->execute([':forecastingId' => $selected_version['id']]); $raw_allocations = $stmt->fetchAll(PDO::FETCH_ASSOC); // Process allocations into a structured array foreach ($raw_allocations as $raw_row) { $alloc_row = [ 'rosterId' => $raw_row['rosterId'], 'resourceName' => $raw_row['resourceName'], 'level' => $raw_row['level'], 'months' => [] ]; foreach($months as $month) { $alloc_row['months'][$month] = 0; // Default } $monthly_pairs = explode(',', $raw_row['monthly_allocations']); foreach ($monthly_pairs as $pair) { list($month, $days) = explode('|', $pair); $alloc_row['months'][$month] = $days; } $allocations[] = $alloc_row; } } // Fetch roster for search $stmt = $pdo->query("SELECT id, sapCode, fullNameEn, `level` FROM roster ORDER BY fullNameEn"); $roster_for_search = $stmt->fetchAll(PDO::FETCH_ASSOC); } catch (PDOException $e) { $db_error = "Database error: " . $e->getMessage(); } $months_headers = $project ? get_months($project['startDate'], $project['endDate']) : []; ?> Forecasting - <?php echo htmlspecialchars($project['name'] ?? ''); ?>
Project Financials
Resource Allocations
$days): ?>
Resource Name Level Actions
No resources allocated yet.