feat: Implement query and reply functionality for Dispatch and Sales teams

This commit is contained in:
Flatlogic Bot 2025-12-05 07:11:51 +00:00
parent 348f175175
commit 929c1ba4df
3 changed files with 243 additions and 9 deletions

View File

@ -7,7 +7,8 @@ function setup_database($pdo) {
email VARCHAR(255) NOT NULL UNIQUE, email VARCHAR(255) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL, password VARCHAR(255) NOT NULL,
role ENUM('Admin', 'Sales Rep', 'Dispatch') NOT NULL, role ENUM('Admin', 'Sales Rep', 'Dispatch') NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)"); )");
$pdo->exec("CREATE TABLE IF NOT EXISTS orders ( $pdo->exec("CREATE TABLE IF NOT EXISTS orders (
@ -16,6 +17,8 @@ function setup_database($pdo) {
order_date DATE NOT NULL, order_date DATE NOT NULL,
order_text TEXT NOT NULL, order_text TEXT NOT NULL,
status ENUM('Pending', 'Query', 'Query Replied', 'Shipped', 'Cancelled') NOT NULL DEFAULT 'Pending', status ENUM('Pending', 'Query', 'Query Replied', 'Shipped', 'Cancelled') NOT NULL DEFAULT 'Pending',
query_text TEXT DEFAULT NULL,
reply_text TEXT DEFAULT NULL,
sales_rep_id INT NOT NULL, sales_rep_id INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

View File

@ -15,20 +15,35 @@ $shipped_orders_month_count = 0;
try { try {
// --- Fetch Dashboard Counts --- // --- Fetch Dashboard Counts ---
$conditions = ''; $base_conditions_arr = [];
$params = []; $params = [];
if ($user_role === 'Sales Rep') { if ($user_role === 'Sales Rep') {
$conditions = " WHERE sales_rep_id = :user_id"; $base_conditions_arr[] = "sales_rep_id = :user_id";
$params[':user_id'] = $user_id; $params[':user_id'] = $user_id;
} }
// Pending Orders Count // Pending Orders Count
$stmt = $pdo->prepare("SELECT COUNT(*) FROM orders " . $conditions . " AND status = 'Pending'"); $pending_orders_conditions_arr = $base_conditions_arr;
$pending_orders_conditions_arr[] = "status = 'Pending'";
$pending_orders_where_clause = '';
if (!empty($pending_orders_conditions_arr)) {
$pending_orders_where_clause = " WHERE " . implode(" AND ", $pending_orders_conditions_arr);
}
$stmt = $pdo->prepare("SELECT COUNT(*) FROM orders " . $pending_orders_where_clause);
$stmt->execute($params); $stmt->execute($params);
$pending_orders_count = $stmt->fetchColumn(); $pending_orders_count = $stmt->fetchColumn();
// Pending Replies Count (Orders with status 'Query' or 'Query Replied') // Pending Replies Count (Orders with status 'Query' or 'Query Replied')
$stmt = $pdo->prepare("SELECT COUNT(*) FROM orders " . $conditions . " AND (status = 'Query' OR status = 'Query Replied')"); $pending_replies_conditions_arr = $base_conditions_arr;
$pending_replies_conditions_arr[] = "(status = 'Query' OR status = 'Query Replied')";
$pending_replies_where_clause = '';
if (!empty($pending_replies_conditions_arr)) {
$pending_replies_where_clause = " WHERE " . implode(" AND ", $pending_replies_conditions_arr);
}
$stmt = $pdo->prepare("SELECT COUNT(*) FROM orders " . $pending_replies_where_clause);
$stmt->execute($params); $stmt->execute($params);
$pending_replies_count = $stmt->fetchColumn(); $pending_replies_count = $stmt->fetchColumn();
@ -36,12 +51,21 @@ try {
$current_month_start = date('Y-m-01 00:00:00'); $current_month_start = date('Y-m-01 00:00:00');
$current_month_end = date('Y-m-t 23:59:59'); $current_month_end = date('Y-m-t 23:59:59');
$shipped_sql = "SELECT COUNT(*) FROM orders " . $conditions . " AND status = 'Shipped' AND created_at >= :start_date AND created_at <= :end_date"; $shipped_conditions_arr = $base_conditions_arr;
$shipped_conditions_arr[] = "status = 'Shipped'";
$shipped_conditions_arr[] = "created_at >= :start_date";
$shipped_conditions_arr[] = "created_at <= :end_date";
$shipped_where_clause = '';
$shipped_params = $params; $shipped_params = $params;
$shipped_params[':start_date'] = $current_month_start; $shipped_params[':start_date'] = $current_month_start;
$shipped_params[':end_date'] = $current_month_end; $shipped_params[':end_date'] = $current_month_end;
$stmt = $pdo->prepare($shipped_sql); if (!empty($shipped_conditions_arr)) {
$shipped_where_clause = " WHERE " . implode(" AND ", $shipped_conditions_arr);
}
$stmt = $pdo->prepare("SELECT COUNT(*) FROM orders " . $shipped_where_clause);
$stmt->execute($shipped_params); $stmt->execute($shipped_params);
$shipped_orders_month_count = $stmt->fetchColumn(); $shipped_orders_month_count = $stmt->fetchColumn();
@ -133,9 +157,9 @@ try {
<td><?php echo htmlspecialchars(substr($order['order_text'], 0, 50)); ?>...</td> <td><?php echo htmlspecialchars(substr($order['order_text'], 0, 50)); ?>...</td>
<td><span class="badge bg-secondary"><?php echo htmlspecialchars($order['status']); ?></span></td> <td><span class="badge bg-secondary"><?php echo htmlspecialchars($order['status']); ?></span></td>
<td> <td>
<a href="#" class="btn btn-sm btn-outline-primary">View</a> <a href="view_order.php?id=<?php echo $order['id']; ?>" class="btn btn-sm btn-outline-primary">View</a>
<?php if ($user_role === 'Sales Rep' && $order['sales_rep_id'] == $user_id): ?> <?php if ($user_role === 'Sales Rep' && $order['sales_rep_id'] == $user_id): ?>
<a href="#" class="btn btn-sm btn-outline-secondary">Edit</a> <a href="view_order.php?id=<?php echo $order['id']; ?>" class="btn btn-sm btn-outline-secondary">Edit</a>
<?php endif; ?> <?php endif; ?>
</td> </td>
</tr> </tr>

207
view_order.php Normal file
View File

@ -0,0 +1,207 @@
<?php
$page_title = 'View/Edit Order';
require_once __DIR__ . '/partials/header.php';
require_once __DIR__ . '/db/config.php';
$user_id = $_SESSION['user_id'];
$user_role = $_SESSION['user_role'];
$pdo = db();
$order = null;
$edit_mode = false;
$errors = [];
$success_message = '';
// Check if order ID is provided
if (isset($_GET['id']) && is_numeric($_GET['id'])) {
$order_id = $_GET['id'];
$stmt = $pdo->prepare("SELECT o.*, o.query_text, o.reply_text, u.name as sales_rep_name FROM orders o JOIN users u ON o.sales_rep_id = u.id WHERE o.id = :id");
$stmt->bindParam(':id', $order_id, PDO::PARAM_INT);
$stmt->execute();
$order = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$order) {
$errors[] = "Order not found.";
} else {
// Determine if user can edit this order
if ($user_role === 'Sales Rep' && $order['sales_rep_id'] == $user_id) {
$edit_mode = true;
} elseif ($user_role === 'Dispatch' || $user_role === 'Admin') {
$edit_mode = true; // Dispatch and Admin can always edit
}
}
} catch (PDOException $e) {
error_log("Database error fetching order: " . $e->getMessage());
$errors[] = "Error loading order details. Please try again later.";
}
} else {
$errors[] = "No order ID provided.";
}
// Handle form submission for updating order
if ($_SERVER['REQUEST_METHOD'] === 'POST' && $edit_mode && $order) {
$new_order_number = trim($_POST['order_number'] ?? '');
$new_order_date = trim($_POST['order_date'] ?? '');
$new_order_text = trim($_POST['order_text'] ?? '');
$new_status = trim($_POST['status'] ?? '');
$new_query_text = trim($_POST['query_text'] ?? '');
$new_reply_text = trim($_POST['reply_text'] ?? '');
// Preserve existing query/reply if not being updated by a specific status change
$query_to_save = $order['query_text'];
$reply_to_save = $order['reply_text'];
if ($new_status === 'Query' && empty($order['query_text'])) {
$query_to_save = $new_query_text;
} elseif ($new_status === 'Query Replied' && empty($order['reply_text'])) {
$reply_to_save = $new_reply_text;
}
if (empty($new_order_number)) {
$errors[] = "Order number cannot be empty.";
}
if (empty($new_order_date)) {
$errors[] = "Order date cannot be empty.";
}
if (empty($new_order_text)) {
$errors[] = "Order text cannot be empty.";
}
if (empty($new_status)) {
$errors[] = "Status cannot be empty.";
}
if (empty($errors)) {
try {
$stmt = $pdo->prepare("UPDATE orders SET order_number = :order_number, order_date = :order_date, order_text = :order_text, status = :status, query_text = :query_text, reply_text = :reply_text WHERE id = :id");
$stmt->bindParam(':order_number', $new_order_number);
$stmt->bindParam(':order_date', $new_order_date);
$stmt->bindParam(':order_text', $new_order_text);
$stmt->bindParam(':status', $new_status);
$stmt->bindParam(':query_text', $query_to_save);
$stmt->bindParam(':reply_text', $reply_to_save);
$stmt->bindParam(':id', $order_id, PDO::PARAM_INT);
$stmt->execute();
$success_message = "Order updated successfully!";
// Re-fetch order to display updated data
$stmt = $pdo->prepare("SELECT o.*, u.name as sales_rep_name FROM orders o JOIN users u ON o.sales_rep_id = u.id WHERE o.id = :id");
$stmt->bindParam(':id', $order_id, PDO::PARAM_INT);
$stmt->execute();
$order = $stmt->fetch(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
error_log("Database error updating order: " . $e->getMessage());
$errors[] = "Error updating order. Please try again later.";
}
}
}
?>
<div class="container mt-4">
<div class="row">
<div class="col-md-8 mx-auto">
<div class="card shadow-sm">
<div class="card-header bg-primary text-white">
<h1 class="card-title h4 mb-0"><?php echo htmlspecialchars($page_title); ?></h1>
</div>
<div class="card-body">
<?php if (!empty($errors)): ?>
<div class="alert alert-danger">
<?php foreach ($errors as $error): ?>
<p class="mb-0"><?php echo htmlspecialchars($error); ?></p>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if (!empty($success_message)): ?>
<div class="alert alert-success">
<?php echo htmlspecialchars($success_message); ?>
</div>
<?php endif; ?>
<?php if ($order): ?>
<form method="POST">
<div class="mb-3">
<label for="order_number" class="form-label">Order Number</label>
<input type="text" class="form-control" id="order_number" name="order_number" value="<?php echo htmlspecialchars($order['order_number']); ?>" <?php echo $edit_mode ? '' : 'readonly'; ?>>
</div>
<div class="mb-3">
<label for="order_date" class="form-label">Order Date</label>
<input type="date" class="form-control" id="order_date" name="order_date" value="<?php echo htmlspecialchars($order['order_date']); ?>" <?php echo $edit_mode ? '' : 'readonly'; ?>>
</div>
<div class="mb-3">
<label for="order_text" class="form-label">Order Details</label>
<textarea class="form-control" id="order_text" name="order_text" rows="5" <?php echo $edit_mode ? '' : 'readonly'; ?>><?php echo htmlspecialchars($order['order_text']); ?></textarea>
</div>
<div class="mb-3">
<label for="sales_rep_name" class="form-label">Sales Rep</label>
<input type="text" class="form-control" id="sales_rep_name" value="<?php echo htmlspecialchars($order['sales_rep_name']); ?>" readonly>
</div>
<div class="mb-3">
<label for="status" class="form-label">Status</label>
<?php if ($edit_mode): ?>
<select class="form-select" id="status" name="status">
<?php $statuses = ['Pending', 'Query', 'Query Replied', 'Shipped', 'Cancelled']; ?>
<?php foreach ($statuses as $status_option): ?>
<option value="<?php echo htmlspecialchars($status_option); ?>" <?php echo ($order['status'] === $status_option) ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($status_option); ?>
</option>
<?php endforeach; ?>
</select>
<?php else: ?>
<input type="text" class="form-control" id="status" name="status" value="<?php echo htmlspecialchars($order['status']); ?>" readonly>
<?php endif; ?>
</div>
<div class="mb-3" id="queryTextBox" style="display: none;">
<label for="query_text" class="form-label">Query</label>
<textarea class="form-control" id="query_text" name="query_text" rows="3" <?php echo ($order['query_text'] && $order['query_text'] !== '') ? 'readonly' : ''; ?>><?php echo htmlspecialchars($order['query_text'] ?? ''); ?></textarea>
</div>
<div class="mb-3" id="replyTextBox" style="display: none;">
<label for="reply_text" class="form-label">Query Reply</label>
<textarea class="form-control" id="reply_text" name="reply_text" rows="3" <?php echo ($order['reply_text'] && $order['reply_text'] !== '') ? 'readonly' : ''; ?>><?php echo htmlspecialchars($order['reply_text'] ?? ''); ?></textarea>
</div>
<?php if ($edit_mode): ?>
<button type="submit" class="btn btn-primary">Update Order</button>
<?php endif; ?>
<a href="index.php" class="btn btn-secondary">Back to Dashboard</a>
</form>
<?php else: ?>
<a href="index.php" class="btn btn-primary">Back to Dashboard</a>
<?php endif; ?>
</div>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const statusSelect = document.getElementById('status');
const queryTextBox = document.getElementById('queryTextBox');
const replyTextBox = document.getElementById('replyTextBox');
function toggleTextBoxes() {
const currentStatus = statusSelect.value;
queryTextBox.style.display = 'none';
replyTextBox.style.display = 'none';
if (currentStatus === 'Query') {
queryTextBox.style.display = 'block';
} else if (currentStatus === 'Query Replied') {
replyTextBox.style.display = 'block';
}
}
// Initial call to set correct visibility on page load
toggleTextBoxes();
// Add event listener for status change
if (statusSelect) {
statusSelect.addEventListener('change', toggleTextBoxes);
}
});
</script>
<?php require_once __DIR__ . '/partials/footer.php'; ?>