uptill here

This commit is contained in:
Flatlogic Bot 2025-12-11 09:11:16 +00:00
parent ab34361c28
commit 32e6c844f1
21 changed files with 1076 additions and 1403 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

View File

@ -8,7 +8,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
try { try {
$pdo = db(); $pdo = db();
$stmt = $pdo->prepare("SELECT u.id, u.username, u.password, r.name as role_name $stmt = $pdo->prepare("SELECT u.id, u.username, u.password, u.role_id, r.name as role_name
FROM users u FROM users u
JOIN roles r ON u.role_id = r.id JOIN roles r ON u.role_id = r.id
WHERE u.username = ?"); WHERE u.username = ?");
@ -20,14 +20,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$stmt = $pdo->prepare("SELECT p.name $stmt = $pdo->prepare("SELECT p.name
FROM permissions p FROM permissions p
JOIN role_permissions rp ON p.id = rp.permission_id JOIN role_permissions rp ON p.id = rp.permission_id
WHERE rp.role_id = (SELECT id FROM roles WHERE name = ?)"); WHERE rp.role_id = ?");
$stmt->execute([$user['role_name']]); $stmt->execute([$user['role_id']]);
$permissions = $stmt->fetchAll(PDO::FETCH_COLUMN); $permissions = $stmt->fetchAll(PDO::FETCH_COLUMN);
$_SESSION['user'] = [ $_SESSION['user'] = [
'id' => $user['id'], 'id' => $user['id'],
'username' => $user['username'], 'username' => $user['username'],
'role' => $user['role_name'], 'role' => $user['role_name'],
'role_id' => $user['role_id'],
'permissions' => $permissions 'permissions' => $permissions
]; ];
unset($_SESSION['error']); unset($_SESSION['error']);

View File

@ -0,0 +1,6 @@
INSERT IGNORE INTO `roles` (`name`) VALUES
('Sales Manager'),
('General Manager'),
('Managing Director'),
('Accounts'),
('IT');

View File

@ -0,0 +1,52 @@
-- New fields for customer_applications from Page 1
ALTER TABLE `customer_applications` ADD COLUMN `fax` VARCHAR(255) DEFAULT NULL;
ALTER TABLE `customer_applications` ADD COLUMN `gst_reg_no` VARCHAR(255) DEFAULT NULL;
ALTER TABLE `customer_applications` ADD COLUMN `company_reg_no` VARCHAR(255) DEFAULT NULL;
ALTER TABLE `customer_applications` ADD COLUMN `date_of_incorporation` DATE DEFAULT NULL;
ALTER TABLE `customer_applications` ADD COLUMN `country_of_incorporation` VARCHAR(255) DEFAULT NULL;
ALTER TABLE `customer_applications` ADD COLUMN `contact_person_designation` VARCHAR(255) DEFAULT NULL;
ALTER TABLE `customer_applications` ADD COLUMN `credit_terms` VARCHAR(255) DEFAULT NULL;
ALTER TABLE `customer_applications` ADD COLUMN `account_setup_ar_statement` BOOLEAN DEFAULT FALSE;
ALTER TABLE `customer_applications` ADD COLUMN `account_setup_dunning_letter` BOOLEAN DEFAULT FALSE;
ALTER TABLE `customer_applications` ADD COLUMN `account_setup_ap_payment` BOOLEAN DEFAULT FALSE;
-- New table for shareholder/director information from Page 2
CREATE TABLE IF NOT EXISTS `shareholder_director_information` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`application_id` INT NOT NULL,
`name` VARCHAR(255) DEFAULT NULL,
`address` TEXT DEFAULT NULL,
`perc_of_shareholding` VARCHAR(255) DEFAULT NULL,
`contact_no` VARCHAR(255) DEFAULT NULL,
FOREIGN KEY (`application_id`) REFERENCES `customer_applications`(`id`) ON DELETE CASCADE
);
-- New fields for customer_trade_references from Page 2
ALTER TABLE `customer_trade_references` ADD COLUMN `telephone_no` VARCHAR(255) DEFAULT NULL;
ALTER TABLE `customer_trade_references` ADD COLUMN `fax_no` VARCHAR(255) DEFAULT NULL;
-- New fields for banker's information from Page 3
ALTER TABLE `customer_bank_details` ADD COLUMN `address` TEXT DEFAULT NULL;
ALTER TABLE `customer_bank_details` ADD COLUMN `swift_code` VARCHAR(255) DEFAULT NULL;
ALTER TABLE `customer_bank_details` ADD COLUMN `contact_person` VARCHAR(255) DEFAULT NULL;
ALTER TABLE `customer_bank_details` ADD COLUMN `telephone_no` VARCHAR(255) DEFAULT NULL;
ALTER TABLE `customer_bank_details` ADD COLUMN `fax_no` VARCHAR(255) DEFAULT NULL;
-- New table for financial information from Page 3
CREATE TABLE IF NOT EXISTS `customer_financial_information` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`customer_application_id` INT NOT NULL,
`latest_audited_financial_year` VARCHAR(255) DEFAULT NULL,
`shareholder_equity` VARCHAR(255) DEFAULT NULL,
`paid_up_capital` VARCHAR(255) DEFAULT NULL,
`annual_turnover` VARCHAR(255) DEFAULT NULL,
`net_profit_loss` VARCHAR(255) DEFAULT NULL,
`currency` VARCHAR(50) DEFAULT NULL,
FOREIGN KEY (`customer_application_id`) REFERENCES `customer_applications`(`id`) ON DELETE CASCADE
);
-- Declaration and Authorisation from Page 3
ALTER TABLE `customer_applications` ADD COLUMN `declaration_name` TEXT DEFAULT NULL;
ALTER TABLE `customer_applications` ADD COLUMN `declaration_designation` TEXT DEFAULT NULL;
ALTER TABLE `customer_applications` ADD COLUMN `declaration_date` DATE DEFAULT NULL;

View File

@ -0,0 +1,7 @@
ALTER TABLE `customer_applications` MODIFY `company_name` TEXT;
ALTER TABLE `customer_applications` MODIFY `company_website` TEXT;
ALTER TABLE `customer_applications` MODIFY `sales_owner` TEXT;
ALTER TABLE `customer_applications` MODIFY `major_product` TEXT;
ALTER TABLE `customer_applications` MODIFY `credit_rank` TEXT;
ALTER TABLE `customer_applications` MODIFY `del_to_customer_name` TEXT;
ALTER TABLE `customer_applications` ADD COLUMN `nature_of_business` VARCHAR(255) DEFAULT NULL;

View File

@ -0,0 +1 @@
ALTER TABLE `customer_applications` ADD COLUMN `credit_terms_requested` VARCHAR(255) DEFAULT NULL;

View File

@ -0,0 +1 @@
ALTER TABLE `customer_applications` ADD COLUMN `credit_limit_requested` DECIMAL(15, 2) DEFAULT NULL;

View File

@ -0,0 +1 @@
ALTER TABLE `shareholder_director_information` ADD COLUMN `nric_fin` VARCHAR(255) DEFAULT NULL;

View File

@ -0,0 +1,10 @@
-- Create customer_principals table
CREATE TABLE IF NOT EXISTS `customer_principals` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`customer_application_id` INT NOT NULL,
`name` VARCHAR(255) NOT NULL,
`designation` VARCHAR(255) NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (`customer_application_id`) REFERENCES `customer_applications`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

View File

@ -7,6 +7,13 @@ function hasPermission($permission_name) {
return false; return false;
} }
function get_user_role_id() {
if (isset($_SESSION['user']['role_id'])) {
return $_SESSION['user']['role_id'];
}
return null;
}
function redirect_if_not_authenticated() { function redirect_if_not_authenticated() {
if (!isset($_SESSION['user'])) { if (!isset($_SESSION['user'])) {
header('Location: login.php'); header('Location: login.php');

View File

@ -3,183 +3,262 @@ session_start();
require_once 'includes/auth_helpers.php'; require_once 'includes/auth_helpers.php';
require_once 'db/config.php'; require_once 'db/config.php';
// Protect route: check if user is logged in and has permission
redirect_if_not_authenticated(); redirect_if_not_authenticated();
redirect_if_no_permission('manage_users'); redirect_if_no_permission('manage_users');
$pdo = db();
$user = $_SESSION['user']; $user = $_SESSION['user'];
// Dynamic project data from environment // Handle POST requests for Create, Update, Delete
$projectName = $_SERVER['PROJECT_NAME'] ?? 'Customer Master'; if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Customer Master Registration & Maintenance'; $action = $_POST['action'] ?? '';
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
// Handle file upload try {
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['userCsv'])) { if ($action === 'create_user') {
$file = $_FILES['userCsv']; $username = $_POST['username'];
$password = $_POST['password'];
$role_id = $_POST['role_id'];
$hashed_password = password_hash($password, PASSWORD_DEFAULT);
if ($file['error'] === UPLOAD_ERR_OK) { $stmt = $pdo->prepare("INSERT INTO users (username, password, role_id) VALUES (?, ?, ?)");
$csvData = array_map('str_getcsv', file($file['tmp_name'])); $stmt->execute([$username, $hashed_password, $role_id]);
$header = array_shift($csvData); $_SESSION['flash_message'] = ['type' => 'success', 'message' => 'User created successfully.'];
$expectedHeader = ['username', 'password', 'role'];
if ($header === $expectedHeader) {
$pdo = db();
$pdo->beginTransaction();
$createdCount = 0;
$errorCount = 0;
$errors = [];
// Get all roles from the database
$stmt = $pdo->query("SELECT id, name FROM roles");
$roles = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
foreach ($csvData as $rowIndex => $row) {
$username = $row[0] ?? null;
$password = $row[1] ?? null;
$roleName = $row[2] ?? null;
if (empty($username) || empty($password) || empty($roleName)) {
$errorCount++;
$errors[] = "Row " . ($rowIndex + 2) . ": Invalid data.";
continue;
}
if (!in_array($roleName, $roles)) {
$errorCount++;
$errors[] = "Row " . ($rowIndex + 2) . ": Role '".htmlspecialchars($roleName)."' does not exist.";
continue;
}
$roleId = array_search($roleName, $roles);
try {
$stmt = $pdo->prepare("SELECT id FROM users WHERE username = ?");
$stmt->execute([$username]);
if ($stmt->fetch()) {
$errorCount++;
$errors[] = "Row " . ($rowIndex + 2) . ": User '".htmlspecialchars($username)."' already exists.";
continue;
}
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
$stmt = $pdo->prepare("INSERT INTO users (username, password, role_id) VALUES (?, ?, ?)");
$stmt->execute([$username, $hashedPassword, $roleId]);
$createdCount++;
} catch (PDOException $e) {
$errorCount++;
$errors[] = "Row " . ($rowIndex + 2) . ": Database error.";
}
}
if ($errorCount > 0) {
$pdo->rollBack();
$_SESSION['flash_message'] = [
'type' => 'danger',
'message' => "User import failed with {$errorCount} errors.",
'errors' => $errors
];
} else {
$pdo->commit();
$_SESSION['flash_message'] = [
'type' => 'success',
'message' => "Successfully created {$createdCount} users."
];
}
} else {
$_SESSION['flash_message'] = [
'type' => 'danger',
'message' => 'Invalid CSV header. Expected: username,password,role'
];
} }
} else {
$_SESSION['flash_message'] = [ if ($action === 'update_role') {
'type' => 'danger', $user_id = $_POST['user_id'];
'message' => 'Error uploading file.' $role_id = $_POST['role_id'];
];
$stmt = $pdo->prepare("UPDATE users SET role_id = ? WHERE id = ?");
$stmt->execute([$role_id, $user_id]);
$_SESSION['flash_message'] = ['type' => 'success', 'message' => 'User role updated successfully.'];
}
if ($action === 'delete_user') {
$user_id = $_POST['user_id'];
// Prevent admin from deleting themselves
if ($user_id == get_user_id()) {
$_SESSION['flash_message'] = ['type' => 'danger', 'message' => 'You cannot delete your own account.'];
} else {
$stmt = $pdo->prepare("DELETE FROM users WHERE id = ?");
$stmt->execute([$user_id]);
$_SESSION['flash_message'] = ['type' => 'success', 'message' => 'User deleted successfully.'];
}
}
} catch (PDOException $e) {
$_SESSION['flash_message'] = ['type' => 'danger', 'message' => 'Database error: ' . $e->getMessage()];
} }
header('Location: manage_users.php'); header('Location: manage_users.php');
exit(); exit();
} }
// Fetch all users and roles
$stmt_users = $pdo->query("SELECT u.id, u.username, r.name as role_name, u.created_at FROM users u JOIN roles r ON u.role_id = r.id ORDER BY u.created_at DESC");
$users_list = $stmt_users->fetchAll();
$stmt_roles = $pdo->query("SELECT id, name FROM roles ORDER BY name");
$roles = $stmt_roles->fetchAll();
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Manage Users - <?php echo htmlspecialchars($projectName); ?></title> <title>Manage Users</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css" rel="stylesheet">
</head> </head>
<body> <body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark"> <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid"> <div class="container-fluid">
<a class="navbar-brand" href="index.php"><i class="bi bi-person-vcard"></i> <?php echo htmlspecialchars($projectName); ?></a> <a class="navbar-brand" href="index.php"><i class="bi bi-person-vcard"></i> Customer Master</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#mainNav"> <div class="collapse navbar-collapse">
<span class="navbar-toggler-icon"></span> <ul class="navbar-nav me-auto">
</button> <li class="nav-item"><a class="nav-link" href="index.php">Dashboard</a></li>
<div class="collapse navbar-collapse" id="mainNav"> <li class="nav-item"><a class="nav-link active" href="manage_users.php">Manage Users</a></li>
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="index.php">Dashboard</a>
</li>
<?php if (hasPermission('manage_users')): ?>
<li class="nav-item">
<a class="nav-link active" href="manage_users.php">Manage Users</a>
</li>
<?php endif; ?>
</ul> </ul>
<ul class="navbar-nav"> <ul class="navbar-nav">
<li class="nav-item dropdown"> <li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown"> <a class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown"><i class="bi bi-person-circle"></i> <?= htmlspecialchars($user['username']) ?></a>
<i class="bi bi-person-circle"></i> <?php echo htmlspecialchars($user['username']); ?>
</a>
<ul class="dropdown-menu dropdown-menu-end"> <ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="profile.php">Profile</a></li> <li><a class="dropdown-item" href="logout.php">Logout</a></li>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="logout.php"><i class="bi bi-box-arrow-right"></i> Logout</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
}
</div> </div>
</div> </div>
</nav> </nav>
<main class="container mt-4"> <main class="container mt-4">
<?php if (isset($_SESSION['flash_message'])): ?> <?php if (isset($_SESSION['flash_message'])): ?>
<div class="alert alert-<?php echo $_SESSION['flash_message']['type']; ?> alert-dismissible fade show" role="alert"> <div class="alert alert-<?= $_SESSION['flash_message']['type'] ?> alert-dismissible fade show" role="alert">
<?php echo $_SESSION['flash_message']['message']; ?> <?= $_SESSION['flash_message']['message'] ?>
<?php if (!empty($_SESSION['flash_message']['errors'])): ?>
<ul>
<?php foreach ($_SESSION['flash_message']['errors'] as $error): ?>
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div> </div>
<?php unset($_SESSION['flash_message']); ?> <?php unset($_SESSION['flash_message']); ?>
<?php endif; ?> <?php endif; ?>
<h1 class="h3 mb-4">Manage Users</h1> <div class="d-flex justify-content-between align-items-center mb-3">
<h1 class="h3">Manage Users</h1>
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#createUserModal"><i class="bi bi-plus-circle"></i> Create User</button>
</div>
<div class="card"> <div class="card">
<div class="card-header">
<h5 class="card-title mb-0">Import Users from CSV</h5>
</div>
<div class="card-body"> <div class="card-body">
<p>Upload a CSV file with the following columns: <strong>username</strong>, <strong>password</strong>, <strong>role</strong>.</p> <table class="table table-striped">
<form action="manage_users.php" method="post" enctype="multipart/form-data"> <thead>
<div class="mb-3"> <tr>
<label for="userCsv" class="form-label">CSV File</label> <th>Username</th>
<input class="form-control" type="file" id="userCsv" name="userCsv" accept=".csv" required> <th>Role</th>
</div> <th>Created At</th>
<button type="submit" class="btn btn-primary">Import Users</button> <th>Actions</th>
</form> </tr>
</thead>
<tbody>
<?php foreach ($users_list as $u): ?>
<tr>
<td><?= htmlspecialchars($u['username']) ?></td>
<td><?= htmlspecialchars($u['role_name']) ?></td>
<td><?= date('Y-m-d H:i', strtotime($u['created_at'])) ?></td>
<td>
<button class="btn btn-sm btn-outline-primary" data-bs-toggle="modal" data-bs-target="#editRoleModal" data-user-id="<?= $u['id'] ?>" data-user-role="<?= $u['role_name'] ?>">
<i class="bi bi-pencil-square"></i> Edit Role
</button>
<button class="btn btn-sm btn-outline-danger" data-bs-toggle="modal" data-bs-target="#deleteUserModal" data-user-id="<?= $u['id'] ?>">
<i class="bi bi-trash"></i> Delete
</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div> </div>
</div> </div>
</main> </main>
<!-- Create User Modal -->
<div class="modal fade" id="createUserModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<form action="manage_users.php" method="POST">
<input type="hidden" name="action" value="create_user">
<div class="modal-header">
<h5 class="modal-title">Create New User</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control" id="username" name="username" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
<div class="mb-3">
<label for="role_id" class="form-label">Role</label>
<select class="form-select" id="role_id" name="role_id" required>
<?php foreach ($roles as $role): ?>
<option value="<?= $role['id'] ?>"><?= htmlspecialchars($role['name']) ?></option>
<?php endforeach; ?>
</select>
</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">Create User</button>
</div>
</form>
</div>
</div>
</div>
<!-- Edit Role Modal -->
<div class="modal fade" id="editRoleModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<form action="manage_users.php" method="POST">
<input type="hidden" name="action" value="update_role">
<input type="hidden" name="user_id" id="editUserId">
<div class="modal-header">
<h5 class="modal-title">Edit User Role</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="edit_role_id" class="form-label">Role</label>
<select class="form-select" id="edit_role_id" name="role_id" required>
<?php foreach ($roles as $role): ?>
<option value="<?= $role['id'] ?>"><?= htmlspecialchars($role['name']) ?></option>
<?php endforeach; ?>
</select>
</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>
<!-- Delete User Modal -->
<div class="modal fade" id="deleteUserModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<form action="manage_users.php" method="POST">
<input type="hidden" name="action" value="delete_user">
<input type="hidden" name="user_id" id="deleteUserId">
<div class="modal-header">
<h5 class="modal-title">Confirm Deletion</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<p>Are you sure you want to delete this user? This action cannot be undone.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-danger">Delete User</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="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script>
// Script to handle modal data population
const editRoleModal = document.getElementById('editRoleModal');
editRoleModal.addEventListener('show.bs.modal', event => {
const button = event.relatedTarget;
const userId = button.getAttribute('data-user-id');
const userRole = button.getAttribute('data-user-role');
const modalUserIdInput = editRoleModal.querySelector('#editUserId');
const modalRoleSelect = editRoleModal.querySelector('#edit_role_id');
modalUserIdInput.value = userId;
// Select the correct role in the dropdown
for (let i = 0; i < modalRoleSelect.options.length; i++) {
if (modalRoleSelect.options[i].text === userRole) {
modalRoleSelect.selectedIndex = i;
break;
}
}
});
const deleteUserModal = document.getElementById('deleteUserModal');
deleteUserModal.addEventListener('show.bs.modal', event => {
const button = event.relatedTarget;
const userId = button.getAttribute('data-user-id');
const modalUserIdInput = deleteUserModal.querySelector('#deleteUserId');
modalUserIdInput.value = userId;
});
</script>
</body> </body>
</html> </html>

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,7 @@ if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
$application_id = $_POST['application_id'] ?? null; $application_id = $_POST['application_id'] ?? null;
$action = $_POST['action'] ?? null; $action = $_POST['action'] ?? null;
$comments = $_POST['comments'] ?? '';
if (!$application_id || !$action) { if (!$application_id || !$action) {
header('Location: view_applications.php'); header('Location: view_applications.php');
@ -21,9 +22,17 @@ if (!$application_id || !$action) {
$pdo = db(); $pdo = db();
// --- New Approval Workflow ---
$approval_levels = [
1 => 'Sales Manager',
2 => 'General Manager',
3 => 'Managing Director'
];
// --- End New Approval Workflow ---
// Helper function to get user emails by role name // Helper function to get user emails by role name
function get_user_emails_by_role($role_name, $pdo) { function get_user_emails_by_role($role_name, $pdo) {
$stmt = $pdo->prepare('SELECT u.email FROM users u JOIN user_roles ur ON u.id = ur.user_id JOIN roles r ON ur.role_id = r.id WHERE r.name = ?'); $stmt = $pdo->prepare('SELECT email FROM users u JOIN roles r ON u.role_id = r.id WHERE r.name = ?');
$stmt->execute([$role_name]); $stmt->execute([$role_name]);
return $stmt->fetchAll(PDO::FETCH_COLUMN); return $stmt->fetchAll(PDO::FETCH_COLUMN);
} }
@ -37,93 +46,127 @@ if (!$application) {
die('Application not found.'); die('Application not found.');
} }
// Check permission
$approval_level = $application['approval_level'];
$permission_needed = 'approve_level_' . $approval_level;
if (!hasPermission($permission_needed)) {
$_SESSION['flash_message'] = [
'type' => 'danger',
'message' => 'You do not have permission to perform this action.'
];
header('Location: view_application.php?id=' . $application_id);
exit();
}
// Get applicant email // Get applicant email
$stmt_applicant = $pdo->prepare('SELECT email FROM customer_contacts WHERE customer_application_id = ? AND is_primary = 1'); $stmt_applicant = $pdo->prepare('SELECT email FROM customer_contacts WHERE customer_application_id = ? AND is_primary = 1');
$stmt_applicant->execute([$application_id]); $stmt_applicant->execute([$application_id]);
$applicant_email = $stmt_applicant->fetchColumn(); $applicant_email = $stmt_applicant->fetchColumn();
// Get current user's role
$current_user_role_id = get_user_role_id();
$stmt_role = $pdo->prepare("SELECT name FROM roles WHERE id = ?");
$stmt_role->execute([$current_user_role_id]);
$current_user_role_name = $stmt_role->fetchColumn();
$current_level = $application['approval_level'];
$required_role = $approval_levels[$current_level] ?? null;
// Check if the current user has the required role for this level
if ($current_user_role_name !== $required_role && $current_user_role_name !== 'admin') {
$_SESSION['flash_message'] = ['type' => 'danger', 'message' => 'You do not have permission to perform this action.'];
header('Location: view_application.php?id=' . $application_id);
exit();
}
try { try {
$pdo->beginTransaction();
// Log the action
$stmt_log = $pdo->prepare("INSERT INTO application_approvals (application_id, approver_id, approval_level, status, comments) VALUES (?, ?, ?, ?, ?)");
$stmt_log->execute([$application_id, get_user_id(), $current_level, ucfirst($action), $comments]);
if ($action === 'approve') { if ($action === 'approve') {
$next_approval_level = $approval_level + 1; $next_level = $current_level + 1;
$next_approver_role_name = 'Approver Level ' . $next_approval_level;
$stmt_role = $pdo->prepare("SELECT id FROM roles WHERE name = ?");
$stmt_role->execute([$next_approver_role_name]);
$next_approver_role = $stmt_role->fetch();
if ($next_approver_role) { if (array_key_exists($next_level, $approval_levels)) {
// Move to next approval level // Move to next approval level
$stmt = $pdo->prepare('UPDATE customer_applications SET approval_level = ?, current_approver_role_id = ? WHERE id = ?'); $next_role_name = $approval_levels[$next_level];
$stmt->execute([$next_approval_level, $next_approver_role['id'], $application_id]); $stmt_next_role = $pdo->prepare("SELECT id FROM roles WHERE name = ?");
$_SESSION['flash_message'] = ['type' => 'success', 'message' => 'Application approved and moved to the next level.']; $stmt_next_role->execute([$next_role_name]);
$next_role_id = $stmt_next_role->fetchColumn();
$stmt_update = $pdo->prepare('UPDATE customer_applications SET approval_level = ?, current_approver_role_id = ?, status = \'Pending\' WHERE id = ?');
$stmt_update->execute([$next_level, $next_role_id, $application_id]);
$_SESSION['flash_message'] = ['type' => 'success', 'message' => "Application approved and sent to {$next_role_name}."];
/*
// Notify next approvers // Notify next approvers
$next_approver_emails = get_user_emails_by_role($next_approver_role_name, $pdo); $next_approver_emails = get_user_emails_by_role($next_role_name, $pdo);
if (!empty($next_approver_emails)) { if (!empty($next_approver_emails)) {
// Get Sales Rep name $subject = "Application requires your approval: " . $application['company_name'];
$stmt_sales_rep = $pdo->prepare('SELECT name FROM users WHERE id = ?'); $body = "<p>A credit application for <b>{$application['company_name']}</b> requires your review.</p><p><a href='http://{\$_SERVER['HTTP_HOST']}/view_application.php?id={$application_id}'>View Application</a></p>";
$stmt_sales_rep->execute([$application['created_by_user_id']]);
$sales_rep_name = $stmt_sales_rep->fetchColumn();
// Get Credit Amount
$stmt_credit = $pdo->prepare('SELECT requested_credit_limit FROM financial_credit_details WHERE customer_application_id = ?');
$stmt_credit->execute([$application_id]);
$credit_amount = $stmt_credit->fetchColumn();
$subject = 'Credit Application - ' . $application['company_name'];
$submission_date = date('Y-m-d');
$body = "
<p>A new credit application requires your approval.</p>
<p><strong>Customer Name:</strong> {$application['company_name']}</p>
<p><strong>Sales Rep:</strong> {$sales_rep_name}</p>
<p><strong>Credit Amount:</strong> $" . number_format($credit_amount, 2) . "</p>
<p><strong>Submission Date:</strong> {$submission_date}</p>
<p><a href='http://{$_SERVER['HTTP_HOST']}/view_application.php?id={$application_id}' style='display: inline-block; padding: 10px 20px; background-color: #007bff; color: #fff; text-decoration: none;'>View Application</a></p>
";
MailService::sendMail($next_approver_emails, $subject, $body); MailService::sendMail($next_approver_emails, $subject, $body);
} }
*/
} else { } else {
// Final approval // Final approval
$stmt = $pdo->prepare("UPDATE customer_applications SET status = 'APPROVED', approval_level = NULL, current_approver_role_id = NULL WHERE id = ?"); $stmt_update = $pdo->prepare("UPDATE customer_applications SET status = 'Approved', approval_level = NULL, current_approver_role_id = NULL WHERE id = ?");
$stmt->execute([$application_id]); $stmt_update->execute([$application_id]);
$_SESSION['flash_message'] = ['type' => 'success', 'message' => 'Application approved.']; $_SESSION['flash_message'] = ['type' => 'success', 'message' => 'Application has been fully approved.'];
/*
// Notify applicant // Notify applicant
if ($applicant_email) { if ($applicant_email) {
$subject = 'Your Application has been Approved: ' . $application['application_id']; $subject = 'Your Application has been Approved: ' . $application['application_id'];
$body = "<p>Congratulations! Your customer application ({$application['application_id']}) has been approved.</p>"; $body = "<p>Congratulations! Your customer application ({$application['application_id']}) has been approved.</p>";
MailService::sendMail($applicant_email, $subject, $body); MailService::sendMail($applicant_email, $subject, $body);
} }
*/
} }
} elseif ($action === 'reject') {
$stmt = $pdo->prepare("UPDATE customer_applications SET status = 'REJECTED' WHERE id = ?");
$stmt->execute([$application_id]);
$_SESSION['flash_message'] = ['type' => 'success', 'message' => 'Application rejected.'];
} elseif ($action === 'return') {
$prev_level = $current_level - 1;
if (array_key_exists($prev_level, $approval_levels)) {
// Return to previous approval level
$prev_role_name = $approval_levels[$prev_level];
$stmt_prev_role = $pdo->prepare("SELECT id FROM roles WHERE name = ?");
$stmt_prev_role->execute([$prev_role_name]);
$prev_role_id = $stmt_prev_role->fetchColumn();
$stmt_update = $pdo->prepare('UPDATE customer_applications SET approval_level = ?, current_approver_role_id = ?, status = \'Returned\' WHERE id = ?');
$stmt_update->execute([$prev_level, $prev_role_id, $application_id]);
$_SESSION['flash_message'] = ['type' => 'warning', 'message' => "Application returned to {$prev_role_name} for review."];
/*
// Notify previous approvers
$prev_approver_emails = get_user_emails_by_role($prev_role_name, $pdo);
if (!empty($prev_approver_emails)) {
$subject = "Application returned for your review: " . $application['company_name'];
$body = "<p>The application for <b>{$application['company_name']}</b> has been returned for your review with the following comments:</p><p><i>" . htmlspecialchars($comments) . "</i></p><p><a href='http://{\$_SERVER['HTTP_HOST']}/view_application.php?id={$application_id}'>View Application</a></p>";
MailService::sendMail($prev_approver_emails, $subject, $body);
}
*/
} else {
// Cannot return from the first level, this case should ideally be handled in the UI
$_SESSION['flash_message'] = ['type' => 'danger', 'message' => "Cannot return the application from the first approval level."];
}
} elseif ($action === 'reject') {
$stmt_update = $pdo->prepare("UPDATE customer_applications SET status = 'Rejected' WHERE id = ?");
$stmt_update->execute([$application_id]);
$_SESSION['flash_message'] = ['type' => 'danger', 'message' => 'Application has been rejected.'];
/*
// Notify applicant // Notify applicant
if ($applicant_email) { if ($applicant_email) {
$subject = 'Your Application has been Rejected: ' . $application['application_id']; $subject = 'Your Application has been Rejected: ' . $application['application_id'];
$body = "<p>We regret to inform you that your customer application ({$application['application_id']}) has been rejected.</p>"; $body = "<p>We regret to inform you that your customer application ({$application['application_id']}) has been rejected. The following comments were provided:</p><p><i>" . htmlspecialchars($comments) . "</i></p>";
MailService::sendMail($applicant_email, $subject, $body); MailService::sendMail($applicant_email, $subject, $body);
} }
*/
} }
} catch (PDOException $e) { $pdo->commit();
} catch (Exception $e) {
$pdo->rollBack();
error_log('Approval processing failed: ' . $e->getMessage()); error_log('Approval processing failed: ' . $e->getMessage());
$_SESSION['flash_message'] = ['type' => 'danger', 'message' => 'An error occurred. Please try again.']; $_SESSION['flash_message'] = ['type' => 'danger', 'message' => 'An error occurred while processing the application. Please try again.'];
} }
header('Location: view_application.php?id=' . $application_id); header('Location: view_application.php?id=' . $application_id);
exit(); exit();

View File

@ -1,6 +1,7 @@
<?php <?php
session_start(); session_start();
require_once __DIR__ . '/db/config.php'; require_once __DIR__ . '/db/config.php';
require_once 'includes/auth_helpers.php';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') { if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405); http_response_code(405);
@ -15,234 +16,164 @@ if (!isset($_SESSION['user'])) {
$pdo = db(); $pdo = db();
try { try {
// Get the role ID for the first approval level $pdo->beginTransaction();
$stmt_role = $pdo->prepare("SELECT id FROM roles WHERE name = 'Approver Level 1'");
// 1. Insert into customer_applications
$stmt = $pdo->prepare(
'INSERT INTO customer_applications (
application_id, customer_id, created_by, company_name, company_phone, fax, gst_reg_no,
company_reg_no, date_of_incorporation, country_of_incorporation, nature_of_business,
credit_terms_requested, credit_limit_requested, account_setup_ar_statement,
account_setup_dunning_letter, account_setup_ap_payment,
declaration_name, declaration_designation, declaration_date
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
);
$stmt->execute([
uniqid(),
$_SESSION['user']['id'],
$_SESSION['user']['id'],
$_POST['company_name'] ?? null,
$_POST['company_phone'] ?? null,
$_POST['fax'] ?? null,
$_POST['gst_reg_no'] ?? null,
$_POST['company_reg_no'] ?? null,
$_POST['date_of_incorporation'] ?? null,
$_POST['country_of_incorporation'] ?? null,
$_POST['nature_of_business'] ?? null,
$_POST['credit_terms_requested'] ?? null,
$_POST['credit_limit_requested'] ?? null,
isset($_POST['account_setup_ar_statement']) ? 1 : 0,
isset($_POST['account_setup_dunning_letter']) ? 1 : 0,
isset($_POST['account_setup_ap_payment']) ? 1 : 0,
$_POST['declaration_name'] ?? null,
$_POST['declaration_designation'] ?? null,
$_POST['declaration_date'] ?? null
]);
$customer_application_id = $pdo->lastInsertId();
// Insert Primary Contact
if (!empty($_POST['contact_person_name']) && !empty($_POST['contact_person_email'])) {
$stmt_contact = $pdo->prepare(
'INSERT INTO customer_contacts (customer_application_id, name, email, phone, is_primary) VALUES (?, ?, ?, ?, ?)'
);
$stmt_contact->execute([
$customer_application_id,
$_POST['contact_person_name'],
$_POST['contact_person_email'],
$_POST['contact_person_phone'] ?? null,
1 // Set as primary contact
]);
}
// Insert Billing Address
if (!empty($_POST['company_address'])) {
$stmt_address = $pdo->prepare(
'INSERT INTO customer_addresses (customer_application_id, address_type, address_line_1) VALUES (?, ?, ?)'
);
$stmt_address->execute([$customer_application_id, 'BILLING', $_POST['company_address']]);
}
// Insert Delivery Address
if (!empty($_POST['del_to_address'])) {
$stmt_del_address = $pdo->prepare(
'INSERT INTO customer_addresses (customer_application_id, address_type, address_line_1) VALUES (?, ?, ?)'
);
$stmt_del_address->execute([$customer_application_id, 'SHIPPING', $_POST['del_to_address']]);
}
// 2. Insert into shareholder_director_information
if (isset($_POST['shareholder']) && is_array($_POST['shareholder'])) {
$stmt_shareholder = $pdo->prepare(
'INSERT INTO shareholder_director_information (application_id, name, address, nric_fin, perc_of_shareholding, contact_no) VALUES (?, ?, ?, ?, ?, ?)'
);
foreach ($_POST['shareholder'] as $shareholder) {
if (empty($shareholder['name'])) continue; // Skip empty rows
$stmt_shareholder->execute([
$customer_application_id,
$shareholder['name'] ?? null,
$shareholder['address'] ?? null,
$shareholder['nric_fin'] ?? null,
$shareholder['perc_of_shareholding'] ?? null,
$shareholder['contact_no'] ?? null
]);
}
}
// 3. Insert into customer_trade_references
if (isset($_POST['trade_reference']) && is_array($_POST['trade_reference'])) {
$stmt_trade_ref = $pdo->prepare(
'INSERT INTO customer_trade_references (customer_application_id, company_name, contact_person, telephone_no, fax_no) VALUES (?, ?, ?, ?, ?)'
);
foreach ($_POST['trade_reference'] as $trade_ref) {
if (empty($trade_ref['company_name'])) continue; // Skip empty rows
$stmt_trade_ref->execute([
$customer_application_id,
$trade_ref['company_name'] ?? null,
$trade_ref['contact_person'] ?? null,
$trade_ref['telephone_no'] ?? null,
$trade_ref['fax_no'] ?? null
]);
}
}
// 4. Insert into customer_bank_details
if (!empty($_POST['bank_name'])) {
$stmt_bank = $pdo->prepare(
'INSERT INTO customer_bank_details (customer_application_id, bank_name, address, swift_code, account_number, contact_person, telephone_no, fax_no) VALUES (?, ?, ?, ?, ?, ?, ?, ?)'
);
$stmt_bank->execute([
$customer_application_id,
$_POST['bank_name'] ?? null,
$_POST['bank_address'] ?? null,
$_POST['bank_swift_code'] ?? null,
$_POST['bank_account_no'] ?? null,
$_POST['bank_contact_person'] ?? null,
$_POST['bank_telephone_no'] ?? null,
$_POST['bank_fax_no'] ?? null
]);
}
// 5. Insert into customer_financial_information
if (!empty($_POST['paid_up_capital'])) {
$stmt_financial = $pdo->prepare(
'INSERT INTO customer_financial_information (customer_application_id, latest_audited_financial_year, shareholder_equity, paid_up_capital, annual_turnover, net_profit_loss, currency) VALUES (?, ?, ?, ?, ?, ?, ?)'
);
$stmt_financial->execute([
$customer_application_id,
$_POST['latest_audited_financial_year'] ?? null,
$_POST['shareholder_equity'] ?? null,
$_POST['paid_up_capital'] ?? null,
$_POST['annual_turnover'] ?? null,
$_POST['net_profit_loss'] ?? null,
$_POST['currency'] ?? null
]);
}
// Set initial approval status
$stmt_role = $pdo->prepare("SELECT id FROM roles WHERE name = 'Sales Manager'");
$stmt_role->execute(); $stmt_role->execute();
$approver_role = $stmt_role->fetch(PDO::FETCH_ASSOC); $approver_role = $stmt_role->fetch(PDO::FETCH_ASSOC);
$approver_role_id = $approver_role ? $approver_role['id'] : null; $approver_role_id = $approver_role ? $approver_role['id'] : null;
$pdo->beginTransaction(); $stmt_update = $pdo->prepare('UPDATE customer_applications SET approval_level = 1, current_approver_role_id = ? WHERE id = ?');
$stmt_update->execute([$approver_role_id, $customer_application_id]);
// 1. Insert into customer_applications
$application_id = 'APP-' . strtoupper(uniqid());
$created_by = $_SESSION['user']['username'] ?? 'system';
$stmt = $pdo->prepare(
'INSERT INTO customer_applications (user_id, company_name, company_website, company_phone, sales_owner, payment_terms, tags, notes, declaration_text, signature_path, major_product, capital, capital_currency, main_shareholders, num_employees, payment_terms_ar, pl_year, net_sales, net_income_margin, net_income_margin_ratio, sales_target_this_year, sales_target_next_year, sales_target_after_next, credit_rank, credit_limit, credit_research_status, credit_research_reason, tax_rate_area, billing_type, del_to_code, delivery_abbreviation, del_to_customer_name, del_to_address_1, del_to_address_2, del_to_address_3, del_to_address_4, del_to_postcode, del_to_phone, del_to_area_code, del_to_transportation_code, del_to_stock_point_code, del_to_recipient_section, del_to_country_code, del_to_shipment_flag, del_to_transport_days, del_to_shipment_condition_category, del_to_transport_service_exist, del_to_shipment_condition_place, doc_req_do, doc_req_packing_list, doc_req_invoice, doc_req_export_permit, doc_req_po_do_inv, doc_req_do_inv, doc_req_others, pack_req_one_line_carton, pack_req_one_item_carton, pack_req_one_item_pocket, pack_req_thomson_label, pack_req_contents_label, pack_req_delivery_schedule, forwarder_name, forwarder_code, forwarder_address, forwarder_contact_person, forwarder_phone, forwarder_fax, forwarder_delivery_method, forwarder_delivery_timings, forwarder_delivery_requirements, special_instructions_shipping_mark, special_instructions_fax_documents, special_instructions_details, special_instructions_attention_to, special_instructions_fax_number, remarks) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
);
$stmt->execute([
$_SESSION['user_id'],
$_POST['company_name'],
$_POST['company_website'],
$_POST['company_phone'],
$_POST['sales_owner'],
$_POST['payment_terms'],
$_POST['tags'],
$_POST['notes'],
$_POST['declaration_text'],
$signature_path,
$_POST['major_product'] ?? null,
$_POST['capital'] ?? null,
$_POST['capital_currency'] ?? null,
$_POST['main_shareholders'] ?? null,
$_POST['num_employees'] ?? null,
$_POST['payment_terms_ar'] ?? null,
$_POST['pl_year'] ?? null,
$_POST['net_sales'] ?? null,
$_POST['net_income_margin'] ?? null,
$_POST['net_income_margin_ratio'] ?? null,
$_POST['sales_target_this_year'] ?? null,
$_POST['sales_target_next_year'] ?? null,
$_POST['sales_target_after_next'] ?? null,
$_POST['credit_rank'] ?? null,
$_POST['credit_limit'] ?? null,
$_POST['credit_research_status'] ?? null,
$_POST['credit_research_reason'] ?? null,
$_POST['tax_rate_area'] ?? null,
$_POST['billing_type'] ?? null,
$_POST['del_to_code'] ?? null,
$_POST['delivery_abbreviation'] ?? null,
$_POST['del_to_customer_name'] ?? null,
$_POST['del_to_address_1'] ?? null,
$_POST['del_to_address_2'] ?? null,
$_POST['del_to_address_3'] ?? null,
$_POST['del_to_address_4'] ?? null,
$_POST['del_to_postcode'] ?? null,
$_POST['del_to_phone'] ?? null,
$_POST['del_to_area_code'] ?? null,
$_POST['del_to_transportation_code'] ?? null,
$_POST['del_to_stock_point_code'] ?? null,
$_POST['del_to_recipient_section'] ?? null,
$_POST['del_to_country_code'] ?? null,
$_POST['del_to_shipment_flag'] ?? null,
$_POST['del_to_transport_days'] ?? null,
$_POST['del_to_shipment_condition_category'] ?? null,
isset($_POST['del_to_transport_service_exist']) ? implode(',', $_POST['del_to_transport_service_exist']) : null,
$_POST['del_to_shipment_condition_place'] ?? null,
$_POST['doc_req_do'] ?? null,
$_POST['doc_req_packing_list'] ?? null,
$_POST['doc_req_invoice'] ?? null,
$_POST['doc_req_export_permit'] ?? null,
$_POST['doc_req_po_do_inv'] ?? null,
$_POST['doc_req_do_inv'] ?? null,
$_POST['doc_req_others'] ?? null,
$_POST['pack_req_one_line_carton'] ?? null,
$_POST['pack_req_one_item_carton'] ?? null,
$_POST['pack_req_one_item_pocket'] ?? null,
$_POST['pack_req_thomson_label'] ?? null,
$_POST['pack_req_contents_label'] ?? null,
$_POST['pack_req_delivery_schedule'] ?? null,
$_POST['forwarder_name'] ?? null,
$_POST['forwarder_code'] ?? null,
$_POST['forwarder_address'] ?? null,
$_POST['forwarder_contact_person'] ?? null,
$_POST['forwarder_phone'] ?? null,
$_POST['forwarder_fax'] ?? null,
$_POST['forwarder_delivery_method'] ?? null,
$_POST['forwarder_delivery_timings'] ?? null,
$_POST['forwarder_delivery_requirements'] ?? null,
$_POST['special_instructions_shipping_mark'] ?? null,
$_POST['special_instructions_fax_documents'] ?? null,
$_POST['special_instructions_details'] ?? null,
$_POST['special_instructions_attention_to'] ?? null,
$_POST['special_instructions_fax_number'] ?? null,
$_POST['remarks'] ?? null
]);
$customer_application_id = $pdo->lastInsertId();
// 2. Insert into customer_contacts
if (isset($_POST['contact']) && is_array($_POST['contact'])) {
$stmt_contact = $pdo->prepare(
'INSERT INTO customer_contacts (customer_application_id, name, email, phone, is_primary) VALUES (?, ?, ?, ?, ?)'
);
foreach ($_POST['contact'] as $index => $contact) {
$is_primary = (isset($contact['is_primary']) && $contact['is_primary'] == '1');
$stmt_contact->execute([
$customer_application_id,
$contact['name'],
$contact['email'],
$contact['phone'],
$is_primary ? 1 : 0
]);
}
}
// 3. Insert into customer_addresses
if (isset($_POST['address']) && is_array($_POST['address'])) {
$stmt_address = $pdo->prepare(
'INSERT INTO customer_addresses (customer_application_id, address_type, address_line_1, address_line_2, city, state, postal_code, country) VALUES (?, ?, ?, ?, ?, ?, ?, ?)'
);
foreach ($_POST['address'] as $address) {
$stmt_address->execute([
$customer_application_id,
$address['type'],
$address['line1'],
$address['line2'],
$address['city'],
$address['state'],
$address['postal_code'],
$address['country']
]);
}
}
// 4. Insert into customer_trade_references
if (isset($_POST['trade_reference']) && is_array($_POST['trade_reference'])) {
$stmt_trade_ref = $pdo->prepare(
'INSERT INTO customer_trade_references (customer_application_id, company_name, contact_person, email, phone, address) VALUES (?, ?, ?, ?, ?, ?)'
);
foreach ($_POST['trade_reference'] as $trade_ref) {
$stmt_trade_ref->execute([
$customer_application_id,
$trade_ref['company_name'],
$trade_ref['contact_person'],
$trade_ref['email'],
$trade_ref['phone'],
$trade_ref['address']
]);
}
}
// 5. Insert into customer_bank_details
if (isset($_POST['bank_name'])) {
$stmt_bank = $pdo->prepare(
'INSERT INTO customer_bank_details (customer_application_id, bank_name, branch, bsb_number, account_number, account_name) VALUES (?, ?, ?, ?, ?, ?)'
);
$stmt_bank->execute([
$customer_application_id,
$_POST['bank_name'],
$_POST['branch'],
$_POST['bsb_number'],
$_POST['account_number'],
$_POST['account_name']
]);
}
// 6. Handle Signature and Declaration
$signature_path = null;
if (isset($_POST['signature']) && !empty($_POST['signature'])) {
$signature_data = $_POST['signature'];
list($type, $data) = explode(';', $signature_data);
list(, $data) = explode(',', $data);
$data = base64_decode($data);
$signature_filename = 'signature_' . $application_id . '_' . time() . '.png';
$signature_path = 'uploads/' . $signature_filename;
file_put_contents($signature_path, $data);
}
$stmt_declar = $pdo->prepare('UPDATE customer_applications SET declaration_text = ?, signature_path = ? WHERE id = ?');
$stmt_declar->execute([
$_POST['declaration_text'],
$signature_path,
$customer_application_id
]);
$pdo->commit(); $pdo->commit();
// Notify approvers
require_once 'mail/MailService.php';
$approver_emails = get_user_emails_by_role('Approver Level 1', $pdo);
if (!empty($approver_emails)) {
// Get Sales Rep name
$stmt_sales_rep = $pdo->prepare('SELECT name FROM users WHERE id = ?');
$stmt_sales_rep->execute([$_SESSION['user_id']]);
$sales_rep_name = $stmt_sales_rep->fetchColumn();
$subject = 'New Credit Application Submitted - ' . $_POST['company_name'];
$submission_date = date('Y-m-d');
$body = "
<p>A new credit application has been submitted and requires your approval.</p>
<p><strong>Customer Name:</strong> {$_POST['company_name']}</p>
<p><strong>Sales Rep:</strong> {$sales_rep_name}</p>
<p><strong>Credit Amount:</strong> $" . number_format($_POST['credit_limit'], 2) . "</p>
<p><strong>Submission Date:</strong> {$submission_date}</p>
<p><a href='http://{$_SERVER['HTTP_HOST']}/view_application.php?id={$customer_application_id}' style='display: inline-block; padding: 10px 20px; background-color: #007bff; color: #fff; text-decoration: none;'>View Application</a></p>
";
MailService::sendMail($approver_emails, $subject, $body);
}
// Redirect to dashboard with success message
$_SESSION['flash_message'] = [ $_SESSION['flash_message'] = [
'type' => 'success', 'type' => 'success',
'message' => 'Customer application (' . $application_id . ') submitted successfully!' 'message' => 'Customer application submitted successfully!'
]; ];
header('Location: index.php'); header('Location: index.php');
exit(); exit();
function get_user_emails_by_role($role_name, $pdo) {
$stmt = $pdo->prepare('SELECT u.email FROM users u JOIN user_roles ur ON u.id = ur.user_id JOIN roles r ON ur.role_id = r.id WHERE r.name = ?');
$stmt->execute([$role_name]);
return $stmt->fetchAll(PDO::FETCH_COLUMN);
}
} catch (PDOException $e) { } catch (PDOException $e) {
$pdo->rollBack(); $pdo->rollBack();
error_log('Application submission failed: ' . $e->getMessage()); error_log('Application submission failed: ' . $e->getMessage());
// Redirect back to form with error message
$_SESSION['flash_message'] = [ $_SESSION['flash_message'] = [
'type' => 'danger', 'type' => 'danger',
'message' => 'There was an error submitting your application. Please try again. ' . $e->getMessage() 'message' => 'There was an error submitting your application. Please check the data and try again. Error: ' . $e->getMessage()
]; ];
header('Location: new_application.php'); header('Location: new_application.php');
exit(); exit();

69
submit_for_approval.php Normal file
View File

@ -0,0 +1,69 @@
<?php
session_start();
require_once 'includes/auth_helpers.php';
require_once 'db/config.php';
redirect_if_not_authenticated();
if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_POST['application_id'])) {
header('Location: view_applications.php');
exit();
}
$application_id = $_POST['application_id'];
$pdo = db();
// Get the role ID for the first approval level (Sales Manager)
$stmt_role = $pdo->prepare("SELECT id FROM roles WHERE name = 'Sales Manager'");
$stmt_role->execute();
$sales_manager_role_id = $stmt_role->fetchColumn();
if (!$sales_manager_role_id) {
$_SESSION['flash_message'] = [
'type' => 'danger',
'message' => 'Error: Sales Manager role not found. Cannot submit for approval.'
];
header('Location: view_application.php?id=' . $application_id);
exit();
}
// Update the application to start the approval process
$stmt = $pdo->prepare(
'UPDATE customer_applications
SET status = ?, approval_level = ?, current_approver_role_id = ?
WHERE id = ? AND status = ?'
);
$success = $stmt->execute([
'Pending',
1, // Start at level 1
$sales_manager_role_id,
$application_id,
'Draft' // Ensure we only update drafts
]);
if ($success && $stmt->rowCount() > 0) {
// Create initial approval history entry
$stmt_history = $pdo->prepare(
'INSERT INTO application_approvals (application_id, approver_id, status, comments, created_at) VALUES (?, ?, ?, ?, NOW())'
);
$stmt_history->execute([
$application_id,
get_user_id(), // The user submitting the application
'Submitted',
'Application submitted for approval.'
]);
$_SESSION['flash_message'] = [
'type' => 'success',
'message' => 'Application successfully submitted for approval.'
];
} else {
$_SESSION['flash_message'] = [
'type' => 'danger',
'message' => 'Failed to submit application. It might not be in a draft state or another error occurred.'
];
}
header('Location: view_application.php?id=' . $application_id);
exit();

View File

@ -1,5 +1,6 @@
<?php <?php
session_start(); session_start();
require_once 'includes/auth_helpers.php'; require_once 'includes/auth_helpers.php';
require_once 'db/config.php'; require_once 'db/config.php';
@ -13,8 +14,18 @@ if (!isset($_GET['id']) || empty($_GET['id'])) {
$application_id = $_GET['id']; $application_id = $_GET['id'];
$pdo = db(); $pdo = db();
// --- New Approval Workflow ---
$approval_levels = [
1 => 'Sales Manager',
2 => 'General Manager',
3 => 'Managing Director',
4 => 'Accounts',
5 => 'IT'
];
// --- End New Approval Workflow ---
// Fetch application details // Fetch application details
$stmt = $pdo->prepare('SELECT * FROM customer_applications WHERE id = ?'); $stmt = $pdo->prepare('SELECT a.*, r.name as current_approver_role FROM customer_applications a LEFT JOIN roles r ON a.current_approver_role_id = r.id WHERE a.id = ?');
$stmt->execute([$application_id]); $stmt->execute([$application_id]);
$application = $stmt->fetch(); $application = $stmt->fetch();
@ -22,30 +33,27 @@ if (!$application) {
die('Application not found.'); die('Application not found.');
} }
// Fetch contacts // Fetch approval history
$stmt = $pdo->prepare('SELECT * FROM customer_contacts WHERE customer_application_id = ?'); $stmt_history = $pdo->prepare('SELECT ah.*, u.username as approver_name FROM application_approvals ah JOIN users u ON ah.approver_id = u.id WHERE ah.application_id = ? ORDER BY ah.created_at DESC');
$stmt->execute([$application_id]); $stmt_history->execute([$application_id]);
$contacts = $stmt->fetchAll(); $approval_history = $stmt_history->fetchAll();
// Fetch addresses // Fetch other details (contacts, addresses, etc.) - condensed for brevity
$stmt = $pdo->prepare('SELECT * FROM customer_addresses WHERE customer_application_id = ?'); $contacts = $pdo->query("SELECT * FROM customer_contacts WHERE customer_application_id = {$application_id}")->fetchAll();
$stmt->execute([$application_id]); $addresses = $pdo->query("SELECT * FROM customer_addresses WHERE customer_application_id = {$application_id}")->fetchAll();
$addresses = $stmt->fetchAll(); $trade_references = $pdo->query("SELECT * FROM customer_trade_references WHERE customer_application_id = {$application_id}")->fetchAll();
$bank_details = $pdo->query("SELECT * FROM customer_bank_details WHERE customer_application_id = {$application_id}")->fetch();
$principals = $pdo->query("SELECT * FROM customer_principals WHERE customer_application_id = {$application_id}")->fetchAll();
// Fetch trade references // Get current user role
$stmt = $pdo->prepare('SELECT * FROM customer_trade_references WHERE customer_application_id = ?'); $current_user_role_id = get_user_role_id();
$stmt->execute([$application_id]); $stmt_role = $pdo->prepare("SELECT name FROM roles WHERE id = ?");
$trade_references = $stmt->fetchAll(); $stmt_role->execute([$current_user_role_id]);
$current_user_role_name = $stmt_role->fetchColumn();
// Fetch bank details $current_level = $application['approval_level'];
$stmt = $pdo->prepare('SELECT * FROM customer_bank_details WHERE customer_application_id = ?'); $required_role = $approval_levels[$current_level] ?? null;
$stmt->execute([$application_id]); $can_approve = ($current_user_role_name === $required_role || $current_user_role_name === 'admin');
$bank_details = $stmt->fetch();
// Fetch principals
$stmt = $pdo->prepare('SELECT * FROM customer_principals WHERE customer_application_id = ?');
$stmt->execute([$application_id]);
$principals = $stmt->fetchAll();
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
@ -60,349 +68,125 @@ $principals = $stmt->fetchAll();
<nav class="navbar navbar-expand-lg navbar-light bg-light"> <nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid"> <div class="container-fluid">
<a class="navbar-brand" href="#">Customer Master</a> <a class="navbar-brand" href="#">Customer Master</a>
<div class="collapse navbar-collapse"> <ul class="navbar-nav ms-auto">
<ul class="navbar-nav ms-auto"> <li class="nav-item"><a class="nav-link" href="index.php">Dashboard</a></li>
<li class="nav-item"> <li class="nav-item"><a class="nav-link" href="view_applications.php">View Applications</a></li>
<a class="nav-link" href="index.php">Dashboard</a> <li class="nav-item"><a class="nav-link" href="logout.php">Logout</a></li>
</li> </ul>
<li class="nav-item">
<a class="nav-link" href="view_applications.php">View Applications</a>
</li>
<li class="nav-item">
<a class="nav-link" href="logout.php">Logout</a>
</li>
</ul>
</div>
</div> </div>
</nav> </nav>
<div class="container mt-4"> <div class="container mt-4">
<?php if (isset($_SESSION['flash_message'])): ?>
<div class="alert alert-<?= $_SESSION['flash_message']['type'] ?> alert-dismissible fade show" role="alert">
<?= $_SESSION['flash_message']['message'] ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<?php unset($_SESSION['flash_message']); ?>
<?php endif; ?>
<h2>Application Details: <?= htmlspecialchars($application['application_id']) ?></h2> <h2>Application Details: <?= htmlspecialchars($application['application_id']) ?></h2>
<!-- Company Details --> <!-- Approval Status & History -->
<div class="card mb-4"> <div class="card mb-4">
<div class="card-header">Company Details</div> <div class="card-header">Approval Status & History</div>
<div class="card-body"> <div class="card-body">
<p><strong>Company Name:</strong> <?= htmlspecialchars($application['company_name']) ?></p> <h4>Current Status:
<p><strong>Company Website:</strong> <a href="<?= htmlspecialchars($application['company_website']) ?>" target="_blank"><?= htmlspecialchars($application['company_website']) ?></a></p> <span class="badge bg-<?=
<p><strong>Company Phone:</strong> <?= htmlspecialchars($application['company_phone']) ?></p> strtoupper($application['status']) === 'APPROVED' ? 'success' : (
<p><strong>Sales Owner:</strong> <?= htmlspecialchars($application['sales_owner']) ?></p> strtoupper($application['status']) === 'REJECTED' ? 'danger' : (
<p><strong>Payment Terms:</strong> <?= htmlspecialchars($application['payment_terms']) ?></p> strtoupper($application['status']) === 'RETURNED' ? 'warning' : 'secondary'
<p><strong>Tags:</strong> <?= htmlspecialchars($application['tags']) ?></p> ))
<p><strong>Notes:</strong> <?= nl2br(htmlspecialchars($application['notes'])) ?></p> ?>">
</div> <?= htmlspecialchars(strtoupper($application['status'])) ?>
</div> </span>
</h4>
<?php if ($application['status'] === 'Pending' && $application['current_approver_role']): ?>
<p class="text-muted">Waiting for approval from: <strong><?= htmlspecialchars($application['current_approver_role']) ?></strong></p>
<?php endif; ?>
<!-- Financial & Credit Details --> <?php if ($application['status'] === 'Draft'): ?>
<div class="card mb-4"> <form action="submit_for_approval.php" method="POST" class="mt-3">
<div class="card-header">Financial & Credit Details</div> <input type="hidden" name="application_id" value="<?= $application['id'] ?>">
<div class="card-body"> <button type="submit" class="btn btn-primary">Submit for Approval</button>
<p><strong>Major Product:</strong> <?= htmlspecialchars($application['major_product']) ?></p> </form>
<p><strong>Capital:</strong> <?= htmlspecialchars($application['capital']) ?> <?= htmlspecialchars($application['capital_currency']) ?></p> <?php endif; ?>
<p><strong>Main Shareholders:</strong> <?= htmlspecialchars($application['main_shareholders']) ?></p>
<p><strong>Number of Employees:</strong> <?= htmlspecialchars($application['num_employees']) ?></p>
<p><strong>Payment Terms AR:</strong> <?= htmlspecialchars($application['payment_terms_ar']) ?></p>
<hr>
<h6>P/L Information</h6>
<p><strong>Year:</strong> <?= htmlspecialchars($application['pl_year']) ?></p>
<p><strong>Net Sales:</strong> <?= htmlspecialchars($application['net_sales']) ?></p>
<p><strong>Net Income Margin:</strong> <?= htmlspecialchars($application['net_income_margin']) ?></p>
<p><strong>Net Income Margin Ratio:</strong> <?= htmlspecialchars($application['net_income_margin_ratio']) ?>%</p>
<hr>
<h6>ROHM Sales Target (KUS$)</h6>
<p><strong>This Year:</strong> <?= htmlspecialchars($application['sales_target_this_year']) ?></p>
<p><strong>Next Year:</strong> <?= htmlspecialchars($application['sales_target_next_year']) ?></p>
<p><strong>After the Next:</strong> <?= htmlspecialchars($application['sales_target_after_next']) ?></p>
<hr>
<h6>Credit Information</h6>
<p><strong>Rank:</strong> <?= htmlspecialchars($application['credit_rank']) ?></p>
<p><strong>Limit:</strong> <?= htmlspecialchars($application['credit_limit']) ?> KUS$</p>
<hr>
<h6>Credit Research</h6>
<p><strong>Status:</strong> <?= htmlspecialchars($application['credit_research_status']) ?></p>
<p><strong>Reason:</strong> <?= htmlspecialchars($application['credit_research_reason']) ?></p>
<hr>
<p><strong>Tax Rate/Area (GST TYPE):</strong> <?= htmlspecialchars($application['tax_rate_area']) ?></p>
<p><strong>Billing Type:</strong> <?= htmlspecialchars($application['billing_type']) ?></p>
</div>
</div>
<!-- Del-To Informations --> <h5 class="mt-4">Approval History</h5>
<div class="card mb-4"> <?php if (empty($approval_history)): ?>
<div class="card-header">Del-To Informations</div> <p>No approval history found.</p>
<div class="card-body">
<p><strong>Del-To Code:</strong> <?= htmlspecialchars($application['del_to_code']) ?></p>
<p><strong>Abbreviation of Delivery-To:</strong> <?= htmlspecialchars($application['delivery_abbreviation']) ?></p>
<p><strong>Customer Name:</strong> <?= htmlspecialchars($application['del_to_customer_name']) ?></p>
<p><strong>Address:</strong><br>
<?= htmlspecialchars($application['del_to_address_1']) ?><br>
<?php if(!empty($application['del_to_address_2'])): ?>
<?= htmlspecialchars($application['del_to_address_2']) ?><br>
<?php endif; ?>
<?php if(!empty($application['del_to_address_3'])): ?>
<?= htmlspecialchars($application['del_to_address_3']) ?><br>
<?php endif; ?>
<?php if(!empty($application['del_to_address_4'])): ?>
<?= htmlspecialchars($application['del_to_address_4']) ?><br>
<?php endif; ?>
</p>
<p><strong>Postcode (Zip Code):</strong> <?= htmlspecialchars($application['del_to_postcode']) ?></p>
<p><strong>Phone Number:</strong> <?= htmlspecialchars($application['del_to_phone']) ?></p>
<p><strong>Area Code:</strong> <?= htmlspecialchars($application['del_to_area_code']) ?></p>
<p><strong>Transportation Code:</strong> <?= htmlspecialchars($application['del_to_transportation_code']) ?></p>
<p><strong>Stock Point Code:</strong> <?= htmlspecialchars($application['del_to_stock_point_code']) ?></p>
<p><strong>Recipient Section:</strong> <?= htmlspecialchars($application['del_to_recipient_section']) ?></p>
<p><strong>Country Code:</strong> <?= htmlspecialchars($application['del_to_country_code']) ?></p>
<p><strong>Shipment Flag:</strong> <?= htmlspecialchars($application['del_to_shipment_flag']) ?></p>
<p><strong>Number of Date for Transport:</strong> <?= htmlspecialchars($application['del_to_transport_days']) ?></p>
<p><strong>Shipment Condition: Category:</strong> <?= htmlspecialchars($application['del_to_shipment_condition_category']) ?></p>
<p><strong>Transport Service Exist:</strong> <?= htmlspecialchars($application['del_to_transport_service_exist']) ?></p>
<p><strong>Shipment Condition: Place:</strong> <?= htmlspecialchars($application['del_to_shipment_condition_place']) ?></p>
</div>
</div>
<!-- SOP -->
<div class="card mb-4">
<div class="card-header">SOP</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<h5>Document Requirements</h5>
<p><strong>D/O*:</strong> <?= htmlspecialchars($application['doc_req_do']) ?></p>
<p><strong>Packing List*:</strong> <?= htmlspecialchars($application['doc_req_packing_list']) ?></p>
<p><strong>Invoice*:</strong> <?= htmlspecialchars($application['doc_req_invoice']) ?></p>
<p><strong>Export Permit:</strong> <?= htmlspecialchars($application['doc_req_export_permit']) ?></p>
<p><strong>1 PO/1 DO/1 INV:</strong> <?= htmlspecialchars($application['doc_req_po_do_inv']) ?></p>
<p><strong>1 DO/1 INV:</strong> <?= htmlspecialchars($application['doc_req_do_inv']) ?></p>
<p><strong>Others:</strong> <?= nl2br(htmlspecialchars($application['doc_req_others'])) ?></p>
</div>
<div class="col-md-6">
<h5>Packing Requirements</h5>
<p><strong>One Line One Carton:</strong> <?= htmlspecialchars($application['pack_req_one_line_carton']) ?></p>
<p><strong>One Item One Carton:</strong> <?= htmlspecialchars($application['pack_req_one_item_carton']) ?></p>
<p><strong>One Item One Pocket:</strong> <?= htmlspecialchars($application['pack_req_one_item_pocket']) ?></p>
<p><strong>Special Thomson Label:</strong> <?= htmlspecialchars($application['pack_req_thomson_label']) ?></p>
<p><strong>Special Contents Label:</strong> <?= htmlspecialchars($application['pack_req_contents_label']) ?></p>
<p><strong>Delivery schedule:</strong> <?= htmlspecialchars($application['pack_req_delivery_schedule']) ?></p>
</div>
</div>
<hr>
<h5>Forwarder Information</h5>
<p><strong>Forwarder Name:</strong> <?= htmlspecialchars($application['forwarder_name']) ?></p>
<p><strong>Forwarder Code:</strong> <?= htmlspecialchars($application['forwarder_code']) ?></p>
<p><strong>Forwarder Address:</strong> <?= nl2br(htmlspecialchars($application['forwarder_address'])) ?></p>
<p><strong>Contact Person:</strong> <?= htmlspecialchars($application['forwarder_contact_person']) ?></p>
<p><strong>Phone:</strong> <?= htmlspecialchars($application['forwarder_phone']) ?></p>
<p><strong>Fax:</strong> <?= htmlspecialchars($application['forwarder_fax']) ?></p>
<p><strong>Delivery Method:</strong> <?= htmlspecialchars($application['forwarder_delivery_method']) ?></p>
<p><strong>Delivery Timings:</strong> <?= htmlspecialchars($application['forwarder_delivery_timings']) ?></p>
<p><strong>Delivery Requirements:</strong> <?= nl2br(htmlspecialchars($application['forwarder_delivery_requirements'])) ?></p>
<hr>
<h5>Special Instructions</h5>
<p><strong>Shipping Mark:</strong> <?= htmlspecialchars($application['special_instructions_shipping_mark']) ?></p>
<p><strong>Fax Documents:</strong> <?= htmlspecialchars($application['special_instructions_fax_documents']) ?></p>
<p><strong>Details:</strong> <?= htmlspecialchars($application['special_instructions_details']) ?></p>
<p><strong>Attention To:</strong> <?= htmlspecialchars($application['special_instructions_attention_to']) ?></p>
<p><strong>Fax Number:</strong> <?= htmlspecialchars($application['special_instructions_fax_number']) ?></p>
<p><strong>Remarks:</strong> <?= nl2br(htmlspecialchars($application['remarks'])) ?></p>
</div>
</div>
<!-- Contacts -->
<div class="card mb-4">
<div class="card-header">Contacts</div>
<div class="card-body">
<?php foreach ($contacts as $contact): ?>
<div class="mb-3 border-bottom pb-3">
<p><strong>Name:</strong> <?= htmlspecialchars($contact['name']) ?> <?= $contact['is_primary'] ? '(Primary)' : '' ?></p>
<p><strong>Email:</strong> <?= htmlspecialchars($contact['email']) ?></p>
<p><strong>Phone:</strong> <?= htmlspecialchars($contact['phone']) ?></p>
</div>
<?php endforeach; ?>
</div>
</div>
<!-- Addresses -->
<div class="card mb-4">
<div class="card-header">Addresses</div>
<div class="card-body">
<?php foreach ($addresses as $address): ?>
<div class="mb-3 border-bottom pb-3">
<p><strong>Type:</strong> <?= htmlspecialchars($address['address_type']) ?></p>
<p><strong>Address:</strong><br>
<?= htmlspecialchars($address['address_line_1']) ?><br>
<?php if(!empty($address['address_line_2'])): ?>
<?= htmlspecialchars($address['address_line_2']) ?><br>
<?php endif; ?>
<?= htmlspecialchars($address['city']) ?>, <?= htmlspecialchars($address['state']) ?> <?= htmlspecialchars($address['postal_code']) ?><br>
<?= htmlspecialchars($address['country']) ?>
</p>
</div>
<?php endforeach; ?>
</div>
</div>
<!-- Trade References -->
<div class="card mb-4">
<div class="card-header">Trade References</div>
<div class="card-body">
<?php foreach ($trade_references as $ref): ?>
<div class="mb-3 border-bottom pb-3">
<p><strong>Company Name:</strong> <?= htmlspecialchars($ref['company_name']) ?></p>
<p><strong>Contact Person:</strong> <?= htmlspecialchars($ref['contact_person']) ?></p>
<p><strong>Email:</strong> <?= htmlspecialchars($ref['email']) ?></p>
<p><strong>Phone:</strong> <?= htmlspecialchars($ref['phone']) ?></p>
<p><strong>Address:</strong> <?= htmlspecialchars($ref['address']) ?></p>
</div>
<?php endforeach; ?>
</div>
</div>
<!-- Bank Details -->
<div class="card mb-4">
<div class="card-header">Bank Details</div>
<div class="card-body">
<p><strong>Bank Name:</strong> <?= htmlspecialchars($bank_details['bank_name']) ?></p>
<p><strong>Branch:</strong> <?= htmlspecialchars($bank_details['branch']) ?></p>
<p><strong>BSB Number:</strong> <?= htmlspecialchars($bank_details['bsb_number']) ?></p>
<p><strong>Account Number:</strong> <?= htmlspecialchars($bank_details['account_number']) ?></p>
<p><strong>Account Name:</strong> <?= htmlspecialchars($bank_details['account_name']) ?></p>
</div>
</div>
<!-- Declaration and Signature -->
<div class="card mb-4">
<div class="card-header">Declaration and Signature</div>
<div class="card-body">
<p><strong>Declaration:</strong> <?= nl2br(htmlspecialchars($application['declaration_text'])) ?></p>
<?php if (!empty($application['signature_path'])): ?>
<p><strong>Signature:</strong></p>
<img src="<?= htmlspecialchars($application['signature_path']) ?>" alt="Signature" class="img-fluid">
<?php else: ?> <?php else: ?>
<p>No signature provided.</p> <ul class="list-group">
<?php foreach ($approval_history as $history): ?>
<li class="list-group-item">
<p class="mb-1"><strong>Action:</strong> <?= htmlspecialchars($history['status']) ?></p>
<p class="mb-1"><strong>By:</strong> <?= htmlspecialchars($history['approver_name']) ?></p>
<?php if (!empty($history['comments'])): ?>
<p class="mb-1"><strong>Comments:</strong> <?= nl2br(htmlspecialchars($history['comments'])) ?></p>
<?php endif; ?>
<small class="text-muted"><?= date('Y-m-d H:i:s', strtotime($history['created_at'])) ?></small>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?> <?php endif; ?>
</div> </div>
</div> </div>
<!-- Application Summary --> <!-- Approval Action Form -->
<div class="card mb-4"> <?php if ($can_approve && in_array($application['status'], ['Pending', 'Returned'])): ?>
<div class="card-header">Application Summary</div>
<div class="card-body">
<h5>Company Details</h5>
<div class="row">
<div class="col-md-6">
<p><strong>Customer Name:</strong> <?= htmlspecialchars($application['company_name']) ?></p>
<p><strong>Major Product of Customer:</strong> <?= htmlspecialchars($application['major_product']) ?></p>
<p><strong>Capital:</strong> <?= htmlspecialchars($application['capital']) ?> <?= htmlspecialchars($application['capital_currency']) ?></p>
<p><strong>Main Shareholders:</strong> <?= htmlspecialchars($application['main_shareholders']) ?></p>
<p><strong>Number of Employee:</strong> <?= htmlspecialchars($application['num_employees']) ?></p>
<p><strong>Payment Terms AR:</strong> <?= htmlspecialchars($application['payment_terms_ar']) ?></p>
</div>
<div class="col-md-6">
<h6>Customer's P/L Information</h6>
<p><strong>Year:</strong> <?= htmlspecialchars($application['pl_year']) ?></p>
<p><strong>Net Sales:</strong> <?= htmlspecialchars($application['net_sales']) ?></p>
<p><strong>Net Income Margin:</strong> <?= htmlspecialchars($application['net_income_margin']) ?></p>
<p><strong>Net Income Margin Ratio(%):</strong> <?= htmlspecialchars($application['net_income_margin_ratio']) ?></p>
</div>
</div>
<hr>
<div class="row">
<div class="col-md-6">
<h6>ROHM Sales Target</h6>
<p><strong>This Year:</strong> <?= htmlspecialchars($application['sales_target_this_year']) ?> KUS$</p>
<p><strong>Next Year:</strong> <?= htmlspecialchars($application['sales_target_next_year']) ?> KUS$</p>
<p><strong>After the Next:</strong> <?= htmlspecialchars($application['sales_target_after_next']) ?> KUS$</p>
</div>
<div class="col-md-6">
<h6>Credit Information</h6>
<p><strong>Rank:</strong> <?= htmlspecialchars($application['credit_rank']) ?></p>
<p><strong>Limit (KUS$):</strong> <?= htmlspecialchars($application['credit_limit']) ?></p>
</div>
</div>
<hr>
<div class="row">
<div class="col-md-6">
<h6>Credit Research</h6>
<p><strong>Status:</strong> <?= htmlspecialchars($application['credit_research_status']) ?></p>
<p><strong>Reason:</strong> <?= htmlspecialchars($application['credit_research_reason']) ?></p>
</div>
<div class="col-md-6">
<h6>Other Details</h6>
<p><strong>Tax Rate/Area (GST TYPE):</strong> <?= htmlspecialchars($application['tax_rate_area']) ?></p>
<p><strong>Billing Type:</strong> <?= htmlspecialchars($application['billing_type']) ?></p>
</div>
</div>
</div>
</div>
<div class="card mb-4">
<div class="card-header">Principals Summary</div>
<div class="card-body">
<?php foreach ($principals as $principal): ?>
<div class="mb-3 border-bottom pb-3">
<p><strong>Name:</strong> <?= htmlspecialchars($principal['name']) ?></p>
<p><strong>Title:</strong> <?= htmlspecialchars($principal['title']) ?></p>
<p><strong>Ownership %:</strong> <?= htmlspecialchars($principal['ownership_percentage']) ?></p>
</div>
<?php endforeach; ?>
</div>
</div>
<div class="card mb-4">
<div class="card-header">Contacts Summary</div>
<div class="card-body">
<?php foreach ($contacts as $contact): ?>
<div class="mb-3 border-bottom pb-3">
<p><strong>Name:</strong> <?= htmlspecialchars($contact['name']) ?> <?= $contact['is_primary'] ? '(Primary)' : '' ?></p>
<p><strong>Email:</strong> <?= htmlspecialchars($contact['email']) ?></p>
<p><strong>Phone:</strong> <?= htmlspecialchars($contact['phone']) ?></p>
</div>
<?php endforeach; ?>
</div>
</div>
<div class="card mb-4">
<div class="card-header">Trade References Summary</div>
<div class="card-body">
<?php foreach ($trade_references as $ref): ?>
<div class="mb-3 border-bottom pb-3">
<p><strong>Company Name:</strong> <?= htmlspecialchars($ref['company_name']) ?></p>
<p><strong>Contact Person:</strong> <?= htmlspecialchars($ref['contact_person']) ?></p>
<p><strong>Email:</strong> <?= htmlspecialchars($ref['email']) ?></p>
<p><strong>Phone:</strong> <?= htmlspecialchars($ref['phone']) ?></p>
</div>
<?php endforeach; ?>
</div>
</div>
<div class="card mb-4">
<div class="card-header">Bank Reference Summary</div>
<div class="card-body">
<p><strong>Bank Name:</strong> <?= htmlspecialchars($bank_details['bank_name']) ?></p>
<p><strong>Branch:</strong> <?= htmlspecialchars($bank_details['branch']) ?></p>
<p><strong>Account Number:</strong> <?= htmlspecialchars($bank_details['account_number']) ?></p>
<p><strong>Account Name:</strong> <?= htmlspecialchars($bank_details['account_name']) ?></p>
</div>
</div>
<!-- Approval Section -->
<?php
$approval_level = $application['approval_level'];
$permission_needed = 'approve_level_' . $approval_level;
if (hasPermission($permission_needed) && $application['status'] === 'PENDING_APPROVAL'):
?>
<div class="card mb-4"> <div class="card mb-4">
<div class="card-header">Approval Action</div> <div class="card-header">Approval Action</div>
<div class="card-body"> <div class="card-body">
<form action="process_approval.php" method="POST"> <form action="process_approval.php" method="POST">
<input type="hidden" name="application_id" value="<?= $application['id'] ?>"> <input type="hidden" name="application_id" value="<?= $application['id'] ?>">
<div class="mb-3">
<label for="comments" class="form-label">Comments (Required for Return/Reject)</label>
<textarea class="form-control" id="comments" name="comments" rows="3"></textarea>
</div>
<button type="submit" name="action" value="approve" class="btn btn-success">Approve</button> <button type="submit" name="action" value="approve" class="btn btn-success">Approve</button>
<?php if ($current_level > 1): // Cannot return from the first level ?>
<button type="submit" name="action" value="return" class="btn btn-warning">Return</button>
<?php endif; ?>
<button type="submit" name="action" value="reject" class="btn btn-danger">Reject</button> <button type="submit" name="action" value="reject" class="btn btn-danger">Reject</button>
</form> </form>
</div> </div>
</div> </div>
<?php endif; ?> <?php endif; ?>
<!-- Tabs for Application Details -->
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="company-tab" data-bs-toggle="tab" data-bs-target="#company" type="button" role="tab" aria-controls="company" aria-selected="true">Company</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="summary-tab" data-bs-toggle="tab" data-bs-target="#summary" type="button" role="tab" aria-controls="summary" aria-selected="false">Summary</button>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="company" role="tabpanel" aria-labelledby="company-tab">
<!-- Company Details -->
<div class="card mb-4">
<div class="card-header">Company Details</div>
<div class="card-body">
<p><strong>Company Name:</strong> <?= htmlspecialchars($application['company_name']) ?></p>
<p><strong>Company Website:</strong> <a href="<?= htmlspecialchars($application['company_website']) ?>" target="_blank"><?= htmlspecialchars($application['company_website']) ?></a></p>
<p><strong>Company Phone:</strong> <?= htmlspecialchars($application['company_phone']) ?></p>
</div>
</div>
</div>
<div class="tab-pane fade" id="summary" role="tabpanel" aria-labelledby="summary-tab">
<!-- Application Summary -->
<div class="card mb-4">
<div class="card-header">Application Summary</div>
<div class="card-body">
<p><strong>Test:</strong> Test</p>
</div>
</div>
</div>
</div>
</div> </div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
</body> </body>
</html> </html>