653 lines
36 KiB
PHP
653 lines
36 KiB
PHP
<?php
|
|
// --- FORM PROCESSING ---
|
|
$form_error = null;
|
|
$form_success = null;
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'create_roster') {
|
|
// Basic validation
|
|
if (empty($_POST['sapCode']) || empty($_POST['fullNameEn'])) {
|
|
$form_error = "SAP Code and Full Name are required.";
|
|
} else {
|
|
try {
|
|
require_once __DIR__ . '/db/config.php';
|
|
$pdo_form = db();
|
|
|
|
// Prepare data from form
|
|
$newAmendedSalary = (float)($_POST['newAmendedSalary'] ?? 0);
|
|
$employerContributions = (float)($_POST['employerContributions'] ?? 0);
|
|
$cars = (float)($_POST['cars'] ?? 0);
|
|
$ticketRestaurant = (float)($_POST['ticketRestaurant'] ?? 0);
|
|
$metlife = (float)($_POST['metlife'] ?? 0);
|
|
$topusPerMonth = (float)($_POST['topusPerMonth'] ?? 0);
|
|
|
|
// Auto-calculations
|
|
$totalSalaryCostWithLabor = $newAmendedSalary + $employerContributions;
|
|
$totalMonthlyCost = $totalSalaryCostWithLabor + $cars + $ticketRestaurant + $metlife + $topusPerMonth;
|
|
$totalAnnualCost = $totalMonthlyCost * 14;
|
|
|
|
$insert_sql = "INSERT INTO roster (sapCode, fullNameEn, legalEntity, functionBusinessUnit, costCenterCode, `level`, newAmendedSalary, employerContributions, cars, ticketRestaurant, metlife, topusPerMonth, totalSalaryCostWithLabor, totalMonthlyCost, totalAnnualCost) VALUES (:sapCode, :fullNameEn, :legalEntity, :functionBusinessUnit, :costCenterCode, :level, :newAmendedSalary, :employerContributions, :cars, :ticketRestaurant, :metlife, :topusPerMonth, :totalSalaryCostWithLabor, :totalMonthlyCost, :totalAnnualCost)";
|
|
$stmt = $pdo_form->prepare($insert_sql);
|
|
|
|
$stmt->execute([
|
|
':sapCode' => $_POST['sapCode'],
|
|
':fullNameEn' => $_POST['fullNameEn'],
|
|
':legalEntity' => $_POST['legalEntity'] ?? null,
|
|
':functionBusinessUnit' => $_POST['functionBusinessUnit'] ?? null,
|
|
':costCenterCode' => $_POST['costCenterCode'] ?? null,
|
|
':level' => $_POST['level'] ?? null,
|
|
':newAmendedSalary' => $newAmendedSalary,
|
|
':employerContributions' => $employerContributions,
|
|
':cars' => $cars,
|
|
':ticketRestaurant' => $ticketRestaurant,
|
|
':metlife' => $metlife,
|
|
':topusPerMonth' => $topusPerMonth,
|
|
':totalSalaryCostWithLabor' => $totalSalaryCostWithLabor,
|
|
':totalMonthlyCost' => $totalMonthlyCost,
|
|
':totalAnnualCost' => $totalAnnualCost
|
|
]);
|
|
|
|
// To prevent form resubmission on refresh, redirect
|
|
header("Location: " . $_SERVER['PHP_SELF']);
|
|
exit();
|
|
|
|
} catch (PDOException $e) {
|
|
// Check for duplicate entry
|
|
if ($e->errorInfo[1] == 1062) {
|
|
$form_error = "Error: A resource with this SAP Code already exists.";
|
|
} else {
|
|
$form_error = "Database error: " . $e->getMessage();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'delete_roster') {
|
|
try {
|
|
require_once __DIR__ . '/db/config.php';
|
|
$pdo_delete = db();
|
|
$delete_sql = "DELETE FROM roster WHERE id = :id";
|
|
$stmt = $pdo_delete->prepare($delete_sql);
|
|
$stmt->execute([':id' => $_POST['id']]);
|
|
header("Location: " . $_SERVER['PHP_SELF']);
|
|
exit();
|
|
} catch (PDOException $e) {
|
|
$form_error = "Database error: " . $e->getMessage();
|
|
}
|
|
}
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'update_roster') {
|
|
if (empty($_POST['id']) || empty($_POST['sapCode']) || empty($_POST['fullNameEn'])) {
|
|
$form_error = "ID, SAP Code, and Full Name are required for an update.";
|
|
} else {
|
|
try {
|
|
require_once __DIR__ . '/db/config.php';
|
|
$pdo_update = db();
|
|
|
|
// Prepare data from form
|
|
$newAmendedSalary = (float)($_POST['newAmendedSalary'] ?? 0);
|
|
$employerContributions = (float)($_POST['employerContributions'] ?? 0);
|
|
$cars = (float)($_POST['cars'] ?? 0);
|
|
$ticketRestaurant = (float)($_POST['ticketRestaurant'] ?? 0);
|
|
$metlife = (float)($_POST['metlife'] ?? 0);
|
|
$topusPerMonth = (float)($_POST['topusPerMonth'] ?? 0);
|
|
|
|
// Auto-calculations
|
|
$totalSalaryCostWithLabor = $newAmendedSalary + $employerContributions;
|
|
$totalMonthlyCost = $totalSalaryCostWithLabor + $cars + $ticketRestaurant + $metlife + $topusPerMonth;
|
|
$totalAnnualCost = $totalMonthlyCost * 14;
|
|
|
|
$update_sql = "UPDATE roster SET
|
|
sapCode = :sapCode,
|
|
fullNameEn = :fullNameEn,
|
|
legalEntity = :legalEntity,
|
|
functionBusinessUnit = :functionBusinessUnit,
|
|
costCenterCode = :costCenterCode,
|
|
`level` = :level,
|
|
newAmendedSalary = :newAmendedSalary,
|
|
employerContributions = :employerContributions,
|
|
cars = :cars,
|
|
ticketRestaurant = :ticketRestaurant,
|
|
metlife = :metlife,
|
|
topusPerMonth = :topusPerMonth,
|
|
totalSalaryCostWithLabor = :totalSalaryCostWithLabor,
|
|
totalMonthlyCost = :totalMonthlyCost,
|
|
totalAnnualCost = :totalAnnualCost
|
|
WHERE id = :id";
|
|
|
|
$stmt = $pdo_update->prepare($update_sql);
|
|
$stmt->execute([
|
|
':id' => $_POST['id'],
|
|
':sapCode' => $_POST['sapCode'],
|
|
':fullNameEn' => $_POST['fullNameEn'],
|
|
':legalEntity' => $_POST['legalEntity'] ?? null,
|
|
':functionBusinessUnit' => $_POST['functionBusinessUnit'] ?? null,
|
|
':costCenterCode' => $_POST['costCenterCode'] ?? null,
|
|
':level' => $_POST['level'] ?? null,
|
|
':newAmendedSalary' => $newAmendedSalary,
|
|
':employerContributions' => $employerContributions,
|
|
':cars' => $cars,
|
|
':ticketRestaurant' => $ticketRestaurant,
|
|
':metlife' => $metlife,
|
|
':topusPerMonth' => $topusPerMonth,
|
|
':totalSalaryCostWithLabor' => $totalSalaryCostWithLabor,
|
|
':totalMonthlyCost' => $totalMonthlyCost,
|
|
':totalAnnualCost' => $totalAnnualCost
|
|
]);
|
|
|
|
header("Location: " . $_SERVER['PHP_SELF']);
|
|
exit();
|
|
|
|
} catch (PDOException $e) {
|
|
if ($e->errorInfo[1] == 1062) {
|
|
$form_error = "Error: A resource with this SAP Code already exists.";
|
|
} else {
|
|
$form_error = "Database error: " . $e->getMessage();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// --- DATABASE INITIALIZATION ---
|
|
require_once __DIR__ . '/db/config.php';
|
|
|
|
function execute_sql_from_file($pdo, $filepath) {
|
|
try {
|
|
$sql = file_get_contents($filepath);
|
|
$pdo->exec($sql);
|
|
return true;
|
|
} catch (PDOException $e) {
|
|
if (strpos($e->getMessage(), 'already exists') === false) {
|
|
error_log("SQL Execution Error: " . $e->getMessage());
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function seed_roster_data($pdo) {
|
|
try {
|
|
$stmt = $pdo->query("SELECT COUNT(*) FROM roster");
|
|
if ($stmt->fetchColumn() > 0) {
|
|
return; // Data already exists
|
|
}
|
|
|
|
$seed_data = [
|
|
[
|
|
'sapCode' => '1001', 'fullNameEn' => 'John Doe', 'legalEntity' => 'Entity A', 'functionBusinessUnit' => 'Finance',
|
|
'costCenterCode' => 'CC100', 'level' => 'Senior', 'newAmendedSalary' => 6000, 'employerContributions' => 1500,
|
|
'cars' => 500, 'ticketRestaurant' => 150, 'metlife' => 50, 'topusPerMonth' => 100
|
|
],
|
|
[
|
|
'sapCode' => '1002', 'fullNameEn' => 'Jane Smith', 'legalEntity' => 'Entity B', 'functionBusinessUnit' => 'IT',
|
|
'costCenterCode' => 'CC200', 'level' => 'Manager', 'newAmendedSalary' => 8000, 'employerContributions' => 2000,
|
|
'cars' => 600, 'ticketRestaurant' => 150, 'metlife' => 60, 'topusPerMonth' => 120
|
|
],
|
|
];
|
|
|
|
$insert_sql = "INSERT INTO roster (sapCode, fullNameEn, legalEntity, functionBusinessUnit, costCenterCode, `level`, newAmendedSalary, employerContributions, cars, ticketRestaurant, metlife, topusPerMonth, totalSalaryCostWithLabor, totalMonthlyCost, totalAnnualCost) VALUES (:sapCode, :fullNameEn, :legalEntity, :functionBusinessUnit, :costCenterCode, :level, :newAmendedSalary, :employerContributions, :cars, :ticketRestaurant, :metlife, :topusPerMonth, :totalSalaryCostWithLabor, :totalMonthlyCost, :totalAnnualCost)";
|
|
$stmt = $pdo->prepare($insert_sql);
|
|
|
|
foreach ($seed_data as $row) {
|
|
$totalSalaryCostWithLabor = $row['newAmendedSalary'] + $row['employerContributions'];
|
|
$totalMonthlyCost = $totalSalaryCostWithLabor + $row['cars'] + $row['ticketRestaurant'] + $row['metlife'] + $row['topusPerMonth'];
|
|
$totalAnnualCost = $totalMonthlyCost * 14;
|
|
|
|
$stmt->execute([
|
|
':sapCode' => $row['sapCode'],
|
|
':fullNameEn' => $row['fullNameEn'],
|
|
':legalEntity' => $row['legalEntity'],
|
|
':functionBusinessUnit' => $row['functionBusinessUnit'],
|
|
':costCenterCode' => $row['costCenterCode'],
|
|
':level' => $row['level'],
|
|
':newAmendedSalary' => $row['newAmendedSalary'],
|
|
':employerContributions' => $row['employerContributions'],
|
|
':cars' => $row['cars'],
|
|
':ticketRestaurant' => $row['ticketRestaurant'],
|
|
':metlife' => $row['metlife'],
|
|
':topusPerMonth' => $row['topusPerMonth'],
|
|
':totalSalaryCostWithLabor' => $totalSalaryCostWithLabor,
|
|
':totalMonthlyCost' => $totalMonthlyCost,
|
|
':totalAnnualCost' => $totalAnnualCost
|
|
]);
|
|
}
|
|
|
|
} catch (PDOException $e) {
|
|
error_log("Seeding Error: " . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
$roster_data = [];
|
|
$search_term = $_GET['search'] ?? '';
|
|
|
|
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);
|
|
}
|
|
|
|
seed_roster_data($pdo);
|
|
|
|
$sql = "SELECT * FROM roster";
|
|
$params = [];
|
|
|
|
if (!empty($search_term)) {
|
|
$sql .= " WHERE fullNameEn LIKE :search OR sapCode LIKE :search";
|
|
$params[':search'] = '%' . $search_term . '%';
|
|
}
|
|
|
|
$sql .= " ORDER BY fullNameEn";
|
|
$stmt = $pdo->prepare($sql);
|
|
$stmt->execute($params);
|
|
$roster_data = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
} catch (PDOException $e) {
|
|
$db_error = "Database connection failed: " . $e->getMessage();
|
|
}
|
|
|
|
// --- RENDER PAGE ---
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="en" data-bs-theme="dark">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Project Financials</title>
|
|
|
|
<meta name="description" content="<?php echo htmlspecialchars($_SERVER['PROJECT_DESCRIPTION'] ?? 'Project Financials Management Tool'); ?>">
|
|
<meta property="og:title" content="Project Financials">
|
|
<meta property="og:description" content="<?php echo htmlspecialchars($_SERVER['PROJECT_DESCRIPTION'] ?? 'Manage your project financials, roster, and budget.'); ?>">
|
|
<meta property="og:image" content="<?php echo htmlspecialchars($_SERVER['PROJECT_IMAGE_URL'] ?? ''); ?>">
|
|
<meta name="twitter:card" content="summary_large_image">
|
|
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
|
</head>
|
|
<body>
|
|
<div class="top-navbar">
|
|
Project Financials
|
|
</div>
|
|
<div class="main-wrapper">
|
|
<nav class="sidebar">
|
|
<ul class="nav flex-column">
|
|
<li class="nav-item">
|
|
<a class="nav-link active" href="index.php"><i class="bi bi-people-fill me-2"></i>Roster</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a class="nav-link" href="projects.php"><i class="bi bi-briefcase-fill me-2"></i>Projects</a>
|
|
</li>
|
|
</ul>
|
|
</nav>
|
|
|
|
<main class="content-wrapper">
|
|
<?php
|
|
if (isset($_GET['import_status'])) {
|
|
$status = $_GET['import_status'];
|
|
$message = htmlspecialchars($_GET['import_message'] ?? '');
|
|
$alert_class = $status === 'success' ? 'alert-success' : 'alert-danger';
|
|
echo "<div class='alert {$alert_class} alert-dismissible fade show' role='alert'>
|
|
{$message}
|
|
<button type='button' class='btn-close' data-bs-dismiss='alert' aria-label='Close'></button>
|
|
</div>";
|
|
}
|
|
?>
|
|
<?php if (isset($db_error)): ?>
|
|
<div class="alert alert-danger"><?php echo htmlspecialchars($db_error); ?></div>
|
|
<?php elseif (isset($form_error)): ?>
|
|
<div class="alert alert-danger"><?php echo htmlspecialchars($form_error); ?></div>
|
|
<?php endif; ?>
|
|
|
|
<div class="page-header">
|
|
<h1 class="h2">Roster</h1>
|
|
<div class="header-actions">
|
|
<button class="btn btn-secondary" data-bs-toggle="modal" data-bs-target="#importModal"><i class="bi bi-upload me-2"></i>Import Excel</button>
|
|
<a href="export.php" class="btn btn-secondary"><i class="bi bi-download me-2"></i>Export Excel</a>
|
|
<button class="btn btn-primary" id="newResourceBtn"><i class="bi bi-plus-circle-fill me-2"></i>New Resource</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<form action="index.php" method="GET" class="row g-3 align-items-center">
|
|
<div class="col-auto">
|
|
<label for="search" class="visually-hidden">Search</label>
|
|
<input type="text" class="form-control" id="search" name="search" placeholder="Search by name or SAP..." value="<?php echo htmlspecialchars($_GET['search'] ?? ''); ?>">
|
|
</div>
|
|
<div class="col-auto">
|
|
<button type="submit" class="btn btn-primary">Search</button>
|
|
<a href="index.php" class="btn btn-secondary">Clear</a>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table table-hover">
|
|
<thead>
|
|
<tr>
|
|
<th>SAP Code</th>
|
|
<th>Full Name</th>
|
|
<th>Legal Entity</th>
|
|
<th>Business Unit</th>
|
|
<th>Cost Center</th>
|
|
<th>Level</th>
|
|
<th>Salary</th>
|
|
<th>Contributions</th>
|
|
<th>Cars</th>
|
|
<th>Ticket Restaurant</th>
|
|
<th>Metlife</th>
|
|
<th>Topus/Month</th>
|
|
<th>Total Salary Cost</th>
|
|
<th>Total Monthly Cost</th>
|
|
<th>Total Annual Cost</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php if (empty($roster_data)): ?>
|
|
<tr>
|
|
<td colspan="15" class="text-center text-secondary">No roster data found.</td>
|
|
</tr>
|
|
<?php else: ?>
|
|
<?php foreach ($roster_data as $row): ?>
|
|
<tr>
|
|
<td><?php echo htmlspecialchars($row['sapCode']); ?></td>
|
|
<td><?php echo htmlspecialchars($row['fullNameEn']); ?></td>
|
|
<td><?php echo htmlspecialchars($row['legalEntity']); ?></td>
|
|
<td><?php echo htmlspecialchars($row['functionBusinessUnit']); ?></td>
|
|
<td><?php echo htmlspecialchars($row['costCenterCode']); ?></td>
|
|
<td><?php echo htmlspecialchars($row['level']); ?></td>
|
|
<td>€<?php echo number_format($row['newAmendedSalary'], 2); ?></td>
|
|
<td>€<?php echo number_format($row['employerContributions'], 2); ?></td>
|
|
<td>€<?php echo number_format($row['cars'], 2); ?></td>
|
|
<td>€<?php echo number_format($row['ticketRestaurant'], 2); ?></td>
|
|
<td>€<?php echo number_format($row['metlife'], 2); ?></td>
|
|
<td>€<?php echo number_format($row['topusPerMonth'], 2); ?></td>
|
|
<td>€<?php echo number_format($row['totalSalaryCostWithLabor'], 2); ?></td>
|
|
<td>€<?php echo number_format($row['totalMonthlyCost'], 2); ?></td>
|
|
<td>€<?php echo number_format($row['totalAnnualCost'], 2); ?></td>
|
|
<td>
|
|
<div class="d-flex">
|
|
<button class="btn btn-sm btn-outline-info me-2 view-btn"
|
|
data-row='<?php echo htmlspecialchars(json_encode($row), ENT_QUOTES, 'UTF-8'); ?>'>
|
|
View
|
|
</button>
|
|
<button class="btn btn-sm btn-outline-primary me-2 edit-btn"
|
|
data-row='<?php echo htmlspecialchars(json_encode($row), ENT_QUOTES, 'UTF-8'); ?>'>
|
|
Edit
|
|
</button>
|
|
<form action="index.php" method="POST" onsubmit="return confirm('Are you sure you want to delete this item?');">
|
|
<input type="hidden" name="action" value="delete_roster">
|
|
<input type="hidden" name="id" value="<?php echo $row['id']; ?>">
|
|
<button type="submit" class="btn btn-sm btn-outline-danger">Delete</button>
|
|
</form>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
|
|
<!-- New Resource Modal -->
|
|
<div class="modal fade" id="newResourceModal" tabindex="-1" aria-labelledby="newResourceModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered modal-lg">
|
|
<div class="modal-content">
|
|
<form action="index.php" method="POST">
|
|
<input type="hidden" name="action" value="create_roster">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="newResourceModalLabel">New Resource</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="sapCode" class="form-label">SAP Code</label>
|
|
<input type="text" class="form-control" id="sapCode" name="sapCode" required>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="fullNameEn" class="form-label">Full Name</label>
|
|
<input type="text" class="form-control" id="fullNameEn" name="fullNameEn" required>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="legalEntity" class="form-label">Legal Entity</label>
|
|
<input type="text" class="form-control" id="legalEntity" name="legalEntity">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="functionBusinessUnit" class="form-label">Function Business Unit</label>
|
|
<input type="text" class="form-control" id="functionBusinessUnit" name="functionBusinessUnit">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="costCenterCode" class="form-label">Cost Center Code</label>
|
|
<input type="text" class="form-control" id="costCenterCode" name="costCenterCode">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="level" class="form-label">Level</label>
|
|
<input type="text" class="form-control" id="level" name="level">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="newAmendedSalary" class="form-label">New Amended Salary (€)</label>
|
|
<input type="number" step="0.01" class="form-control" id="newAmendedSalary" name="newAmendedSalary" value="0">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="employerContributions" class="form-label">Employer Contributions (€)</label>
|
|
<input type="number" step="0.01" class="form-control" id="employerContributions" name="employerContributions" value="0">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="cars" class="form-label">Cars (€)</label>
|
|
<input type="number" step="0.01" class="form-control" id="cars" name="cars" value="0">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="ticketRestaurant" class="form-label">Ticket Restaurant (€)</label>
|
|
<input type="number" step="0.01" class="form-control" id="ticketRestaurant" name="ticketRestaurant" value="0">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="metlife" class="form-label">Metlife (€)</label>
|
|
<input type="number" step="0.01" class="form-control" id="metlife" name="metlife" value="0">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="topusPerMonth" class="form-label">Topus/Month (€)</label>
|
|
<input type="number" step="0.01" class="form-control" id="topusPerMonth" name="topusPerMonth" value="0">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
<button type="submit" class="btn btn-primary">Save Resource</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
|
|
|
<!-- Edit Resource Modal -->
|
|
<div class="modal fade" id="editResourceModal" tabindex="-1" aria-labelledby="editResourceModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered modal-lg">
|
|
<div class="modal-content">
|
|
<form action="index.php" method="POST">
|
|
<input type="hidden" name="action" value="update_roster">
|
|
<input type="hidden" name="id" id="edit-id">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="editResourceModalLabel">Edit Resource</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="edit-sapCode" class="form-label">SAP Code</label>
|
|
<input type="text" class="form-control" id="edit-sapCode" name="sapCode" required>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="edit-fullNameEn" class="form-label">Full Name</label>
|
|
<input type="text" class="form-control" id="edit-fullNameEn" name="fullNameEn" required>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="edit-legalEntity" class="form-label">Legal Entity</label>
|
|
<input type="text" class="form-control" id="edit-legalEntity" name="legalEntity">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="edit-functionBusinessUnit" class="form-label">Function Business Unit</label>
|
|
<input type="text" class="form-control" id="edit-functionBusinessUnit" name="functionBusinessUnit">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="edit-costCenterCode" class="form-label">Cost Center Code</label>
|
|
<input type="text" class="form-control" id="edit-costCenterCode" name="costCenterCode">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="edit-level" class="form-label">Level</label>
|
|
<input type="text" class="form-control" id="edit-level" name="level">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="edit-newAmendedSalary" class="form-label">New Amended Salary (€)</label>
|
|
<input type="number" step="0.01" class="form-control" id="edit-newAmendedSalary" name="newAmendedSalary">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="edit-employerContributions" class="form-label">Employer Contributions (€)</label>
|
|
<input type="number" step="0.01" class="form-control" id="edit-employerContributions" name="employerContributions">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="edit-cars" class="form-label">Cars (€)</label>
|
|
<input type="number" step="0.01" class="form-control" id="edit-cars" name="cars">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="edit-ticketRestaurant" class="form-label">Ticket Restaurant (€)</label>
|
|
<input type="number" step="0.01" class="form-control" id="edit-ticketRestaurant" name="ticketRestaurant">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="edit-metlife" class="form-label">Metlife (€)</label>
|
|
<input type="number" step="0.01" class="form-control" id="edit-metlife" name="metlife">
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label for="edit-topusPerMonth" class="form-label">Topus/Month (€)</label>
|
|
<input type="number" step="0.01" class="form-control" id="edit-topusPerMonth" name="topusPerMonth">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
<button type="submit" class="btn btn-primary">Save Changes</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- View Resource Modal -->
|
|
<div class="modal fade" id="viewResourceModal" tabindex="-1" aria-labelledby="viewResourceModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="viewResourceModalLabel">View Resource</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label">SAP Code</label>
|
|
<input type="text" class="form-control" id="view-sapCode" readonly>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label">Full Name</label>
|
|
<input type="text" class="form-control" id="view-fullNameEn" readonly>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label">Legal Entity</label>
|
|
<input type="text" class="form-control" id="view-legalEntity" readonly>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label">Function Business Unit</label>
|
|
<input type="text" class="form-control" id="view-functionBusinessUnit" readonly>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label">Cost Center Code</label>
|
|
<input type="text" class="form-control" id="view-costCenterCode" readonly>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label">Level</label>
|
|
<input type="text" class="form-control" id="view-level" readonly>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label">New Amended Salary (€)</label>
|
|
<input type="text" class="form-control" id="view-newAmendedSalary" readonly>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label">Employer Contributions (€)</label>
|
|
<input type="text" class="form-control" id="view-employerContributions" readonly>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label">Cars (€)</label>
|
|
<input type="text" class="form-control" id="view-cars" readonly>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label">Ticket Restaurant (€)</label>
|
|
<input type="text" class="form-control" id="view-ticketRestaurant" readonly>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label">Metlife (€)</label>
|
|
<input type="text" class="form-control" id="view-metlife" readonly>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label">Topus/Month (€)</label>
|
|
<input type="text" class="form-control" id="view-topusPerMonth" readonly>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label">Total Salary Cost With Labor (€)</label>
|
|
<input type="text" class="form-control" id="view-totalSalaryCostWithLabor" readonly>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label">Total Monthly Cost (€)</label>
|
|
<input type="text" class="form-control" id="view-totalMonthlyCost" readonly>
|
|
</div>
|
|
<div class="col-md-6 mb-3">
|
|
<label class="form-label">Total Annual Cost (€)</label>
|
|
<input type="text" class="form-control" id="view-totalAnnualCost" readonly>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<!-- Import Modal -->
|
|
<div class="modal fade" id="importModal" tabindex="-1" aria-labelledby="importModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-dialog-centered">
|
|
<div class="modal-content">
|
|
<form action="import.php" method="POST" enctype="multipart/form-data">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="importModalLabel">Import Excel</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="mb-3">
|
|
<label for="importFile" class="form-label">Select .csv or .xlsx file</label>
|
|
<input class="form-control" type="file" id="importFile" name="importFile" accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" required>
|
|
</div>
|
|
<div class="form-text">
|
|
The file should have columns matching the roster table: sapCode, fullNameEn, legalEntity, etc.
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
<button type="submit" class="btn btn-primary">Upload and Import</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</body>
|
|
</html>
|