Bringing It All Together
This module is where our front-end and back-end skills truly merge. We will build a dynamic Point of Sale (POS) system that allows staff to select products, add them to a cart, and submit an order—all without page reloads. This requires a combination of PHP for fetching data, JavaScript for handling user interactions, and a robust PHP script on the back end to process the final order.
We will also build a page to view the history of all completed orders, a crucial feature for any business.
Step 1: The POS Interface (The "Front End")
First, we need to create the user interface. Create a file named `pos.php` in the `admin/` directory. This page will have two main sections: a grid displaying all available products and a "cart" area on the side to show the current order.
<?php session_start(); require_once '../includes/db.php'; // Fetch all available products $products = $conn->query("SELECT * FROM products WHERE stock > 0 ORDER BY name ASC"); ?> <!-- Basic HTML Structure --> <div class="pos-container"> <div class="product-grid"> <?php while($product = $products->fetch_assoc()): ?> <div class="product-card" data-id="<?php echo $product['id']; ?>" data-name="<?php echo htmlspecialchars($product['name']); ?>" data-price="<?php echo $product['price']; ?>"> <img src="../<?php echo $product['image_url']; ?>" alt="<?php echo htmlspecialchars($product['name']); ?>"> <h5><?php echo htmlspecialchars($product['name']); ?></h5> <p>$<?php echo $product['price']; ?></p> </div> <?php endwhile; ?> </div> <div class="order-summary"> <h3>Current Order</h3> <ul id="cart-items"></ul> <h4>Total: $<span id="cart-total">0.00</span></h4> <input type="text" id="customer-name" placeholder="Customer Name"> <button id="submit-order">Place Order</button> </div> </div> <!-- Include jQuery --> <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> <!-- Custom JS for POS functionality --> <script src="../assets/js/pos.js"></script>
Step 2: The JavaScript for Interactivity
Now for the magic. We'll use jQuery to handle clicks on products, add them to a cart object, and update the display. Create a file named `pos.js` inside `assets/js/`.
$(document).ready(function() { let cart = {}; // Add item to cart when a product card is clicked $('.product-card').on('click', function() { const id = $(this).data('id'); const name = $(this).data('name'); const price = parseFloat($(this).data('price')); if (cart[id]) { cart[id].quantity++; } else { cart[id] = { name: name, price: price, quantity: 1 }; } updateCartDisplay(); }); // Function to update the cart display and total function updateCartDisplay() { $('#cart-items').empty(); let total = 0; for (const id in cart) { const item = cart[id]; total += item.price * item.quantity; $('#cart-items').append(`<li>${item.name} x${item.quantity} - $${(item.price * item.quantity).toFixed(2)}</li>`); } $('#cart-total').text(total.toFixed(2)); } // Submit order via AJAX $('#submit-order').on('click', function() { const customerName = $('#customer-name').val(); if (!customerName || Object.keys(cart).length === 0) { alert('Please add items to the cart and enter a customer name.'); return; } $.ajax({ url: 'process_order.php', method: 'POST', data: { customer_name: customerName, cart: JSON.stringify(cart) }, success: function(response) { alert('Order placed successfully!'); cart = {}; $('#customer-name').val(''); updateCartDisplay(); }, error: function() { alert('Error processing order.'); } }); }); });
Step 3: Processing the Order (The "Back End")
The JavaScript sends the cart data to this PHP script. This is a critical process, so we use a **database transaction**. A transaction ensures that all SQL queries must succeed; if any one of them fails, all previous changes are rolled back. This prevents partial orders or incorrect stock levels.
Create `process_order.php` in the `admin/` folder.
<?php require_once '../includes/db.php'; $customer_name = $_POST['customer_name']; $cart = json_decode($_POST['cart'], true); $total_amount = 0; // Calculate total amount foreach ($cart as $item) { $total_amount += $item['price'] * $item['quantity']; } // Start a transaction $conn->begin_transaction(); try { // 1. Insert into the orders table $sql_order = "INSERT INTO orders (customer_name, total_amount, status) VALUES (?, ?, 'completed')"; $stmt_order = $conn->prepare($sql_order); $stmt_order->bind_param("sd", $customer_name, $total_amount); $stmt_order->execute(); $order_id = $stmt_order->insert_id; // Get the ID of the new order // 2. Insert into order_items and update product stock $sql_item = "INSERT INTO order_items (order_id, product_id, quantity, price) VALUES (?, ?, ?, ?)"; $sql_update_stock = "UPDATE products SET stock = stock - ? WHERE id = ?"; foreach ($cart as $id => $item) { // Insert order item $stmt_item = $conn->prepare($sql_item); $stmt_item->bind_param("iiid", $order_id, $id, $item['quantity'], $item['price']); $stmt_item->execute(); // Update stock $stmt_update = $conn->prepare($sql_update_stock); $stmt_update->bind_param("ii", $item['quantity'], $id); $stmt_update->execute(); } // If everything is successful, commit the transaction $conn->commit(); echo "Success"; } catch (Exception $e) { // If any query fails, roll back the changes $conn->rollback(); echo "Failed: " . $e->getMessage(); } ?>