Fix barcode direct print

parent 69e46405
...@@ -4291,6 +4291,10 @@ def get_cashier_bets(): ...@@ -4291,6 +4291,10 @@ def get_cashier_bets():
else: else:
target_date = date.today() target_date = date.today()
# Get filter parameters
status_filter = request.args.get('status', '').strip()
match_number_filter = request.args.get('match_number', '').strip()
session = api_bp.db_manager.get_session() session = api_bp.db_manager.get_session()
try: try:
# Import models # Import models
...@@ -4326,6 +4330,17 @@ def get_cashier_bets(): ...@@ -4326,6 +4330,17 @@ def get_cashier_bets():
BetModel.bet_datetime <= end_datetime BetModel.bet_datetime <= end_datetime
).order_by(BetModel.bet_datetime.desc()) ).order_by(BetModel.bet_datetime.desc())
# Apply match number filter if specified
if match_number_filter:
try:
match_number = int(match_number_filter)
# Filter bets that have details for the specified match number
bets_query = bets_query.join(BetDetailModel).join(MatchModel).filter(
MatchModel.match_number == match_number
).distinct()
except ValueError:
return jsonify({"error": "Invalid match number format"}), 400
bets = bets_query.all() bets = bets_query.all()
logger.info(f"Found {len(bets)} bets in database for date {date_param}") logger.info(f"Found {len(bets)} bets in database for date {date_param}")
bets_data = [] bets_data = []
...@@ -4347,13 +4362,14 @@ def get_cashier_bets(): ...@@ -4347,13 +4362,14 @@ def get_cashier_bets():
# Calculate total amount for this bet # Calculate total amount for this bet
bet_total = sum(float(detail.amount) for detail in bet_details) bet_total = sum(float(detail.amount) for detail in bet_details)
bet_data['total_amount'] = bet_total bet_data['total_amount'] = bet_total
total_amount += bet_total
# Determine overall bet status for statistics using same logic as bet details page # Determine overall bet status for filtering and statistics using same logic as bet details page
overall_status = 'pending'
if bet_details: if bet_details:
won_count = 0 won_count = 0
lost_count = 0 lost_count = 0
pending_count = 0 pending_count = 0
cancelled_count = 0
for detail in bet_details: for detail in bet_details:
# Get match information for winning check # Get match information for winning check
...@@ -4366,14 +4382,31 @@ def get_cashier_bets(): ...@@ -4366,14 +4382,31 @@ def get_cashier_bets():
elif detail.result == 'pending': elif detail.result == 'pending':
pending_count += 1 pending_count += 1
elif detail.result == 'cancelled': elif detail.result == 'cancelled':
lost_count += 1 # Treat cancelled as lost for statistics cancelled_count += 1
if won_count > 0 and lost_count == 0 and pending_count == 0: # Determine overall status
won_bets += 1 if pending_count > 0:
elif lost_count > 0: overall_status = 'pending'
lost_bets += 1 elif won_count > 0 and lost_count == 0 and cancelled_count == 0:
else: overall_status = 'won'
pending_bets += 1 elif lost_count > 0 or cancelled_count > 0:
overall_status = 'lost'
elif cancelled_count > 0:
overall_status = 'cancelled'
bet_data['overall_status'] = overall_status
# Apply status filter if specified
if status_filter and status_filter != overall_status:
continue # Skip this bet if it doesn't match the status filter
total_amount += bet_total
# Update statistics counters
if overall_status == 'won':
won_bets += 1
elif overall_status == 'lost':
lost_bets += 1
else: else:
pending_bets += 1 pending_bets += 1
......
...@@ -330,13 +330,7 @@ body { ...@@ -330,13 +330,7 @@ body {
} }
} }
/* Dark mode support (future enhancement) */ /* Dark mode support disabled - forced light mode */
@media (prefers-color-scheme: dark) {
:root {
--bs-body-bg: #1a1a1a;
--bs-body-color: #f8f9fa;
}
}
/* Loading states */ /* Loading states */
.loading { .loading {
......
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en" data-bs-theme="light">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
......
...@@ -47,21 +47,34 @@ ...@@ -47,21 +47,34 @@
<div class="card mb-4"> <div class="card mb-4">
<div class="card-header"> <div class="card-header">
<div class="row"> <div class="row">
<div class="col-md-8"> <div class="col-md-4">
<h5 class="card-title mb-0"> <h5 class="card-title mb-0">
<i class="fas fa-calendar-alt me-2"></i>Bets for Today <i class="fas fa-calendar-alt me-2"></i>Bets for Today
<span class="badge bg-info ms-2" id="bets-count">0</span> <span class="badge bg-info ms-2" id="bets-count">0</span>
</h5> </h5>
</div> </div>
<div class="col-md-4"> <div class="col-md-2">
<div class="input-group"> <div class="input-group">
<span class="input-group-text"> <span class="input-group-text">
<i class="fas fa-calendar"></i> <i class="fas fa-calendar"></i>
</span> </span>
<input type="date" class="form-control" id="bet-date-picker" <input type="date" class="form-control" id="bet-date-picker"
value="{{ today_date }}" max="{{ today_date }}"> value="{{ today_date }}" max="{{ today_date }}">
</div> </div>
</div> </div>
<div class="col-md-3">
<select class="form-select" id="bet-status-filter">
<option value="">All Status</option>
<option value="won">Won</option>
<option value="lost">Lost</option>
<option value="pending">Pending</option>
<option value="cancelled">Cancelled</option>
</select>
</div>
<div class="col-md-3">
<input type="number" class="form-control" id="match-number-filter"
placeholder="Match # (optional)" min="1">
</div>
</div> </div>
</div> </div>
<div class="card-body"> <div class="card-body">
...@@ -331,6 +344,16 @@ document.addEventListener('DOMContentLoaded', function() { ...@@ -331,6 +344,16 @@ document.addEventListener('DOMContentLoaded', function() {
loadBets(); loadBets();
}); });
// Status filter change event
document.getElementById('bet-status-filter').addEventListener('change', function() {
loadBets();
});
// Match number filter change event
document.getElementById('match-number-filter').addEventListener('input', function() {
loadBets();
});
// New bet button // New bet button
document.getElementById('btn-new-bet').addEventListener('click', function() { document.getElementById('btn-new-bet').addEventListener('click', function() {
window.location.href = '/bets/new'; window.location.href = '/bets/new';
...@@ -398,14 +421,23 @@ function loadBets() { ...@@ -398,14 +421,23 @@ function loadBets() {
const container = document.getElementById('bets-container'); const container = document.getElementById('bets-container');
const countBadge = document.getElementById('bets-count'); const countBadge = document.getElementById('bets-count');
const dateInput = document.getElementById('bet-date-picker'); const dateInput = document.getElementById('bet-date-picker');
const statusFilter = document.getElementById('bet-status-filter');
const matchFilter = document.getElementById('match-number-filter');
const selectedDate = dateInput.value; const selectedDate = dateInput.value;
const selectedStatus = statusFilter.value;
const selectedMatch = matchFilter.value;
if (!container) { if (!container) {
console.error('❌ bets-container not found'); console.error('❌ bets-container not found');
return; return;
} }
console.log('📡 Making API request to /api/cashier/bets for date:', selectedDate); console.log('📡 Making API request to /api/cashier/bets with filters:', {
date: selectedDate,
status: selectedStatus,
match: selectedMatch
});
// Show loading state // Show loading state
container.innerHTML = ` container.innerHTML = `
...@@ -414,7 +446,16 @@ function loadBets() { ...@@ -414,7 +446,16 @@ function loadBets() {
</div> </div>
`; `;
fetch(`/api/cashier/bets?date=${selectedDate}`) // Build query string with filters
let queryParams = `date=${selectedDate}`;
if (selectedStatus) {
queryParams += `&status=${selectedStatus}`;
}
if (selectedMatch) {
queryParams += `&match_number=${selectedMatch}`;
}
fetch(`/api/cashier/bets?${queryParams}`)
.then(response => { .then(response => {
console.log('📡 API response status:', response.status); console.log('📡 API response status:', response.status);
if (!response.ok) { if (!response.ok) {
......
...@@ -839,28 +839,33 @@ function generateVerificationCodes(betUuid) { ...@@ -839,28 +839,33 @@ function generateVerificationCodes(betUuid) {
.then(settings => { .then(settings => {
if (settings.success && settings.settings && settings.settings.show_on_thermal) { if (settings.success && settings.settings && settings.settings.show_on_thermal) {
// Generate barcode image using the saved barcode data // Generate barcode image using the saved barcode data
fetch(`/api/barcode/${betUuid}`) return fetch(`/api/barcode/${betUuid}`)
.then(response => response.blob()) .then(response => response.blob())
.then(blob => { .then(blob => {
const reader = new FileReader(); return new Promise((resolve) => {
reader.onload = function() { const reader = new FileReader();
const base64 = reader.result; reader.onload = function() {
// Add barcode to receipt const base64 = reader.result;
const barcodeHtml = ` // Add barcode to receipt
<div class="receipt-barcode" id="barcode-container-${betUuid}"> const barcodeHtml = `
<div class="barcode-image" id="barcode-${betUuid}"></div> <div class="receipt-barcode" id="barcode-container-${betUuid}">
<div class="barcode-text">Scan barcode for verification</div> <div class="barcode-image" id="barcode-${betUuid}"></div>
</div> <div class="barcode-text">Scan barcode for verification</div>
`; </div>
verificationContainer.insertAdjacentHTML('beforeend', barcodeHtml); `;
verificationContainer.insertAdjacentHTML('beforeend', barcodeHtml);
// Display barcode
const barcodeElement = document.getElementById(`barcode-${betUuid}`); // Display barcode
if (barcodeElement) { const barcodeElement = document.getElementById(`barcode-${betUuid}`);
barcodeElement.innerHTML = `<img src="${base64}" alt="Barcode" class="barcode-img" style="width: 200px; height: 100px;">`; if (barcodeElement) {
} barcodeElement.innerHTML = `<img src="${base64}" alt="Barcode" class="barcode-img" style="width: 200px; height: 100px;">`;
}; }
reader.readAsDataURL(blob); resolve();
};
reader.readAsDataURL(blob);
});
})
.then(() => {
checkComplete(); checkComplete();
}) })
.catch(error => { .catch(error => {
......
...@@ -47,21 +47,34 @@ ...@@ -47,21 +47,34 @@
<div class="card mb-4"> <div class="card mb-4">
<div class="card-header"> <div class="card-header">
<div class="row"> <div class="row">
<div class="col-md-8"> <div class="col-md-4">
<h5 class="card-title mb-0"> <h5 class="card-title mb-0">
<i class="fas fa-calendar-alt me-2"></i>Bets for Today <i class="fas fa-calendar-alt me-2"></i>Bets for Today
<span class="badge bg-info ms-2" id="bets-count">0</span> <span class="badge bg-info ms-2" id="bets-count">0</span>
</h5> </h5>
</div> </div>
<div class="col-md-4"> <div class="col-md-2">
<div class="input-group"> <div class="input-group">
<span class="input-group-text"> <span class="input-group-text">
<i class="fas fa-calendar"></i> <i class="fas fa-calendar"></i>
</span> </span>
<input type="date" class="form-control" id="bet-date-picker" <input type="date" class="form-control" id="bet-date-picker"
value="{{ today_date }}" max="{{ today_date }}"> value="{{ today_date }}" max="{{ today_date }}">
</div> </div>
</div> </div>
<div class="col-md-3">
<select class="form-select" id="bet-status-filter">
<option value="">All Status</option>
<option value="won">Won</option>
<option value="lost">Lost</option>
<option value="pending">Pending</option>
<option value="cancelled">Cancelled</option>
</select>
</div>
<div class="col-md-3">
<input type="number" class="form-control" id="match-number-filter"
placeholder="Match # (optional)" min="1">
</div>
</div> </div>
</div> </div>
<div class="card-body"> <div class="card-body">
...@@ -328,6 +341,16 @@ document.addEventListener('DOMContentLoaded', function() { ...@@ -328,6 +341,16 @@ document.addEventListener('DOMContentLoaded', function() {
loadBets(); loadBets();
}); });
// Status filter change event
document.getElementById('bet-status-filter').addEventListener('change', function() {
loadBets();
});
// Match number filter change event
document.getElementById('match-number-filter').addEventListener('input', function() {
loadBets();
});
// New bet button // New bet button
document.getElementById('btn-new-bet').addEventListener('click', function() { document.getElementById('btn-new-bet').addEventListener('click', function() {
window.location.href = '/cashier/bets/new'; window.location.href = '/cashier/bets/new';
...@@ -398,14 +421,23 @@ function loadBets() { ...@@ -398,14 +421,23 @@ function loadBets() {
const container = document.getElementById('bets-container'); const container = document.getElementById('bets-container');
const countBadge = document.getElementById('bets-count'); const countBadge = document.getElementById('bets-count');
const dateInput = document.getElementById('bet-date-picker'); const dateInput = document.getElementById('bet-date-picker');
const statusFilter = document.getElementById('bet-status-filter');
const matchFilter = document.getElementById('match-number-filter');
const selectedDate = dateInput.value; const selectedDate = dateInput.value;
const selectedStatus = statusFilter.value;
const selectedMatch = matchFilter.value;
if (!container) { if (!container) {
console.error('❌ bets-container not found'); console.error('❌ bets-container not found');
return; return;
} }
console.log('📡 Making API request to /api/cashier/bets for date:', selectedDate); console.log('📡 Making API request to /api/cashier/bets with filters:', {
date: selectedDate,
status: selectedStatus,
match: selectedMatch
});
// Show loading state // Show loading state
container.innerHTML = ` container.innerHTML = `
...@@ -414,7 +446,16 @@ function loadBets() { ...@@ -414,7 +446,16 @@ function loadBets() {
</div> </div>
`; `;
fetch(`/api/cashier/bets?date=${selectedDate}`) // Build query string with filters
let queryParams = `date=${selectedDate}`;
if (selectedStatus) {
queryParams += `&status=${selectedStatus}`;
}
if (selectedMatch) {
queryParams += `&match_number=${selectedMatch}`;
}
fetch(`/api/cashier/bets?${queryParams}`)
.then(response => { .then(response => {
console.log('📡 API response status:', response.status); console.log('📡 API response status:', response.status);
if (!response.ok) { if (!response.ok) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment