* fixed extracion outcomes filtering

 * print now is automatically on bet insertion
parent 4d8fb1f1
...@@ -1289,34 +1289,53 @@ class GamesThread(ThreadedComponent): ...@@ -1289,34 +1289,53 @@ class GamesThread(ThreadedComponent):
return None return None
def _initialize_new_fixture(self) -> Optional[str]: def _initialize_new_fixture(self) -> Optional[str]:
"""Initialize a new fixture by finding the first one with no start_time set, or create one from old matches""" """Initialize a new fixture by finding the first one where ALL matches have start_time NULL or today, or create one from old matches"""
try: try:
session = self.db_manager.get_session() session = self.db_manager.get_session()
try: try:
# First, try to find the first fixture with no start_time set # Get today's date in UTC (consistent with database storage)
fixtures_no_start_time = session.query(MatchModel.fixture_id).filter( today = self._get_today_utc_date()
MatchModel.start_time.is_(None),
MatchModel.active_status == True # Find candidate fixtures that have at least one match with start_time NULL or today
candidate_fixtures = session.query(MatchModel.fixture_id).filter(
MatchModel.active_status == True,
((MatchModel.start_time.is_(None)) |
(MatchModel.start_time >= datetime.combine(today, datetime.min.time())) &
(MatchModel.start_time < datetime.combine(today, datetime.max.time())))
).distinct().order_by(MatchModel.created_at.asc()).all() ).distinct().order_by(MatchModel.created_at.asc()).all()
if fixtures_no_start_time: # Check each candidate fixture to ensure ALL matches are NULL or today
fixture_id = fixtures_no_start_time[0].fixture_id for fixture_row in candidate_fixtures:
logger.info(f"Initializing existing fixture with no start_time: {fixture_id}") fixture_id = fixture_row.fixture_id
# Set start_time to now for all matches in this fixture # Get all matches for this fixture
now = datetime.utcnow() all_matches = session.query(MatchModel).filter(
matches = session.query(MatchModel).filter(
MatchModel.fixture_id == fixture_id, MatchModel.fixture_id == fixture_id,
MatchModel.active_status == True MatchModel.active_status == True
).all() ).all()
for match in matches: # Check if ALL matches have start_time NULL or today
match.start_time = now all_valid = all(
match.status = 'scheduled' match.start_time is None or match.start_time.date() == today
logger.debug(f"Set start_time for match {match.match_number}") for match in all_matches
)
session.commit() if all_valid:
return fixture_id logger.info(f"Initializing existing fixture where all matches are NULL or today: {fixture_id}")
# Set start_time to now for matches that don't have it
now = datetime.utcnow()
for match in all_matches:
if match.start_time is None:
match.start_time = now
match.status = 'scheduled'
logger.debug(f"Set/confirmed start_time for match {match.match_number}")
session.commit()
return fixture_id
# No suitable existing fixtures found - create new fixture from old matches
logger.info("No fixtures found where all matches are NULL or today - creating new fixture from old completed matches")
# No fixtures with no start_time found - create a new fixture from old completed matches # No fixtures with no start_time found - create a new fixture from old completed matches
logger.info("No fixtures with no start_time found - creating new fixture from old completed matches") logger.info("No fixtures with no start_time found - creating new fixture from old completed matches")
...@@ -2552,6 +2571,9 @@ class GamesThread(ThreadedComponent): ...@@ -2552,6 +2571,9 @@ class GamesThread(ThreadedComponent):
ExtractionAssociationModel.extraction_result == selected_result ExtractionAssociationModel.extraction_result == selected_result
).distinct().all() ).distinct().all()
extraction_winning_outcome_names = [outcome.outcome_name for outcome in winning_outcomes] extraction_winning_outcome_names = [outcome.outcome_name for outcome in winning_outcomes]
# Filter winning outcomes to only include those available in the match fixture
extraction_winning_outcome_names = [outcome for outcome in extraction_winning_outcome_names if outcome in available_outcome_names]
logger.info(f"🏆 [EXTRACTION DEBUG] Winning outcomes for result '{selected_result}': {extraction_winning_outcome_names}") logger.info(f"🏆 [EXTRACTION DEBUG] Winning outcomes for result '{selected_result}': {extraction_winning_outcome_names}")
# Log expected redistribution and actual selected payout # Log expected redistribution and actual selected payout
...@@ -2762,16 +2784,9 @@ class GamesThread(ThreadedComponent): ...@@ -2762,16 +2784,9 @@ class GamesThread(ThreadedComponent):
# extraction_winning_outcome_names is already passed as parameter # extraction_winning_outcome_names is already passed as parameter
logger.info(f"DEBUG _update_bet_results: Using passed extraction_winning_outcome_names: {extraction_winning_outcome_names}") logger.info(f"DEBUG _update_bet_results: Using passed extraction_winning_outcome_names: {extraction_winning_outcome_names}")
# Get possible outcomes for this match # Winning outcomes are now pre-filtered in _perform_result_extraction
possible_outcomes = session.query(MatchOutcomeModel.column_name).filter( winning_outcome_names = extraction_winning_outcome_names
MatchOutcomeModel.match_id == match_id logger.info(f"DEBUG _update_bet_results: Using pre-filtered winning outcomes: {winning_outcome_names}")
).all()
possible_outcome_names = [outcome.column_name for outcome in possible_outcomes]
logger.info(f"DEBUG _update_bet_results: Match {match_id} has {len(possible_outcomes)} possible outcomes: {possible_outcome_names}")
# Filter winning outcomes to only include those that are possible for this match
winning_outcome_names = [outcome for outcome in extraction_winning_outcome_names if outcome in possible_outcome_names]
logger.info(f"DEBUG _update_bet_results: After filtering against possible outcomes, {len(winning_outcome_names)} winning outcomes remain: {winning_outcome_names}")
# Set the main result (selected_result) # Set the main result (selected_result)
match.result = selected_result match.result = selected_result
......
...@@ -478,9 +478,18 @@ document.addEventListener('currencySettingsLoaded', function(event) { ...@@ -478,9 +478,18 @@ document.addEventListener('currencySettingsLoaded', function(event) {
}); });
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
// Check for print parameter and automatically print if present
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.get('print') === 'true') {
// Automatically print the ticket after a short delay to ensure page is fully loaded
setTimeout(() => {
directPrintBet(window.betData.uuid);
}, 1000);
}
// Generate QR code for bet verification // Generate QR code for bet verification
generateBetVerificationQR(); generateBetVerificationQR();
// Cancel entire bet button // Cancel entire bet button
const cancelBetBtn = document.getElementById('btn-cancel-bet'); const cancelBetBtn = document.getElementById('btn-cancel-bet');
if (cancelBetBtn) { if (cancelBetBtn) {
......
...@@ -819,7 +819,7 @@ function submitBet() { ...@@ -819,7 +819,7 @@ function submitBet() {
if (data.success) { if (data.success) {
showNotification('Bet submitted successfully!', 'success'); showNotification('Bet submitted successfully!', 'success');
setTimeout(() => { setTimeout(() => {
window.location.href = `/bets/${data.bet_id}`; window.location.href = `/bets/${data.bet_id}?print=true`;
}, 1500); }, 1500);
} else { } else {
showNotification('Failed to submit bet: ' + (data.error || 'Unknown error'), 'error'); showNotification('Failed to submit bet: ' + (data.error || 'Unknown error'), 'error');
......
...@@ -480,6 +480,15 @@ document.addEventListener('currencySettingsLoaded', function(event) { ...@@ -480,6 +480,15 @@ document.addEventListener('currencySettingsLoaded', function(event) {
}); });
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
// Check for print parameter and automatically print if present
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.get('print') === 'true') {
// Automatically print the ticket after a short delay to ensure page is fully loaded
setTimeout(() => {
directPrintBet(window.betData.uuid);
}, 1000);
}
// Generate QR code for bet verification // Generate QR code for bet verification
generateBetVerificationQR(); generateBetVerificationQR();
......
...@@ -861,7 +861,7 @@ function submitBet() { ...@@ -861,7 +861,7 @@ function submitBet() {
if (data.success) { if (data.success) {
showNotification('Bet submitted successfully!', 'success'); showNotification('Bet submitted successfully!', 'success');
setTimeout(() => { setTimeout(() => {
window.location.href = `/cashier/bets/${data.bet_id}`; window.location.href = `/cashier/bets/${data.bet_id}?print=true`;
}, 1500); }, 1500);
} else { } else {
showNotification('Failed to submit bet: ' + (data.error || 'Unknown error'), 'error'); showNotification('Failed to submit bet: ' + (data.error || 'Unknown error'), 'error');
......
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