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,
password VARCHAR(255) 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 (
@ -16,6 +17,8 @@ function setup_database($pdo) {
order_date DATE NOT NULL,
order_text TEXT NOT NULL,
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,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

View File

@ -15,20 +15,35 @@ $shipped_orders_month_count = 0;
try {
// --- Fetch Dashboard Counts ---
$conditions = '';
$base_conditions_arr = [];
$params = [];
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;
}
// 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);
$pending_orders_count = $stmt->fetchColumn();
// 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);
$pending_replies_count = $stmt->fetchColumn();
@ -36,12 +51,21 @@ try {
$current_month_start = date('Y-m-01 00:00:00');
$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[':start_date'] = $current_month_start;
$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);
$shipped_orders_month_count = $stmt->fetchColumn();
@ -133,9 +157,9 @@ try {
<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>
<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): ?>
<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; ?>
</td>
</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'; ?>