diff --git a/api.php b/api.php new file mode 100644 index 0000000..bb03fd0 --- /dev/null +++ b/api.php @@ -0,0 +1,24 @@ +prepare("SELECT id, name FROM departments WHERE division_id = ? ORDER BY name"); + $stmt->execute([$division_id]); + $departments = $stmt->fetchAll(); + echo json_encode($departments); + exit; +} + +if ($action == 'get_roles') { + $department_id = $_GET['department_id'] ?? 0; + $stmt = db()->prepare("SELECT id, name FROM roles WHERE department_id = ? ORDER BY name"); + $stmt->execute([$department_id]); + $roles = $stmt->fetchAll(); + echo json_encode($roles); + exit; +} \ No newline at end of file diff --git a/approve_request.php b/approve_request.php new file mode 100644 index 0000000..3270291 --- /dev/null +++ b/approve_request.php @@ -0,0 +1,92 @@ +prepare('SELECT * FROM ChangeRequests WHERE id = ?'); + $stmt->execute([$request_id]); + $request = $stmt->fetch(); + + if (!$request) { + header('Location: request_dashboard.php?error=not_found'); + exit; + } + + // Authorization check + $is_authorized = false; + if (isset($_SESSION['role'])) { + $user_role = $_SESSION['role']; + $user_department = $_SESSION['department'] ?? null; + $request_status = $request['status']; + $pending_level = $request['approval_level_pending']; + $request_department = $request['department_name']; + + if ($request_status === 'Pending Approval' && $user_role === $pending_level) { + if ($user_role === 'Admin' || $user_department === $request_department) { + $is_authorized = true; + } + } + } + + if (!$is_authorized) { + header('Location: request_dashboard.php?error=unauthorized'); + exit; + } + + $next_approval_level = ''; + $new_status = ''; + $rejection_reason = null; + + if ($action === 'approve') { + $current_level = $request['approval_level_pending']; + $approval_flow = ['Dept Manager/GM', 'System Div Admin', 'Planning Dept', 'System GM']; + $current_index = array_search($current_level, $approval_flow); + + if ($current_index !== false && $current_index < count($approval_flow) - 1) { + $next_approval_level = $approval_flow[$current_index + 1]; + $new_status = 'Pending Approval'; + } else { + $next_approval_level = 'None'; + $new_status = 'Approved'; + } + $sql = 'UPDATE ChangeRequests SET status = ?, approval_level_pending = ? WHERE id = ?'; + $params = [$new_status, $next_approval_level, $request_id]; + + } elseif ($action === 'reject') { + $next_approval_level = $request['approval_level_pending']; + $new_status = 'Rejected'; + $rejection_reason = $_POST['rejection_reason'] ?? ''; + + $sql = 'UPDATE ChangeRequests SET status = ?, approval_level_pending = ?, rejection_reason = ? WHERE id = ?'; + $params = [$new_status, $next_approval_level, $rejection_reason, $request_id]; + } + + + if (isset($sql)) { + $stmt = $pdo->prepare($sql); + $stmt->execute($params); + } + + header('Location: request_dashboard.php?success=updated'); + exit; + +} catch (PDOException $e) { + header('Location: request_dashboard.php?error=db_error'); + exit; +} diff --git a/assets/js/edit_user.js b/assets/js/edit_user.js new file mode 100644 index 0000000..79d8ed1 --- /dev/null +++ b/assets/js/edit_user.js @@ -0,0 +1,71 @@ +document.addEventListener('DOMContentLoaded', function () { + const divisionSelect = document.getElementById('division_id'); + const departmentSelect = document.getElementById('department_id'); + const roleSelect = document.getElementById('role_id'); + + const initialDepartmentId = departmentSelect.dataset.initial; + const initialRoleId = roleSelect.dataset.initial; + + function fetchDepartments(divisionId, callback) { + fetch(`api.php?action=get_departments&division_id=${divisionId}`) + .then(response => response.json()) + .then(data => { + departmentSelect.innerHTML = ''; + data.forEach(department => { + const option = document.createElement('option'); + option.value = department.id; + option.textContent = department.name; + if (department.id == initialDepartmentId) { + option.selected = true; + } + departmentSelect.appendChild(option); + }); + if (callback) callback(); + }); + } + + function fetchRoles(departmentId, callback) { + fetch(`api.php?action=get_roles&department_id=${departmentId}`) + .then(response => response.json()) + .then(data => { + roleSelect.innerHTML = ''; + data.forEach(role => { + const option = document.createElement('option'); + option.value = role.id; + option.textContent = role.name; + if (role.id == initialRoleId) { + option.selected = true; + } + roleSelect.appendChild(option); + }); + if (callback) callback(); + }); + } + + divisionSelect.addEventListener('change', function () { + const divisionId = this.value; + departmentSelect.dataset.initial = ''; // Clear initial value on change + roleSelect.dataset.initial = ''; // Clear initial value on change + fetchDepartments(divisionId, () => { + // After loading departments, if there's a selected one, load its roles + if (departmentSelect.value) { + fetchRoles(departmentSelect.value); + } + }); + }); + + departmentSelect.addEventListener('change', function () { + const departmentId = this.value; + roleSelect.dataset.initial = ''; // Clear initial value on change + fetchRoles(departmentId); + }); + + // Initial load + if (divisionSelect.value) { + fetchDepartments(divisionSelect.value, () => { + if (initialDepartmentId) { + fetchRoles(initialDepartmentId); + } + }); + } +}); diff --git a/assets/pasted-20260116-065324-ee98bca3.png b/assets/pasted-20260116-065324-ee98bca3.png new file mode 100644 index 0000000..a9e4a3d Binary files /dev/null and b/assets/pasted-20260116-065324-ee98bca3.png differ diff --git a/assets/pasted-20260116-080540-0df3cd75.png b/assets/pasted-20260116-080540-0df3cd75.png new file mode 100644 index 0000000..aff343f Binary files /dev/null and b/assets/pasted-20260116-080540-0df3cd75.png differ diff --git a/assets/pasted-20260116-082242-faefdc14.png b/assets/pasted-20260116-082242-faefdc14.png new file mode 100644 index 0000000..a9d7a1f Binary files /dev/null and b/assets/pasted-20260116-082242-faefdc14.png differ diff --git a/create_department.php b/create_department.php new file mode 100644 index 0000000..8ba6af1 --- /dev/null +++ b/create_department.php @@ -0,0 +1,15 @@ +prepare("INSERT INTO departments (name, division_id) VALUES (?, ?)"); + $stmt->execute([$name, $division_id]); + header('Location: user_management.php'); + } catch (PDOException $e) { + echo "Error: " . $e->getMessage(); + } +} +?> \ No newline at end of file diff --git a/create_division.php b/create_division.php new file mode 100644 index 0000000..d21e46e --- /dev/null +++ b/create_division.php @@ -0,0 +1,30 @@ +prepare("INSERT INTO divisions (name) VALUES (?)"); + $stmt->execute([$name]); + header('Location: user_management.php'); + } catch (PDOException $e) { + echo "Error: " . $e->getMessage(); + } +} +?> + + + + + Create Division + + +

Create Division

+
+ + + +
+ Back to User Management + + \ No newline at end of file diff --git a/create_request.php b/create_request.php new file mode 100644 index 0000000..43dd328 --- /dev/null +++ b/create_request.php @@ -0,0 +1,184 @@ +prepare('SELECT request_number FROM ChangeRequests WHERE request_number LIKE ? ORDER BY request_number DESC LIMIT 1'); + $stmt->execute(["RSS/$department/$yearMonth/%"]); + $lastRequest = $stmt->fetch(); + + $runningNumber = 1; + if ($lastRequest) { + $parts = explode('/', $lastRequest['request_number']); + $lastRunningNumber = (int)end($parts); + $runningNumber = $lastRunningNumber + 1; + } + + $requestNumber = sprintf('RSS/%s/%s/%03d', $department, $yearMonth, $runningNumber); + + $stmt = $pdo->prepare( + 'INSERT INTO ChangeRequests (request_number, company, hq_name, department_name, requester_name, extension, issued_date, desired_date, request_title, background_purpose, implementation_details, quantitative_effect, basis_of_calculation, qualitative_effect, category, impact_range, status, approval_level_pending) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' + ); + + $stmt->execute([ + $requestNumber, + $_POST['company'], + $_POST['hq_name'], + $_POST['department_name'], + $_POST['requester_name'], + $_POST['extension'] ?? null, + $_POST['issued_date'], + $_POST['desired_date'] ?? null, + $_POST['request_title'], + $_POST['background_purpose'], + $_POST['implementation_details'], + $_POST['quantitative_effect'] ?? null, + $_POST['basis_of_calculation'] ?? null, + $_POST['qualitative_effect'] ?? null, + $_POST['category'], + $_POST['impact_range'], + 'Pending Approval', // Initial status + 'Dept Manager/GM' // Initial approval level + ]); + + $success_message = 'Request submitted successfully!'; + } catch (Exception $e) { + $error_message = 'Error: ' . $e->getMessage(); + } +} +?> + + + + + + Create Program Change Request + + + +
+
+ Logged in as | Logout +
+

Create Program Change Request

+ + +
+ + +
+ + +
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+
+ + +
+
+ + +
+
+ + + Back to Home +
+
+ + diff --git a/create_role.php b/create_role.php new file mode 100644 index 0000000..4b5a24d --- /dev/null +++ b/create_role.php @@ -0,0 +1,15 @@ +prepare("INSERT INTO roles (name, department_id) VALUES (?, ?)"); + $stmt->execute([$name, $department_id]); + header('Location: user_management.php'); + } catch (PDOException $e) { + echo "Error: " . $e->getMessage(); + } +} +?> \ No newline at end of file diff --git a/create_user.php b/create_user.php new file mode 100644 index 0000000..2314fc7 --- /dev/null +++ b/create_user.php @@ -0,0 +1,46 @@ +prepare("SELECT * FROM users WHERE username = ? OR email = ?"); + $stmt->execute([$username, $email]); + if ($stmt->fetch()) { + header('Location: user_management.php?error=user_exists'); + exit; + } + + $hashed_password = password_hash($password, PASSWORD_DEFAULT); + + $division_id = $_POST['division_id'] ?? null; + $department_id = $_POST['department_id'] ?? null; + + $stmt = $pdo->prepare("INSERT INTO users (username, email, password, role_id, division_id, department_id) VALUES (?, ?, ?, ?, ?, ?)"); + $stmt->execute([$username, $email, $hashed_password, $role_id, $division_id, $department_id]); + + header('Location: user_management.php?success=user_created'); + exit; + + } catch (PDOException $e) { + header('Location: user_management.php?error=db_error'); + exit; + } +} \ No newline at end of file diff --git a/dashboard.php b/dashboard.php new file mode 100644 index 0000000..6391a5d --- /dev/null +++ b/dashboard.php @@ -0,0 +1,41 @@ + + + + + + + Dashboard + + + +
+
+ Logged in as +
+

Dashboard

+ + +
+ + \ No newline at end of file diff --git a/db/migrations/001_create_tables.sql b/db/migrations/001_create_tables.sql new file mode 100644 index 0000000..4d7521e --- /dev/null +++ b/db/migrations/001_create_tables.sql @@ -0,0 +1,35 @@ +CREATE TABLE IF NOT EXISTS `ChangeRequests` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `system_receipt_no` VARCHAR(255) NULL, + `request_mgmt_no` VARCHAR(255) NULL, + `company` VARCHAR(255) NOT NULL, + `hq_name` VARCHAR(255) NOT NULL, + `department_name` VARCHAR(255) NOT NULL, + `requester_name` VARCHAR(255) NOT NULL, + `extension` VARCHAR(255) NULL, + `issued_date` DATE NOT NULL, + `desired_date` DATE NULL, + `has_attachment` BOOLEAN DEFAULT FALSE, + `request_title` VARCHAR(255) NOT NULL, + `background_purpose` TEXT NOT NULL, + `implementation_details` TEXT NOT NULL, + `quantitative_effect` TEXT NULL, + `basis_of_calculation` TEXT NULL, + `qualitative_effect` TEXT NULL, + `category` ENUM('Legal', 'Business Challenge', 'Cust. Complaint', 'Cust. Request', 'Settings/Conversions', 'Improvement', 'Other') NOT NULL, + `impact_range` ENUM('All ROHM', 'Within Headquarters', 'Within Dept/Div', 'Other') NOT NULL, + `workload_estimation` DECIMAL(10, 2) NULL, + `scheduled_start_date` DATE NULL, + `system_div_comments` TEXT NULL, + `effect_confirmation_required` BOOLEAN DEFAULT FALSE, + `actual_effect_amount` DECIMAL(10, 2) NULL, + `status` ENUM('Draft', 'Dept_Approval_Pending', 'System_Reception', 'Under_Consideration', 'In_Progress', 'Completed', 'Rejected') DEFAULT 'Draft' +); + +CREATE TABLE IF NOT EXISTS `Attachments` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `request_id` INT NOT NULL, + `file_path` VARCHAR(255) NOT NULL, + `file_name` VARCHAR(255) NOT NULL, + FOREIGN KEY (`request_id`) REFERENCES `ChangeRequests`(`id`) ON DELETE CASCADE +); diff --git a/db/migrations/002_create_users_table.sql b/db/migrations/002_create_users_table.sql new file mode 100644 index 0000000..5cca067 --- /dev/null +++ b/db/migrations/002_create_users_table.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS `users` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `username` VARCHAR(255) NOT NULL UNIQUE, + `email` VARCHAR(255) NOT NULL UNIQUE, + `password` VARCHAR(255) NOT NULL, + `role` ENUM('Requester', 'Dept Manager/GM', 'System Div Admin', 'Planning Dept', 'System GM', 'Admin') NOT NULL DEFAULT 'Requester', + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; diff --git a/db/migrations/003_add_approval_flow.sql b/db/migrations/003_add_approval_flow.sql new file mode 100644 index 0000000..2ad625c --- /dev/null +++ b/db/migrations/003_add_approval_flow.sql @@ -0,0 +1,7 @@ + +ALTER TABLE `users` ADD COLUMN `department` VARCHAR(255) NULL; + +ALTER TABLE `ChangeRequests` + ADD COLUMN `approval_level_pending` ENUM('Dept Manager/GM', 'System Div Admin', 'Planning Dept', 'System GM', 'None') DEFAULT 'Dept Manager/GM', + ADD COLUMN `rejection_reason` TEXT NULL, + MODIFY COLUMN `status` ENUM('Draft', 'Pending Approval', 'Approved', 'Rejected', 'In Progress', 'Completed') DEFAULT 'Draft'; diff --git a/db/migrations/004_add_request_number.sql b/db/migrations/004_add_request_number.sql new file mode 100644 index 0000000..e70e1f1 --- /dev/null +++ b/db/migrations/004_add_request_number.sql @@ -0,0 +1 @@ +ALTER TABLE `ChangeRequests` ADD `request_number` VARCHAR(255) NULL AFTER `id`; \ No newline at end of file diff --git a/db/migrations/005_add_organization_structure.sql b/db/migrations/005_add_organization_structure.sql new file mode 100644 index 0000000..903ad7b --- /dev/null +++ b/db/migrations/005_add_organization_structure.sql @@ -0,0 +1,23 @@ +CREATE TABLE divisions ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255) NOT NULL UNIQUE +); + +CREATE TABLE departments ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255) NOT NULL, + division_id INT NOT NULL, + FOREIGN KEY (division_id) REFERENCES divisions(id) ON DELETE CASCADE +); + +CREATE TABLE roles ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255) NOT NULL, + department_id INT NOT NULL, + FOREIGN KEY (department_id) REFERENCES departments(id) ON DELETE CASCADE +); + +ALTER TABLE users +ADD COLUMN division_id INT, +ADD COLUMN department_id INT, +ADD COLUMN role_id INT; \ No newline at end of file diff --git a/db/migrations/006_remove_old_user_columns.sql b/db/migrations/006_remove_old_user_columns.sql new file mode 100644 index 0000000..4992584 --- /dev/null +++ b/db/migrations/006_remove_old_user_columns.sql @@ -0,0 +1,3 @@ +-- Remove old role and department columns from users table +ALTER TABLE users DROP COLUMN role; +ALTER TABLE users DROP COLUMN department; diff --git a/delete_department.php b/delete_department.php new file mode 100644 index 0000000..0b4c773 --- /dev/null +++ b/delete_department.php @@ -0,0 +1,12 @@ +prepare("DELETE FROM departments WHERE id = ?"); + $stmt->execute([$id]); + header('Location: user_management.php'); +} catch (PDOException $e) { + echo "Error: " . $e->getMessage(); +} \ No newline at end of file diff --git a/delete_division.php b/delete_division.php new file mode 100644 index 0000000..4883ef4 --- /dev/null +++ b/delete_division.php @@ -0,0 +1,12 @@ +prepare("DELETE FROM divisions WHERE id = ?"); + $stmt->execute([$id]); + header('Location: user_management.php'); +} catch (PDOException $e) { + echo "Error: " . $e->getMessage(); +} \ No newline at end of file diff --git a/delete_role.php b/delete_role.php new file mode 100644 index 0000000..f1db049 --- /dev/null +++ b/delete_role.php @@ -0,0 +1,12 @@ +prepare("DELETE FROM roles WHERE id = ?"); + $stmt->execute([$id]); + header('Location: user_management.php'); +} catch (PDOException $e) { + echo "Error: " . $e->getMessage(); +} \ No newline at end of file diff --git a/edit_department.php b/edit_department.php new file mode 100644 index 0000000..0597cf4 --- /dev/null +++ b/edit_department.php @@ -0,0 +1,50 @@ +prepare("UPDATE departments SET name = ?, division_id = ? WHERE id = ?"); + $stmt->execute([$name, $division_id, $id]); + header('Location: user_management.php'); + } catch (PDOException $e) { + echo "Error: " . $e->getMessage(); + } +} + +try { + $stmt = db()->prepare("SELECT * FROM departments WHERE id = ?"); + $stmt->execute([$id]); + $department = $stmt->fetch(); + + $div_stmt = db()->query('SELECT id, name FROM divisions ORDER BY name'); + $divisions = $div_stmt->fetchAll(); +} catch (PDOException $e) { + echo "Error: " . $e->getMessage(); +} +?> + + + + + Edit Department + + +

Edit Department

+
+ + + + + +
+ Back to User Management + + \ No newline at end of file diff --git a/edit_division.php b/edit_division.php new file mode 100644 index 0000000..6b946b5 --- /dev/null +++ b/edit_division.php @@ -0,0 +1,40 @@ +prepare("UPDATE divisions SET name = ? WHERE id = ?"); + $stmt->execute([$name, $id]); + header('Location: user_management.php'); + } catch (PDOException $e) { + echo "Error: " . $e->getMessage(); + } +} + +try { + $stmt = db()->prepare("SELECT * FROM divisions WHERE id = ?"); + $stmt->execute([$id]); + $division = $stmt->fetch(); +} catch (PDOException $e) { + echo "Error: " . $e->getMessage(); +} +?> + + + + + Edit Division + + +

Edit Division

+
+ + + +
+ Back to User Management + + \ No newline at end of file diff --git a/edit_role.php b/edit_role.php new file mode 100644 index 0000000..00ea430 --- /dev/null +++ b/edit_role.php @@ -0,0 +1,50 @@ +prepare("UPDATE roles SET name = ?, department_id = ? WHERE id = ?"); + $stmt->execute([$name, $department_id, $id]); + header('Location: user_management.php'); + } catch (PDOException $e) { + echo "Error: " . $e->getMessage(); + } +} + +try { + $stmt = db()->prepare("SELECT * FROM roles WHERE id = ?"); + $stmt->execute([$id]); + $role = $stmt->fetch(); + + $dept_stmt = db()->query('SELECT id, name FROM departments ORDER BY name'); + $departments = $dept_stmt->fetchAll(); +} catch (PDOException $e) { + echo "Error: " . $e->getMessage(); +} +?> + + + + + Edit Role + + +

Edit Role

+
+ + + + + +
+ Back to User Management + + \ No newline at end of file diff --git a/edit_user.php b/edit_user.php new file mode 100644 index 0000000..6651308 --- /dev/null +++ b/edit_user.php @@ -0,0 +1,108 @@ +prepare("UPDATE users SET role_id = ?, division_id = ?, department_id = ? WHERE id = ?"); + $stmt->execute([$role_id, $division_id, $department_id, $user_id]); + header('Location: user_management.php?success=user_updated'); + exit; + } catch (PDOException $e) { + header('Location: edit_user.php?id=' . $user_id . '&error=db_error'); + exit; + } +} + +try { + // Fetch user data along with their division, department, and role IDs + $stmt = $pdo->prepare("SELECT u.id, u.username, u.email, u.role_id, r.department_id, d.division_id FROM users u LEFT JOIN roles r ON u.role_id = r.id LEFT JOIN departments d ON r.department_id = d.id WHERE u.id = ?"); + $stmt->execute([$user_id]); + $user = $stmt->fetch(); + if (!$user) { + header('Location: user_management.php?error=user_not_found'); + exit; + } + + // Fetch all divisions + $divisions = $pdo->query("SELECT id, name FROM divisions ORDER BY name")->fetchAll(); + +} catch (PDOException $e) { + die('Database error: ' . $e->getMessage()); +} + +?> + + + + + + Edit User + + + +
+

Edit User:

+ +
An error occurred. Please try again.
+ +
+
+ + +
+
+ + +
+
+ + +
+ + Cancel +
+
+ + + \ No newline at end of file diff --git a/index.php b/index.php index 7205f3d..3e83a3b 100644 --- a/index.php +++ b/index.php @@ -3,6 +3,7 @@ declare(strict_types=1); @ini_set('display_errors', '1'); @error_reporting(E_ALL); @date_default_timezone_set('UTC'); +session_start(); $phpVersion = PHP_VERSION; $now = date('Y-m-d H:i:s'); @@ -129,18 +130,46 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? ''; font-size: 0.8rem; opacity: 0.7; } + .btn { + display: inline-block; + padding: 10px 20px; + margin: 5px; + border-radius: 5px; + text-decoration: none; + color: white; + font-weight: bold; + transition: background-color 0.3s; + } + .btn-primary { + background-color: #4A90E2; + } + .btn-primary:hover { + background-color: #357ABD; + } + .btn-secondary { + background-color: #50E3C2; + } + .btn-secondary:hover { + background-color: #45B8A0; + }
-

Analyzing your requirements and generating your website…

-
- Loading… -
-

AI is collecting your requirements and applying the first changes.

-

This page will update automatically as the plan is implemented.

-

Runtime: PHP — UTC

+

Program Change Request System

+

Welcome to the Program Change Request System. You can use this system to submit, track, and manage program change requests.

+ + +

Logged in as .

+ Create a new Request + View Requests + Dashboard + Logout + + Login + Register +