0 total for loyalty

This commit is contained in:
Flatlogic Bot 2026-02-27 07:01:59 +00:00
parent 9b31c32aba
commit a7bd1b142a
3 changed files with 53 additions and 30 deletions

View File

@ -46,7 +46,8 @@ foreach ($items as $item) {
$subtotal += $item['unit_price'] * $item['quantity']; $subtotal += $item['unit_price'] * $item['quantity'];
} }
$vat_or_discount = (float)$order['discount']; $vat_amount = (float)($order['vat'] ?? 0);
$discount_amount = (float)($order['discount'] ?? 0);
$company_settings = get_company_settings(); $company_settings = get_company_settings();
$vat_rate = (float)($company_settings['vat_rate'] ?? 0); $vat_rate = (float)($company_settings['vat_rate'] ?? 0);
?> ?>
@ -191,16 +192,24 @@ $vat_rate = (float)($company_settings['vat_rate'] ?? 0);
</tbody> </tbody>
<tfoot class="bg-light"> <tfoot class="bg-light">
<tr> <tr>
<td colspan="3" class="text-end py-3 ps-4"> <td colspan="3" class="text-end py-3 ps-4 border-0">
<div class="text-muted mb-1">Subtotal</div> <div class="text-muted mb-1 small">Subtotal</div>
<div class="text-muted mb-1"><?= ($vat_or_discount >= 0) ? "VAT ($vat_rate%)" : 'Discount' ?></div> <?php if ($vat_amount > 0): ?>
<div class="text-muted mb-1 small">VAT</div>
<?php endif; ?>
<?php if ($discount_amount > 0): ?>
<div class="text-muted mb-1 small">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 border-0">
<div class="mb-1"><?= format_currency($subtotal) ?></div> <div class="mb-1 small"><?= format_currency($subtotal) ?></div>
<div class="mb-1 <?= $vat_or_discount < 0 ? 'text-danger' : 'text-primary' ?>"> <?php if ($vat_amount > 0): ?>
<?= ($vat_or_discount > 0 ? '+' : '') . format_currency($vat_or_discount) ?> <div class="mb-1 small text-primary">+<?= format_currency($vat_amount) ?></div>
</div> <?php endif; ?>
<?php if ($discount_amount > 0): ?>
<div class="mb-1 small text-danger">-<?= format_currency($discount_amount) ?></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>
@ -343,12 +352,13 @@ function printThermalReceipt() {
]; ];
}, $items)) ?>, }, $items)) ?>,
total: <?= (float)$order['total_amount'] ?>, total: <?= (float)$order['total_amount'] ?>,
vat: <?= (float)$order['discount'] ?>, vat: <?= (float)$order['vat'] ?>,
discount: <?= (float)$order['discount'] ?>,
orderType: '<?= $order['order_type'] ?>', orderType: '<?= $order['order_type'] ?>',
tableNumber: '<?= $order['table_number'] ?>', tableNumber: '<?= $order['table_number'] ?>',
date: '<?= date('M d, Y H:i', strtotime($order['created_at'])) ?>', date: '<?= date('M d, Y H:i', strtotime($order['created_at'])) ?>',
paymentMethod: '<?= $order['payment_type_name'] ?? 'Unpaid' ?>', paymentMethod: '<?= $order['payment_type_name'] ?? 'Unpaid' ?>',
loyaltyRedeemed: <?= ($order['discount'] < 0) ? 'true' : 'false' ?> loyaltyRedeemed: <?= ($order['payment_type_name'] === 'Loyalty Redeem' || (float)$order['total_amount'] <= 0) ? 'true' : 'false' ?>
}; };
const width = 400; const width = 400;
@ -424,7 +434,6 @@ function printThermalReceipt() {
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 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 vatRate = COMPANY_SETTINGS.vat_rate || 0;
@ -519,12 +528,18 @@ function printThermalReceipt() {
<table style="width: 100%"> <table style="width: 100%">
<tr> <tr>
<td>Subtotal / ${tr['Subtotal']}</td> <td>Subtotal / ${tr['Subtotal']}</td>
<td style="text-align: right">${formatCurrency(subtotal)}</td> <td style="text-align: right">${formatCurrency(data.items.reduce((acc, i) => acc + (i.price * i.quantity), 0))}</td>
</tr> </tr>
${data.vat > 0 ? `
<tr> <tr>
<td>${data.vat < 0 ? 'Discount' : 'VAT (' + vatRate + '%)'} / ${tr['VAT']}</td> <td>VAT (${vatRate}%) / ${tr['VAT']}</td>
<td style="text-align: right">${data.vat < 0 ? '-' : '+'}${formatCurrency(Math.abs(data.vat))}</td> <td style="text-align: right">+${formatCurrency(data.vat)}</td>
</tr> </tr>` : ''}
${data.discount > 0 ? `
<tr>
<td>Discount / الخصم</td>
<td style="text-align: right">-${formatCurrency(data.discount)}</td>
</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>

View File

@ -169,9 +169,11 @@ try {
$total_loyalty_qty = 0; $total_loyalty_qty = 0;
foreach ($processed_items as $item) { foreach ($processed_items as $item) {
if ($item['is_loyalty']) { // Safety check: Redemption orders should only contain loyalty items as per JS logic
$total_loyalty_qty += $item['quantity']; if (!$item['is_loyalty']) {
throw new Exception("Loyalty redemption orders can only contain loyalty-eligible products. Please remove non-eligible items.");
} }
$total_loyalty_qty += $item['quantity'];
} }
$possible_redemptions = floor($current_points / $points_threshold); $possible_redemptions = floor($current_points / $points_threshold);
@ -266,6 +268,12 @@ try {
$final_total = max(0, $calculated_subtotal + $calculated_vat); $final_total = max(0, $calculated_subtotal + $calculated_vat);
// Explicitly ensure loyalty redemption orders have 0 total
if ($redeem_loyalty) {
$final_total = 0;
$calculated_vat = 0;
}
// User/Payment info // User/Payment info
$user = get_logged_user(); $user = get_logged_user();
$user_id = $user ? $user['id'] : null; $user_id = $user ? $user['id'] : null;

View File

@ -697,8 +697,8 @@ document.addEventListener('DOMContentLoaded', () => {
customer_id: selectedCustomerId ? selectedCustomerId.value : null, customer_id: selectedCustomerId ? selectedCustomerId.value : null,
outlet_id: CURRENT_OUTLET ? CURRENT_OUTLET.id : 1, outlet_id: CURRENT_OUTLET ? CURRENT_OUTLET.id : 1,
payment_type_id: paymentTypeId, payment_type_id: paymentTypeId,
total_amount: subtotal + totalVat, total_amount: isLoyaltyRedemption ? 0 : (subtotal + totalVat), // If loyalty redeemed, total is 0 for this transaction
vat: totalVat, vat: isLoyaltyRedemption ? 0 : totalVat,
items: itemsData, items: itemsData,
redeem_loyalty: isLoyaltyRedemption redeem_loyalty: isLoyaltyRedemption
}; };
@ -711,17 +711,17 @@ document.addEventListener('DOMContentLoaded', () => {
name: item.name, name: item.name,
variant_name: item.variant_name, variant_name: item.variant_name,
quantity: item.quantity, quantity: item.quantity,
price: item.price, price: isLoyaltyRedemption ? 0 : item.price, // If loyalty redeemed, price is 0 for this transaction
vat_percent: item.vat_percent, vat_percent: isLoyaltyRedemption ? 0 : item.vat_percent,
vat_amount: (item.price * item.quantity) * (item.vat_percent / 100) vat_amount: isLoyaltyRedemption ? 0 : ((item.price * item.quantity) * (item.vat_percent / 100))
})), })),
subtotal: subtotal, subtotal: isLoyaltyRedemption ? 0 : subtotal,
total: subtotal + totalVat, total: isLoyaltyRedemption ? 0 : (subtotal + totalVat),
vat: totalVat, vat: isLoyaltyRedemption ? 0 : totalVat,
orderType: orderType, orderType: orderType,
tableNumber: (orderType === 'dine-in') ? currentTableName : null, tableNumber: (orderType === 'dine-in') ? currentTableName : null,
date: new Date().toLocaleString('en-US', { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }), date: new Date().toLocaleString('en-US', { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }),
paymentMethod: paymentTypeName || 'Unpaid', paymentMethod: paymentTypeName || (isLoyaltyRedemption ? 'Loyalty Redeem' : 'Unpaid'),
loyaltyRedeemed: isLoyaltyRedemption loyaltyRedeemed: isLoyaltyRedemption
}; };