prepare("INSERT IGNORE INTO users (tenant_id, name, email, role) VALUES (?, ?, ?, 'staff')"); $stmt->execute([$tenant_id, "$first_name $last_name", $email]); $user_id = (int)db()->lastInsertId(); if ($user_id === 0) { // Already exists $stmt = db()->prepare("SELECT id FROM users WHERE email = ?"); $stmt->execute([$email]); $user_id = (int)($stmt->fetchColumn() ?: null); } } $stmt = db()->prepare("INSERT INTO employees (tenant_id, first_name, last_name, email, position, start_date, is_limited, user_id, name) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"); $stmt->execute([$tenant_id, $first_name, $last_name, $email, $position, $start_date, $is_limited, $user_id, "$first_name $last_name"]); $employee_id = (int)db()->lastInsertId(); // Initial Wage if ($initial_wage > 0) { $stmt = db()->prepare("INSERT INTO employee_wages (tenant_id, employee_id, hourly_rate, effective_date) VALUES (?, ?, ?, ?)"); $stmt->execute([$tenant_id, $employee_id, $initial_wage, $start_date]); } // Teams if (!empty($team_ids)) { foreach ($team_ids as $tid) { $stmt = db()->prepare("INSERT INTO employee_teams (tenant_id, employee_id, team_id) VALUES (?, ?, ?)"); $stmt->execute([$tenant_id, $employee_id, $tid]); } } // Log Activity $stmt = db()->prepare("INSERT INTO activity_log (tenant_id, action, details) VALUES (?, ?, ?)"); $stmt->execute([$tenant_id, 'Employee Created', "Added employee: $first_name $last_name"]); header("Location: index.php?success=employee"); exit; } } // Handle Add Team if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_team'])) { $name = $_POST['name'] ?? ''; if ($name) { $stmt = db()->prepare("INSERT INTO teams (tenant_id, name) VALUES (?, ?)"); $stmt->execute([$tenant_id, $name]); header("Location: index.php?success=team"); exit; } } // Handle Add Wage Adjustment if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_wage'])) { $employee_id = (int)$_POST['employee_id']; $rate = (float)$_POST['hourly_rate']; $effective_date = $_POST['effective_date']; if ($employee_id && $rate > 0) { $stmt = db()->prepare("INSERT INTO employee_wages (tenant_id, employee_id, hourly_rate, effective_date) VALUES (?, ?, ?, ?)"); $stmt->execute([$tenant_id, $employee_id, $rate, $effective_date]); header("Location: index.php?success=wage"); exit; } } // Handle Add Project if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_project'])) { $name = $_POST['name'] ?? ''; $code = $_POST['code'] ?? ''; $start_date = $_POST['start_date'] ?? date('Y-m-d'); if ($name && $code) { $stmt = db()->prepare("INSERT INTO projects (tenant_id, name, code, start_date) VALUES (?, ?, ?, ?)"); $stmt->execute([$tenant_id, $name, $code, $start_date]); // Log Activity $stmt = db()->prepare("INSERT INTO activity_log (tenant_id, action, details) VALUES (?, ?, ?)"); $stmt->execute([$tenant_id, 'Project Created', "Added project: $name ($code)"]); header("Location: index.php?success=1"); exit; } } // Handle Add Labour if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_labour'])) { $project_id = (int)($_POST['project_id'] ?? 0); $employee_id = (int)($_POST['employee_id'] ?? 0); $entry_date = $_POST['entry_date'] ?? date('Y-m-d'); $hours = (float)($_POST['hours'] ?? 0); $labour_type_id = (int)($_POST['labour_type_id'] ?? 0); $evidence_type_id = (int)($_POST['evidence_type_id'] ?? 0); $notes = $_POST['notes'] ?? ''; if ($project_id && $employee_id && $hours > 0) { $stmt = db()->prepare("INSERT INTO labour_entries (tenant_id, project_id, employee_id, entry_date, hours, labour_type_id, evidence_type_id, notes) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); $stmt->execute([$tenant_id, $project_id, $employee_id, $entry_date, $hours, $labour_type_id, $evidence_type_id, $notes]); $labour_entry_id = (int)db()->lastInsertId(); // Handle File Uploads if (!empty($_FILES['attachments']['name'][0])) { foreach ($_FILES['attachments']['tmp_name'] as $key => $tmp_name) { $file_name = $_FILES['attachments']['name'][$key]; $file_size = $_FILES['attachments']['size'][$key]; $mime_type = $_FILES['attachments']['type'][$key]; $file_ext = pathinfo($file_name, PATHINFO_EXTENSION); $new_file_name = uniqid() . '.' . $file_ext; $file_path = 'uploads/' . $new_file_name; if (move_uploaded_file($tmp_name, $file_path)) { $stmt = db()->prepare("INSERT INTO attachments (tenant_id, entity_type, entity_id, file_name, file_path, file_size, mime_type) VALUES (?, 'labour_entry', ?, ?, ?, ?, ?)"); $stmt->execute([$tenant_id, $labour_entry_id, $file_name, $file_path, $file_size, $mime_type]); } } } // Log Activity $stmt = db()->prepare("INSERT INTO activity_log (tenant_id, action, details) VALUES (?, ?, ?)"); $stmt->execute([$tenant_id, 'Labour Added', "Logged $hours hours for employee ID $employee_id"]); header("Location: index.php?success=labour"); exit; } } // Handle Add Expense if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_expense'])) { $project_id = (int)($_POST['project_id'] ?? 0); $supplier_id = (int)($_POST['supplier_id'] ?? 0); $expense_type_id = (int)($_POST['expense_type_id'] ?? 0); $amount = (float)($_POST['amount'] ?? 0); $allocation = (float)($_POST['allocation_percent'] ?? 100); $entry_date = $_POST['entry_date'] ?? date('Y-m-d'); $notes = $_POST['notes'] ?? ''; if ($project_id && $supplier_id && $amount > 0) { $stmt = db()->prepare("INSERT INTO expenses (tenant_id, project_id, supplier_id, expense_type_id, amount, allocation_percent, entry_date, notes) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); $stmt->execute([$tenant_id, $project_id, $supplier_id, $expense_type_id, $amount, $allocation, $entry_date, $notes]); $expense_id = (int)db()->lastInsertId(); // Handle File Uploads (Centralized Attachments) if (!empty($_FILES['attachments']['name'][0])) { foreach ($_FILES['attachments']['tmp_name'] as $key => $tmp_name) { if (!$_FILES['attachments']['error'][$key]) { $file_name = $_FILES['attachments']['name'][$key]; $file_size = $_FILES['attachments']['size'][$key]; $mime_type = $_FILES['attachments']['type'][$key]; $file_ext = pathinfo($file_name, PATHINFO_EXTENSION); $new_file_name = uniqid() . '.' . $file_ext; $file_path = 'uploads/' . $new_file_name; if (move_uploaded_file($tmp_name, $file_path)) { $stmt = db()->prepare("INSERT INTO attachments (tenant_id, entity_type, entity_id, file_name, file_path, file_size, mime_type) VALUES (?, 'expense', ?, ?, ?, ?, ?)"); $stmt->execute([$tenant_id, $expense_id, $file_name, $file_path, $file_size, $mime_type]); } } } } // Log Activity $stmt = db()->prepare("INSERT INTO activity_log (tenant_id, action, details) VALUES (?, ?, ?)"); $stmt->execute([$tenant_id, 'Expense Logged', "Logged \$" . number_format($amount, 2) . " expense for project ID $project_id"]); header("Location: index.php?success=expense"); exit; } } // Handle Add Supplier if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_supplier'])) { $name = $_POST['name'] ?? ''; $type = $_POST['type'] ?? 'supplier'; $contact = $_POST['contact_info'] ?? ''; if ($name) { $stmt = db()->prepare("INSERT INTO suppliers (tenant_id, name, type, contact_info) VALUES (?, ?, ?, ?)"); $stmt->execute([$tenant_id, $name, $type, $contact]); header("Location: index.php?success=supplier"); exit; } } // Fetch Data $projects = db()->prepare("SELECT * FROM projects WHERE tenant_id = ? ORDER BY created_at DESC"); $projects->execute([$tenant_id]); $projectList = $projects->fetchAll(); $employees = db()->prepare(" SELECT e.*, (SELECT hourly_rate FROM employee_wages WHERE employee_id = e.id ORDER BY effective_date DESC LIMIT 1) as current_wage FROM employees e WHERE e.tenant_id = ? ORDER BY e.first_name, e.last_name "); $employees->execute([$tenant_id]); $employeeList = $employees->fetchAll(); $teams = db()->prepare("SELECT * FROM teams WHERE tenant_id = ? ORDER BY name"); $teams->execute([$tenant_id]); $teamList = $teams->fetchAll(); $suppliers = db()->prepare("SELECT * FROM suppliers WHERE tenant_id = ? ORDER BY name"); $suppliers->execute([$tenant_id]); $supplierList = $suppliers->fetchAll(); $expenseTypes = db()->prepare("SELECT * FROM expense_types WHERE tenant_id = ? ORDER BY name"); $expenseTypes->execute([$tenant_id]); $expenseTypeList = $expenseTypes->fetchAll(); $labourTypes = db()->prepare("SELECT * FROM labour_types WHERE tenant_id = ? ORDER BY name"); $labourTypes->execute([$tenant_id]); $labourTypeList = $labourTypes->fetchAll(); $evidenceTypes = db()->prepare("SELECT * FROM evidence_types WHERE tenant_id = ? ORDER BY name"); $evidenceTypes->execute([$tenant_id]); $evidenceTypeList = $evidenceTypes->fetchAll(); $labourEntries = db()->prepare(" SELECT le.*, p.name as project_name, e.name as employee_name, lt.name as labour_type, et.name as evidence_type FROM labour_entries le JOIN projects p ON le.project_id = p.id JOIN employees e ON le.employee_id = e.id LEFT JOIN labour_types lt ON le.labour_type_id = lt.id LEFT JOIN evidence_types et ON le.evidence_type_id = et.id WHERE le.tenant_id = ? ORDER BY le.entry_date DESC, le.created_at DESC "); $labourEntries->execute([$tenant_id]); $labourList = $labourEntries->fetchAll(); $expenseEntries = db()->prepare(" SELECT e.*, p.name as project_name, s.name as supplier_name, et.name as expense_type FROM expenses e JOIN projects p ON e.project_id = p.id JOIN suppliers s ON e.supplier_id = s.id LEFT JOIN expense_types et ON e.expense_type_id = et.id WHERE e.tenant_id = ? ORDER BY e.entry_date DESC, e.created_at DESC "); $expenseEntries->execute([$tenant_id]); $expenseList = $expenseEntries->fetchAll(); $activities = db()->prepare("SELECT * FROM activity_log WHERE tenant_id = ? ORDER BY created_at DESC LIMIT 10"); $activities->execute([$tenant_id]); $activityList = $activities->fetchAll(); $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'SR&ED Project Tracking Software'; ?>
| Project Name | Code | Start Date | Status | Actions |
|---|---|---|---|---|
| = htmlspecialchars($p['name']) ?> | = htmlspecialchars($p['code']) ?> |
= $p['start_date'] ?> | = ucfirst($p['status']) ?> |
| Date | Employee | Project | Hours | Type / Evidence | Actions |
|---|---|---|---|---|---|
| = $l['entry_date'] ?> | = htmlspecialchars($l['employee_name']) ?> | = htmlspecialchars($l['project_name']) ?> | = number_format((float)$l['hours'], 2) ?> h |
= htmlspecialchars($l['labour_type'] ?? 'N/A') ?>
= htmlspecialchars($l['evidence_type'] ?? 'N/A') ?>
|
| Date | Supplier | Project | Amount | Allocation | Actions |
|---|---|---|---|---|---|
| = $ex['entry_date'] ?> | = htmlspecialchars($ex['supplier_name']) ?> = htmlspecialchars($ex['expense_type'] ?? '') ?> |
= htmlspecialchars($ex['project_name']) ?> | $= number_format((float)$ex['amount'], 2) ?> |
|
| Name | Teams | Wage | Access | Actions |
|---|---|---|---|---|
|
= htmlspecialchars($e['first_name'] . ' ' . $e['last_name']) ?> = htmlspecialchars($e['position']) ?> |
prepare("SELECT t.name FROM teams t JOIN employee_teams et ON t.id = et.team_id WHERE et.employee_id = ?"); $e_teams->execute([$e['id']]); $t_names = $e_teams->fetchAll(PDO::FETCH_COLUMN); foreach ($t_names as $tn) { echo '' . htmlspecialchars($tn) . ''; } ?> | $= number_format((float)($e['current_wage'] ?? 0), 2) ?>/h | = $e['is_limited'] ? 'Limited' : 'Regular' ?> |