Compare commits
No commits in common. "ai-dev" and "master" have entirely different histories.
@ -1,54 +0,0 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['error' => 'Method Not Allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
$first_name = $data['first_name'] ?? null;
|
||||
$last_name = $data['last_name'] ?? null;
|
||||
$email = $data['email'] ?? null;
|
||||
$phone = $data['phone'] ?? null;
|
||||
$address = $data['address'] ?? null;
|
||||
|
||||
if (!$first_name || !$last_name || !$email) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Missing required fields: first_name, last_name, email']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Invalid email format']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
$stmt = $pdo->prepare("SELECT id FROM customers WHERE email = ?");
|
||||
$stmt->execute([$email]);
|
||||
if ($stmt->fetch()) {
|
||||
http_response_code(409);
|
||||
echo json_encode(['error' => 'Customer with this email already exists']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("INSERT INTO customers (first_name, last_name, email, phone, address) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$first_name, $last_name, $email, $phone, $address]);
|
||||
|
||||
$id = $pdo->lastInsertId();
|
||||
|
||||
http_response_code(201);
|
||||
echo json_encode(['success' => 'Customer created successfully', 'id' => $id]);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$id = $_GET['id'] ?? null;
|
||||
|
||||
if (!$id) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Customer ID is required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
$stmt = $pdo->prepare("SELECT id FROM customers WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
if (!$stmt->fetch()) {
|
||||
http_response_code(404);
|
||||
echo json_encode(['error' => 'Customer not found']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("DELETE FROM customers WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
|
||||
echo json_encode(['success' => 'Customer deleted successfully']);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$id = $_GET['id'] ?? null;
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
if ($id) {
|
||||
$stmt = $pdo->prepare("SELECT * FROM customers WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$customer = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($customer) {
|
||||
echo json_encode($customer);
|
||||
} else {
|
||||
http_response_code(404);
|
||||
echo json_code(['error' => 'Customer not found']);
|
||||
}
|
||||
} else {
|
||||
$stmt = $pdo->query("SELECT * FROM customers");
|
||||
$customers = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
echo json_encode($customers);
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||
}
|
||||
@ -1,67 +0,0 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') { // Should be PUT or POST
|
||||
http_response_code(405);
|
||||
echo json_encode(['error' => 'Method Not Allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$id = $_GET['id'] ?? null;
|
||||
|
||||
if (!$id) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Customer ID is required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
$first_name = $data['first_name'] ?? null;
|
||||
$last_name = $data['last_name'] ?? null;
|
||||
$email = $data['email'] ?? null;
|
||||
$phone = $data['phone'] ?? null;
|
||||
$address = $data['address'] ?? null;
|
||||
|
||||
if (!$first_name || !$last_name || !$email) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Missing required fields: first_name, last_name, email']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Invalid email format']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
$stmt = $pdo->prepare("SELECT id FROM customers WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
if (!$stmt->fetch()) {
|
||||
http_response_code(404);
|
||||
echo json_encode(['error' => 'Customer not found']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("SELECT id FROM customers WHERE email = ? AND id != ?");
|
||||
$stmt->execute([$email, $id]);
|
||||
if ($stmt->fetch()) {
|
||||
http_response_code(409);
|
||||
echo json_encode(['error' => 'Another customer with this email already exists']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("UPDATE customers SET first_name = ?, last_name = ?, email = ?, phone = ?, address = ? WHERE id = ?");
|
||||
$stmt->execute([$first_name, $last_name, $email, $phone, $address, $id]);
|
||||
|
||||
echo json_encode(['success' => 'Customer updated successfully']);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||
}
|
||||
@ -1,80 +0,0 @@
|
||||
-- Initial schema for CheersPOS System
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `roles` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`name` VARCHAR(255) NOT NULL UNIQUE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Insert default roles
|
||||
INSERT IGNORE INTO `roles` (`name`) VALUES
|
||||
('Admin'),
|
||||
('Manager'),
|
||||
('Inventory Manager'),
|
||||
('Cashier'),
|
||||
('HR Manager'),
|
||||
('Customer Manager');
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `users` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`username` VARCHAR(255) NOT NULL UNIQUE,
|
||||
`password` VARCHAR(255) NOT NULL,
|
||||
`email` VARCHAR(255) NOT NULL UNIQUE,
|
||||
`role_id` INT,
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (`role_id`) REFERENCES `roles`(`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `products` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`description` TEXT,
|
||||
`price` DECIMAL(10, 2) NOT NULL,
|
||||
`cost` DECIMAL(10, 2) NOT NULL DEFAULT 0.00,
|
||||
`quantity` INT NOT NULL DEFAULT 0,
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `customers` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`first_name` VARCHAR(255) NOT NULL,
|
||||
`last_name` VARCHAR(255) NOT NULL,
|
||||
`email` VARCHAR(255) NOT NULL UNIQUE,
|
||||
`phone` VARCHAR(50),
|
||||
`address` TEXT,
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `sales` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`customer_id` INT,
|
||||
`subtotal` DECIMAL(10, 2) NOT NULL,
|
||||
`tax_total` DECIMAL(10, 2) NOT NULL DEFAULT 0.00,
|
||||
`total_amount` DECIMAL(10, 2) NOT NULL,
|
||||
`sale_date` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (`customer_id`) REFERENCES `customers`(`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `sale_items` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`sale_id` INT,
|
||||
`product_id` INT,
|
||||
`quantity` INT NOT NULL,
|
||||
`price` DECIMAL(10, 2) NOT NULL,
|
||||
FOREIGN KEY (`sale_id`) REFERENCES `sales`(`id`) ON DELETE CASCADE,
|
||||
FOREIGN KEY (`product_id`) REFERENCES `products`(`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `taxes` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`name` VARCHAR(255) NOT NULL UNIQUE,
|
||||
`rate` DECIMAL(5, 2) NOT NULL COMMENT 'Percentage'
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `sale_taxes` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`sale_id` INT,
|
||||
`tax_id` INT,
|
||||
`tax_amount` DECIMAL(10, 2) NOT NULL,
|
||||
FOREIGN KEY (`sale_id`) REFERENCES `sales`(`id`) ON DELETE CASCADE,
|
||||
FOREIGN KEY (`tax_id`) REFERENCES `taxes`(`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
42
db/setup.php
42
db/setup.php
@ -1,42 +0,0 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
try {
|
||||
// Connect to MySQL server without specifying a database
|
||||
$pdo = new PDO('mysql:host=' . DB_HOST . ';charset=utf8mb4', DB_USER, DB_PASS, [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
]);
|
||||
|
||||
// Create the database if it doesn't exist
|
||||
$pdo->exec("CREATE DATABASE IF NOT EXISTS `" . DB_NAME . "`");
|
||||
|
||||
// Reconnect to the specific database
|
||||
$pdo = db();
|
||||
|
||||
$sql = file_get_contents(__DIR__ . '/schema.sql');
|
||||
$pdo->exec($sql);
|
||||
echo "Database schema created successfully.\n";
|
||||
|
||||
// Check if 'cost' column exists in 'products' table and add it if not
|
||||
$stmt = $pdo->query("SHOW COLUMNS FROM `products` LIKE 'cost'");
|
||||
$column_exists = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$column_exists) {
|
||||
$pdo->exec("ALTER TABLE `products` ADD `cost` DECIMAL(10, 2) NOT NULL DEFAULT 0.00 AFTER `price`");
|
||||
echo "Column 'cost' added to 'products' table successfully.\n";
|
||||
}
|
||||
|
||||
// Check if 'subtotal' column exists in 'sales' table and add columns if not
|
||||
$stmt = $pdo->query("SHOW COLUMNS FROM `sales` LIKE 'subtotal'");
|
||||
$column_exists = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$column_exists) {
|
||||
$pdo->exec("ALTER TABLE `sales` ADD `subtotal` DECIMAL(10, 2) NOT NULL AFTER `customer_id`");
|
||||
$pdo->exec("ALTER TABLE `sales` ADD `tax_total` DECIMAL(10, 2) NOT NULL DEFAULT 0.00 AFTER `subtotal`");
|
||||
echo "Columns 'subtotal' and 'tax_total' added to 'sales' table successfully.\n";
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
die("Database setup failed: " . $e->getMessage() . "\n");
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['error' => 'Method Not Allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
$first_name = $data['first_name'] ?? null;
|
||||
$last_name = $data['last_name'] ?? null;
|
||||
$email = $data['email'] ?? null;
|
||||
$phone = $data['phone'] ?? null;
|
||||
$role_id = $data['role_id'] ?? null;
|
||||
$hire_date = $data['hire_date'] ?? null;
|
||||
|
||||
if (!$first_name || !$last_name || !$email || !$role_id) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Missing required fields: first_name, last_name, email, role_id']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Invalid email format']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
$stmt = $pdo->prepare("SELECT id FROM employees WHERE email = ?");
|
||||
$stmt->execute([$email]);
|
||||
if ($stmt->fetch()) {
|
||||
http_response_code(409);
|
||||
echo json_encode(['error' => 'Employee with this email already exists']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("INSERT INTO employees (first_name, last_name, email, phone, role_id, hire_date) VALUES (?, ?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$first_name, $last_name, $email, $phone, $role_id, $hire_date]);
|
||||
|
||||
$id = $pdo->lastInsertId();
|
||||
|
||||
http_response_code(201);
|
||||
echo json_encode(['success' => 'Employee created successfully', 'id' => $id]);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$id = $_GET['id'] ?? null;
|
||||
|
||||
if (!$id) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Employee ID is required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
$stmt = $pdo->prepare("SELECT id FROM employees WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
if (!$stmt->fetch()) {
|
||||
http_response_code(404);
|
||||
echo json_encode(['error' => 'Employee not found']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("DELETE FROM employees WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
|
||||
echo json_encode(['success' => 'Employee deleted successfully']);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$id = $_GET['id'] ?? null;
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
if ($id) {
|
||||
$stmt = $pdo->prepare("SELECT e.*, r.name as role_name FROM employees e LEFT JOIN roles r ON e.role_id = r.id WHERE e.id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$employee = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($employee) {
|
||||
echo json_encode($employee);
|
||||
} else {
|
||||
http_response_code(404);
|
||||
echo json_encode(['error' => 'Employee not found']);
|
||||
}
|
||||
} else {
|
||||
$stmt = $pdo->query("SELECT e.*, r.name as role_name FROM employees e LEFT JOIN roles r ON e.role_id = r.id");
|
||||
$employees = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
echo json_encode($employees);
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||
}
|
||||
@ -1,68 +0,0 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') { // Should be PUT or POST
|
||||
http_response_code(405);
|
||||
echo json_encode(['error' => 'Method Not Allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$id = $_GET['id'] ?? null;
|
||||
|
||||
if (!$id) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Employee ID is required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
$first_name = $data['first_name'] ?? null;
|
||||
$last_name = $data['last_name'] ?? null;
|
||||
$email = $data['email'] ?? null;
|
||||
$phone = $data['phone'] ?? null;
|
||||
$role_id = $data['role_id'] ?? null;
|
||||
$hire_date = $data['hire_date'] ?? null;
|
||||
|
||||
if (!$first_name || !$last_name || !$email || !$role_id) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Missing required fields: first_name, last_name, email, role_id']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Invalid email format']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
$stmt = $pdo->prepare("SELECT id FROM employees WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
if (!$stmt->fetch()) {
|
||||
http_response_code(404);
|
||||
echo json_encode(['error' => 'Employee not found']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("SELECT id FROM employees WHERE email = ? AND id != ?");
|
||||
$stmt->execute([$email, $id]);
|
||||
if ($stmt->fetch()) {
|
||||
http_response_code(409);
|
||||
echo json_encode(['error' => 'Another employee with this email already exists']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("UPDATE employees SET first_name = ?, last_name = ?, email = ?, phone = ?, role_id = ?, hire_date = ? WHERE id = ?");
|
||||
$stmt->execute([$first_name, $last_name, $email, $phone, $role_id, $hire_date, $id]);
|
||||
|
||||
echo json_encode(['success' => 'Employee updated successfully']);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||
}
|
||||
310
index.php
310
index.php
@ -1,225 +1,103 @@
|
||||
<!DOCTYPE html>
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
@ini_set('display_errors', '1');
|
||||
@error_reporting(E_ALL);
|
||||
@date_default_timezone_set('UTC');
|
||||
|
||||
$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.0">
|
||||
<title>CheersPOS System</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>New Style</title>
|
||||
<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>
|
||||
body { font-family: sans-serif; margin: 2em; background-color: #f4f4f9; color: #333; }
|
||||
h1 { color: #0056b3; }
|
||||
nav { margin-bottom: 1em; }
|
||||
nav button { padding: 10px 15px; border: none; background-color: #007bff; color: white; cursor: pointer; margin-right: 10px; border-radius: 5px; }
|
||||
nav button:hover { background-color: #0056b3; }
|
||||
#content { background-color: white; padding: 1em; border-radius: 5px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
|
||||
table { width: 100%; border-collapse: collapse; margin-top: 1em; }
|
||||
th, td { padding: 8px; text-align: left; border-bottom: 1px solid #ddd; }
|
||||
th { background-color: #f2f2f2; }
|
||||
.error { color: red; }
|
||||
.success { color: green; }
|
||||
form div { margin-bottom: 10px; }
|
||||
:root {
|
||||
--bg-color-start: #4B0082;
|
||||
--bg-color-end: #8A2BE2;
|
||||
--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);
|
||||
}
|
||||
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>
|
||||
|
||||
<h1>CheersPOS System</h1>
|
||||
|
||||
<nav>
|
||||
<button onclick="loadProducts()">Products</button>
|
||||
<button onclick="loadCustomers()">Customers</button>
|
||||
<button onclick="loadEmployees()">Employees</button>
|
||||
<button onclick="loadTaxes()">Manage Taxes</button>
|
||||
<button onclick="showSaleForm()">Create Sale</button>
|
||||
</nav>
|
||||
|
||||
<div id="content">
|
||||
<p>Welcome to the AI Retail Management Solution. Select an option above to get started.</p>
|
||||
<main>
|
||||
<div class="card">
|
||||
<h1>Welcome!</h1>
|
||||
<p>This is your new landing page.</p>
|
||||
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const contentDiv = document.getElementById('content');
|
||||
|
||||
|
||||
|
||||
async function loadTaxes() {
|
||||
try {
|
||||
const response = await fetch('taxes/read.php');
|
||||
const taxes = await response.json();
|
||||
let html = `
|
||||
<h2>Manage Taxes</h2>
|
||||
<form id="taxForm" onsubmit="createTax(event)">
|
||||
<input type="text" name="name" placeholder="Tax Name" required>
|
||||
<input type="number" step="0.01" name="rate" placeholder="Rate (%)" required>
|
||||
<button type="submit">Add Tax</button>
|
||||
</form>
|
||||
<div id="taxResult"></div>
|
||||
`;
|
||||
if (taxes.length === 0) {
|
||||
html += '<p>No taxes found.</p>';
|
||||
} else {
|
||||
html += '<table><tr><th>ID</th><th>Name</th><th>Rate (%)</th><th>Action</th></tr>';
|
||||
taxes.forEach(t => {
|
||||
html += `<tr><td>${t.id}</td><td>${t.name}</td><td>${t.rate}</td><td><button onclick="deleteTax(${t.id})">Delete</button></td></tr>`;
|
||||
});
|
||||
html += '</table>';
|
||||
}
|
||||
contentDiv.innerHTML = html;
|
||||
} catch (error) {
|
||||
contentDiv.innerHTML = `<p class="error">Error loading taxes: ${error}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
async function createTax(event) {
|
||||
event.preventDefault();
|
||||
const form = document.getElementById('taxForm');
|
||||
const resultDiv = document.getElementById('taxResult');
|
||||
const formData = new FormData(form);
|
||||
const taxData = Object.fromEntries(formData.entries());
|
||||
|
||||
try {
|
||||
const response = await fetch('taxes/create.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(taxData)
|
||||
});
|
||||
const result = await response.json();
|
||||
if (response.ok) {
|
||||
resultDiv.innerHTML = `<p class="success">${result.success}</p>`;
|
||||
loadTaxes(); // Refresh list
|
||||
} else {
|
||||
resultDiv.innerHTML = `<p class="error">${result.error}</p>`;
|
||||
}
|
||||
} catch (error) {
|
||||
resultDiv.innerHTML = `<p class="error">Error creating tax: ${error}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteTax(id) {
|
||||
if (!confirm('Are you sure you want to delete this tax?')) return;
|
||||
try {
|
||||
const response = await fetch(`taxes/delete.php?id=${id}`);
|
||||
const result = await response.json();
|
||||
if (response.ok) {
|
||||
loadTaxes();
|
||||
} else {
|
||||
alert(result.error);
|
||||
}
|
||||
} catch (error) {
|
||||
alert(`Error deleting tax: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function showSaleForm() {
|
||||
let taxCheckboxes = '';
|
||||
try {
|
||||
const taxResponse = await fetch('taxes/read.php');
|
||||
const taxes = await taxResponse.json();
|
||||
taxes.forEach(tax => {
|
||||
taxCheckboxes += `
|
||||
<label>
|
||||
<input type="checkbox" name="tax_ids[]" value="${tax.id}">
|
||||
${tax.name} (${tax.rate}%)
|
||||
</label><br>
|
||||
`;
|
||||
});
|
||||
} catch (e) { taxCheckboxes = '<p class="error">Could not load taxes.</p>'; }
|
||||
|
||||
contentDiv.innerHTML = `
|
||||
<h2>Create Sale</h2>
|
||||
<form id="saleForm" onsubmit="createSale(event)">
|
||||
<div>
|
||||
<label for="customer_id">Customer ID (optional):</label>
|
||||
<input type="number" id="customer_id" name="customer_id">
|
||||
</div>
|
||||
<h3>Items</h3>
|
||||
<div id="saleItems">
|
||||
<div class="sale-item">
|
||||
<input type="number" name="product_id[]" placeholder="Product ID" required>
|
||||
<input type="number" name="quantity[]" placeholder="Quantity" required>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" onclick="addSaleItem()">Add Item</button>
|
||||
<h3>Taxes</h3>
|
||||
<div id="taxItems">
|
||||
${taxCheckboxes}
|
||||
</div>
|
||||
<button type="submit">Submit Sale</button>
|
||||
</form>
|
||||
<div id="saleResult"></div>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
async function loadProducts() {
|
||||
try {
|
||||
const response = await fetch('products/read.php');
|
||||
const products = await response.json();
|
||||
let html = '<h2>Products</h2>';
|
||||
if (products.length === 0) {
|
||||
html += '<p>No products found.</p>';
|
||||
} else {
|
||||
html += '<table><tr><th>ID</th><th>Name</th><th>Description</th><th>Price</th><th>Cost</th><th>Quantity</th></tr>';
|
||||
products.forEach(p => {
|
||||
html += `<tr><td>${p.id}</td><td>${p.name}</td><td>${p.description}</td><td>${p.price}</td><td>${p.cost}</td><td>${p.quantity}</td></tr>`;
|
||||
});
|
||||
html += '</table>';
|
||||
}
|
||||
contentDiv.innerHTML = html;
|
||||
} catch (error) {
|
||||
contentDiv.innerHTML = `<p class="error">Error loading products: ${error}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadCustomers() {
|
||||
try {
|
||||
const response = await fetch('customers/read.php');
|
||||
const customers = await response.json();
|
||||
let html = '<h2>Customers</h2>';
|
||||
if (customers.length === 0) {
|
||||
html += '<p>No customers found.</p>';
|
||||
} else {
|
||||
html += '<table><tr><th>ID</th><th>Name</th><th>Email</th><th>Phone</th><th>Address</th></tr>';
|
||||
customers.forEach(c => {
|
||||
html += `<tr><td>${c.id}</td><td>${c.first_name} ${c.last_name}</td><td>${c.email}</td><td>${c.phone}</td><td>${c.address}</td></tr>`;
|
||||
});
|
||||
html += '</table>';
|
||||
}
|
||||
contentDiv.innerHTML = html;
|
||||
} catch (error) {
|
||||
contentDiv.innerHTML = `<p class="error">Error loading customers: ${error}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
async function loadEmployees() {
|
||||
try {
|
||||
const response = await fetch('employees/read.php');
|
||||
const employees = await response.json();
|
||||
let html = '<h2>Employees</h2>';
|
||||
if (employees.length === 0) {
|
||||
html += '<p>No employees found.</p>';
|
||||
} else {
|
||||
html += '<table><tr><th>ID</th><th>Name</th><th>Email</th><th>Phone</th><th>Role</th><th>Hire Date</th></tr>';
|
||||
employees.forEach(e => {
|
||||
html += `<tr><td>${e.id}</td><td>${e.first_name} ${e.last_name}</td><td>${e.email}</td><td>${e.phone}</td><td>${e.role_name}</td><td>${e.hire_date}</td></tr>`;
|
||||
});
|
||||
html += '</table>';
|
||||
}
|
||||
contentDiv.innerHTML = html;
|
||||
} catch (error) {
|
||||
contentDiv.innerHTML = `<p class="error">Error loading employees: ${error}</p>`;
|
||||
}
|
||||
}
|
||||
function addSaleItem() {
|
||||
const saleItems = document.getElementById('saleItems');
|
||||
const newItem = document.createElement('div');
|
||||
newItem.classList.add('sale-item');
|
||||
newItem.innerHTML = '
|
||||
<input type="number" name="product_id[]" placeholder="Product ID" required>
|
||||
<input type="number" name="quantity[]" placeholder="Quantity" required>
|
||||
';
|
||||
saleItems.appendChild(newItem);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
</main>
|
||||
<footer>
|
||||
Page updated: <?= htmlspecialchars($now) ?> (UTC)
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,48 +0,0 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['error' => 'Method Not Allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
$product_id = $data['product_id'] ?? null;
|
||||
$quantity = $data['quantity'] ?? null;
|
||||
|
||||
if (!$product_id || !isset($quantity)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Missing required fields: product_id, quantity']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!is_numeric($quantity) || $quantity < 0) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Invalid quantity']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
$stmt = $pdo->prepare("SELECT id FROM products WHERE id = ?");
|
||||
$stmt->execute([$product_id]);
|
||||
if (!$stmt->fetch()) {
|
||||
http_response_code(404);
|
||||
echo json_encode(['error' => 'Product not found']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("UPDATE products SET quantity = ? WHERE id = ?");
|
||||
$stmt->execute([$quantity, $product_id]);
|
||||
|
||||
echo json_encode(['success' => 'Inventory updated successfully']);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['error' => 'Method Not Allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
if (empty($data['name']) || !isset($data['price']) || !isset($data['cost']) || !isset($data['quantity'])) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Missing required fields: name, price, cost, and quantity']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$name = $data['name'];
|
||||
$description = $data['description'] ?? null;
|
||||
$price = $data['price'];
|
||||
$cost = $data['cost'];
|
||||
$quantity = $data['quantity'];
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("INSERT INTO products (name, description, price, cost, quantity) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$name, $description, $price, $cost, $quantity]);
|
||||
|
||||
http_response_code(201);
|
||||
echo json_encode(['message' => 'Product created successfully', 'id' => $pdo->lastInsertId()]);
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['error' => 'Method Not Allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$id = $_GET['id'] ?? null;
|
||||
|
||||
if (!$id) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Missing required parameter: id']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("DELETE FROM products WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
|
||||
if ($stmt->rowCount() > 0) {
|
||||
echo json_encode(['message' => 'Product deleted successfully']);
|
||||
} else {
|
||||
http_response_code(404);
|
||||
echo json_encode(['error' => 'Product not found']);
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$id = $_GET['id'] ?? null;
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
if ($id) {
|
||||
$stmt = $pdo->prepare("SELECT * FROM products WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$product = $stmt->fetch();
|
||||
if ($product) {
|
||||
echo json_encode($product);
|
||||
} else {
|
||||
http_response_code(404);
|
||||
echo json_encode(['error' => 'Product not found']);
|
||||
}
|
||||
} else {
|
||||
$stmt = $pdo->query("SELECT * FROM products");
|
||||
$products = $stmt->fetchAll();
|
||||
echo json_encode($products);
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['error' => 'Method Not Allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
if (empty($data['id'])) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Missing required field: id']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$id = $data['id'];
|
||||
|
||||
// Fetch the existing product to see which fields are being updated
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("SELECT * FROM products WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$product = $stmt->fetch();
|
||||
|
||||
if (!$product) {
|
||||
http_response_code(404);
|
||||
echo json_encode(['error' => 'Product not found']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$name = $data['name'] ?? $product['name'];
|
||||
$description = $data['description'] ?? $product['description'];
|
||||
$price = $data['price'] ?? $product['price'];
|
||||
$cost = $data['cost'] ?? $product['cost'];
|
||||
$quantity = $data['quantity'] ?? $product['quantity'];
|
||||
|
||||
try {
|
||||
$stmt = $pdo->prepare("UPDATE products SET name = ?, description = ?, price = ?, cost = ?, quantity = ? WHERE id = ?");
|
||||
$stmt->execute([$name, $description, $price, $cost, $quantity, $id]);
|
||||
|
||||
echo json_encode(['message' => 'Product updated successfully']);
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||
}
|
||||
106
sales/create.php
106
sales/create.php
@ -1,106 +0,0 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['error' => 'Method Not Allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
$customer_id = $data['customer_id'] ?? null;
|
||||
$items = $data['items'] ?? [];
|
||||
$tax_ids = $data['tax_ids'] ?? [];
|
||||
|
||||
if (empty($items)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Sale must have at least one item']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$pdo->beginTransaction();
|
||||
|
||||
// 1. Calculate subtotal and check stock
|
||||
$subtotal = 0;
|
||||
foreach ($items as $item) {
|
||||
$product_id = $item['product_id'] ?? null;
|
||||
$quantity = $item['quantity'] ?? null;
|
||||
|
||||
if (!$product_id || !$quantity || $quantity <= 0) {
|
||||
throw new Exception('Invalid item data');
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("SELECT price, quantity FROM products WHERE id = ? FOR UPDATE");
|
||||
$stmt->execute([$product_id]);
|
||||
$product = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$product) {
|
||||
throw new Exception("Product with ID $product_id not found");
|
||||
}
|
||||
if ($product['quantity'] < $quantity) {
|
||||
throw new Exception("Not enough stock for product ID $product_id");
|
||||
}
|
||||
|
||||
$subtotal += $product['price'] * $quantity;
|
||||
}
|
||||
|
||||
// 2. Calculate taxes
|
||||
$tax_total = 0;
|
||||
$taxes_to_apply = [];
|
||||
if (!empty($tax_ids)) {
|
||||
$sql = "SELECT id, rate FROM taxes WHERE id IN (" . implode(',', array_fill(0, count($tax_ids), '?')) . ")";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($tax_ids);
|
||||
$taxes = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
foreach ($taxes as $tax) {
|
||||
$tax_amount = ($subtotal * $tax['rate']) / 100;
|
||||
$tax_total += $tax_amount;
|
||||
$taxes_to_apply[] = ['id' => $tax['id'], 'amount' => $tax_amount];
|
||||
}
|
||||
}
|
||||
|
||||
$total_amount = $subtotal + $tax_total;
|
||||
|
||||
// 3. Update product quantities
|
||||
foreach ($items as $item) {
|
||||
$stmt = $pdo->prepare("UPDATE products SET quantity = quantity - ? WHERE id = ?");
|
||||
$stmt->execute([$item['quantity'], $item['product_id']]);
|
||||
}
|
||||
|
||||
// 4. Insert into sales table
|
||||
$stmt = $pdo->prepare("INSERT INTO sales (customer_id, subtotal, tax_total, total_amount) VALUES (?, ?, ?, ?)");
|
||||
$stmt->execute([$customer_id, $subtotal, $tax_total, $total_amount]);
|
||||
$sale_id = $pdo->lastInsertId();
|
||||
|
||||
// 5. Insert into sale_items
|
||||
$stmt = $pdo->prepare("INSERT INTO sale_items (sale_id, product_id, quantity, price) VALUES (?, ?, ?, (SELECT price FROM products WHERE id = ?))");
|
||||
foreach ($items as $item) {
|
||||
$stmt->execute([$sale_id, $item['product_id'], $item['quantity'], $item['product_id']]);
|
||||
}
|
||||
|
||||
// 6. Insert into sale_taxes
|
||||
if (!empty($taxes_to_apply)) {
|
||||
$stmt = $pdo->prepare("INSERT INTO sale_taxes (sale_id, tax_id, tax_amount) VALUES (?, ?, ?)");
|
||||
foreach ($taxes_to_apply as $tax) {
|
||||
$stmt->execute([$sale_id, $tax['id'], $tax['amount']]);
|
||||
}
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
http_response_code(201);
|
||||
echo json_encode(['success' => 'Sale created successfully', 'sale_id' => $sale_id, 'total_amount' => $total_amount]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
if ($pdo->inTransaction()) {
|
||||
$pdo->rollBack();
|
||||
}
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => $e->getMessage()]);
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['error' => 'Method Not Allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
$name = $data['name'] ?? null;
|
||||
$rate = $data['rate'] ?? null;
|
||||
|
||||
if (!$name || !isset($rate)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Missing required fields: name, rate']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!is_numeric($rate) || $rate < 0 || $rate > 100) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Invalid rate. Must be a number between 0 and 100.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
$stmt = $pdo->prepare("INSERT INTO taxes (name, rate) VALUES (?, ?)");
|
||||
$stmt->execute([$name, $rate]);
|
||||
|
||||
$id = $pdo->lastInsertId();
|
||||
|
||||
http_response_code(201);
|
||||
echo json_encode(['success' => 'Tax created successfully', 'id' => $id]);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
if ($e->errorInfo[1] == 1062) { // Duplicate entry
|
||||
http_response_code(409);
|
||||
echo json_encode(['error' => 'A tax with this name already exists.']);
|
||||
} else {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
@ -1,42 +0,0 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$id = $_GET['id'] ?? null;
|
||||
|
||||
if (!$id) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Tax ID is required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
$stmt = $pdo->prepare("SELECT id FROM taxes WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
if (!$stmt->fetch()) {
|
||||
http_response_code(404);
|
||||
echo json_encode(['error' => 'Tax not found']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Check if the tax is being used in any sale
|
||||
$stmt = $pdo->prepare("SELECT id FROM sale_taxes WHERE tax_id = ?");
|
||||
$stmt->execute([$id]);
|
||||
if ($stmt->fetch()) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Cannot delete tax because it is associated with existing sales.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("DELETE FROM taxes WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
|
||||
echo json_encode(['success' => 'Tax deleted successfully']);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$id = $_GET['id'] ?? null;
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
if ($id) {
|
||||
$stmt = $pdo->prepare("SELECT * FROM taxes WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$tax = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($tax) {
|
||||
echo json_encode($tax);
|
||||
} else {
|
||||
http_response_code(404);
|
||||
echo json_encode(['error' => 'Tax not found']);
|
||||
}
|
||||
} else {
|
||||
$stmt = $pdo->query("SELECT * FROM taxes ORDER BY name");
|
||||
$taxes = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
echo json_encode($taxes);
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||
}
|
||||
@ -1,61 +0,0 @@
|
||||
<?php
|
||||
require_once '../db/config.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['error' => 'Method Not Allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$id = $_GET['id'] ?? null;
|
||||
|
||||
if (!$id) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Tax ID is required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
$name = $data['name'] ?? null;
|
||||
$rate = $data['rate'] ?? null;
|
||||
|
||||
if (!$name || !isset($rate)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Missing required fields: name, rate']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!is_numeric($rate) || $rate < 0 || $rate > 100) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Invalid rate. Must be a number between 0 and 100.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
|
||||
$stmt = $pdo->prepare("SELECT id FROM taxes WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
if (!$stmt->fetch()) {
|
||||
http_response_code(404);
|
||||
echo json_encode(['error' => 'Tax not found']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("UPDATE taxes SET name = ?, rate = ? WHERE id = ?");
|
||||
$stmt->execute([$name, $rate, $id]);
|
||||
|
||||
echo json_encode(['success' => 'Tax updated successfully']);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
if ($e->errorInfo[1] == 1062) { // Duplicate entry
|
||||
http_response_code(409);
|
||||
echo json_encode(['error' => 'A tax with this name already exists.']);
|
||||
} else {
|
||||
http_response_code(500);
|
||||
echo json_encode(['error' => 'Database error: ' . $e->getMessage()]);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user