missing migrations
This commit is contained in:
parent
ac32148f05
commit
8faf7adbb6
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . "/../includes/functions.php";
|
require_once __DIR__ . "/../includes/functions.php";
|
||||||
|
require_once __DIR__ . "/../db/config.php";
|
||||||
require_permission("ads");
|
require_permission("ads");
|
||||||
require_once __DIR__ . '/../db/config.php';
|
require_once __DIR__ . '/../db/config.php';
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . "/../includes/functions.php";
|
require_once __DIR__ . "/../includes/functions.php";
|
||||||
|
require_once __DIR__ . "/../db/config.php";
|
||||||
require_permission("areas_view");
|
require_permission("areas_view");
|
||||||
require_once __DIR__ . '/../db/config.php';
|
require_once __DIR__ . '/../db/config.php';
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . "/../includes/functions.php";
|
require_once __DIR__ . "/../includes/functions.php";
|
||||||
|
require_once __DIR__ . "/../db/config.php";
|
||||||
require_permission("settings_view");
|
require_permission("settings_view");
|
||||||
require_once __DIR__ . '/../db/config.php';
|
require_once __DIR__ . '/../db/config.php';
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . "/../includes/functions.php";
|
require_once __DIR__ . "/../includes/functions.php";
|
||||||
|
require_once __DIR__ . "/../db/config.php";
|
||||||
require_permission("settings_view");
|
require_permission("settings_view");
|
||||||
require_once __DIR__ . '/../db/config.php';
|
require_once __DIR__ . '/../db/config.php';
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . "/../includes/functions.php";
|
require_once __DIR__ . "/../includes/functions.php";
|
||||||
|
require_once __DIR__ . "/../db/config.php";
|
||||||
require_permission("expense_categories_view");
|
require_permission("expense_categories_view");
|
||||||
require_once __DIR__ . '/../db/config.php';
|
require_once __DIR__ . '/../db/config.php';
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . "/../includes/functions.php";
|
require_once __DIR__ . "/../includes/functions.php";
|
||||||
|
require_once __DIR__ . "/../db/config.php";
|
||||||
require_permission("settings_view");
|
require_permission("settings_view");
|
||||||
require_once __DIR__ . '/../db/config.php';
|
require_once __DIR__ . '/../db/config.php';
|
||||||
require_once __DIR__ . '/../includes/WablasService.php';
|
require_once __DIR__ . '/../includes/WablasService.php';
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . "/../includes/functions.php";
|
require_once __DIR__ . "/../includes/functions.php";
|
||||||
|
require_once __DIR__ . "/../db/config.php";
|
||||||
require_permission("loyalty_view");
|
require_permission("loyalty_view");
|
||||||
require_once __DIR__ . '/../db/config.php';
|
require_once __DIR__ . '/../db/config.php';
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
|
|||||||
@ -48,6 +48,7 @@ foreach ($items as $item) {
|
|||||||
|
|
||||||
$vat_or_discount = (float)$order['discount'];
|
$vat_or_discount = (float)$order['discount'];
|
||||||
$company_settings = get_company_settings();
|
$company_settings = get_company_settings();
|
||||||
|
$vat_rate = (float)($company_settings['vat_rate'] ?? 0);
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@ -192,18 +193,14 @@ $company_settings = get_company_settings();
|
|||||||
<tr>
|
<tr>
|
||||||
<td colspan="3" class="text-end py-3 ps-4">
|
<td colspan="3" class="text-end py-3 ps-4">
|
||||||
<div class="text-muted mb-1">Subtotal</div>
|
<div class="text-muted mb-1">Subtotal</div>
|
||||||
<?php if ($vat_or_discount != 0): ?>
|
<div class="text-muted mb-1"><?= ($vat_or_discount >= 0) ? "VAT ($vat_rate%)" : 'Discount' ?></div>
|
||||||
<div class="text-muted mb-1"><?= $vat_or_discount > 0 ? 'VAT' : 'Discount' ?></div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<h5 class="fw-bold mb-0 text-dark">Total Amount</h5>
|
<h5 class="fw-bold mb-0 text-dark">Total Amount</h5>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-end py-3 pe-4">
|
<td class="text-end py-3 pe-4">
|
||||||
<div class="mb-1"><?= format_currency($subtotal) ?></div>
|
<div class="mb-1"><?= format_currency($subtotal) ?></div>
|
||||||
<?php if ($vat_or_discount != 0): ?>
|
<div class="mb-1 <?= $vat_or_discount < 0 ? 'text-danger' : 'text-primary' ?>">
|
||||||
<div class="mb-1 <?= $vat_or_discount < 0 ? 'text-danger' : 'text-primary' ?>">
|
<?= ($vat_or_discount > 0 ? '+' : '') . format_currency($vat_or_discount) ?>
|
||||||
<?= ($vat_or_discount > 0 ? '+' : '') . format_currency($vat_or_discount) ?>
|
</div>
|
||||||
</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
<h5 class="fw-bold mb-0 text-primary"><?= format_currency($order['total_amount']) ?></h5>
|
<h5 class="fw-bold mb-0 text-primary"><?= format_currency($order['total_amount']) ?></h5>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -429,6 +426,7 @@ function printThermalReceipt() {
|
|||||||
|
|
||||||
const subtotal = data.total - data.vat;
|
const subtotal = data.total - data.vat;
|
||||||
const logoHtml = COMPANY_SETTINGS.logo_url ? `<img src="${BASE_URL}${COMPANY_SETTINGS.logo_url}" style="max-height: 80px; max-width: 150px; margin-bottom: 10px;">` : '';
|
const logoHtml = COMPANY_SETTINGS.logo_url ? `<img src="${BASE_URL}${COMPANY_SETTINGS.logo_url}" style="max-height: 80px; max-width: 150px; margin-bottom: 10px;">` : '';
|
||||||
|
const vatRate = COMPANY_SETTINGS.vat_rate || 0;
|
||||||
|
|
||||||
const html = `
|
const html = `
|
||||||
<html dir="ltr">
|
<html dir="ltr">
|
||||||
@ -523,11 +521,10 @@ function printThermalReceipt() {
|
|||||||
<td>Subtotal / ${tr['Subtotal']}</td>
|
<td>Subtotal / ${tr['Subtotal']}</td>
|
||||||
<td style="text-align: right">${formatCurrency(subtotal)}</td>
|
<td style="text-align: right">${formatCurrency(subtotal)}</td>
|
||||||
</tr>
|
</tr>
|
||||||
${Math.abs(data.vat) > 0 ? `
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>${data.vat < 0 ? 'Discount' : 'VAT'} / ${tr['VAT']}</td>
|
<td>${data.vat < 0 ? 'Discount' : 'VAT (' + vatRate + '%)'} / ${tr['VAT']}</td>
|
||||||
<td style="text-align: right">${data.vat < 0 ? '-' : '+'}${formatCurrency(Math.abs(data.vat))}</td>
|
<td style="text-align: right">${data.vat < 0 ? '-' : '+'}${formatCurrency(Math.abs(data.vat))}</td>
|
||||||
</tr>` : ''}
|
</tr>
|
||||||
<tr style="font-weight: bold; font-size: 18px;">
|
<tr style="font-weight: bold; font-size: 18px;">
|
||||||
<td style="padding-top: 10px;">TOTAL / ${tr['TOTAL']}</td>
|
<td style="padding-top: 10px;">TOTAL / ${tr['TOTAL']}</td>
|
||||||
<td style="text-align: right; padding-top: 10px;">${formatCurrency(data.total)}</td>
|
<td style="text-align: right; padding-top: 10px;">${formatCurrency(data.total)}</td>
|
||||||
@ -558,4 +555,4 @@ function printThermalReceipt() {
|
|||||||
win.document.write(html);
|
win.document.write(html);
|
||||||
win.document.close();
|
win.document.close();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . "/../includes/functions.php";
|
require_once __DIR__ . "/../includes/functions.php";
|
||||||
|
require_once __DIR__ . "/../db/config.php";
|
||||||
require_permission("outlets_view");
|
require_permission("outlets_view");
|
||||||
require_once __DIR__ . '/../db/config.php';
|
require_once __DIR__ . '/../db/config.php';
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . "/../includes/functions.php";
|
require_once __DIR__ . "/../includes/functions.php";
|
||||||
|
require_once __DIR__ . "/../db/config.php";
|
||||||
require_permission("payment_types_view");
|
require_permission("payment_types_view");
|
||||||
require_once __DIR__ . '/../db/config.php';
|
require_once __DIR__ . '/../db/config.php';
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . "/../includes/functions.php";
|
require_once __DIR__ . "/../includes/functions.php";
|
||||||
|
require_once __DIR__ . "/../db/config.php";
|
||||||
require_permission("purchases_view");
|
require_permission("purchases_view");
|
||||||
require_once __DIR__ . '/../db/config.php';
|
require_once __DIR__ . '/../db/config.php';
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . "/../includes/functions.php";
|
require_once __DIR__ . "/../includes/functions.php";
|
||||||
|
require_once __DIR__ . "/../db/config.php";
|
||||||
require_permission("ratings_view");
|
require_permission("ratings_view");
|
||||||
require_once __DIR__ . '/../db/config.php';
|
require_once __DIR__ . '/../db/config.php';
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . "/../includes/functions.php";
|
require_once __DIR__ . "/../includes/functions.php";
|
||||||
|
require_once __DIR__ . "/../db/config.php";
|
||||||
require_permission("suppliers_view");
|
require_permission("suppliers_view");
|
||||||
require_once __DIR__ . '/../db/config.php';
|
require_once __DIR__ . '/../db/config.php';
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
require_once __DIR__ . '/../db/config.php';
|
||||||
require_once __DIR__ . "/../includes/functions.php";
|
require_once __DIR__ . "/../includes/functions.php";
|
||||||
require_permission("tables_view");
|
require_permission("tables_view");
|
||||||
require_once __DIR__ . '/../db/config.php';
|
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
|
|
||||||
$message = '';
|
$message = '';
|
||||||
@ -206,7 +206,7 @@ $baseUrl = $protocol . $host . $project_root;
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||||
<button type="submit" class="btn btn-primary">Save Table</button>
|
<button type="submit" class="btn btn-primary">Save Table</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@ -217,76 +217,96 @@ $baseUrl = $protocol . $host . $project_root;
|
|||||||
|
|
||||||
<!-- QR Modal -->
|
<!-- QR Modal -->
|
||||||
<div class="modal fade" id="qrModal" tabindex="-1" aria-hidden="true">
|
<div class="modal fade" id="qrModal" tabindex="-1" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-sm">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title">Table QR Code</h5>
|
<h5 class="modal-title">Table QR Code</h5>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body text-center" id="printableQR">
|
<div class="modal-body text-center p-5">
|
||||||
<h4 class="fw-bold mb-3" id="qrTableNumber">Table</h4>
|
<h4 id="qrTableNumber" class="mb-4 fw-bold"></h4>
|
||||||
<div id="qrContainer" class="mb-3">
|
<div id="qrcode" class="mb-4 d-flex justify-content-center"></div>
|
||||||
<!-- QR Image will be loaded here -->
|
<p class="text-muted small">Scan this QR to order from this table</p>
|
||||||
|
<div class="d-grid gap-2">
|
||||||
|
<button type="button" class="btn btn-outline-primary" onclick="downloadQR()">
|
||||||
|
<i class="bi bi-download"></i> Download QR
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-outline-secondary" onclick="printQR()">
|
||||||
|
<i class="bi bi-printer"></i> Print
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<p class="small text-muted mb-0">Scan to Order</p>
|
|
||||||
<div class="mt-2 small text-break text-muted" id="qrLink" style="font-size: 0.7rem;"></div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer justify-content-center">
|
|
||||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
||||||
<button type="button" class="btn btn-primary" onclick="printQR()">
|
|
||||||
<i class="bi bi-printer"></i> Print
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
let qrGenerator = null;
|
||||||
|
const baseUrl = '<?= $baseUrl ?>';
|
||||||
|
|
||||||
function prepareAddForm() {
|
function prepareAddForm() {
|
||||||
document.getElementById('tableModalTitle').innerText = 'Add New Table';
|
document.getElementById('tableModalTitle').innerText = 'Add New Table';
|
||||||
document.getElementById('tableAction').value = 'add_table';
|
document.getElementById('tableAction').value = 'add_table';
|
||||||
document.getElementById('tableForm').reset();
|
|
||||||
document.getElementById('tableId').value = '';
|
document.getElementById('tableId').value = '';
|
||||||
|
document.getElementById('tableNumber').value = '';
|
||||||
|
document.getElementById('tableAreaId').value = '';
|
||||||
|
document.getElementById('tableCapacity').value = '2';
|
||||||
|
document.getElementById('tableStatus').value = 'available';
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareEditForm(table) {
|
function prepareEditForm(table) {
|
||||||
if (!table) return;
|
|
||||||
document.getElementById('tableModalTitle').innerText = 'Edit Table';
|
document.getElementById('tableModalTitle').innerText = 'Edit Table';
|
||||||
document.getElementById('tableAction').value = 'edit_table';
|
document.getElementById('tableAction').value = 'edit_table';
|
||||||
document.getElementById('tableId').value = table.id;
|
document.getElementById('tableId').value = table.id;
|
||||||
document.getElementById('tableNumber').value = table.table_number || '';
|
document.getElementById('tableNumber').value = table.table_number || '';
|
||||||
document.getElementById('tableAreaId').value = table.area_id || '';
|
document.getElementById('tableAreaId').value = table.area_id || '';
|
||||||
document.getElementById('tableCapacity').value = table.capacity || 2;
|
document.getElementById('tableCapacity').value = table.capacity || '2';
|
||||||
document.getElementById('tableStatus').value = table.status || 'available';
|
document.getElementById('tableStatus').value = table.status || 'available';
|
||||||
}
|
}
|
||||||
|
|
||||||
function showTableQR(id, number) {
|
function showTableQR(id, number) {
|
||||||
const baseUrl = '<?= $baseUrl ?>';
|
|
||||||
const qorderUrl = baseUrl + '/qorder.php?table_id=' + id;
|
|
||||||
const qrCodeUrl = "https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=" + encodeURIComponent(qorderUrl);
|
|
||||||
|
|
||||||
document.getElementById('qrTableNumber').innerText = 'Table ' + number;
|
document.getElementById('qrTableNumber').innerText = 'Table ' + number;
|
||||||
document.getElementById('qrContainer').innerHTML = '<img src="' + qrCodeUrl + '" alt="QR Code" class="img-fluid shadow-sm" style="max-width: 200px;">';
|
const qrContainer = document.getElementById('qrcode');
|
||||||
document.getElementById('qrLink').innerText = qorderUrl;
|
qrContainer.innerHTML = '';
|
||||||
|
|
||||||
const modal = new bootstrap.Modal(document.getElementById('qrModal'));
|
const url = baseUrl + '/qorder.php?table=' + id;
|
||||||
modal.show();
|
|
||||||
|
qrGenerator = new QRCode(qrContainer, {
|
||||||
|
text: url,
|
||||||
|
width: 256,
|
||||||
|
height: 256,
|
||||||
|
colorDark: "#000000",
|
||||||
|
colorLight: "#ffffff",
|
||||||
|
correctLevel: QRCode.CorrectLevel.H
|
||||||
|
});
|
||||||
|
|
||||||
|
new bootstrap.Modal(document.getElementById('qrModal')).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
function downloadQR() {
|
||||||
|
const img = document.querySelector('#qrcode img');
|
||||||
|
if (img) {
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.download = 'table-qr.png';
|
||||||
|
link.href = img.src;
|
||||||
|
link.click();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function printQR() {
|
function printQR() {
|
||||||
const content = document.getElementById('printableQR').innerHTML;
|
const img = document.querySelector('#qrcode img');
|
||||||
const printWindow = window.open('', '_blank');
|
if (!img) return;
|
||||||
printWindow.document.write('<html><head><title>Print Table QR</title>');
|
|
||||||
printWindow.document.write('<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">');
|
const win = window.open('', '_blank');
|
||||||
printWindow.document.write('<style>body { text-align: center; padding: 50px; }</style>');
|
win.document.write('<html><body style="text-align:center;padding:50px;">');
|
||||||
printWindow.document.write('</head><body>');
|
win.document.write('<h1>' + document.getElementById('qrTableNumber').innerText + '</h1>');
|
||||||
printWindow.document.write(content);
|
win.document.write('<img src="' + img.src + '" style="width:300px;">');
|
||||||
printWindow.document.write('</body></html>');
|
win.document.write('<p style="font-family:sans-serif;margin-top:20px;">Scan to Order</p>');
|
||||||
printWindow.document.close();
|
win.document.write('</body></html>');
|
||||||
setTimeout(() => {
|
win.document.close();
|
||||||
printWindow.print();
|
win.print();
|
||||||
printWindow.close();
|
win.close();
|
||||||
}, 500);
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . "/../includes/functions.php";
|
require_once __DIR__ . "/../includes/functions.php";
|
||||||
|
require_once __DIR__ . "/../db/config.php";
|
||||||
require_permission("user_groups_view");
|
require_permission("user_groups_view");
|
||||||
require_once __DIR__ . '/../db/config.php';
|
require_once __DIR__ . '/../db/config.php';
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . "/../includes/functions.php";
|
require_once __DIR__ . "/../includes/functions.php";
|
||||||
|
require_once __DIR__ . "/../db/config.php";
|
||||||
require_permission("users_view");
|
require_permission("users_view");
|
||||||
require_once __DIR__ . '/../db/config.php';
|
require_once __DIR__ . '/../db/config.php';
|
||||||
$pdo = db();
|
$pdo = db();
|
||||||
|
|||||||
@ -467,7 +467,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
const statusClass = table.is_occupied ? "btn-outline-danger" : "btn-outline-success";
|
const statusClass = table.is_occupied ? "btn-outline-danger" : "btn-outline-success";
|
||||||
col.innerHTML = `
|
col.innerHTML = `
|
||||||
<button class=\"btn ${statusClass} w-100 py-3 rounded-3 position-relative\" onclick=\"selectTable(${table.id}, '${table.name}')\">
|
<button class=\"btn ${statusClass} w-100 py-3 rounded-3 position-relative\" onclick=\"selectTable(${table.id}, '${table.name}')\">
|
||||||
<div class=\"fw-bold\">${table.name}</div>
|
<div class=\"fw-bold">${table.name}</div>
|
||||||
<div class=\"small\" style=\"font-size: 0.7rem;\">Cap: ${table.capacity}</div>
|
<div class=\"small\" style=\"font-size: 0.7rem;\">Cap: ${table.capacity}</div>
|
||||||
${table.is_occupied ? '<span class="position-absolute top-0 start-100 translate-middle p-1 bg-danger border border-light rounded-circle" title="Occupied"></span>' : ''}
|
${table.is_occupied ? '<span class="position-absolute top-0 start-100 translate-middle p-1 bg-danger border border-light rounded-circle" title="Occupied"></span>' : ''}
|
||||||
</button>
|
</button>
|
||||||
@ -516,7 +516,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
price: parseFloat(product.price), base_price: parseFloat(product.price),
|
price: parseFloat(product.price), base_price: parseFloat(product.price),
|
||||||
hasVariants: false, quantity: 1, variant_id: null, variant_name: null,
|
hasVariants: false, quantity: 1, variant_id: null, variant_name: null,
|
||||||
is_loyalty: parseInt(product.is_loyalty) === 1,
|
is_loyalty: parseInt(product.is_loyalty) === 1,
|
||||||
vat_percent: parseFloat(product.vat_percent || 0)
|
vat_percent: parseFloat(product.vat_percent || settings.vat_rate || 0)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -540,7 +540,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
price: finalPrice, base_price: parseFloat(product.price),
|
price: finalPrice, base_price: parseFloat(product.price),
|
||||||
hasVariants: true, quantity: 1, variant_id: v.id, variant_name: v.name,
|
hasVariants: true, quantity: 1, variant_id: v.id, variant_name: v.name,
|
||||||
is_loyalty: parseInt(product.is_loyalty) === 1,
|
is_loyalty: parseInt(product.is_loyalty) === 1,
|
||||||
vat_percent: parseFloat(product.vat_percent || 0)
|
vat_percent: parseFloat(product.vat_percent || settings.vat_rate || 0)
|
||||||
});
|
});
|
||||||
variantSelectionModal.hide();
|
variantSelectionModal.hide();
|
||||||
};
|
};
|
||||||
@ -587,7 +587,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
cartItemsContainer.innerHTML = `<div class="text-center text-muted mt-5"><i class="bi bi-basket3 fs-1 text-light"></i><p class="mt-2">${_t('cart_empty')}</p></div>`;
|
cartItemsContainer.innerHTML = `<div class="text-center text-muted mt-5"><i class="bi bi-basket3 fs-1 text-light"></i><p class="mt-2">${_t('cart_empty')}</p></div>`;
|
||||||
if (cartSubtotal) cartSubtotal.innerText = formatCurrency(0);
|
if (cartSubtotal) cartSubtotal.innerText = formatCurrency(0);
|
||||||
if (cartVatAmount) cartVatAmount.innerText = formatCurrency(0);
|
if (cartVatAmount) cartVatAmount.innerText = formatCurrency(0);
|
||||||
if (cartVatRow) cartVatRow.classList.add('d-none');
|
// Always show VAT row even if 0
|
||||||
|
if (cartVatRow) cartVatRow.classList.remove('d-none');
|
||||||
if (cartTotalPrice) cartTotalPrice.innerText = formatCurrency(0);
|
if (cartTotalPrice) cartTotalPrice.innerText = formatCurrency(0);
|
||||||
if (quickOrderBtn) { quickOrderBtn.disabled = true; quickOrderBtn.innerText = _t('quick_pay'); }
|
if (quickOrderBtn) { quickOrderBtn.disabled = true; quickOrderBtn.innerText = _t('quick_pay'); }
|
||||||
if (placeOrderBtn) { placeOrderBtn.disabled = true; placeOrderBtn.innerText = _t('save_bill'); }
|
if (placeOrderBtn) { placeOrderBtn.disabled = true; placeOrderBtn.innerText = _t('save_bill'); }
|
||||||
@ -629,10 +630,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
if (cartSubtotal) cartSubtotal.innerText = formatCurrency(subtotal);
|
if (cartSubtotal) cartSubtotal.innerText = formatCurrency(subtotal);
|
||||||
if (cartVatAmount) cartVatAmount.innerText = formatCurrency(totalVat);
|
if (cartVatAmount) cartVatAmount.innerText = formatCurrency(totalVat);
|
||||||
if (cartVatRow) {
|
// Always show VAT row
|
||||||
if (totalVat > 0) cartVatRow.classList.remove('d-none');
|
if (cartVatRow) cartVatRow.classList.remove('d-none');
|
||||||
else cartVatRow.classList.add('d-none');
|
|
||||||
}
|
|
||||||
if (cartVatInput) cartVatInput.value = totalVat.toFixed(3);
|
if (cartVatInput) cartVatInput.value = totalVat.toFixed(3);
|
||||||
|
|
||||||
const total = subtotal + totalVat;
|
const total = subtotal + totalVat;
|
||||||
@ -805,6 +804,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
const loyaltyHtml = data.loyaltyRedeemed ? `<div style="color: #d63384; font-weight: bold; margin: 5px 0; text-align: center;">* Loyalty Reward Applied *</div>` : '';
|
const loyaltyHtml = data.loyaltyRedeemed ? `<div style="color: #d63384; font-weight: bold; margin: 5px 0; text-align: center;">* Loyalty Reward Applied *</div>` : '';
|
||||||
|
|
||||||
const logoHtml = settings.logo_url ? `<img src="${BASE_URL}${settings.logo_url}" style="max-height: 80px; max-width: 150px; margin-bottom: 10px;">` : '';
|
const logoHtml = settings.logo_url ? `<img src="${BASE_URL}${settings.logo_url}" style="max-height: 80px; max-width: 150px; margin-bottom: 10px;">` : '';
|
||||||
|
|
||||||
|
const vatRate = settings.vat_rate || 0;
|
||||||
|
|
||||||
const html = `
|
const html = `
|
||||||
<html dir="ltr">
|
<html dir="ltr">
|
||||||
@ -860,7 +861,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
<div class="totals">
|
<div class="totals">
|
||||||
<table style="width: 100%">
|
<table style="width: 100%">
|
||||||
<tr><td>Subtotal / ${tr['Subtotal']}</td><td style="text-align: right">${formatCurrency(data.subtotal)}</td></tr>
|
<tr><td>Subtotal / ${tr['Subtotal']}</td><td style="text-align: right">${formatCurrency(data.subtotal)}</td></tr>
|
||||||
${Math.abs(data.vat) > 0 ? `<tr><td>VAT / ${tr['VAT']}</td><td style="text-align: right">${formatCurrency(Math.abs(data.vat))}</td></tr>` : ''}
|
<tr><td>VAT (${vatRate}%) / ${tr['VAT']}</td><td style="text-align: right">${formatCurrency(Math.abs(data.vat))}</td></tr>
|
||||||
<tr style="font-weight: bold; font-size: 18px;"><td style="padding-top: 10px;">TOTAL / ${tr['TOTAL']}</td><td style="text-align: right; padding-top: 10px;">${formatCurrency(data.total)}</td></tr>
|
<tr style="font-weight: bold; font-size: 18px;"><td style="padding-top: 10px;">TOTAL / ${tr['TOTAL']}</td><td style="text-align: right; padding-top: 10px;">${formatCurrency(data.total)}</td></tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
@ -889,4 +890,4 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
const modal = new bootstrap.Modal(document.getElementById('qrRatingModal'));
|
const modal = new bootstrap.Modal(document.getElementById('qrRatingModal'));
|
||||||
modal.show();
|
modal.show();
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
45
db/migrate.php
Normal file
45
db/migrate.php
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/config.php';
|
||||||
|
$pdo = db();
|
||||||
|
|
||||||
|
// Ensure migrations table exists
|
||||||
|
$pdo->exec("CREATE TABLE IF NOT EXISTS migrations (
|
||||||
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
migration_name VARCHAR(255) NOT NULL UNIQUE,
|
||||||
|
applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
)");
|
||||||
|
|
||||||
|
$migrations_folder = array_diff(scandir(__DIR__ . '/migrations'), ['.', '..']);
|
||||||
|
sort($migrations_folder);
|
||||||
|
|
||||||
|
$applied_migrations = $pdo->query("SELECT migration_name FROM migrations")->fetchAll(PDO::FETCH_COLUMN);
|
||||||
|
|
||||||
|
foreach ($migrations_folder as $migration) {
|
||||||
|
if (!in_array($migration, $applied_migrations)) {
|
||||||
|
echo "Applying migration: $migration\n";
|
||||||
|
$sql = file_get_contents(__DIR__ . '/migrations/' . $migration);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (!empty(trim($sql))) {
|
||||||
|
$pdo->exec($sql);
|
||||||
|
}
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO migrations (migration_name) VALUES (?)");
|
||||||
|
$stmt->execute([$migration]);
|
||||||
|
echo "Successfully applied $migration\n";
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo "Error applying $migration: " . $e->getMessage() . "\n";
|
||||||
|
// If it's a "Duplicate column name" error, we can assume it was applied manually and just record it
|
||||||
|
if (strpos($e->getMessage(), 'Duplicate column name') !== false || strpos($e->getMessage(), 'already exists') !== false) {
|
||||||
|
echo "Column/Table already exists, recording as applied.\n";
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO migrations (migration_name) VALUES (?)");
|
||||||
|
$stmt->execute([$migration]);
|
||||||
|
} else {
|
||||||
|
// For other errors, we might want to stop or continue
|
||||||
|
echo "Stopping migrations due to error.\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo "Migration process finished.\n";
|
||||||
|
|
||||||
@ -108,6 +108,7 @@ function t($key, $lang = null) {
|
|||||||
'orders' => 'Orders',
|
'orders' => 'Orders',
|
||||||
'kitchen' => 'Kitchen',
|
'kitchen' => 'Kitchen',
|
||||||
'switch' => 'Switch',
|
'switch' => 'Switch',
|
||||||
|
'are_you_sure' => 'Are you sure?',
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
4
pos.php
4
pos.php
@ -75,6 +75,8 @@ $loyalty_settings = $loyalty_stmt->fetch(PDO::FETCH_ASSOC);
|
|||||||
if (!$loyalty_settings) {
|
if (!$loyalty_settings) {
|
||||||
$loyalty_settings = ['is_enabled' => 0, 'points_per_order' => 0, 'points_for_free_meal' => 0];
|
$loyalty_settings = ['is_enabled' => 0, 'points_per_order' => 0, 'points_for_free_meal' => 0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$vat_rate = (float)($settings['vat_rate'] ?? 0);
|
||||||
?>
|
?>
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en" dir="ltr">
|
<html lang="en" dir="ltr">
|
||||||
@ -327,7 +329,7 @@ if (!$loyalty_settings) {
|
|||||||
<span class="fw-bold small" id="cart-subtotal"><?= format_currency(0) ?></span>
|
<span class="fw-bold small" id="cart-subtotal"><?= format_currency(0) ?></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex justify-content-between mb-1" id="cart-vat-row">
|
<div class="d-flex justify-content-between mb-1" id="cart-vat-row">
|
||||||
<span class="text-muted small">VAT</span>
|
<span class="text-muted small">VAT (<?= $vat_rate ?>%)</span>
|
||||||
<span class="fw-bold small" id="cart-vat-amount"><?= format_currency(0) ?></span>
|
<span class="fw-bold small" id="cart-vat-amount"><?= format_currency(0) ?></span>
|
||||||
<input type="hidden" id="cart-vat-input" value="0">
|
<input type="hidden" id="cart-vat-input" value="0">
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
1269
storage/backups/backup_2026-02-26_18-54-32.sql
Normal file
1269
storage/backups/backup_2026-02-26_18-54-32.sql
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user