mirror of
https://github.com/myronblair/tomsjavajive-app
synced 2026-06-30 17:50:56 -05:00
192 lines
5.8 KiB
PHP
192 lines
5.8 KiB
PHP
<?php
|
|
/**
|
|
* Tom's Java Jive - POS Order API
|
|
* Creates orders from the POS system
|
|
*/
|
|
|
|
header('Content-Type: application/json');
|
|
|
|
require_once __DIR__ . '/../includes/functions.php';
|
|
require_once __DIR__ . '/../includes/auth.php';
|
|
|
|
// Only accept POST
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
|
jsonResponse(['error' => 'Method not allowed'], 405);
|
|
}
|
|
|
|
$input = json_decode(file_get_contents('php://input'), true);
|
|
|
|
if (empty($input['items']) || !is_array($input['items'])) {
|
|
jsonResponse(['error' => 'No items provided'], 400);
|
|
}
|
|
|
|
$items = $input['items'];
|
|
$paymentMethod = $input['payment_method'] ?? 'cash';
|
|
$notes = $input['notes'] ?? '';
|
|
$customerId = $input['customer_id'] ?? null;
|
|
$customerEmail = $input['customer_email'] ?? null;
|
|
$discountAmount = floatval($input['discount'] ?? 0);
|
|
$couponCode = $input['coupon_code'] ?? null;
|
|
|
|
// Calculate totals
|
|
$subtotal = 0;
|
|
$orderItems = [];
|
|
|
|
foreach ($items as $item) {
|
|
// Verify product exists and has stock
|
|
$product = db()->fetch(
|
|
"SELECT product_id, name, price, sale_price, stock FROM products WHERE product_id = :id AND is_active = 1",
|
|
['id' => $item['product_id']]
|
|
);
|
|
|
|
if (!$product) {
|
|
jsonResponse(['error' => 'Product not found: ' . $item['name']], 400);
|
|
}
|
|
|
|
if ($product['stock'] < $item['quantity']) {
|
|
jsonResponse(['error' => 'Insufficient stock for: ' . $product['name']], 400);
|
|
}
|
|
|
|
$price = $product['sale_price'] ?? $product['price'];
|
|
$lineTotal = $price * $item['quantity'];
|
|
$subtotal += $lineTotal;
|
|
|
|
$orderItems[] = [
|
|
'product_id' => $product['product_id'],
|
|
'name' => $product['name'],
|
|
'price' => $price,
|
|
'quantity' => $item['quantity'],
|
|
'total' => $lineTotal
|
|
];
|
|
}
|
|
|
|
// Apply coupon if provided
|
|
$couponDiscount = 0;
|
|
if ($couponCode) {
|
|
$coupon = db()->fetch(
|
|
"SELECT * FROM coupons WHERE code = :code AND is_active = 1
|
|
AND (starts_at IS NULL OR starts_at <= NOW())
|
|
AND (expires_at IS NULL OR expires_at > NOW())
|
|
AND (max_uses IS NULL OR times_used < max_uses)",
|
|
['code' => strtoupper($couponCode)]
|
|
);
|
|
|
|
if ($coupon) {
|
|
if ($coupon['min_order_amount'] && $subtotal < $coupon['min_order_amount']) {
|
|
// Coupon minimum not met, ignore
|
|
} else {
|
|
if ($coupon['discount_type'] === 'percentage') {
|
|
$couponDiscount = $subtotal * ($coupon['discount_value'] / 100);
|
|
} else {
|
|
$couponDiscount = min($coupon['discount_value'], $subtotal);
|
|
}
|
|
|
|
// Update coupon usage
|
|
db()->query("UPDATE coupons SET times_used = times_used + 1 WHERE coupon_id = :id",
|
|
['id' => $coupon['coupon_id']]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Calculate final total
|
|
$discount = $discountAmount + $couponDiscount;
|
|
$taxRate = 0; // Adjust based on settings
|
|
$tax = ($subtotal - $discount) * $taxRate;
|
|
$total = $subtotal - $discount + $tax;
|
|
|
|
// Handle wallet payment
|
|
$walletUsed = 0;
|
|
if ($paymentMethod === 'wallet' && $customerId) {
|
|
$customer = db()->fetch(
|
|
"SELECT wallet_balance FROM customers WHERE customer_id = :id",
|
|
['id' => $customerId]
|
|
);
|
|
|
|
if (!$customer || $customer['wallet_balance'] < $total) {
|
|
jsonResponse(['error' => 'Insufficient wallet balance'], 400);
|
|
}
|
|
|
|
$walletUsed = $total;
|
|
|
|
// Deduct from wallet
|
|
db()->query(
|
|
"UPDATE customers SET wallet_balance = wallet_balance - :amount WHERE customer_id = :id",
|
|
['amount' => $walletUsed, 'id' => $customerId]
|
|
);
|
|
|
|
// Log wallet transaction
|
|
$newBalance = $customer['wallet_balance'] - $walletUsed;
|
|
db()->insert('wallet_transactions', [
|
|
'transaction_id' => generateId('wt_'),
|
|
'customer_id' => $customerId,
|
|
'amount' => -$walletUsed,
|
|
'balance_after' => $newBalance,
|
|
'type' => 'purchase',
|
|
'description' => 'POS Purchase'
|
|
]);
|
|
}
|
|
|
|
// Generate order
|
|
$orderId = generateId('ord_');
|
|
$orderNumber = generateOrderNumber();
|
|
|
|
try {
|
|
// Create order
|
|
db()->insert('orders', [
|
|
'order_id' => $orderId,
|
|
'order_number' => $orderNumber,
|
|
'customer_id' => $customerId,
|
|
'customer_email' => $customerEmail ?? 'pos@store.local',
|
|
'customer_name' => $input['customer_name'] ?? 'POS Customer',
|
|
'items' => json_encode($orderItems),
|
|
'subtotal' => $subtotal,
|
|
'tax' => $tax,
|
|
'discount' => $discount,
|
|
'wallet_amount_used' => $walletUsed,
|
|
'total' => $total,
|
|
'payment_method' => $paymentMethod,
|
|
'payment_status' => 'paid',
|
|
'order_status' => 'confirmed',
|
|
'notes' => $notes,
|
|
'is_pos_order' => 1
|
|
]);
|
|
|
|
// Insert order items
|
|
foreach ($orderItems as $item) {
|
|
db()->insert('order_items', [
|
|
'order_id' => $orderId,
|
|
'product_id' => $item['product_id'],
|
|
'name' => $item['name'],
|
|
'price' => $item['price'],
|
|
'quantity' => $item['quantity'],
|
|
'total' => $item['total']
|
|
]);
|
|
|
|
// Update stock
|
|
db()->query(
|
|
"UPDATE products SET stock = stock - :qty WHERE product_id = :id",
|
|
['qty' => $item['quantity'], 'id' => $item['product_id']]
|
|
);
|
|
}
|
|
|
|
// Award reward points if customer
|
|
if ($customerId) {
|
|
$pointsEarned = floor($total); // 1 point per dollar
|
|
db()->query(
|
|
"UPDATE customers SET reward_points = reward_points + :points WHERE customer_id = :id",
|
|
['points' => $pointsEarned, 'id' => $customerId]
|
|
);
|
|
}
|
|
|
|
jsonResponse([
|
|
'success' => true,
|
|
'order_id' => $orderId,
|
|
'order_number' => $orderNumber,
|
|
'total' => $total,
|
|
'items' => $orderItems
|
|
]);
|
|
|
|
} catch (Exception $e) {
|
|
jsonResponse(['error' => 'Failed to create order: ' . $e->getMessage()], 500);
|
|
}
|