2.0
This commit is contained in:
parent
64b932eb64
commit
6c14b2436f
74
add_shipment_details.php
Normal file
74
add_shipment_details.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
require_once 'includes/header.php';
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id']) || (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) && empty($_SESSION['dealer_id'])) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$request_id = null;
|
||||
if (isset($_GET['request_id'])) {
|
||||
$request_id = $_GET['request_id'];
|
||||
} elseif (isset($_POST['request_id'])) {
|
||||
$request_id = $_POST['request_id'];
|
||||
}
|
||||
|
||||
if ($request_id === null) {
|
||||
header('Location: service_requests.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$carrier = $_POST['carrier'];
|
||||
$tracking_number = $_POST['tracking_number'];
|
||||
$shipment_date = $_POST['shipment_date'];
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$sql = "INSERT INTO shipment_details (service_request_id, carrier, tracking_number, shipment_date) VALUES (?, ?, ?, ?)";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$request_id, $carrier, $tracking_number, $shipment_date]);
|
||||
|
||||
header('Location: service_request_details.php?id=' . $request_id);
|
||||
exit;
|
||||
|
||||
} catch (PDOException $e) {
|
||||
die("Database error: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h1 class="h3 mb-0">Add Shipment Details</h1>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="add_shipment_details.php" method="POST">
|
||||
<input type="hidden" name="request_id" value="<?php echo htmlspecialchars($request_id); ?>">
|
||||
<div class="mb-3">
|
||||
<label for="carrier" class="form-label">Carrier</label>
|
||||
<input type="text" class="form-control" id="carrier" name="carrier" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="tracking_number" class="form-label">Tracking Number</label>
|
||||
<input type="text" class="form-control" id="tracking_number" name="tracking_number" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="shipment_date" class="form-label">Shipment Date</label>
|
||||
<input type="date" class="form-control" id="shipment_date" name="shipment_date" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Add Shipment</button>
|
||||
<a href="service_request_details.php?id=<?php echo htmlspecialchars($request_id); ?>" class="btn btn-secondary">Cancel</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once 'includes/footer.php';
|
||||
?>
|
||||
52
admin/add_dealer.php
Normal file
52
admin/add_dealer.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../includes/header.php';
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
|
||||
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
|
||||
header('Location: /login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$error = '';
|
||||
$success = '';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$name = $_POST['name'] ?? '';
|
||||
$email = $_POST['email'] ?? '';
|
||||
|
||||
if (empty($name) || empty($email)) {
|
||||
$error = 'Name and email are required.';
|
||||
} else {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("INSERT INTO dealers (name, email) VALUES (?, ?)");
|
||||
if ($stmt->execute([$name, $email])) {
|
||||
$success = 'Dealer added successfully.';
|
||||
} else {
|
||||
$error = 'Failed to add dealer.';
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="container">
|
||||
<h1 class="mt-5">Add Dealer</h1>
|
||||
<?php if ($error): ?>
|
||||
<div class="alert alert-danger"><?php echo $error; ?></div>
|
||||
<?php endif; ?>
|
||||
<?php if ($success): ?>
|
||||
<div class="alert alert-success"><?php echo $success; ?></div>
|
||||
<?php endif; ?>
|
||||
<form method="POST" action="add_dealer.php">
|
||||
<div class="form-group">
|
||||
<label for="name">Name</label>
|
||||
<input type="text" class="form-control" id="name" name="name" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email">Email</label>
|
||||
<input type="email" class="form-control" id="email" name="email" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Add Dealer</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php require_once __DIR__ . '/../includes/footer.php'; ?>
|
||||
47
admin/delete_dealer.php
Normal file
47
admin/delete_dealer.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../includes/header.php';
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
|
||||
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
|
||||
header('Location: /login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$dealer_id = $_GET['id'] ?? null;
|
||||
|
||||
if (!$dealer_id) {
|
||||
header('Location: manage_dealers.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$pdo = db();
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (isset($_POST['confirm'])) {
|
||||
$stmt = $pdo->prepare("DELETE FROM dealers WHERE id = ?");
|
||||
$stmt->execute([$dealer_id]);
|
||||
}
|
||||
header('Location: manage_dealers.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("SELECT * FROM dealers WHERE id = ?");
|
||||
$stmt->execute([$dealer_id]);
|
||||
$dealer = $stmt->fetch();
|
||||
|
||||
if (!$dealer) {
|
||||
header('Location: manage_dealers.php');
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="container">
|
||||
<h1 class="mt-5">Delete Dealer</h1>
|
||||
<p>Are you sure you want to delete the dealer "<?php echo htmlspecialchars($dealer['name']); ?>"?</p>
|
||||
<form method="POST" action="delete_dealer.php?id=<?php echo $dealer_id; ?>">
|
||||
<button type="submit" name="confirm" class="btn btn-danger">Yes, Delete</button>
|
||||
<a href="manage_dealers.php" class="btn btn-secondary">No, Cancel</a>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php require_once __DIR__ . '/../includes/footer.php'; ?>
|
||||
68
admin/edit_dealer.php
Normal file
68
admin/edit_dealer.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../includes/header.php';
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
|
||||
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
|
||||
header('Location: /login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$error = '';
|
||||
$success = '';
|
||||
$dealer_id = $_GET['id'] ?? null;
|
||||
|
||||
if (!$dealer_id) {
|
||||
header('Location: manage_dealers.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$pdo = db();
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$name = $_POST['name'] ?? '';
|
||||
$email = $_POST['email'] ?? '';
|
||||
|
||||
if (empty($name) || empty($email)) {
|
||||
$error = 'Name and email are required.';
|
||||
} else {
|
||||
$stmt = $pdo->prepare("UPDATE dealers SET name = ?, email = ? WHERE id = ?");
|
||||
if ($stmt->execute([$name, $email, $dealer_id])) {
|
||||
$success = 'Dealer updated successfully.';
|
||||
} else {
|
||||
$error = 'Failed to update dealer.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("SELECT * FROM dealers WHERE id = ?");
|
||||
$stmt->execute([$dealer_id]);
|
||||
$dealer = $stmt->fetch();
|
||||
|
||||
if (!$dealer) {
|
||||
header('Location: manage_dealers.php');
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="container">
|
||||
<h1 class="mt-5">Edit Dealer</h1>
|
||||
<?php if ($error): ?>
|
||||
<div class="alert alert-danger"><?php echo $error; ?></div>
|
||||
<?php endif; ?>
|
||||
<?php if ($success): ?>
|
||||
<div class="alert alert-success"><?php echo $success; ?></div>
|
||||
<?php endif; ?>
|
||||
<form method="POST" action="edit_dealer.php?id=<?php echo $dealer_id; ?>">
|
||||
<div class="form-group">
|
||||
<label for="name">Name</label>
|
||||
<input type="text" class="form-control" id="name" name="name" value="<?php echo htmlspecialchars($dealer['name']); ?>" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="email">Email</label>
|
||||
<input type="email" class="form-control" id="email" name="email" value="<?php echo htmlspecialchars($dealer['email']); ?>" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Update Dealer</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<?php require_once __DIR__ . '/../includes/footer.php'; ?>
|
||||
61
admin/import_products.php
Normal file
61
admin/import_products.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
require_once '../includes/header.php';
|
||||
require_once '../db/config.php';
|
||||
|
||||
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
|
||||
header('Location: ../login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$message = '';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['product_csv'])) {
|
||||
$file = $_FILES['product_csv']['tmp_name'];
|
||||
|
||||
if (($handle = fopen($file, 'r')) !== FALSE) {
|
||||
$pdo = db();
|
||||
$pdo->beginTransaction();
|
||||
|
||||
try {
|
||||
$stmt = $pdo->prepare("INSERT INTO products (name, model_number, description, image_url, price, category_id, features, sample_type, measurement_parameters, result_speed) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
||||
|
||||
fgetcsv($handle); // Skip header row
|
||||
|
||||
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
|
||||
//Pad the array with nulls if it doesn't have enough elements
|
||||
$data = array_pad($data, 10, null);
|
||||
$stmt->execute($data);
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
$message = "<div class='alert alert-success'>Products imported successfully.</div>";
|
||||
} catch (Exception $e) {
|
||||
$pdo->rollBack();
|
||||
$message = "<div class='alert alert-danger'>Error importing products: " . $e->getMessage() . "</div>";
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
} else {
|
||||
$message = "<div class='alert alert-danger'>Error opening the CSV file.</div>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<h1 class="mb-4">Import Products from CSV</h1>
|
||||
|
||||
<?php echo $message; ?>
|
||||
|
||||
<p>Upload a CSV file with the following columns: `name`, `model_number`, `description`, `image_url`, `price`, `category_id`, `features`, `sample_type`, `measurement_parameters`, `result_speed`.</p>
|
||||
<p>The `category_id` should correspond to an existing ID in the `product_categories` table.</p>
|
||||
|
||||
<form action="import_products.php" method="post" enctype="multipart/form-data">
|
||||
<div class="mb-3">
|
||||
<label for="product_csv" class="form-label">Product CSV File</label>
|
||||
<input class="form-control" type="file" id="product_csv" name="product_csv" accept=".csv" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Import Products</button>
|
||||
</form>
|
||||
|
||||
<p class="mt-4"><a href="index.php">Back to Admin</a></p>
|
||||
|
||||
<?php require_once '../includes/footer.php'; ?>
|
||||
23
admin/index.php
Normal file
23
admin/index.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../includes/header.php';
|
||||
|
||||
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
|
||||
// Redirect non-admin users to the login page
|
||||
header('Location: /login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
// Admin dashboard content goes here
|
||||
?>
|
||||
|
||||
<div class="container">
|
||||
<h1 class="mt-5">Admin Panel</h1>
|
||||
<p class="lead">Welcome to the admin panel. Here you can manage users, products, and other settings.</p>
|
||||
<a href="manage_dealers.php" class="btn btn-primary">Manage Dealers</a>
|
||||
<a href="reports.php" class="btn btn-info">Reports</a>
|
||||
<a href="import_products.php" class="btn btn-success">Import Products</a>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once __DIR__ . '/../includes/footer.php';
|
||||
?>
|
||||
47
admin/manage_dealers.php
Normal file
47
admin/manage_dealers.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../includes/header.php';
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
|
||||
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
|
||||
// Redirect non-admin users to the login page
|
||||
header('Location: /login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$pdo = db();
|
||||
$stmt = $pdo->query("SELECT * FROM dealers");
|
||||
$dealers = $stmt->fetchAll();
|
||||
|
||||
?>
|
||||
|
||||
<div class="container">
|
||||
<h1 class="mt-5">Manage Dealers</h1>
|
||||
<a href="add_dealer.php" class="btn btn-primary mb-3">Add Dealer</a>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Name</th>
|
||||
<th>Email</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($dealers as $dealer): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($dealer['id']); ?></td>
|
||||
<td><?php echo htmlspecialchars($dealer['name']); ?></td>
|
||||
<td><?php echo htmlspecialchars($dealer['email']); ?></td>
|
||||
<td>
|
||||
<a href="edit_dealer.php?id=<?php echo $dealer['id']; ?>" class="btn btn-sm btn-info">Edit</a>
|
||||
<a href="delete_dealer.php?id=<?php echo $dealer['id']; ?>" class="btn btn-sm btn-danger">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once __DIR__ . '/../includes/footer.php';
|
||||
?>
|
||||
113
admin/reports.php
Normal file
113
admin/reports.php
Normal file
@ -0,0 +1,113 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../includes/header.php';
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
|
||||
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
|
||||
header('Location: /login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$pdo = db();
|
||||
|
||||
// Fetch dealers for the filter dropdown
|
||||
$stmt_dealers = $pdo->query("SELECT id, name FROM dealers ORDER BY name ASC");
|
||||
$dealers = $stmt_dealers->fetchAll();
|
||||
|
||||
// Get filter values
|
||||
$status_filter = $_GET['status'] ?? '';
|
||||
$dealer_filter = $_GET['dealer_id'] ?? '';
|
||||
|
||||
$sql = "SELECT sr.*, p.name as product_name, d.name as dealer_name
|
||||
FROM service_requests sr
|
||||
JOIN products p ON sr.product_id = p.id
|
||||
JOIN dealers d ON sr.dealer_id = d.id";
|
||||
|
||||
$where_clauses = [];
|
||||
$params = [];
|
||||
|
||||
if (!empty($status_filter)) {
|
||||
$where_clauses[] = "sr.status = ?";
|
||||
$params[] = $status_filter;
|
||||
}
|
||||
|
||||
if (!empty($dealer_filter)) {
|
||||
$where_clauses[] = "sr.dealer_id = ?";
|
||||
$params[] = $dealer_filter;
|
||||
}
|
||||
|
||||
if (!empty($where_clauses)) {
|
||||
$sql .= " WHERE " . implode(" AND ", $where_clauses);
|
||||
}
|
||||
|
||||
$sql .= " ORDER BY sr.created_at DESC";
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
$service_requests = $stmt->fetchAll();
|
||||
|
||||
?>
|
||||
|
||||
<div class="container">
|
||||
<h1 class="mt-5">Service Request Report</h1>
|
||||
|
||||
<form method="GET" class="mb-4">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="form-group">
|
||||
<label for="status">Filter by Status</label>
|
||||
<select name="status" id="status" class="form-control">
|
||||
<option value="">All</option>
|
||||
<option value="pending" <?php echo ($status_filter === 'pending') ? 'selected' : ''; ?>>Pending</option>
|
||||
<option value="in_progress" <?php echo ($status_filter === 'in_progress') ? 'selected' : ''; ?>>In Progress</option>
|
||||
<option value="resolved" <?php echo ($status_filter === 'resolved') ? 'selected' : ''; ?>>Resolved</option>
|
||||
<option value="closed" <?php echo ($status_filter === 'closed') ? 'selected' : ''; ?>>Closed</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="form-group">
|
||||
<label for="dealer_id">Filter by Dealer</label>
|
||||
<select name="dealer_id" id="dealer_id" class="form-control">
|
||||
<option value="">All</option>
|
||||
<?php foreach ($dealers as $dealer): ?>
|
||||
<option value="<?php echo $dealer['id']; ?>" <?php echo ($dealer_filter == $dealer['id']) ? 'selected' : ''; ?>><?php echo htmlspecialchars($dealer['name']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="form-group">
|
||||
<label> </label>
|
||||
<button type="submit" class="btn btn-primary btn-block">Filter</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Dealer</th>
|
||||
<th>Product</th>
|
||||
<th>Serial</th>
|
||||
<th>Status</th>
|
||||
<th>Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($service_requests as $request): ?>
|
||||
<tr>
|
||||
<td><?php echo $request['id']; ?></td>
|
||||
<td><?php echo htmlspecialchars($request['dealer_name']); ?></td>
|
||||
<td><?php echo htmlspecialchars($request['product_name']); ?></td>
|
||||
<td><a href="../service_request_details.php?id=<?php echo $request['id']; ?>"><?php echo htmlspecialchars($request['serial_number']); ?></a></td>
|
||||
<td><span class="badge bg-warning text-dark"><?php echo htmlspecialchars(ucfirst($request['status'])); ?></span></td>
|
||||
<td><?php echo date('M j, Y', strtotime($request['created_at'])); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<?php require_once __DIR__ . '/../includes/footer.php'; ?>
|
||||
32
api/get_product_details.php
Normal file
32
api/get_product_details.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
|
||||
if (isset($_GET['sold_serial_id'])) {
|
||||
$sold_serial_id = $_GET['sold_serial_id'];
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT p.name, p.model_number, p.part_number, p.description, p.image_url
|
||||
FROM products p
|
||||
JOIN sold_serials ss ON p.id = ss.product_id
|
||||
WHERE ss.id = ?"
|
||||
);
|
||||
$stmt->execute([$sold_serial_id]);
|
||||
$product = $stmt->fetch();
|
||||
|
||||
if ($product) {
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode($product);
|
||||
} else {
|
||||
header("HTTP/1.0 404 Not Found");
|
||||
echo json_encode(['error' => 'Product not found']);
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
header("HTTP/1.0 500 Internal Server Error");
|
||||
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||
}
|
||||
} else {
|
||||
header("HTTP/1.0 400 Bad Request");
|
||||
echo json_encode(['error' => 'No serial ID provided']);
|
||||
}
|
||||
23
assets/css/custom.css
Normal file
23
assets/css/custom.css
Normal file
@ -0,0 +1,23 @@
|
||||
body {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,.1);
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 0.375rem;
|
||||
box-shadow: 0 4px 6px rgba(0,0,0,.05);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #0d6efd;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
BIN
assets/vm-shot-2025-12-09T05-39-13-528Z.jpg
Normal file
BIN
assets/vm-shot-2025-12-09T05-39-13-528Z.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
180
cart.php
Normal file
180
cart.php
Normal file
@ -0,0 +1,180 @@
|
||||
<?php
|
||||
require_once 'includes/header.php';
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
// Initialize cart if it doesn't exist
|
||||
if (!isset($_SESSION['cart'])) {
|
||||
$_SESSION['cart'] = [];
|
||||
}
|
||||
|
||||
$pdo = db();
|
||||
$action = $_GET['action'] ?? '';
|
||||
|
||||
switch ($action) {
|
||||
case 'add':
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['product_id'])) {
|
||||
$product_id = $_POST['product_id'];
|
||||
$quantity = (int)($_POST['quantity'] ?? 1);
|
||||
if ($quantity > 0) {
|
||||
if (isset($_SESSION['cart'][$product_id])) {
|
||||
$_SESSION['cart'][$product_id] += $quantity;
|
||||
} else {
|
||||
$_SESSION['cart'][$product_id] = $quantity;
|
||||
}
|
||||
}
|
||||
}
|
||||
header('Location: products.php');
|
||||
exit;
|
||||
|
||||
case 'update':
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['quantities'])) {
|
||||
foreach ($_POST['quantities'] as $product_id => $quantity) {
|
||||
$quantity = (int)$quantity;
|
||||
if ($quantity > 0) {
|
||||
$_SESSION['cart'][$product_id] = $quantity;
|
||||
} else {
|
||||
unset($_SESSION['cart'][$product_id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
header('Location: cart.php');
|
||||
exit;
|
||||
|
||||
case 'place_order':
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_SESSION['cart'])) {
|
||||
|
||||
|
||||
$total_amount = 0;
|
||||
$cart_products = [];
|
||||
|
||||
$product_ids = array_keys($_SESSION['cart']);
|
||||
if (empty($product_ids)) {
|
||||
header('Location: cart.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$sql = "SELECT * FROM products WHERE id IN (" . implode(',', array_fill(0, count($product_ids), '?')) . ")";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($product_ids);
|
||||
$products_array = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
$products = [];
|
||||
foreach ($products_array as $product) {
|
||||
$products[$product['id']] = $product;
|
||||
}
|
||||
|
||||
// Debug: Dump products array
|
||||
// var_dump($products);
|
||||
|
||||
foreach ($_SESSION['cart'] as $product_id => $quantity) {
|
||||
if (isset($products[$product_id])) {
|
||||
$product = $products[$product_id];
|
||||
$price = $product['price'] ?? 0;
|
||||
$total_amount += $price * $quantity;
|
||||
$cart_products[] = ['product' => $product, 'quantity' => $quantity];
|
||||
}
|
||||
}
|
||||
|
||||
// Debug: Dump total amount
|
||||
// var_dump($total_amount);
|
||||
|
||||
if ($total_amount > 0) {
|
||||
$pdo->beginTransaction();
|
||||
try {
|
||||
$sql = 'INSERT INTO orders (user_id, total_amount, status) VALUES (?, ?, ?)';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$_SESSION['user_id'], $total_amount, 'Pending']);
|
||||
$order_id = $pdo->lastInsertId();
|
||||
|
||||
$sql = 'INSERT INTO order_items (order_id, product_id, quantity, price) VALUES (?, ?, ?, ?)';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
foreach ($cart_products as $item) {
|
||||
// Use the price from the database, not the one from the session/cart loop
|
||||
$product_price = $products[$item['product']['id']]['price'] ?? 0;
|
||||
$stmt->execute([$order_id, $item['product']['id'], $item['quantity'], $product_price]);
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
$_SESSION['cart'] = [];
|
||||
header('Location: order_details.php?id=' . $order_id);
|
||||
exit;
|
||||
} catch (Exception $e) {
|
||||
$pdo->rollBack();
|
||||
// Debug: Log exception
|
||||
error_log($e->getMessage());
|
||||
header('Location: cart.php?error=place_order_failed');
|
||||
exit;
|
||||
}
|
||||
} else {
|
||||
header('Location: cart.php?error=zero_total');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
header('Location: cart.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
// Display Cart
|
||||
$cart_items = [];
|
||||
$total_price = 0;
|
||||
|
||||
if (!empty($_SESSION['cart'])) {
|
||||
$product_ids = array_keys($_SESSION['cart']);
|
||||
$sql = "SELECT * FROM products WHERE id IN (" . implode(',', array_fill(0, count($product_ids), '?')) . ")";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($product_ids);
|
||||
$products = $stmt->fetchAll();
|
||||
|
||||
foreach ($products as $product) {
|
||||
$product_id = $product['id'];
|
||||
$quantity = $_SESSION['cart'][$product_id];
|
||||
$price = $product['price'] ?? 0;
|
||||
$cart_items[] = ['product' => $product, 'quantity' => $quantity, 'price' => $price];
|
||||
$total_price += $price * $quantity;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<h1 class="mb-4">Shopping Cart</h1>
|
||||
|
||||
<?php if (empty($cart_items)) : ?>
|
||||
<div class="alert alert-info">Your cart is empty.</div>
|
||||
<?php else : ?>
|
||||
<form action="cart.php?action=update" method="post">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Product</th>
|
||||
<th>Price</th>
|
||||
<th>Quantity</th>
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($cart_items as $item) : ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($item['product']['name']); ?></td>
|
||||
<td>$<?php echo number_format($item['price'], 2); ?></td>
|
||||
<td>
|
||||
<input type="number" name="quantities[<?php echo $item['product']['id']; ?>]" value="<?php echo $item['quantity']; ?>" min="1" class="form-control" style="width: 80px;">
|
||||
</td>
|
||||
<td>$<?php echo number_format($item['price'] * $item['quantity'], 2); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<button type="submit" class="btn btn-secondary">Update Cart</button>
|
||||
<h4>Total: $<?php echo number_format($total_price, 2); ?></h4>
|
||||
</div>
|
||||
</form>
|
||||
<form action="cart.php?action=place_order" method="post" class="text-end">
|
||||
<button type="submit" class="btn btn-primary">Place Order</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php require_once 'includes/footer.php'; ?>
|
||||
19
db/migration_001_warranty.php
Normal file
19
db/migration_001_warranty.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$sql = "
|
||||
CREATE TABLE IF NOT EXISTS warranty_registrations (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
serial_number VARCHAR(255) NOT NULL,
|
||||
customer_name VARCHAR(255) NOT NULL,
|
||||
installation_date DATE NOT NULL,
|
||||
registration_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);";
|
||||
$pdo->exec($sql);
|
||||
echo "Table 'warranty_registrations' created successfully." . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
die("DB ERROR: " . $e->getMessage());
|
||||
}
|
||||
?>
|
||||
18
db/migration_002_products.php
Normal file
18
db/migration_002_products.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$sql = <<<SQL
|
||||
CREATE TABLE IF NOT EXISTS products (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
model_number VARCHAR(100) NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
SQL;
|
||||
$pdo->exec($sql);
|
||||
echo "Table 'products' created successfully." . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
die("DB ERROR: " . $e->getMessage());
|
||||
}
|
||||
18
db/migration_003_dealers.php
Normal file
18
db/migration_003_dealers.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$sql = <<<SQL
|
||||
CREATE TABLE IF NOT EXISTS dealers (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
email VARCHAR(255) UNIQUE NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
SQL;
|
||||
$pdo->exec($sql);
|
||||
echo "Table 'dealers' created successfully." . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
die("DB ERROR: " . $e->getMessage());
|
||||
}
|
||||
22
db/migration_004_sold_serials.php
Normal file
22
db/migration_004_sold_serials.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$sql = <<<SQL
|
||||
CREATE TABLE IF NOT EXISTS sold_serials (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
product_id INT NOT NULL,
|
||||
dealer_id INT NOT NULL,
|
||||
serial_number VARCHAR(255) UNIQUE NOT NULL,
|
||||
is_activated BOOLEAN DEFAULT FALSE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (dealer_id) REFERENCES dealers(id) ON DELETE CASCADE
|
||||
);
|
||||
SQL;
|
||||
$pdo->exec($sql);
|
||||
echo "Table 'sold_serials' created successfully." . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
die("DB ERROR: " . $e->getMessage());
|
||||
}
|
||||
22
db/migration_005_alter_warranty.php
Normal file
22
db/migration_005_alter_warranty.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
// Add sold_serial_id column
|
||||
$sql_add_column = "ALTER TABLE warranty_registrations ADD COLUMN sold_serial_id INT NULL AFTER serial_number";
|
||||
$pdo->exec($sql_add_column);
|
||||
|
||||
// Add foreign key constraint
|
||||
$sql_add_fk = "ALTER TABLE warranty_registrations ADD CONSTRAINT fk_sold_serial FOREIGN KEY (sold_serial_id) REFERENCES sold_serials(id) ON DELETE SET NULL";
|
||||
$pdo->exec($sql_add_fk);
|
||||
|
||||
echo "Table 'warranty_registrations' modified successfully." . PHP_EOL;
|
||||
|
||||
} catch (PDOException $e) {
|
||||
// Check if column already exists to avoid fatal error on re-run
|
||||
if (strpos($e->getMessage(), 'Duplicate column name') === false) {
|
||||
die("DB ERROR: " . $e->getMessage());
|
||||
}
|
||||
echo "Column 'sold_serial_id' already exists in 'warranty_registrations'." . PHP_EOL;
|
||||
}
|
||||
21
db/migration_006_users.php
Normal file
21
db/migration_006_users.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$sql = <<<SQL
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
dealer_id INT NOT NULL,
|
||||
username VARCHAR(255) NOT NULL UNIQUE,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (dealer_id) REFERENCES dealers(id) ON DELETE CASCADE
|
||||
);
|
||||
SQL;
|
||||
$pdo->exec($sql);
|
||||
echo "Migration for users table applied successfully." . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
die("Migration failed: " . $e->getMessage());
|
||||
}
|
||||
15
db/migration_007_alter_products.php
Normal file
15
db/migration_007_alter_products.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$sql = <<<SQL
|
||||
ALTER TABLE products
|
||||
ADD COLUMN description TEXT NULL,
|
||||
ADD COLUMN image_url VARCHAR(255) NULL;
|
||||
SQL;
|
||||
$pdo->exec($sql);
|
||||
echo "Migration to add description and image_url to products table applied successfully." . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
die("Migration failed: " . $e->getMessage());
|
||||
}
|
||||
24
db/migration_008_service_requests.php
Normal file
24
db/migration_008_service_requests.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$sql = <<<SQL
|
||||
CREATE TABLE IF NOT EXISTS service_requests (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
dealer_id INT NOT NULL,
|
||||
product_id INT NOT NULL,
|
||||
serial_number VARCHAR(255) NOT NULL,
|
||||
issue_description TEXT NOT NULL,
|
||||
status VARCHAR(50) NOT NULL DEFAULT 'pending', -- e.g., pending, in_progress, resolved, closed
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (dealer_id) REFERENCES dealers(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE
|
||||
);
|
||||
SQL;
|
||||
$pdo->exec($sql);
|
||||
echo "Migration for service_requests table applied successfully." . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
die("Migration failed: " . $e->getMessage());
|
||||
}
|
||||
21
db/migration_009_service_request_comments.php
Normal file
21
db/migration_009_service_request_comments.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$sql = <<<SQL
|
||||
CREATE TABLE IF NOT EXISTS service_request_comments (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
service_request_id INT NOT NULL,
|
||||
user_id INT NOT NULL,
|
||||
comment TEXT NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (service_request_id) REFERENCES service_requests(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||
);
|
||||
SQL;
|
||||
$pdo->exec($sql);
|
||||
echo "Migration for service_request_comments table applied successfully." . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
die("Migration failed: " . $e->getMessage());
|
||||
}
|
||||
11
db/migration_010_add_is_admin_to_users.php
Normal file
11
db/migration_010_add_is_admin_to_users.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$sql = "ALTER TABLE users ADD COLUMN is_admin BOOLEAN NOT NULL DEFAULT FALSE";
|
||||
$pdo->exec($sql);
|
||||
echo "Migration to add is_admin to users table applied successfully." . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
die("Migration failed: " . $e->getMessage());
|
||||
}
|
||||
11
db/migration_011_add_file_path_to_service_requests.php
Normal file
11
db/migration_011_add_file_path_to_service_requests.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$sql = "ALTER TABLE service_requests ADD COLUMN file_path VARCHAR(255) DEFAULT NULL";
|
||||
$pdo->exec($sql);
|
||||
echo "Migration to add file_path to service_requests table applied successfully." . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
die("Migration failed: " . $e->getMessage());
|
||||
}
|
||||
22
db/migration_012_create_notifications_table.php
Normal file
22
db/migration_012_create_notifications_table.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$sql = <<<SQL
|
||||
CREATE TABLE IF NOT EXISTS notifications (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
service_request_id INT NOT NULL,
|
||||
message VARCHAR(255) NOT NULL,
|
||||
is_read BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (service_request_id) REFERENCES service_requests(id) ON DELETE CASCADE
|
||||
);
|
||||
SQL;
|
||||
$pdo->exec($sql);
|
||||
echo "Migration for notifications table applied successfully." . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
die("Migration failed: " . $e->getMessage());
|
||||
}
|
||||
13
db/migration_013_add_user_id_to_service_requests.php
Normal file
13
db/migration_013_add_user_id_to_service_requests.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$sql = "ALTER TABLE service_requests ADD COLUMN user_id INT NOT NULL AFTER dealer_id";
|
||||
$pdo->exec($sql);
|
||||
$sql_fk = "ALTER TABLE service_requests ADD FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE";
|
||||
$pdo->exec($sql_fk);
|
||||
echo "Migration to add user_id to service_requests table applied successfully." . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
die("Migration failed: " . $e->getMessage());
|
||||
}
|
||||
19
db/migration_014_create_product_categories.php
Normal file
19
db/migration_014_create_product_categories.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
require_once 'config.php';
|
||||
|
||||
try {
|
||||
$db = db();
|
||||
$sql = "
|
||||
CREATE TABLE IF NOT EXISTS `product_categories` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`description` TEXT,
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
";
|
||||
$db->exec($sql);
|
||||
echo "Table 'product_categories' created successfully." . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
die("Error creating table: " . $e->getMessage());
|
||||
}
|
||||
?>
|
||||
20
db/migration_015_alter_products_add_details.php
Normal file
20
db/migration_015_alter_products_add_details.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
require_once 'config.php';
|
||||
|
||||
try {
|
||||
$db = db();
|
||||
$sql = "
|
||||
ALTER TABLE `products`
|
||||
ADD COLUMN `category_id` INT NULL,
|
||||
ADD COLUMN `features` TEXT NULL,
|
||||
ADD COLUMN `sample_type` VARCHAR(255) NULL,
|
||||
ADD COLUMN `measurement_parameters` TEXT NULL,
|
||||
ADD COLUMN `result_speed` VARCHAR(255) NULL,
|
||||
ADD CONSTRAINT `fk_products_category_id` FOREIGN KEY (`category_id`) REFERENCES `product_categories`(`id`) ON DELETE SET NULL;
|
||||
";
|
||||
$db->exec($sql);
|
||||
echo "Table 'products' altered successfully." . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
die("Error altering table: " . $e->getMessage());
|
||||
}
|
||||
?>
|
||||
21
db/migration_016_create_orders_table.php
Normal file
21
db/migration_016_create_orders_table.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
require_once 'config.php';
|
||||
|
||||
try {
|
||||
$db = db();
|
||||
$sql = "
|
||||
CREATE TABLE IF NOT EXISTS `orders` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`user_id` INT NOT NULL,
|
||||
`total_amount` DECIMAL(10, 2) NOT NULL,
|
||||
`status` VARCHAR(50) NOT NULL DEFAULT 'Pending',
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)
|
||||
);
|
||||
";
|
||||
$db->exec($sql);
|
||||
echo "Table 'orders' created successfully." . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
die("Error creating table: " . $e->getMessage());
|
||||
}
|
||||
?>
|
||||
23
db/migration_017_create_order_items_table.php
Normal file
23
db/migration_017_create_order_items_table.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
require_once 'config.php';
|
||||
|
||||
try {
|
||||
$db = db();
|
||||
$sql = "
|
||||
CREATE TABLE IF NOT EXISTS `order_items` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`order_id` INT NOT NULL,
|
||||
`product_id` INT NOT NULL,
|
||||
`quantity` INT NOT NULL,
|
||||
`price` DECIMAL(10, 2) NOT NULL,
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (`order_id`) REFERENCES `orders`(`id`),
|
||||
FOREIGN KEY (`product_id`) REFERENCES `products`(`id`)
|
||||
);
|
||||
";
|
||||
$db->exec($sql);
|
||||
echo "Table 'order_items' created successfully." . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
die("Error creating table: " . $e->getMessage());
|
||||
}
|
||||
?>
|
||||
17
db/migration_018_add_dealer_kpis.php
Normal file
17
db/migration_018_add_dealer_kpis.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$sql = <<<SQL
|
||||
ALTER TABLE dealers
|
||||
ADD COLUMN target DECIMAL(10, 2) DEFAULT 0.00,
|
||||
ADD COLUMN achievement DECIMAL(10, 2) DEFAULT 0.00,
|
||||
ADD COLUMN credit_limit DECIMAL(10, 2) DEFAULT 0.00,
|
||||
ADD COLUMN credit_limit_utilisation DECIMAL(10, 2) DEFAULT 0.00;
|
||||
SQL;
|
||||
$pdo->exec($sql);
|
||||
echo "Table 'dealers' updated successfully." . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
die("DB ERROR: " . $e->getMessage());
|
||||
}
|
||||
14
db/migration_019_add_paid_amount_to_invoices.php
Normal file
14
db/migration_019_add_paid_amount_to_invoices.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$sql = <<<SQL
|
||||
ALTER TABLE invoices
|
||||
ADD COLUMN paid_amount DECIMAL(10, 2) DEFAULT 0.00;
|
||||
SQL;
|
||||
$pdo->exec($sql);
|
||||
echo "Table 'invoices' updated successfully." . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
die("DB ERROR: " . $e->getMessage());
|
||||
}
|
||||
38
db/migration_020_add_dealer_id_to_orders.php
Normal file
38
db/migration_020_add_dealer_id_to_orders.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$pdo->exec("SET FOREIGN_KEY_CHECKS=0;");
|
||||
|
||||
$sql = <<<SQL
|
||||
ALTER TABLE orders
|
||||
ADD COLUMN dealer_id INT NULL AFTER user_id;
|
||||
SQL;
|
||||
$pdo->exec($sql);
|
||||
|
||||
$sql_update = <<<SQL
|
||||
UPDATE orders o
|
||||
JOIN users u ON o.user_id = u.id
|
||||
SET o.dealer_id = u.dealer_id;
|
||||
SQL;
|
||||
$pdo->exec($sql_update);
|
||||
|
||||
$sql_alter = <<<SQL
|
||||
ALTER TABLE orders
|
||||
MODIFY COLUMN dealer_id INT NOT NULL;
|
||||
SQL;
|
||||
$pdo->exec($sql_alter);
|
||||
|
||||
$sql_fk = <<<SQL
|
||||
ALTER TABLE orders
|
||||
ADD FOREIGN KEY (dealer_id) REFERENCES dealers(id);
|
||||
SQL;
|
||||
$pdo->exec($sql_fk);
|
||||
|
||||
$pdo->exec("SET FOREIGN_KEY_CHECKS=1;");
|
||||
|
||||
echo "Table 'orders' updated successfully." . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
die("DB ERROR: " . $e->getMessage());
|
||||
}
|
||||
26
db/migration_021_fix_orders_dealer_id.php
Normal file
26
db/migration_021_fix_orders_dealer_id.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$pdo->exec("SET FOREIGN_KEY_CHECKS=0;");
|
||||
|
||||
$sql_update = <<<SQL
|
||||
UPDATE orders o
|
||||
JOIN users u ON o.user_id = u.id
|
||||
SET o.dealer_id = u.dealer_id;
|
||||
SQL;
|
||||
$pdo->exec($sql_update);
|
||||
|
||||
$sql_fk = <<<SQL
|
||||
ALTER TABLE orders
|
||||
ADD FOREIGN KEY (dealer_id) REFERENCES dealers(id);
|
||||
SQL;
|
||||
$pdo->exec($sql_fk);
|
||||
|
||||
$pdo->exec("SET FOREIGN_KEY_CHECKS=1;");
|
||||
|
||||
echo "Table 'orders' fixed successfully." . PHP_EOL;
|
||||
} catch (PDOException $e) {
|
||||
die("DB ERROR: " . $e->getMessage());
|
||||
}
|
||||
74
db/seed_data.php
Normal file
74
db/seed_data.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
// Truncate tables to reset data
|
||||
$pdo->exec("SET FOREIGN_KEY_CHECKS = 0;");
|
||||
$pdo->exec("TRUNCATE TABLE order_items;");
|
||||
$pdo->exec("TRUNCATE TABLE orders;");
|
||||
$pdo->exec("TRUNCATE TABLE notifications;");
|
||||
$pdo->exec("TRUNCATE TABLE service_request_comments;");
|
||||
$pdo->exec("TRUNCATE TABLE service_requests;");
|
||||
$pdo->exec("TRUNCATE TABLE sold_serials;");
|
||||
$pdo->exec("TRUNCATE TABLE warranty_registrations;");
|
||||
$pdo->exec("TRUNCATE TABLE users;");
|
||||
$pdo->exec("TRUNCATE TABLE dealers;");
|
||||
$pdo->exec("TRUNCATE TABLE products;");
|
||||
$pdo->exec("TRUNCATE TABLE product_categories;");
|
||||
$pdo->exec("SET FOREIGN_KEY_CHECKS = 1;");
|
||||
|
||||
echo "Tables truncated successfully.\n";
|
||||
|
||||
// Seed Dealers
|
||||
$dealers = [
|
||||
['Dealer One', 'contact1@dealerone.com'],
|
||||
['Dealer Two', 'contact2@dealertwo.com'],
|
||||
];
|
||||
$stmt = $pdo->prepare("INSERT INTO dealers (name, email) VALUES (?, ?)");
|
||||
foreach ($dealers as $dealer) {
|
||||
$stmt->execute($dealer);
|
||||
}
|
||||
echo "Dealers seeded successfully.\n";
|
||||
|
||||
// Get Dealer One ID
|
||||
$stmt = $pdo->prepare("SELECT id FROM dealers WHERE name = ?");
|
||||
$stmt->execute(['Dealer One']);
|
||||
$dealer1_id = $stmt->fetchColumn();
|
||||
|
||||
// Seed Users
|
||||
$users = [
|
||||
['dealer', password_hash('password', PASSWORD_DEFAULT), $dealer1_id, 0],
|
||||
['admin', password_hash('admin', PASSWORD_DEFAULT), null, 1],
|
||||
];
|
||||
$stmt = $pdo->prepare("INSERT INTO users (username, password_hash, dealer_id, is_admin) VALUES (?, ?, ?, ?)");
|
||||
foreach ($users as $user) {
|
||||
$stmt->execute($user);
|
||||
}
|
||||
echo "Users seeded successfully.\n";
|
||||
|
||||
// Seed Product Categories
|
||||
$categories = ['Analyzers', 'Reagents', 'Consumables'];
|
||||
$stmt = $pdo->prepare("INSERT INTO product_categories (name) VALUES (?)");
|
||||
foreach ($categories as $category) {
|
||||
$stmt->execute([$category]);
|
||||
}
|
||||
echo "Product categories seeded successfully.\n";
|
||||
|
||||
// Seed Products
|
||||
$products = [
|
||||
['Sensa-100 Analyzer', 'SENSA-100', 'Advanced blood gas analyzer.', 'assets/images/products/sensa-100.jpg', 1, 15000.00, 'features of Sensa-100'],
|
||||
['Sensa-200 Electrolyte Analyzer', 'SENSA-200', 'Automated electrolyte analysis.', 'assets/images/products/sensa-200.jpg', 1, 25000.00, 'features of Sensa-200'],
|
||||
['Blood Gas Reagent Kit', 'REAGENT-BG', 'Reagent kit for Sensa-100.', 'assets/images/products/reagent-bg.jpg', 2, 500.00, 'features of Reagent-BG'],
|
||||
['Replacement Electrode', 'CONSUME-ELECTRODE', 'Replacement electrode for analyzers.', 'assets/images/products/electrode.jpg', 3, 250.00, 'features of Electrode']
|
||||
];
|
||||
$stmt = $pdo->prepare("INSERT INTO products (name, model_number, description, image_url, category_id, price, features) VALUES (?, ?, ?, ?, ?, ?, ?)");
|
||||
foreach ($products as $product) {
|
||||
$stmt->execute($product);
|
||||
}
|
||||
echo "Products seeded successfully.\n";
|
||||
|
||||
} catch (PDOException $e) {
|
||||
die("DB ERROR: " . $e->getMessage());
|
||||
}
|
||||
59
db/seed_invoices.php
Normal file
59
db/seed_invoices.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
// Check for users
|
||||
$stmt = $pdo->query("SELECT id, dealer_id FROM users WHERE dealer_id IS NOT NULL AND dealer_id != 0 LIMIT 1");
|
||||
$user = $stmt->fetch();
|
||||
|
||||
if (!$user) {
|
||||
// Create a dealer
|
||||
$stmt = $pdo->prepare("INSERT INTO dealers (name, email) VALUES (?, ?)");
|
||||
$stmt->execute(['Dummy Dealer', 'dummy@dealer.com']);
|
||||
$dealer_id = $pdo->lastInsertId();
|
||||
|
||||
// Create a user
|
||||
$stmt = $pdo->prepare("INSERT INTO users (dealer_id, username, password_hash) VALUES (?, ?, ?)");
|
||||
$stmt->execute([$dealer_id, 'dummyuser', password_hash('password', PASSWORD_DEFAULT)]);
|
||||
$user_id = $pdo->lastInsertId();
|
||||
} else {
|
||||
$user_id = $user['id'];
|
||||
$dealer_id = $user['dealer_id'];
|
||||
}
|
||||
|
||||
// Check for orders
|
||||
$stmt = $pdo->prepare("SELECT id FROM orders WHERE user_id = ? LIMIT 5");
|
||||
$stmt->execute([$user_id]);
|
||||
$orders = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||
|
||||
if (count($orders) < 5) {
|
||||
// Create some orders if there aren't enough
|
||||
$stmt = $pdo->prepare("INSERT INTO orders (user_id, dealer_id, total_amount, status) VALUES (?, ?, ?, ?)");
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$total_amount = rand(100, 1000);
|
||||
$stmt->execute([$user_id, $dealer_id, $total_amount, 'Completed']);
|
||||
}
|
||||
$stmt = $pdo->prepare("SELECT id FROM orders WHERE user_id = ? LIMIT 5");
|
||||
$stmt->execute([$user_id]);
|
||||
$orders = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("INSERT INTO invoices (dealer_id, order_id, invoice_date, due_date, total_amount, status, paid_amount) VALUES (?, ?, ?, ?, ?, ?, ?)");
|
||||
|
||||
foreach ($orders as $order_id) {
|
||||
$invoice_date = date('Y-m-d', strtotime('-' . rand(1, 30) . ' days'));
|
||||
$due_date = date('Y-m-d', strtotime($invoice_date . ' +30 days'));
|
||||
$total_amount = rand(100, 1000);
|
||||
$paid_amount = rand(0, $total_amount);
|
||||
$status = ($paid_amount == $total_amount) ? 'paid' : 'pending';
|
||||
|
||||
$stmt->execute([$dealer_id, $order_id, $invoice_date, $due_date, $total_amount, $status, $paid_amount]);
|
||||
}
|
||||
|
||||
echo "Dummy invoices created successfully." . PHP_EOL;
|
||||
|
||||
} catch (PDOException $e) {
|
||||
die("DB ERROR: " . $e->getMessage());
|
||||
}
|
||||
36
delete_shipment_details.php
Normal file
36
delete_shipment_details.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
require_once 'db/config.php';
|
||||
session_start();
|
||||
|
||||
if (!isset($_SESSION['user_id']) || (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) && empty($_SESSION['dealer_id'])) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
|
||||
header('Location: service_requests.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$shipment_id = $_GET['id'];
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
// Get the service_request_id before deleting
|
||||
$stmt_get_id = $pdo->prepare("SELECT service_request_id FROM shipment_details WHERE id = ?");
|
||||
$stmt_get_id->execute([$shipment_id]);
|
||||
$service_request_id = $stmt_get_id->fetchColumn();
|
||||
|
||||
if ($service_request_id) {
|
||||
$stmt_delete = $pdo->prepare("DELETE FROM shipment_details WHERE id = ?");
|
||||
$stmt_delete->execute([$shipment_id]);
|
||||
header("Location: service_request_details.php?id=$service_request_id");
|
||||
} else {
|
||||
header('Location: service_requests.php');
|
||||
}
|
||||
exit;
|
||||
|
||||
} catch (PDOException $e) {
|
||||
die("Database error: " . $e->getMessage());
|
||||
}
|
||||
87
edit_shipment_details.php
Normal file
87
edit_shipment_details.php
Normal file
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
require_once 'includes/header.php';
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id']) || (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) && empty($_SESSION['dealer_id'])) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
|
||||
header('Location: service_requests.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$shipment_id = $_GET['id'];
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("SELECT * FROM shipment_details WHERE id = ?");
|
||||
$stmt->execute([$shipment_id]);
|
||||
$shipment = $stmt->fetch();
|
||||
|
||||
if (!$shipment) {
|
||||
header('Location: service_requests.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$service_request_id = $shipment['service_request_id'];
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$carrier = trim($_POST['carrier']);
|
||||
$tracking_number = trim($_POST['tracking_number']);
|
||||
$shipment_date = trim($_POST['shipment_date']);
|
||||
|
||||
if (empty($carrier) || empty($tracking_number) || empty($shipment_date)) {
|
||||
$error_message = "All fields are required.";
|
||||
} else {
|
||||
$stmt_update = $pdo->prepare(
|
||||
"UPDATE shipment_details SET carrier = ?, tracking_number = ?, shipment_date = ? WHERE id = ?"
|
||||
);
|
||||
$stmt_update->execute([$carrier, $tracking_number, $shipment_date, $shipment_id]);
|
||||
|
||||
header("Location: service_request_details.php?id=$service_request_id");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
die("Database error: " . $e->getMessage());
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h1 class="h3 mb-0">Edit Shipment Details</h1>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<?php if (!empty($error_message)): ?>
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<?php echo $error_message; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<form action="edit_shipment_details.php?id=<?php echo $shipment_id; ?>" method="POST">
|
||||
<div class="mb-3">
|
||||
<label for="carrier" class="form-label">Carrier</label>
|
||||
<input type="text" class="form-control" id="carrier" name="carrier" value="<?php echo htmlspecialchars($shipment['carrier']); ?>" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="tracking_number" class="form-label">Tracking Number</label>
|
||||
<input type="text" class="form-control" id="tracking_number" name="tracking_number" value="<?php echo htmlspecialchars($shipment['tracking_number']); ?>" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="shipment_date" class="form-label">Shipment Date</label>
|
||||
<input type="date" class="form-control" id="shipment_date" name="shipment_date" value="<?php echo htmlspecialchars($shipment['shipment_date']); ?>" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Update Shipment</button>
|
||||
<a href="service_request_details.php?id=<?php echo $service_request_id; ?>" class="btn btn-secondary">Cancel</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once 'includes/footer.php';
|
||||
?>
|
||||
11
includes/footer.php
Normal file
11
includes/footer.php
Normal file
@ -0,0 +1,11 @@
|
||||
</div> <!-- /container -->
|
||||
|
||||
<footer class="footer mt-auto py-3 bg-light">
|
||||
<div class="container text-center">
|
||||
<span class="text-muted">© 2025 Sensa Core. All rights reserved.</span>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
100
includes/header.php
Normal file
100
includes/header.php
Normal file
@ -0,0 +1,100 @@
|
||||
<?php session_start(); ?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Sensa Core Dealer Portal</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||
<link rel="stylesheet" href="assets/css/custom.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="index.php">Sensa Core</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<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>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="warranty_registration.php">Warranty Registration</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="products.php">Product Catalog</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="service_requests.php">Service Requests</a>
|
||||
</li>
|
||||
<?php if (isset($_SESSION['is_admin']) && $_SESSION['is_admin']): ?>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="admin/index.php">Admin</a>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
<ul class="navbar-nav">
|
||||
<?php if (isset($_SESSION['user_id'])): ?>
|
||||
<?php
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
$pdo = db();
|
||||
$stmt_unread = $pdo->prepare("SELECT COUNT(*) as count FROM notifications WHERE user_id = ? AND is_read = 0");
|
||||
$stmt_unread->execute([$_SESSION['user_id']]);
|
||||
$unread_count = $stmt_unread->fetchColumn();
|
||||
|
||||
$stmt_notifications = $pdo->prepare("SELECT * FROM notifications WHERE user_id = ? ORDER BY created_at DESC LIMIT 5");
|
||||
$stmt_notifications->execute([$_SESSION['user_id']]);
|
||||
$notifications = $stmt_notifications->fetchAll();
|
||||
?>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="bi bi-bell"></i>
|
||||
<?php if ($unread_count > 0): ?>
|
||||
<span class="badge bg-danger"><?php echo $unread_count; ?></span>
|
||||
<?php endif; ?>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
|
||||
<?php if (empty($notifications)): ?>
|
||||
<li><a class="dropdown-item" href="#">No notifications</a></li>
|
||||
<?php else: ?>
|
||||
<?php foreach ($notifications as $notification): ?>
|
||||
<li><a class="dropdown-item <?php echo $notification['is_read'] ? '' : 'fw-bold'; ?>" href="service_request_details.php?id=<?php echo $notification['service_request_id']; ?>"><?php echo htmlspecialchars($notification['message']); ?></a></li>
|
||||
<?php endforeach; ?>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item text-center" href="notifications.php">View all notifications</a></li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="cart.php"><i class="bi bi-cart"></i> Cart</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="orders.php">My Orders</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="invoices.php">Invoices</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="targets.php">Targets</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="profile.php">Profile</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="logout.php">Logout</a>
|
||||
</li>
|
||||
<?php else: ?>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="login.php">Login</a>
|
||||
</li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container mt-4">
|
||||
254
index.php
254
index.php
@ -1,150 +1,114 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
@ini_set('display_errors', '1');
|
||||
@error_reporting(E_ALL);
|
||||
@date_default_timezone_set('UTC');
|
||||
require_once __DIR__ . '/includes/header.php';
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$dealer_id = $_SESSION['dealer_id'];
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
// Fetch pending service requests
|
||||
$stmt_pending_requests = $pdo->prepare("SELECT COUNT(*) FROM service_requests WHERE dealer_id = ? AND status = 'pending'");
|
||||
$stmt_pending_requests->execute([$dealer_id]);
|
||||
$pending_requests_count = $stmt_pending_requests->fetchColumn();
|
||||
|
||||
// Fetch unactivated warranties
|
||||
$stmt_unactivated_warranties = $pdo->prepare("SELECT COUNT(*) FROM sold_serials WHERE dealer_id = ? AND is_activated = FALSE");
|
||||
$stmt_unactivated_warranties->execute([$dealer_id]);
|
||||
$unactivated_warranties_count = $stmt_unactivated_warranties->fetchColumn();
|
||||
|
||||
// Fetch total products
|
||||
$stmt_products = $pdo->query("SELECT COUNT(*) FROM products");
|
||||
$products_count = $stmt_products->fetchColumn();
|
||||
|
||||
} catch (PDOException $e) {
|
||||
// For simplicity, we'll just display 0 if there's a db error.
|
||||
$pending_requests_count = 0;
|
||||
$unactivated_warranties_count = 0;
|
||||
$products_count = 0;
|
||||
$open_invoices_count = 0;
|
||||
$total_due = 0;
|
||||
}
|
||||
|
||||
// Fetch open invoices summary
|
||||
try {
|
||||
$user_id = $_SESSION['user_id'];
|
||||
$is_admin = $_SESSION['is_admin'] ?? false;
|
||||
|
||||
$sql = "SELECT COUNT(*) as count, SUM(total_amount) as total FROM invoices WHERE status = 'open'";
|
||||
$params = [];
|
||||
|
||||
if (!$is_admin) {
|
||||
$sql .= " AND dealer_id = ?";
|
||||
$params[] = $user_id;
|
||||
}
|
||||
|
||||
$stmt_invoices = $pdo->prepare($sql);
|
||||
$stmt_invoices->execute($params);
|
||||
$invoices_summary = $stmt_invoices->fetch();
|
||||
$open_invoices_count = $invoices_summary['count'] ?? 0;
|
||||
$total_due = $invoices_summary['total'] ?? 0;
|
||||
} catch (PDOException $e) {
|
||||
$open_invoices_count = 0;
|
||||
$total_due = 0;
|
||||
}
|
||||
|
||||
$phpVersion = PHP_VERSION;
|
||||
$now = date('Y-m-d H:i:s');
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>New Style</title>
|
||||
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-4">
|
||||
<div class="card text-white bg-warning">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title"><i class="bi bi-clock-history"></i> Pending Service Requests</h5>
|
||||
<p class="card-text display-4"><?php echo $pending_requests_count; ?></p>
|
||||
<a href="service_requests.php" class="text-white">View Details <i class="bi bi-arrow-right-circle"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card text-white bg-info">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title"><i class="bi bi-shield-exclamation"></i> Unactivated Warranties</h5>
|
||||
<p class="card-text display-4"><?php echo $unactivated_warranties_count; ?></p>
|
||||
<a href="warranty_registration.php" class="text-white">Register Now <i class="bi bi-arrow-right-circle"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card text-white bg-success">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title"><i class="bi bi-box-seam"></i> Total Products</h5>
|
||||
<p class="card-text display-4"><?php echo $products_count; ?></p>
|
||||
<a href="products.php" class="text-white">Browse Catalog <i class="bi bi-arrow-right-circle"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card text-white bg-danger">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title"><i class="bi bi-file-earmark-text"></i> Open Invoices</h5>
|
||||
<p class="card-text display-4"><?php echo $open_invoices_count; ?></p>
|
||||
<p class="card-text">Total Due: $<?php echo number_format($total_due, 2); ?></p>
|
||||
<a href="invoices.php" class="text-white">View Invoices <i class="bi bi-arrow-right-circle"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="p-5 mb-4 bg-light rounded-3">
|
||||
<div class="container-fluid py-5">
|
||||
<h1 class="display-5 fw-bold">Sensa Core Dealer Portal</h1>
|
||||
<p class="col-md-8 fs-4">Welcome to the central hub for sales, service, and finance operations. Manage your orders, register warranties, and track service requests all in one place.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<?php
|
||||
// Read project preview data from environment
|
||||
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
|
||||
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
require_once 'includes/footer.php';
|
||||
?>
|
||||
<?php if ($projectDescription): ?>
|
||||
<!-- Meta description -->
|
||||
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
|
||||
<!-- Open Graph meta tags -->
|
||||
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
||||
<!-- Twitter meta tags -->
|
||||
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
||||
<?php endif; ?>
|
||||
<?php if ($projectImageUrl): ?>
|
||||
<!-- Open Graph image -->
|
||||
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
||||
<!-- Twitter image -->
|
||||
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
||||
<?php endif; ?>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg-color-start: #6a11cb;
|
||||
--bg-color-end: #2575fc;
|
||||
--text-color: #ffffff;
|
||||
--card-bg-color: rgba(255, 255, 255, 0.01);
|
||||
--card-border-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: 'Inter', sans-serif;
|
||||
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
|
||||
color: var(--text-color);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
body::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
|
||||
animation: bg-pan 20s linear infinite;
|
||||
z-index: -1;
|
||||
}
|
||||
@keyframes bg-pan {
|
||||
0% { background-position: 0% 0%; }
|
||||
100% { background-position: 100% 100%; }
|
||||
}
|
||||
main {
|
||||
padding: 2rem;
|
||||
}
|
||||
.card {
|
||||
background: var(--card-bg-color);
|
||||
border: 1px solid var(--card-border-color);
|
||||
border-radius: 16px;
|
||||
padding: 2rem;
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.loader {
|
||||
margin: 1.25rem auto 1.25rem;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border: 3px solid rgba(255, 255, 255, 0.25);
|
||||
border-top-color: #fff;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
.hint {
|
||||
opacity: 0.9;
|
||||
}
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px; height: 1px;
|
||||
padding: 0; margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap; border: 0;
|
||||
}
|
||||
h1 {
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
margin: 0 0 1rem;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
p {
|
||||
margin: 0.5rem 0;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
code {
|
||||
background: rgba(0,0,0,0.2);
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||
}
|
||||
footer {
|
||||
position: absolute;
|
||||
bottom: 1rem;
|
||||
font-size: 0.8rem;
|
||||
opacity: 0.7;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<div class="card">
|
||||
<h1>Analyzing your requirements and generating your website…</h1>
|
||||
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
|
||||
<span class="sr-only">Loading…</span>
|
||||
</div>
|
||||
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
|
||||
<p class="hint">This page will update automatically as the plan is implemented.</p>
|
||||
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
|
||||
</div>
|
||||
</main>
|
||||
<footer>
|
||||
Page updated: <?= htmlspecialchars($now) ?> (UTC)
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
105
invoice_details.php
Normal file
105
invoice_details.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
require_once 'includes/header.php';
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!isset($_GET['id'])) {
|
||||
header('Location: invoices.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$invoice_id = $_GET['id'];
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$sql = "SELECT i.*, o.id as order_id FROM invoices i JOIN orders o ON i.order_id = o.id WHERE i.id = ?";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$invoice_id]);
|
||||
$invoice = $stmt->fetch();
|
||||
|
||||
if (!$invoice) {
|
||||
die('Invoice not found.');
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
die("Database error: " . $e->getMessage());
|
||||
}
|
||||
?>
|
||||
|
||||
<h1 class="mb-4">Invoice Details #<?php echo htmlspecialchars($invoice['id']); ?></h1>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">Invoice Information</div>
|
||||
<div class="card-body">
|
||||
<p><strong>Invoice ID:</strong> <?php echo htmlspecialchars($invoice['id']); ?></p>
|
||||
<p><strong>Order ID:</strong> <a href="order_details.php?order_id=<?php echo htmlspecialchars($invoice['order_id']); ?>"><?php echo htmlspecialchars($invoice['order_id']); ?></a></p>
|
||||
<p><strong>Invoice Date:</strong> <?php echo htmlspecialchars($invoice['invoice_date']); ?></p>
|
||||
<p><strong>Due Date:</strong> <?php echo htmlspecialchars($invoice['due_date']); ?></p>
|
||||
<p><strong>Total Amount:</strong> $<?php echo htmlspecialchars(number_format($invoice['total_amount'], 2)); ?></p>
|
||||
<p><strong>Status:</strong> <?php echo htmlspecialchars(ucfirst($invoice['status'])); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">Payments</div>
|
||||
<div class="card-body">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Payment Date</th>
|
||||
<th>Amount</th>
|
||||
<th>Payment Method</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$sql = "SELECT * FROM payments WHERE invoice_id = ?";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$invoice_id]);
|
||||
$payments = $stmt->fetchAll();
|
||||
$total_paid = 0;
|
||||
foreach ($payments as $payment) {
|
||||
$total_paid += $payment['amount'];
|
||||
echo '<tr>';
|
||||
echo '<td>' . htmlspecialchars($payment['payment_date']) . '</td>';
|
||||
echo '<td>$' . htmlspecialchars(number_format($payment['amount'], 2)) . '</td>';
|
||||
echo '<td>' . htmlspecialchars($payment['payment_method']) . '</td>';
|
||||
echo '</tr>';
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
<p><strong>Total Paid:</strong> $<?php echo htmlspecialchars(number_format($total_paid, 2)); ?></p>
|
||||
<p><strong>Amount Due:</strong> $<?php echo htmlspecialchars(number_format($invoice['total_amount'] - $total_paid, 2)); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($invoice['status'] !== 'paid'): ?>
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">Post a Payment</div>
|
||||
<div class="card-body">
|
||||
<form action="post_payment.php" method="POST">
|
||||
<input type="hidden" name="invoice_id" value="<?php echo $invoice_id; ?>">
|
||||
<div class="mb-3">
|
||||
<label for="amount" class="form-label">Amount</label>
|
||||
<input type="number" class="form-control" id="amount" name="amount" step="0.01" min="0.01" max="<?php echo $invoice['total_amount'] - $total_paid; ?>" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="payment_method" class="form-label">Payment Method</label>
|
||||
<select class="form-select" id="payment_method" name="payment_method" required>
|
||||
<option value="Credit Card">Credit Card</option>
|
||||
<option value="Bank Transfer">Bank Transfer</option>
|
||||
<option value="Cheque">Cheque</option>
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Submit Payment</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php require_once 'includes/footer.php'; ?>
|
||||
80
invoices.php
Normal file
80
invoices.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
require_once 'includes/header.php';
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$user_id = $_SESSION['user_id'];
|
||||
$is_admin = $_SESSION['is_admin'] ?? false;
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
// Base query
|
||||
$sql = "SELECT i.*, o.id as order_id FROM invoices i JOIN orders o ON i.order_id = o.id";
|
||||
$params = [];
|
||||
|
||||
// If the user is not an admin, they can only see their own invoices
|
||||
if (!$is_admin) {
|
||||
$sql .= " WHERE o.user_id = ?";
|
||||
$params[] = $user_id;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
$invoices = $stmt->fetchAll();
|
||||
|
||||
} catch (PDOException $e) {
|
||||
die("Database error: " . $e->getMessage());
|
||||
}
|
||||
?>
|
||||
|
||||
<h1 class="mb-4">Invoices</h1>
|
||||
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Invoice ID</th>
|
||||
<th>Order ID</th>
|
||||
<th>Invoice Date</th>
|
||||
<th>Due Date</th>
|
||||
<th>Total Amount</th>
|
||||
<th>Paid Amount</th>
|
||||
<th>Balance</th>
|
||||
<th>Age of Invoice</th>
|
||||
<th>Status</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($invoices as $invoice): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($invoice['id']); ?></td>
|
||||
<td><a href="order_details.php?order_id=<?php echo htmlspecialchars($invoice['order_id']); ?>"><?php echo htmlspecialchars($invoice['order_id']); ?></a></td>
|
||||
<td><?php echo htmlspecialchars($invoice['invoice_date']); ?></td>
|
||||
<td><?php echo htmlspecialchars($invoice['due_date']); ?></td>
|
||||
<td>$<?php echo htmlspecialchars(number_format($invoice['total_amount'], 2)); ?></td>
|
||||
<td>$<?php echo htmlspecialchars(number_format($invoice['paid_amount'], 2)); ?></td>
|
||||
<td>$<?php
|
||||
$balance = $invoice['total_amount'] - $invoice['paid_amount'];
|
||||
echo htmlspecialchars(number_format($balance, 2));
|
||||
?></td>
|
||||
<td><?php
|
||||
$invoice_date = new DateTime($invoice['invoice_date']);
|
||||
$now = new DateTime();
|
||||
$age = $now->diff($invoice_date)->days;
|
||||
echo $age . ' days';
|
||||
?></td>
|
||||
<td><?php echo htmlspecialchars(ucfirst($invoice['status'])); ?></td>
|
||||
<td>
|
||||
<a href="invoice_details.php?id=<?php echo $invoice['id']; ?>" class="btn btn-primary btn-sm">View Details</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<?php require_once 'includes/footer.php'; ?>
|
||||
58
login.php
Normal file
58
login.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/includes/header.php';
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
|
||||
$error = '';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$username = $_POST['username'] ?? '';
|
||||
$password = $_POST['password'] ?? '';
|
||||
|
||||
if (empty($username) || empty($password)) {
|
||||
$error = 'Username and password are required.';
|
||||
} else {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
|
||||
$stmt->execute([$username]);
|
||||
$user = $stmt->fetch();
|
||||
|
||||
if ($user && password_verify($password, $user['password_hash'])) {
|
||||
$_SESSION['user_id'] = $user['id'];
|
||||
$_SESSION['dealer_id'] = $user['dealer_id'];
|
||||
$_SESSION['is_admin'] = $user['is_admin'];
|
||||
header('Location: index.php');
|
||||
exit;
|
||||
} else {
|
||||
$error = 'Invalid username or password.';
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<div class="card mt-5">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title text-center">Dealer Login</h3>
|
||||
<?php if ($error): ?>
|
||||
<div class="alert alert-danger"><?php echo $error; ?></div>
|
||||
<?php endif; ?>
|
||||
<form method="POST" action="login.php">
|
||||
<div class="form-group">
|
||||
<label for="username">Username</label>
|
||||
<input type="text" class="form-control" id="username" name="username" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password</label>
|
||||
<input type="password" class="form-control" id="password" name="password" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-block">Login</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||
6
logout.php
Normal file
6
logout.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
session_start();
|
||||
session_unset();
|
||||
session_destroy();
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
46
notifications.php
Normal file
46
notifications.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/includes/header.php';
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$user_id = $_SESSION['user_id'];
|
||||
$pdo = db();
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['mark_all_read'])) {
|
||||
$stmt = $pdo->prepare("UPDATE notifications SET is_read = 1 WHERE user_id = ?");
|
||||
$stmt->execute([$user_id]);
|
||||
header('Location: notifications.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("SELECT * FROM notifications WHERE user_id = ? ORDER BY created_at DESC");
|
||||
$stmt->execute([$user_id]);
|
||||
$notifications = $stmt->fetchAll();
|
||||
|
||||
?>
|
||||
|
||||
<div class="container">
|
||||
<h1 class="mt-5">Notifications</h1>
|
||||
<form method="POST" class="mb-3">
|
||||
<button type="submit" name="mark_all_read" class="btn btn-primary">Mark all as read</button>
|
||||
</form>
|
||||
<ul class="list-group">
|
||||
<?php foreach ($notifications as $notification): ?>
|
||||
<li class="list-group-item <?php echo $notification['is_read'] ? '' : 'list-group-item-secondary'; ?>">
|
||||
<a href="service_request_details.php?id=<?php echo $notification['service_request_id']; ?>" class="text-decoration-none text-dark">
|
||||
<p class="mb-1"><?php echo htmlspecialchars($notification['message']); ?></p>
|
||||
<small class="text-muted"><?php echo date('F j, Y, g:i a', strtotime($notification['created_at'])); ?></small>
|
||||
</a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
<?php if (empty($notifications)): ?>
|
||||
<li class="list-group-item">You have no notifications.</li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||
78
order_details.php
Normal file
78
order_details.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
require_once 'includes/header.php';
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!isset($_GET['id'])) {
|
||||
header('Location: orders.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$order_id = $_GET['id'];
|
||||
$pdo = db();
|
||||
|
||||
// Fetch order details
|
||||
$sql = "SELECT * FROM orders WHERE id = ? AND user_id = ?";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$order_id, $_SESSION['user_id']]);
|
||||
$order = $stmt->fetch();
|
||||
|
||||
if (!$order) {
|
||||
header('Location: orders.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
// Fetch order items
|
||||
$sql = "
|
||||
SELECT oi.*, p.name as product_name
|
||||
FROM order_items oi
|
||||
JOIN products p ON oi.product_id = p.id
|
||||
WHERE oi.order_id = ?
|
||||
";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$order_id]);
|
||||
$order_items = $stmt->fetchAll();
|
||||
|
||||
?>
|
||||
|
||||
<h1 class="mb-4">Order Details #<?php echo $order['id']; ?></h1>
|
||||
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Order Summary</h5>
|
||||
<p><strong>Total Amount:</strong> $<?php echo number_format($order['total_amount'], 2); ?></p>
|
||||
<p><strong>Status:</strong> <?php echo htmlspecialchars($order['status']); ?></p>
|
||||
<p><strong>Date:</strong> <?php echo $order['created_at']; ?></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="mb-4">Items in this Order</h2>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Product</th>
|
||||
<th>Quantity</th>
|
||||
<th>Price</th>
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($order_items as $item): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($item['product_name']); ?></td>
|
||||
<td><?php echo $item['quantity']; ?></td>
|
||||
<td>$<?php echo number_format($item['price'], 2); ?></td>
|
||||
<td>$<?php echo number_format($item['price'] * $item['quantity'], 2); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="orders.php" class="btn btn-secondary">Back to Orders</a>
|
||||
|
||||
<?php require_once 'includes/footer.php'; ?>
|
||||
72
orders.php
Normal file
72
orders.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
require_once 'includes/header.php';
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$pdo = db();
|
||||
$status = isset($_GET['status']) ? $_GET['status'] : 'All';
|
||||
|
||||
$statuses = ['All', 'Pending', 'Completed', 'Shipped', 'Delivered'];
|
||||
if (!in_array($status, $statuses)) {
|
||||
$status = 'All';
|
||||
}
|
||||
|
||||
$sql = "SELECT * FROM orders WHERE user_id = ?";
|
||||
$params = [$_SESSION['user_id']];
|
||||
|
||||
if ($status !== 'All') {
|
||||
$sql .= " AND status = ?";
|
||||
$params[] = $status;
|
||||
}
|
||||
|
||||
$sql .= " ORDER BY created_at DESC";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
$orders = $stmt->fetchAll();
|
||||
|
||||
?>
|
||||
|
||||
<h1 class="mb-4">My Orders</h1>
|
||||
|
||||
<ul class="nav nav-tabs mb-3">
|
||||
<?php foreach ($statuses as $s): ?>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link <?php echo ($status === $s) ? 'active' : ''; ?>" href="?status=<?php echo $s; ?>"><?php echo $s; ?></a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
|
||||
<?php if (empty($orders)): ?>
|
||||
<div class="alert alert-info">
|
||||
You have no orders with the status '<?php echo htmlspecialchars($status); ?>'.
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Order ID</th>
|
||||
<th>Total Amount</th>
|
||||
<th>Status</th>
|
||||
<th>Date</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($orders as $order): ?>
|
||||
<tr>
|
||||
<td>#<?php echo $order['id']; ?></td>
|
||||
<td>$<?php echo number_format($order['total_amount'], 2); ?></td>
|
||||
<td><span class="badge bg-primary"><?php echo htmlspecialchars($order['status']); ?></span></td>
|
||||
<td><?php echo date("F j, Y, g:i a", strtotime($order['created_at'])); ?></td>
|
||||
<td><a href="order_details.php?id=<?php echo $order['id']; ?>" class="btn btn-sm btn-info">View Details</a></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php require_once 'includes/footer.php'; ?>
|
||||
46
post_payment.php
Normal file
46
post_payment.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
require_once 'includes/header.php';
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$invoice_id = $_POST['invoice_id'];
|
||||
$amount = $_POST['amount'];
|
||||
$payment_method = $_POST['payment_method'];
|
||||
$payment_date = date('Y-m-d');
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
// Insert payment
|
||||
$sql = "INSERT INTO payments (invoice_id, payment_date, amount, payment_method) VALUES (?, ?, ?, ?)";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$invoice_id, $payment_date, $amount, $payment_method]);
|
||||
|
||||
// Update invoice status if fully paid
|
||||
$sql = "SELECT i.total_amount, SUM(p.amount) as total_paid FROM invoices i LEFT JOIN payments p ON i.id = p.invoice_id WHERE i.id = ? GROUP BY i.id";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$invoice_id]);
|
||||
$invoice_data = $stmt->fetch();
|
||||
|
||||
if ($invoice_data['total_paid'] >= $invoice_data['total_amount']) {
|
||||
$sql = "UPDATE invoices SET status = 'paid' WHERE id = ?";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$invoice_id]);
|
||||
}
|
||||
|
||||
header('Location: invoice_details.php?id=' . $invoice_id);
|
||||
exit;
|
||||
|
||||
} catch (PDOException $e) {
|
||||
die("Database error: " . $e->getMessage());
|
||||
}
|
||||
} else {
|
||||
header('Location: invoices.php');
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
122
products.php
Normal file
122
products.php
Normal file
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
require_once 'includes/header.php';
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
// Fetch categories for filter dropdown
|
||||
$category_stmt = $pdo->query("SELECT * FROM product_categories ORDER BY name ASC");
|
||||
$categories = $category_stmt->fetchAll();
|
||||
|
||||
// Get filter parameters
|
||||
$search = $_GET['search'] ?? '';
|
||||
$selected_category = $_GET['category'] ?? '';
|
||||
|
||||
// Build product query
|
||||
$sql = "SELECT p.*, c.name AS category_name FROM products p LEFT JOIN product_categories c ON p.category_id = c.id";
|
||||
$params = [];
|
||||
$where_clauses = [];
|
||||
|
||||
if ($search) {
|
||||
$where_clauses[] = "(p.name LIKE ? OR p.model_number LIKE ?)";
|
||||
$params[] = '%' . $search . '%';
|
||||
$params[] = '%' . $search . '%';
|
||||
}
|
||||
|
||||
if ($selected_category) {
|
||||
$where_clauses[] = "p.category_id = ?";
|
||||
$params[] = $selected_category;
|
||||
}
|
||||
|
||||
if (!empty($where_clauses)) {
|
||||
$sql .= " WHERE " . implode(" AND ", $where_clauses);
|
||||
}
|
||||
|
||||
$sql .= " ORDER BY p.name ASC";
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
$products = $stmt->fetchAll();
|
||||
|
||||
} catch (PDOException $e) {
|
||||
die("Database error: " . $e->getMessage());
|
||||
}
|
||||
?>
|
||||
|
||||
<h1 class="mb-4">Product Catalog</h1>
|
||||
|
||||
<form method="GET" action="products.php" class="mb-4">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<input type="text" class="form-control" placeholder="Search by product name or model..." name="search" value="<?php echo htmlspecialchars($search); ?>">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<select name="category" class="form-select">
|
||||
<option value="">All Categories</option>
|
||||
<?php foreach ($categories as $category): ?>
|
||||
<option value="<?php echo $category['id']; ?>" <?php if ($selected_category == $category['id']) echo 'selected'; ?>>
|
||||
<?php echo htmlspecialchars($category['name']); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button class="btn btn-primary w-100" type="submit">Filter</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4">
|
||||
<?php if (empty($products)): ?>
|
||||
<div class="col">
|
||||
<p>No products found.</p>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<?php foreach ($products as $product): ?>
|
||||
<div class="col">
|
||||
<div class="card h-100">
|
||||
<img src="<?php echo htmlspecialchars($product['image_url']); ?>" class="card-img-top" alt="<?php echo htmlspecialchars($product['name']); ?>">
|
||||
<div class="card-body d-flex flex-column">
|
||||
<h5 class="card-title"><?php echo htmlspecialchars($product['name']); ?></h5>
|
||||
<p class="card-text"><strong>Price:</strong> $<?php echo htmlspecialchars(number_format($product['price'], 2)); ?></p>
|
||||
<h6 class="card-subtitle mb-2 text-muted">Model: <?php echo htmlspecialchars($product['model_number']); ?></h6>
|
||||
<?php if ($product['category_name']): ?>
|
||||
<h6 class="card-subtitle mb-2 text-muted">Category: <?php echo htmlspecialchars($product['category_name']); ?></h6>
|
||||
<?php endif; ?>
|
||||
<p class="card-text"><?php echo htmlspecialchars($product['description']); ?></p>
|
||||
|
||||
<?php if ($product['features']): ?>
|
||||
<p class="card-text"><small><strong>Features:</strong> <?php echo htmlspecialchars($product['features']); ?></small></p>
|
||||
<?php endif; ?>
|
||||
<?php if ($product['sample_type']): ?>
|
||||
<p class="card-text"><small><strong>Sample Type:</strong> <?php echo htmlspecialchars($product['sample_type']); ?></small></p>
|
||||
<?php endif; ?>
|
||||
<?php if ($product['measurement_parameters']): ?>
|
||||
<p class="card-text"><small><strong>Parameters:</strong> <?php echo htmlspecialchars($product['measurement_parameters']); ?></small></p>
|
||||
<?php endif; ?>
|
||||
<?php if ($product['result_speed']): ?>
|
||||
<p class="card-text"><small><strong>Result Speed:</strong> <?php echo htmlspecialchars($product['result_speed']); ?></small></p>
|
||||
<?php endif; ?>
|
||||
<div class="mt-auto">
|
||||
<form action="cart.php?action=add" method="post">
|
||||
<input type="hidden" name="product_id" value="<?php echo $product['id']; ?>">
|
||||
<div class="input-group mb-3">
|
||||
<input type="number" name="quantity" id="quantity-<?php echo $product['id']; ?>" class="form-control" value="1" min="1">
|
||||
<button type="submit" class="btn btn-primary">Add to Cart</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php require_once 'includes/footer.php'; ?>
|
||||
95
profile.php
Normal file
95
profile.php
Normal file
@ -0,0 +1,95 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/includes/header.php';
|
||||
require_once __DIR__ . '/db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$user_id = $_SESSION['user_id'];
|
||||
$pdo = db();
|
||||
$error = '';
|
||||
$success = '';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$current_password = $_POST['current_password'] ?? '';
|
||||
$new_password = $_POST['new_password'] ?? '';
|
||||
$confirm_password = $_POST['confirm_password'] ?? '';
|
||||
|
||||
if (empty($current_password) || empty($new_password) || empty($confirm_password)) {
|
||||
$error = 'All password fields are required.';
|
||||
} elseif ($new_password !== $confirm_password) {
|
||||
$error = 'New password and confirm password do not match.';
|
||||
} else {
|
||||
$stmt = $pdo->prepare("SELECT password_hash FROM users WHERE id = ?");
|
||||
$stmt->execute([$user_id]);
|
||||
$user = $stmt->fetch();
|
||||
|
||||
if ($user && password_verify($current_password, $user['password_hash'])) {
|
||||
$password_hash = password_hash($new_password, PASSWORD_DEFAULT);
|
||||
$stmt = $pdo->prepare("UPDATE users SET password_hash = ? WHERE id = ?");
|
||||
if ($stmt->execute([$password_hash, $user_id])) {
|
||||
$success = 'Password updated successfully.';
|
||||
} else {
|
||||
$error = 'Failed to update password.';
|
||||
}
|
||||
} else {
|
||||
$error = 'Incorrect current password.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$stmt->execute([$user_id]);
|
||||
$user = $stmt->fetch();
|
||||
|
||||
?>
|
||||
|
||||
<div class="container">
|
||||
<h1 class="mt-5">Profile</h1>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Your Information</h5>
|
||||
<p><strong>Username:</strong> <?php echo htmlspecialchars($user['username']); ?></p>
|
||||
<?php if (!$user['is_admin']): ?>
|
||||
<?php
|
||||
$stmt_dealer = $pdo->prepare("SELECT * FROM dealers WHERE id = ?");
|
||||
$stmt_dealer->execute([$user['dealer_id']]);
|
||||
$dealer = $stmt_dealer->fetch();
|
||||
?>
|
||||
<p><strong>Dealer:</strong> <?php echo htmlspecialchars($dealer['name']); ?></p>
|
||||
<p><strong>Email:</strong> <?php echo htmlspecialchars($dealer['email']); ?></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-4">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Change Password</h5>
|
||||
<?php if ($error): ?>
|
||||
<div class="alert alert-danger"><?php echo $error; ?></div>
|
||||
<?php endif; ?>
|
||||
<?php if ($success): ?>
|
||||
<div class="alert alert-success"><?php echo $success; ?></div>
|
||||
<?php endif; ?>
|
||||
<form method="POST" action="profile.php">
|
||||
<div class="form-group">
|
||||
<label for="current_password">Current Password</label>
|
||||
<input type="password" class="form-control" id="current_password" name="current_password" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="new_password">New Password</label>
|
||||
<input type="password" class="form-control" id="new_password" name="new_password" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="confirm_password">Confirm New Password</label>
|
||||
<input type="password" class="form-control" id="confirm_password" name="confirm_password" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Change Password</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once __DIR__ . '/includes/footer.php'; ?>
|
||||
249
service_request_details.php
Normal file
249
service_request_details.php
Normal file
@ -0,0 +1,249 @@
|
||||
<?php
|
||||
require_once 'includes/header.php';
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!isset($_GET['id']) || !is_numeric($_GET['id'])) {
|
||||
header('Location: service_requests.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$request_id = $_GET['id'];
|
||||
$dealer_id = $_SESSION['dealer_id'];
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT sr.*
|
||||
FROM service_requests sr
|
||||
WHERE sr.id = ? AND (sr.dealer_id = ? OR ?)"
|
||||
);
|
||||
$stmt->execute([$request_id, $dealer_id, $_SESSION['is_admin']]);
|
||||
$request = $stmt->fetch();
|
||||
|
||||
if (!$request) {
|
||||
// Request not found or doesn't belong to the dealer
|
||||
header('Location: service_requests.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
// Fetch service request items
|
||||
$stmt_items = $pdo->prepare(
|
||||
"SELECT sri.serial_number, sri.issue_description, p.name as product_name
|
||||
FROM service_request_items sri
|
||||
JOIN products p ON sri.product_id = p.id
|
||||
WHERE sri.service_request_id = ?"
|
||||
);
|
||||
$stmt_items->execute([$request_id]);
|
||||
$request_items = $stmt_items->fetchAll();
|
||||
|
||||
|
||||
// Handle comment submission
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['comment'])) {
|
||||
$comment = trim($_POST['comment']);
|
||||
if (!empty($comment)) {
|
||||
$stmt_insert_comment = $pdo->prepare(
|
||||
"INSERT INTO service_request_comments (service_request_id, user_id, comment) VALUES (?, ?, ?)"
|
||||
);
|
||||
$stmt_insert_comment->execute([$request_id, $_SESSION['user_id'], $comment]);
|
||||
|
||||
// Create a notification
|
||||
$current_user_id = $_SESSION['user_id'];
|
||||
$request_owner_id = $request['user_id'];
|
||||
|
||||
$message = "A new comment has been added to your service request #{$request_id}.";
|
||||
|
||||
if ($current_user_id != $request_owner_id) {
|
||||
// Notify the request owner
|
||||
$stmt_notify = $pdo->prepare("INSERT INTO notifications (user_id, service_request_id, message) VALUES (?, ?, ?)");
|
||||
$stmt_notify->execute([$request_owner_id, $request_id, $message]);
|
||||
} else {
|
||||
// Notify all admins
|
||||
$stmt_admins = $pdo->query("SELECT id FROM users WHERE is_admin = 1");
|
||||
$admins = $stmt_admins->fetchAll(PDO::FETCH_COLUMN);
|
||||
$stmt_notify = $pdo->prepare("INSERT INTO notifications (user_id, service_request_id, message) VALUES (?, ?, ?)");
|
||||
foreach ($admins as $admin_id) {
|
||||
if($admin_id != $current_user_id) {
|
||||
$stmt_notify->execute([$admin_id, $request_id, $message]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Redirect to the same page to prevent form resubmission
|
||||
header("Location: service_request_details.php?id=$request_id");
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch comments for the service request
|
||||
$stmt_comments = $pdo->prepare(
|
||||
"SELECT c.*, u.username
|
||||
FROM service_request_comments c
|
||||
JOIN users u ON c.user_id = u.id
|
||||
WHERE c.service_request_id = ?
|
||||
ORDER BY c.created_at ASC"
|
||||
);
|
||||
$stmt_comments->execute([$request_id]);
|
||||
$comments = $stmt_comments->fetchAll();
|
||||
|
||||
} catch (PDOException $e) {
|
||||
die("Database error: " . $e->getMessage());
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="service_requests.php">Service Requests</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">Request #<?php echo htmlspecialchars($request['id']); ?></li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<h1 class="mb-4">Service Request Details</h1>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0">Request #<?php echo htmlspecialchars($request['id']); ?></h5>
|
||||
<span class="badge bg-warning text-dark"><?php echo htmlspecialchars(ucfirst($request['status'])); ?></span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<p><strong>Submitted At:</strong> <?php echo date('F j, Y, g:i a', strtotime($request['created_at'])); ?></p>
|
||||
<p><strong>Last Updated:</strong> <?php echo date('F j, Y, g:i a', strtotime($request['updated_at'])); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<h5>Products</h5>
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Product Name</th>
|
||||
<th>Serial Number</th>
|
||||
<th>Issue Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($request_items as $item): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($item['product_name']); ?></td>
|
||||
<td><?php echo htmlspecialchars($item['serial_number']); ?></td>
|
||||
<td><?php echo nl2br(htmlspecialchars($item['issue_description'])); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php if (!empty($request['file_path'])) : ?>
|
||||
<hr>
|
||||
<h5>Attached File</h5>
|
||||
<p><a href="<?php echo htmlspecialchars($request['file_path']); ?>" target="_blank">View Attached File</a></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (isset($_SESSION['is_admin']) && $_SESSION['is_admin'] || !empty($_SESSION['dealer_id'])) : ?>
|
||||
<hr>
|
||||
<h5>Update Status</h5>
|
||||
<form action="update_service_request_status.php" method="POST">
|
||||
<input type="hidden" name="request_id" value="<?php echo $request_id; ?>">
|
||||
<div class="input-group">
|
||||
<select name="status" class="form-select">
|
||||
<option value="pending" <?php if ($request['status'] == 'pending') echo 'selected'; ?>>Pending</option>
|
||||
<option value="in_progress" <?php if ($request['status'] == 'in_progress') echo 'selected'; ?>>In Progress</option>
|
||||
<option value="resolved" <?php if ($request['status'] == 'resolved') echo 'selected'; ?>>Resolved</option>
|
||||
<option value="closed" <?php if ($request['status'] == 'closed') echo 'selected'; ?>>Closed</option>
|
||||
</select>
|
||||
<button type="submit" class="btn btn-primary">Update</button>
|
||||
</div>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">Shipment Details</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<?php
|
||||
$stmt_shipment = $pdo->prepare("SELECT * FROM shipment_details WHERE service_request_id = ?");
|
||||
$stmt_shipment->execute([$request_id]);
|
||||
$shipments = $stmt_shipment->fetchAll();
|
||||
?>
|
||||
<?php if (empty($shipments)): ?>
|
||||
<p>No shipment details available.</p>
|
||||
<?php if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin'] && empty($_SESSION['dealer_id'])) : ?>
|
||||
<p class="text-muted">Only administrators and dealers can add shipment details.</p>
|
||||
<?php endif; ?>
|
||||
<?php else: ?>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Carrier</th>
|
||||
<th>Tracking Number</th>
|
||||
<th>Shipment Date</th>
|
||||
<?php if (isset($_SESSION['is_admin']) && $_SESSION['is_admin'] || !empty($_SESSION['dealer_id'])) : ?>
|
||||
<th>Actions</th>
|
||||
<?php endif; ?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($shipments as $shipment): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($shipment['carrier']); ?></td>
|
||||
<td><?php echo htmlspecialchars($shipment['tracking_number']); ?></td>
|
||||
<td><?php echo htmlspecialchars($shipment['shipment_date']); ?></td>
|
||||
<?php if (isset($_SESSION['is_admin']) && $_SESSION['is_admin'] || !empty($_SESSION['dealer_id'])) : ?>
|
||||
<td>
|
||||
<a href="edit_shipment_details.php?id=<?php echo $shipment['id']; ?>" class="btn btn-sm btn-primary">Edit</a>
|
||||
<a href="delete_shipment_details.php?id=<?php echo $shipment['id']; ?>" class="btn btn-sm btn-danger" onclick="return confirm('Are you sure you want to delete this shipment?')">Delete</a>
|
||||
</td>
|
||||
<?php endif; ?>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="d-flex justify-content-end">
|
||||
<?php if ((isset($_SESSION['is_admin']) && $_SESSION['is_admin']) || !empty($_SESSION['dealer_id'])) : ?>
|
||||
<a href="add_shipment_details.php?request_id=<?php echo $request_id; ?>" class="btn btn-primary">Add Shipment</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card mt-4">
|
||||
<div class="card-header">
|
||||
<h5 class="mb-0">Comments</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<?php foreach ($comments as $comment): ?>
|
||||
<div class="d-flex mb-3">
|
||||
<div class="flex-shrink-0">
|
||||
<i class="bi bi-person-circle fs-3"></i>
|
||||
</div>
|
||||
<div class="ms-3">
|
||||
<div class="fw-bold"><?php echo htmlspecialchars($comment['username']); ?></div>
|
||||
<?php echo nl2br(htmlspecialchars($comment['comment'])); ?>
|
||||
<div class="text-muted fs-sm"><?php echo date('F j, Y, g:i a', strtotime($comment['created_at'])); ?></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php if (empty($comments)): ?>
|
||||
<p>No comments yet.</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<form method="POST" action="service_request_details.php?id=<?php echo $request_id; ?>">
|
||||
<div class="input-group">
|
||||
<textarea class="form-control" name="comment" placeholder="Add a comment..." rows="3" required></textarea>
|
||||
<button class="btn btn-primary" type="submit">Post Comment</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once 'includes/footer.php'; ?>
|
||||
227
service_requests.php
Normal file
227
service_requests.php
Normal file
@ -0,0 +1,227 @@
|
||||
<?php
|
||||
require_once 'includes/header.php';
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$dealer_id = $_SESSION['dealer_id'];
|
||||
$success_message = '';
|
||||
$error_message = '';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
// Fetch products for the dropdown
|
||||
$stmt_products = $pdo->query("SELECT id, name, model_number FROM products ORDER BY name ASC");
|
||||
$products = $stmt_products->fetchAll();
|
||||
|
||||
// Handle form submission
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
$submitted_products = $_POST['products'] ?? [];
|
||||
$file_path = null;
|
||||
|
||||
if (isset($_FILES['file_upload']) && $_FILES['file_upload']['error'] == UPLOAD_ERR_OK) {
|
||||
$upload_dir = __DIR__ . '/uploads/';
|
||||
if (!is_dir($upload_dir)) {
|
||||
mkdir($upload_dir, 0777, true);
|
||||
}
|
||||
|
||||
$file_name = uniqid('file_') . '_' . basename($_FILES['file_upload']['name']);
|
||||
$target_file = $upload_dir . $file_name;
|
||||
|
||||
if (move_uploaded_file($_FILES['file_upload']['tmp_name'], $target_file)) {
|
||||
$file_path = 'uploads/' . $file_name;
|
||||
} else {
|
||||
$error_message = "Sorry, there was an error uploading your file.";
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($submitted_products)) {
|
||||
$error_message = "Please add at least one product and provide an issue description.";
|
||||
} else {
|
||||
try {
|
||||
$pdo->beginTransaction();
|
||||
|
||||
// Create the main service request
|
||||
$sql_request = "INSERT INTO service_requests (dealer_id, user_id, file_path) VALUES (?, ?, ?)";
|
||||
$stmt_request = $pdo->prepare($sql_request);
|
||||
$stmt_request->execute([$dealer_id, $_SESSION['user_id'], $file_path]);
|
||||
$service_request_id = $pdo->lastInsertId();
|
||||
|
||||
// Add each product to the service_request_items table
|
||||
$sql_item = "INSERT INTO service_request_items (service_request_id, product_id, serial_number, issue_description) VALUES (?, ?, ?, ?)";
|
||||
$stmt_item = $pdo->prepare($sql_item);
|
||||
|
||||
foreach ($submitted_products as $product_data) {
|
||||
$product_id = trim($product_data['product_id']);
|
||||
$serial_number = trim($product_data['serial_number']);
|
||||
$issue_description = trim($product_data['issue_description']);
|
||||
if (!empty($product_id) && !empty($serial_number) && !empty($issue_description)) {
|
||||
$stmt_item->execute([$service_request_id, $product_id, $serial_number, $issue_description]);
|
||||
}
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
$success_message = "Service request submitted successfully!";
|
||||
|
||||
} catch (PDOException $e) {
|
||||
$pdo->rollBack();
|
||||
$error_message = "Failed to submit service request: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch existing service requests for the dealer
|
||||
$stmt_requests = $pdo->prepare(
|
||||
"SELECT sr.id, sr.status, sr.created_at,
|
||||
GROUP_CONCAT(p.name SEPARATOR ', ') as product_names,
|
||||
GROUP_CONCAT(sri.serial_number SEPARATOR ', ') as serial_numbers
|
||||
FROM service_requests sr
|
||||
LEFT JOIN service_request_items sri ON sr.id = sri.service_request_id
|
||||
LEFT JOIN products p ON sri.product_id = p.id
|
||||
WHERE sr.dealer_id = ?
|
||||
GROUP BY sr.id
|
||||
ORDER BY sr.created_at DESC"
|
||||
);
|
||||
$stmt_requests->execute([$dealer_id]);
|
||||
$service_requests = $stmt_requests->fetchAll();
|
||||
|
||||
} catch (PDOException $e) {
|
||||
$error_message = "Database error: " . $e->getMessage();
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-5">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h1 class="h3 mb-0">Submit a Service Request</h1>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<?php if ($success_message): ?>
|
||||
<div class="alert alert-success"><?php echo $success_message; ?></div>
|
||||
<?php endif; ?>
|
||||
<?php if ($error_message): ?>
|
||||
<div class="alert alert-danger"><?php echo $error_message; ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form action="service_requests.php" method="POST" enctype="multipart/form-data">
|
||||
<div id="product-entries">
|
||||
<div class="product-entry mb-3 border p-3">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label for="product_id_1" class="form-label">Product</label>
|
||||
<select class="form-select" id="product_id_1" name="products[1][product_id]" required>
|
||||
<option value="">-- Select a Product --</option>
|
||||
<?php foreach ($products as $product): ?>
|
||||
<option value="<?php echo htmlspecialchars($product['id']); ?>">
|
||||
<?php echo htmlspecialchars($product['name'] . ' (' . $product['model_number'] . ')'); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="serial_number_1" class="form-label">Serial Number</label>
|
||||
<input type="text" class="form-control" id="serial_number_1" name="products[1][serial_number]" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<label for="issue_description_1" class="form-label">Issue Description</label>
|
||||
<textarea class="form-control" id="issue_description_1" name="products[1][issue_description]" rows="2" required></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-secondary mb-3" id="add-product-btn">Add Another Product</button>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="file_upload" class="form-label">Attach a File (optional)</label>
|
||||
<input type="file" class="form-control" id="file_upload" name="file_upload">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary"><i class="bi bi-send"></i> Submit Request</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h1 class="h3 mb-0">Your Service Requests</h1>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<?php if (empty($service_requests)): ?>
|
||||
<p>You have not submitted any service requests yet.</p>
|
||||
<?php else: ?>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Request ID</th>
|
||||
<th>Products</th>
|
||||
<th>Serials</th>
|
||||
<th>Status</th>
|
||||
<th>Date</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($service_requests as $request): ?>
|
||||
<tr>
|
||||
<td><?php echo htmlspecialchars($request['id']); ?></td>
|
||||
<td><?php echo htmlspecialchars($request['product_names']); ?></td>
|
||||
<td><?php echo htmlspecialchars($request['serial_numbers']); ?></td>
|
||||
<td><span class="badge bg-warning text-dark"><?php echo htmlspecialchars(ucfirst($request['status'])); ?></span></td>
|
||||
<td><?php echo date('M j, Y', strtotime($request['created_at'])); ?></td>
|
||||
<td>
|
||||
<a href="service_request_details.php?id=<?php echo $request['id']; ?>" class="btn btn-primary btn-sm">View Details</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
let productEntryCount = 1;
|
||||
const addProductBtn = document.getElementById('add-product-btn');
|
||||
const productEntries = document.getElementById('product-entries');
|
||||
const productOptions = `<?php foreach ($products as $product) { echo '<option value="' . htmlspecialchars($product['id']) . '">' . htmlspecialchars($product['name'] . ' (' . $product['model_number'] . ')') . '</option>'; } ?>`;
|
||||
|
||||
addProductBtn.addEventListener('click', function() {
|
||||
productEntryCount++;
|
||||
const newEntry = document.createElement('div');
|
||||
newEntry.classList.add('product-entry', 'mb-3', 'border', 'p-3');
|
||||
newEntry.innerHTML = `
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label for="product_id_${productEntryCount}" class="form-label">Product</label>
|
||||
<select class="form-select" id="product_id_${productEntryCount}" name="products[${productEntryCount}][product_id]" required>
|
||||
<option value="">-- Select a Product --</option>
|
||||
${productOptions}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="serial_number_${productEntryCount}" class="form-label">Serial Number</label>
|
||||
<input type="text" class="form-control" id="serial_number_${productEntryCount}" name="products[${productEntryCount}][serial_number]" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<label for="issue_description_${productEntryCount}" class="form-label">Issue Description</label>
|
||||
<textarea class="form-control" id="issue_description_${productEntryCount}" name="products[${productEntryCount}][issue_description]" rows="2" required></textarea>
|
||||
</div>
|
||||
`;
|
||||
productEntries.appendChild(newEntry);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php
|
||||
require_once 'includes/footer.php';
|
||||
?>
|
||||
74
targets.php
Normal file
74
targets.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
session_start();
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header("Location: login.php");
|
||||
exit();
|
||||
}
|
||||
|
||||
require_once 'db/config.php';
|
||||
|
||||
include_once 'includes/header.php';
|
||||
|
||||
$dealer_id = $_SESSION['dealer_id'] ?? 0;
|
||||
|
||||
if (!$dealer_id) {
|
||||
echo "<div class='alert alert-danger'>No dealer ID found in session.</div>";
|
||||
include_once 'includes/footer.php';
|
||||
exit();
|
||||
}
|
||||
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("SELECT * FROM dealers WHERE id = ?");
|
||||
$stmt->execute([$dealer_id]);
|
||||
$dealer = $stmt->fetch();
|
||||
|
||||
if (!$dealer) {
|
||||
echo "<div class='alert alert-danger'>Dealer not found.</div>";
|
||||
include_once 'includes/footer.php';
|
||||
exit();
|
||||
}
|
||||
|
||||
$target = $dealer['target'] ?? 0;
|
||||
$achievement = $dealer['achievement'] ?? 0;
|
||||
$credit_limit = $dealer['credit_limit'] ?? 0;
|
||||
$credit_limit_utilisation = $dealer['credit_limit_utilisation'] ?? 0;
|
||||
|
||||
$achievement_percentage = $target > 0 ? ($achievement / $target) * 100 : 0;
|
||||
$credit_utilisation_percentage = $credit_limit > 0 ? ($credit_limit_utilisation / $credit_limit) * 100 : 0;
|
||||
?>
|
||||
|
||||
<div class="container">
|
||||
<h1 class="mt-5">Targets and Achievements</h1>
|
||||
<div class="card mt-4">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Targets</h5>
|
||||
<p class="card-text">Your sales target for the current quarter is: <strong>$<?php echo number_format($target, 2); ?></strong></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mt-4">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Achievements</h5>
|
||||
<p class="card-text">Your sales so far this quarter: <strong>$<?php echo number_format($achievement, 2); ?></strong></p>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" role="progressbar" style="width: <?php echo $achievement_percentage; ?>%;" aria-valuenow="<?php echo $achievement_percentage; ?>" aria-valuemin="0" aria-valuemax="100"><?php echo round($achievement_percentage); ?>%</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mt-4">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Credit Limit</h5>
|
||||
<p class="card-text">Your credit limit is: <strong>$<?php echo number_format($credit_limit, 2); ?></strong></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card mt-4">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Credit Limit Utilisation</h5>
|
||||
<p class="card-text">You have used: <strong>$<?php echo number_format($credit_limit_utilisation, 2); ?></strong></p>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-warning" role="progressbar" style="width: <?php echo $credit_utilisation_percentage; ?>%;" aria-valuenow="<?php echo $credit_utilisation_percentage; ?>" aria-valuemin="0" aria-valuemax="100"><?php echo round($credit_utilisation_percentage); ?>%</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include_once 'includes/footer.php'; ?>
|
||||
30
update_service_request_status.php
Normal file
30
update_service_request_status.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
require_once 'includes/header.php';
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id']) || !$_SESSION['is_admin']) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$request_id = $_POST['request_id'];
|
||||
$status = $_POST['status'];
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$sql = "UPDATE service_requests SET status = ? WHERE id = ?";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$status, $request_id]);
|
||||
|
||||
header('Location: service_request_details.php?id=' . $request_id);
|
||||
exit;
|
||||
|
||||
} catch (PDOException $e) {
|
||||
die("Database error: " . $e->getMessage());
|
||||
}
|
||||
} else {
|
||||
header('Location: service_requests.php');
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
226
warranty_registration.php
Normal file
226
warranty_registration.php
Normal file
@ -0,0 +1,226 @@
|
||||
<?php
|
||||
require_once 'includes/header.php';
|
||||
require_once 'db/config.php';
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$dealer_id = $_SESSION['dealer_id'];
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
// Fetch unactivated serial numbers for the dealer
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT ss.id, ss.serial_number, p.name as product_name
|
||||
FROM sold_serials ss
|
||||
JOIN products p ON ss.product_id = p.id
|
||||
WHERE ss.dealer_id = ? AND ss.is_activated = FALSE"
|
||||
);
|
||||
$stmt->execute([$dealer_id]);
|
||||
$unactivated_serials = $stmt->fetchAll();
|
||||
|
||||
} catch (PDOException $e) {
|
||||
die("Database error: " . $e->getMessage());
|
||||
}
|
||||
|
||||
$success_message = '';
|
||||
$error_message = '';
|
||||
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
$sold_serial_id = trim($_POST['sold_serial_id']);
|
||||
$end_customer_name = trim($_POST['end_customer_name']);
|
||||
$end_customer_address = trim($_POST['end_customer_address']);
|
||||
$dealer_invoice_date = trim($_POST['dealer_invoice_date']);
|
||||
$dealer_invoice_no = trim($_POST['dealer_invoice_no']);
|
||||
$installation_date = trim($_POST['installation_date']);
|
||||
|
||||
if (empty($sold_serial_id) || empty($end_customer_name) || empty($end_customer_address) || empty($dealer_invoice_date) || empty($dealer_invoice_no) || empty($installation_date)) {
|
||||
$error_message = "All fields are required.";
|
||||
} else {
|
||||
$target_dir = "uploads/invoices/";
|
||||
if (!is_dir($target_dir)) {
|
||||
mkdir($target_dir, 0777, true);
|
||||
}
|
||||
$target_file = $target_dir . basename($_FILES["dealer_invoice"]["name"]);
|
||||
$uploadOk = 1;
|
||||
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
|
||||
|
||||
// Check if file already exists
|
||||
if (file_exists($target_file)) {
|
||||
$error_message = "Sorry, file already exists.";
|
||||
$uploadOk = 0;
|
||||
}
|
||||
|
||||
// Check file size
|
||||
if ($_FILES["dealer_invoice"]["size"] > 500000) {
|
||||
$error_message = "Sorry, your file is too large.";
|
||||
$uploadOk = 0;
|
||||
}
|
||||
|
||||
// Allow certain file formats
|
||||
if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
|
||||
&& $imageFileType != "gif" && $imageFileType != "pdf" ) {
|
||||
$error_message = "Sorry, only JPG, JPEG, PNG, GIF & PDF files are allowed.";
|
||||
$uploadOk = 0;
|
||||
}
|
||||
|
||||
if ($uploadOk == 0) {
|
||||
$error_message = "Sorry, your file was not uploaded.";
|
||||
// if everything is ok, try to upload file
|
||||
} else {
|
||||
if (move_uploaded_file($_FILES["dealer_invoice"]["tmp_name"], $target_file)) {
|
||||
try {
|
||||
$pdo = db();
|
||||
$pdo->beginTransaction();
|
||||
|
||||
// 1. Insert warranty registration
|
||||
$sql = "INSERT INTO warranty_registrations (sold_serial_id, end_customer_name, end_customer_address, dealer_invoice_date, dealer_invoice_no, dealer_invoice_path, installation_date, serial_number)
|
||||
SELECT ?, ?, ?, ?, ?, ?, ?, serial_number FROM sold_serials WHERE id = ?";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$sold_serial_id, $end_customer_name, $end_customer_address, $dealer_invoice_date, $dealer_invoice_no, $target_file, $installation_date, $sold_serial_id]);
|
||||
|
||||
// 2. Mark serial as activated
|
||||
$sql_update = "UPDATE sold_serials SET is_activated = TRUE WHERE id = ?";
|
||||
$stmt_update = $pdo->prepare($sql_update);
|
||||
$stmt_update->execute([$sold_serial_id]);
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
// Fetch serial number for display message
|
||||
$stmt_sn = $pdo->prepare("SELECT serial_number FROM sold_serials WHERE id = ?");
|
||||
$stmt_sn->execute([$sold_serial_id]);
|
||||
$serial_number = $stmt_sn->fetchColumn();
|
||||
|
||||
$success_message = "Warranty for serial number <strong>" . htmlspecialchars($serial_number) . "</strong> registered successfully!";
|
||||
|
||||
} catch (PDOException $e) {
|
||||
$pdo->rollBack();
|
||||
$error_message = "Database error: " . $e->getMessage();
|
||||
}
|
||||
} else {
|
||||
$error_message = "Sorry, there was an error uploading your file.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
require_once 'includes/header.php';
|
||||
?>
|
||||
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h1 class="h3 mb-0">Device Warranty Registration</h1>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="card-text">Register a device installation to activate the warranty. Please select a device serial number, enter the end customer's name, and the installation date.</p>
|
||||
|
||||
<?php if ($success_message): ?>
|
||||
<div class="alert alert-success" role="alert">
|
||||
<?php echo $success_message; ?>
|
||||
<script>
|
||||
// Refresh the page after 3 seconds to update the dropdown
|
||||
setTimeout(() => window.location.href = 'warranty_registration.php', 3000);
|
||||
</script>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($error_message): ?>
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<?php echo $error_message; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form action="warranty_registration.php" method="POST" enctype="multipart/form-data">
|
||||
<div class="mb-3">
|
||||
<label for="sold_serial_id" class="form-label">Device Serial Number</label>
|
||||
<select class="form-select" id="sold_serial_id" name="sold_serial_id" required>
|
||||
<option value="">-- Select a Serial Number --</option>
|
||||
<?php foreach ($unactivated_serials as $serial): ?>
|
||||
<option value="<?php echo htmlspecialchars($serial['id']); ?>">
|
||||
<?php echo htmlspecialchars($serial['serial_number'] . ' (' . $serial['product_name'] . ')'); ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<?php if (empty($unactivated_serials)): ?>
|
||||
<div class="form-text">No devices are pending warranty activation.</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div id="product-details" class="mb-3" style="display: none;">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5>Product Details</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p><strong>Name:</strong> <span id="product-name"></span></p>
|
||||
<p><strong>Model Number:</strong> <span id="product-model"></span></p>
|
||||
<p><strong>Part Number:</strong> <span id="product-part"></span></p>
|
||||
<p><strong>Description:</strong> <span id="product-description"></span></p>
|
||||
<img id="product-image" src="" alt="Product Image" class="img-fluid" style="max-height: 200px;"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="end_customer_name" class="form-label">End Customer's Name (Hospital/Lab)</label>
|
||||
<input type="text" class="form-control" id="end_customer_name" name="end_customer_name" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="end_customer_address" class="form-label">End Customer's Address</label>
|
||||
<textarea class="form-control" id="end_customer_address" name="end_customer_address" rows="3" required></textarea>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="dealer_invoice_date" class="form-label">Dealer Invoice Date</label>
|
||||
<input type="date" class="form-control" id="dealer_invoice_date" name="dealer_invoice_date" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="dealer_invoice_no" class="form-label">Dealer Invoice No</label>
|
||||
<input type="text" class="form-control" id="dealer_invoice_no" name="dealer_invoice_no" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="dealer_invoice" class="form-label">Dealer Invoice</label>
|
||||
<input class="form-control" type="file" id="dealer_invoice" name="dealer_invoice" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="installation_date" class="form-label">Installation Date</label>
|
||||
<input type="date" class="form-control" id="installation_date" name="installation_date" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" <?php echo empty($unactivated_serials) ? 'disabled' : ''; ?>><i class="bi bi-check-circle"></i> Register Warranty</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.getElementById('sold_serial_id').addEventListener('change', function() {
|
||||
var soldSerialId = this.value;
|
||||
if (soldSerialId) {
|
||||
fetch('api/get_product_details.php?sold_serial_id=' + soldSerialId)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.error) {
|
||||
alert(data.error);
|
||||
} else {
|
||||
document.getElementById('product-details').style.display = 'block';
|
||||
document.getElementById('product-name').textContent = data.name;
|
||||
document.getElementById('product-model').textContent = data.model_number;
|
||||
document.getElementById('product-part').textContent = data.part_number;
|
||||
document.getElementById('product-description').textContent = data.description;
|
||||
document.getElementById('product-image').src = data.image_url;
|
||||
}
|
||||
})
|
||||
.catch(error => console.error('Error:', error));
|
||||
} else {
|
||||
document.getElementById('product-details').style.display = 'none';
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php
|
||||
require_once 'includes/footer.php';
|
||||
?>
|
||||
Loading…
x
Reference in New Issue
Block a user