Update reports

parent e3eef4f3
This diff is collapsed.
This diff is collapsed.
...@@ -1041,6 +1041,9 @@ def api_reports_sync(): ...@@ -1041,6 +1041,9 @@ def api_reports_sync():
'details': f'Missing required field: {field}' 'details': f'Missing required field: {field}'
}), 400 }), 400
# Get cap compensation balance (optional field)
cap_compensation_balance = data.get('cap_compensation_balance', 0.00)
# Check for duplicate sync_id (idempotency) # Check for duplicate sync_id (idempotency)
existing_sync = ReportSync.query.filter_by(sync_id=data['sync_id']).first() existing_sync = ReportSync.query.filter_by(sync_id=data['sync_id']).first()
if existing_sync: if existing_sync:
...@@ -1111,12 +1114,16 @@ def api_reports_sync(): ...@@ -1111,12 +1114,16 @@ def api_reports_sync():
total_payout=summary['total_payout'], total_payout=summary['total_payout'],
net_profit=summary['net_profit'], net_profit=summary['net_profit'],
total_bets=summary['total_bets'], total_bets=summary['total_bets'],
total_matches=summary['total_matches'] total_matches=summary['total_matches'],
cap_compensation_balance=cap_compensation_balance
) )
db.session.add(report_sync) db.session.add(report_sync)
# Process bets # Process bets
bets_count = 0 bets_count = 0
bets_new = 0
bets_duplicate = 0
for bet_data in data['bets']: for bet_data in data['bets']:
# Validate bet UUID # Validate bet UUID
try: try:
...@@ -1131,7 +1138,26 @@ def api_reports_sync(): ...@@ -1131,7 +1138,26 @@ def api_reports_sync():
# Check for duplicate bet UUID # Check for duplicate bet UUID
existing_bet = Bet.query.filter_by(uuid=bet_data['uuid']).first() existing_bet = Bet.query.filter_by(uuid=bet_data['uuid']).first()
if existing_bet: if existing_bet:
logger.warning(f"Duplicate bet UUID {bet_data['uuid']} detected, skipping") # Update existing bet if it has changed
bet_updated = False
if existing_bet.total_amount != bet_data['total_amount']:
existing_bet.total_amount = bet_data['total_amount']
bet_updated = True
if existing_bet.paid != bet_data.get('paid', False):
existing_bet.paid = bet_data.get('paid', False)
bet_updated = True
if existing_bet.paid_out != bet_data.get('paid_out', False):
existing_bet.paid_out = bet_data.get('paid_out', False)
bet_updated = True
if bet_updated:
existing_bet.sync_id = report_sync.id
bets_count += 1
bets_duplicate += 1
logger.info(f"Updated existing bet {bet_data['uuid']}")
else:
logger.warning(f"Duplicate bet UUID {bet_data['uuid']} detected, skipping (no changes)")
bets_duplicate += 1
continue continue
# Parse bet datetime # Parse bet datetime
...@@ -1160,6 +1186,7 @@ def api_reports_sync(): ...@@ -1160,6 +1186,7 @@ def api_reports_sync():
# Flush to get bet.id before creating bet details # Flush to get bet.id before creating bet details
db.session.flush() db.session.flush()
bets_count += 1 bets_count += 1
bets_new += 1
# Process bet details # Process bet details
for detail_data in bet_data.get('details', []): for detail_data in bet_data.get('details', []):
...@@ -1250,8 +1277,8 @@ def api_reports_sync(): ...@@ -1250,8 +1277,8 @@ def api_reports_sync():
operation_type='new_sync', operation_type='new_sync',
status='success', status='success',
bets_processed=bets_count, bets_processed=bets_count,
bets_new=bets_count, bets_new=bets_new,
bets_duplicate=0, bets_duplicate=bets_duplicate,
stats_processed=stats_count, stats_processed=stats_count,
stats_new=stats_new, stats_new=stats_new,
stats_updated=stats_updated, stats_updated=stats_updated,
......
...@@ -775,6 +775,61 @@ class Migration_010_CreateReportsTables(Migration): ...@@ -775,6 +775,61 @@ class Migration_010_CreateReportsTables(Migration):
def can_rollback(self) -> bool: def can_rollback(self) -> bool:
return True return True
class Migration_011_AddCapCompensationBalance(Migration):
"""Add cap_compensation_balance column to report_syncs table"""
def __init__(self):
super().__init__("011", "Add cap_compensation_balance column to report_syncs table")
def up(self):
"""Add cap_compensation_balance column"""
try:
# Check if column already exists
inspector = inspect(db.engine)
# Check if report_syncs table exists
if 'report_syncs' not in inspector.get_table_names():
logger.info("report_syncs table does not exist yet, skipping migration")
return True
columns = [col['name'] for col in inspector.get_columns('report_syncs')]
if 'cap_compensation_balance' in columns:
logger.info("cap_compensation_balance column already exists, skipping creation")
return True
# Add column
alter_table_sql = '''
ALTER TABLE report_syncs
ADD COLUMN cap_compensation_balance DECIMAL(15,2) NOT NULL DEFAULT 0.00
'''
with db.engine.connect() as conn:
conn.execute(text(alter_table_sql))
conn.commit()
logger.info("Added cap_compensation_balance column successfully")
return True
except Exception as e:
logger.error(f"Migration 011 failed: {str(e)}")
raise
def down(self):
"""Drop cap_compensation_balance column"""
try:
with db.engine.connect() as conn:
conn.execute(text("ALTER TABLE report_syncs DROP COLUMN IF EXISTS cap_compensation_balance"))
conn.commit()
logger.info("Dropped cap_compensation_balance column")
return True
except Exception as e:
logger.error(f"Rollback of migration 011 failed: {str(e)}")
raise
def can_rollback(self) -> bool:
return True
class MigrationManager: class MigrationManager:
"""Manages database migrations and versioning""" """Manages database migrations and versioning"""
...@@ -790,6 +845,7 @@ class MigrationManager: ...@@ -790,6 +845,7 @@ class MigrationManager:
Migration_008_AddRemoteDomainSetting(), Migration_008_AddRemoteDomainSetting(),
Migration_009_CreateClientActivityTable(), Migration_009_CreateClientActivityTable(),
Migration_010_CreateReportsTables(), Migration_010_CreateReportsTables(),
Migration_011_AddCapCompensationBalance(),
] ]
def ensure_version_table(self): def ensure_version_table(self):
......
"""
Migration to add cap_compensation_balance field to report_syncs table
"""
from datetime import datetime
from app import db
from app.models import ReportSync
def upgrade():
"""Add cap_compensation_balance column to report_syncs table"""
try:
# Check if column already exists
inspector = db.inspect(db.engine)
columns = [col['name'] for col in inspector.get_columns('report_syncs')]
if 'cap_compensation_balance' not in columns:
# Add the column
with db.engine.connect() as conn:
conn.execute(db.text("""
ALTER TABLE report_syncs
ADD COLUMN cap_compensation_balance NUMERIC(15, 2) DEFAULT 0.00
"""))
db.session.commit()
print("Successfully added cap_compensation_balance column to report_syncs table")
else:
print("cap_compensation_balance column already exists in report_syncs table")
except Exception as e:
db.session.rollback()
print(f"Error adding cap_compensation_balance column: {str(e)}")
raise
def downgrade():
"""Remove cap_compensation_balance column from report_syncs table"""
try:
with db.engine.connect() as conn:
conn.execute(db.text("""
ALTER TABLE report_syncs
DROP COLUMN IF EXISTS cap_compensation_balance
"""))
db.session.commit()
print("Successfully removed cap_compensation_balance column from report_syncs table")
except Exception as e:
db.session.rollback()
print(f"Error removing cap_compensation_balance column: {str(e)}")
raise
if __name__ == '__main__':
print("Running migration: add_cap_compensation_balance")
upgrade()
\ No newline at end of file
...@@ -1541,14 +1541,16 @@ def clients(): ...@@ -1541,14 +1541,16 @@ def clients():
def reports(): def reports():
"""Reports page with filtering, pagination, and export""" """Reports page with filtering, pagination, and export"""
try: try:
from app.models import ReportSync, Bet, ExtractionStats from app.models import ReportSync, Bet, ExtractionStats, APIToken, ClientActivity
from sqlalchemy import func, and_, or_ from sqlalchemy import func, and_, or_
# Get filter parameters # Get filter parameters
client_id_filter = request.args.get('client_id', '').strip() client_id_filter = request.args.get('client_id', '').strip()
date_range_filter = request.args.get('date_range', '').strip() date_range_filter = request.args.get('date_range', 'today').strip()
start_date_filter = request.args.get('start_date', '').strip() start_date_filter = request.args.get('start_date', '').strip()
end_date_filter = request.args.get('end_date', '').strip() end_date_filter = request.args.get('end_date', '').strip()
start_time_filter = request.args.get('start_time', '').strip()
end_time_filter = request.args.get('end_time', '').strip()
sort_by = request.args.get('sort_by', 'sync_timestamp') sort_by = request.args.get('sort_by', 'sync_timestamp')
sort_order = request.args.get('sort_order', 'desc') sort_order = request.args.get('sort_order', 'desc')
export_format = request.args.get('export', '').strip() export_format = request.args.get('export', '').strip()
...@@ -1557,16 +1559,66 @@ def reports(): ...@@ -1557,16 +1559,66 @@ def reports():
page = request.args.get('page', 1, type=int) page = request.args.get('page', 1, type=int)
per_page = min(request.args.get('per_page', 20, type=int), 100) per_page = min(request.args.get('per_page', 20, type=int), 100)
# Calculate date range based on filter
now = datetime.utcnow()
start_date = None
end_date = None
if date_range_filter == 'today':
start_date = now.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'yesterday':
yesterday = now - timedelta(days=1)
start_date = yesterday.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = yesterday.replace(hour=23, minute=59, second=59, microsecond=999999)
elif date_range_filter == 'this_week':
# Start of current week (Monday)
start_date = now - timedelta(days=now.weekday())
start_date = start_date.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'last_week':
# Start of last week (Monday)
last_week_end = now - timedelta(days=now.weekday() + 1)
last_week_start = last_week_end - timedelta(days=6)
start_date = last_week_start.replace(hour=0, minute=0, second=0, microsecond=0)
end_date = last_week_end.replace(hour=23, minute=59, second=59, microsecond=999999)
elif date_range_filter == 'this_month':
start_date = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
end_date = now
elif date_range_filter == 'all':
start_date = None
end_date = None
elif date_range_filter == 'custom':
# Use custom date range
if start_date_filter:
try:
start_date = datetime.strptime(start_date_filter, '%Y-%m-%d')
if start_time_filter:
hour, minute = map(int, start_time_filter.split(':'))
start_date = start_date.replace(hour=hour, minute=minute, second=0, microsecond=0)
else:
start_date = start_date.replace(hour=0, minute=0, second=0, microsecond=0)
except ValueError:
pass
if end_date_filter:
try:
end_date = datetime.strptime(end_date_filter, '%Y-%m-%d')
if end_time_filter:
hour, minute = map(int, end_time_filter.split(':'))
end_date = end_date.replace(hour=hour, minute=minute, second=59, microsecond=999999)
else:
end_date = end_date.replace(hour=23, minute=59, second=59, microsecond=999999)
except ValueError:
pass
# Base query # Base query
if current_user.is_admin: if current_user.is_admin:
query = ReportSync.query query = ReportSync.query
else: else:
# Non-admin users can only see reports from their own clients # Non-admin users can only see reports from their own clients
from app.models import APIToken
user_token_ids = [t.id for t in APIToken.query.filter_by(user_id=current_user.id).all()] user_token_ids = [t.id for t in APIToken.query.filter_by(user_id=current_user.id).all()]
if user_token_ids: if user_token_ids:
# Get client_ids from ClientActivity for this user's tokens # Get client_ids from ClientActivity for this user's tokens
from app.models import ClientActivity
client_ids = [c.rustdesk_id for c in ClientActivity.query.filter( client_ids = [c.rustdesk_id for c in ClientActivity.query.filter(
ClientActivity.api_token_id.in_(user_token_ids) ClientActivity.api_token_id.in_(user_token_ids)
).all()] ).all()]
...@@ -1581,21 +1633,11 @@ def reports(): ...@@ -1581,21 +1633,11 @@ def reports():
if client_id_filter: if client_id_filter:
query = query.filter(ReportSync.client_id == client_id_filter) query = query.filter(ReportSync.client_id == client_id_filter)
if start_date_filter: if start_date:
try:
start_date = datetime.strptime(start_date_filter, '%Y-%m-%d')
query = query.filter(ReportSync.start_date >= start_date) query = query.filter(ReportSync.start_date >= start_date)
except ValueError:
pass
if end_date_filter: if end_date:
try:
end_date = datetime.strptime(end_date_filter, '%Y-%m-%d')
# Include the entire end date
end_date = end_date.replace(hour=23, minute=59, second=59)
query = query.filter(ReportSync.end_date <= end_date) query = query.filter(ReportSync.end_date <= end_date)
except ValueError:
pass
# Sorting # Sorting
if hasattr(ReportSync, sort_by): if hasattr(ReportSync, sort_by):
...@@ -1614,29 +1656,48 @@ def reports(): ...@@ -1614,29 +1656,48 @@ def reports():
# Pagination # Pagination
reports_pagination = query.paginate(page=page, per_page=per_page, error_out=False) reports_pagination = query.paginate(page=page, per_page=per_page, error_out=False)
# Get unique client IDs for filter dropdown # Get unique client IDs for filter dropdown with token names
if current_user.is_admin: if current_user.is_admin:
all_client_ids = db.session.query(ReportSync.client_id).distinct().all() # Get all clients with their token names
clients_query = db.session.query(
ReportSync.client_id,
APIToken.name.label('token_name')
).join(
ClientActivity, ReportSync.client_id == ClientActivity.rustdesk_id
).join(
APIToken, ClientActivity.api_token_id == APIToken.id
).filter(
APIToken.is_active == True
).distinct().all()
client_data = [{'client_id': c.client_id, 'token_name': c.token_name} for c in clients_query]
else: else:
if user_token_ids: if user_token_ids:
from app.models import ClientActivity clients_query = db.session.query(
all_client_ids = db.session.query(ClientActivity.rustdesk_id).filter( ClientActivity.rustdesk_id.label('client_id'),
ClientActivity.api_token_id.in_(user_token_ids) APIToken.name.label('token_name')
).join(
APIToken, ClientActivity.api_token_id == APIToken.id
).filter(
ClientActivity.api_token_id.in_(user_token_ids),
APIToken.is_active == True
).distinct().all() ).distinct().all()
else:
all_client_ids = []
client_ids = [cid[0] for cid in all_client_ids if cid[0]] client_data = [{'client_id': c.client_id, 'token_name': c.token_name} for c in clients_query]
else:
client_data = []
return render_template('main/reports.html', return render_template('main/reports.html',
reports=reports_pagination.items, reports=reports_pagination.items,
pagination=reports_pagination, pagination=reports_pagination,
client_ids=client_ids, client_data=client_data,
filters={ filters={
'client_id': client_id_filter, 'client_id': client_id_filter,
'date_range': date_range_filter, 'date_range': date_range_filter,
'start_date': start_date_filter, 'start_date': start_date_filter,
'end_date': end_date_filter, 'end_date': end_date_filter,
'start_time': start_time_filter,
'end_time': end_time_filter,
'sort_by': sort_by, 'sort_by': sort_by,
'sort_order': sort_order 'sort_order': sort_order
}) })
......
...@@ -857,6 +857,9 @@ class ReportSync(db.Model): ...@@ -857,6 +857,9 @@ class ReportSync(db.Model):
total_bets = db.Column(db.Integer, default=0) total_bets = db.Column(db.Integer, default=0)
total_matches = db.Column(db.Integer, default=0) total_matches = db.Column(db.Integer, default=0)
# Cap compensation balance at the time of sync
cap_compensation_balance = db.Column(db.Numeric(15, 2), default=0.00)
# Metadata # Metadata
created_at = db.Column(db.DateTime, default=datetime.utcnow) created_at = db.Column(db.DateTime, default=datetime.utcnow)
...@@ -879,6 +882,7 @@ class ReportSync(db.Model): ...@@ -879,6 +882,7 @@ class ReportSync(db.Model):
'net_profit': float(self.net_profit) if self.net_profit else 0.0, 'net_profit': float(self.net_profit) if self.net_profit else 0.0,
'total_bets': self.total_bets, 'total_bets': self.total_bets,
'total_matches': self.total_matches, 'total_matches': self.total_matches,
'cap_compensation_balance': float(self.cap_compensation_balance) if self.cap_compensation_balance else 0.0,
'created_at': self.created_at.isoformat() if self.created_at else None 'created_at': self.created_at.isoformat() if self.created_at else None
} }
......
...@@ -80,22 +80,28 @@ ...@@ -80,22 +80,28 @@
</div> </div>
</div> </div>
<div class="row mt-3"> <div class="row mt-3">
<div class="col-md-4"> <div class="col-md-3">
<div class="p-3 bg-primary text-white rounded"> <div class="p-3 bg-primary text-white rounded">
<h6 class="mb-1">Total Payin</h6> <h6 class="mb-1">Total Payin</h6>
<h3 class="mb-0">{{ "{:,.2f}".format(report.total_payin) if report.total_payin else '0.00' }}</h3> <h3 class="mb-0">{{ "{:,.2f}".format(report.total_payin) if report.total_payin else '0.00' }}</h3>
</div> </div>
</div> </div>
<div class="col-md-4"> <div class="col-md-3">
<div class="p-3 bg-info text-white rounded"> <div class="p-3 bg-info text-white rounded">
<h6 class="mb-1">Total Payout</h6> <h6 class="mb-1">Total Payout</h6>
<h3 class="mb-0">{{ "{:,.2f}".format(report.total_payout) if report.total_payout else '0.00' }}</h3> <h3 class="mb-0">{{ "{:,.2f}".format(report.total_payout) if report.total_payout else '0.00' }}</h3>
</div> </div>
</div> </div>
<div class="col-md-4"> <div class="col-md-3">
<div class="p-3 {% if report.net_profit >= 0 %}bg-success{% else %}bg-danger{% endif %} text-white rounded"> <div class="p-3 {% if (report.total_payin - report.total_payout) >= 0 %}bg-success{% else %}bg-danger{% endif %} text-white rounded">
<h6 class="mb-1">Net Profit</h6> <h6 class="mb-1">Balance</h6>
<h3 class="mb-0">{{ "{:,.2f}".format(report.net_profit) if report.net_profit else '0.00' }}</h3> <h3 class="mb-0">{{ "{:,.2f}".format(report.total_payin - report.total_payout) if report.total_payin and report.total_payout else '0.00' }}</h3>
</div>
</div>
<div class="col-md-3">
<div class="p-3 bg-warning text-white rounded">
<h6 class="mb-1">CAP Redistribution Balance</h6>
<h3 class="mb-0">{{ "{:,.2f}".format(report.cap_compensation_balance) if report.cap_compensation_balance else '0.00' }}</h3>
</div> </div>
</div> </div>
</div> </div>
...@@ -189,7 +195,7 @@ ...@@ -189,7 +195,7 @@
<td class="text-end">{{ "{:,.2f}".format(detail.amount) if detail.amount else '0.00' }}</td> <td class="text-end">{{ "{:,.2f}".format(detail.amount) if detail.amount else '0.00' }}</td>
<td class="text-end">{{ "{:,.2f}".format(detail.win_amount) if detail.win_amount else '0.00' }}</td> <td class="text-end">{{ "{:,.2f}".format(detail.win_amount) if detail.win_amount else '0.00' }}</td>
<td> <td>
<span class="badge bg-{% if detail.result == 'won' %}success{% elif detail.result == 'lost' %}danger{% elif detail.result == 'pending' %}warning{% else %}secondary{% endif %}"> <span class="badge bg-{% if detail.result == 'win' %}success{% elif detail.result == 'lost' %}danger{% elif detail.result == 'pending' %}warning{% else %}secondary{% endif %}">
{{ detail.result }} {{ detail.result }}
</span> </span>
</td> </td>
...@@ -295,7 +301,6 @@ ...@@ -295,7 +301,6 @@
<th>Outcome</th> <th>Outcome</th>
<th>Bets</th> <th>Bets</th>
<th>Amount</th> <th>Amount</th>
<th>Coefficient</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
...@@ -304,7 +309,6 @@ ...@@ -304,7 +309,6 @@
<td>{{ outcome }}</td> <td>{{ outcome }}</td>
<td>{{ data.bets }}</td> <td>{{ data.bets }}</td>
<td>{{ "{:,.2f}".format(data.amount) if data.amount else '0.00' }}</td> <td>{{ "{:,.2f}".format(data.amount) if data.amount else '0.00' }}</td>
<td>{{ data.coefficient }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>
......
...@@ -28,33 +28,43 @@ ...@@ -28,33 +28,43 @@
<div class="card-body"> <div class="card-body">
<form method="GET" action="{{ url_for('main.reports') }}" class="row g-3"> <form method="GET" action="{{ url_for('main.reports') }}" class="row g-3">
<div class="col-md-3"> <div class="col-md-3">
<label for="client_id" class="form-label">Client ID</label> <label for="client_id" class="form-label">Client</label>
<select class="form-select" id="client_id" name="client_id"> <select class="form-select" id="client_id" name="client_id">
<option value="">All Clients</option> <option value="">All Clients</option>
{% for cid in client_ids %} {% for client in client_data %}
<option value="{{ cid }}" {% if filters.client_id == cid %}selected{% endif %}>{{ cid }}</option> <option value="{{ client.client_id }}" {% if filters.client_id == client.client_id %}selected{% endif %}>{{ client.token_name }} ({{ client.client_id }})</option>
{% endfor %} {% endfor %}
</select> </select>
</div> </div>
<div class="col-md-2"> <div class="col-md-2">
<label for="date_range" class="form-label">Date Range</label> <label for="date_range" class="form-label">Date Range</label>
<select class="form-select" id="date_range" name="date_range"> <select class="form-select" id="date_range" name="date_range" onchange="toggleCustomDateRange()">
<option value="">All</option>
<option value="today" {% if filters.date_range == 'today' %}selected{% endif %}>Today</option> <option value="today" {% if filters.date_range == 'today' %}selected{% endif %}>Today</option>
<option value="yesterday" {% if filters.date_range == 'yesterday' %}selected{% endif %}>Yesterday</option> <option value="yesterday" {% if filters.date_range == 'yesterday' %}selected{% endif %}>Yesterday</option>
<option value="week" {% if filters.date_range == 'week' %}selected{% endif %}>This Week</option> <option value="this_week" {% if filters.date_range == 'this_week' %}selected{% endif %}>This Week</option>
<option value="last_week" {% if filters.date_range == 'last_week' %}selected{% endif %}>Last Week</option>
<option value="this_month" {% if filters.date_range == 'this_month' %}selected{% endif %}>This Month</option>
<option value="all" {% if filters.date_range == 'all' %}selected{% endif %}>All Time</option> <option value="all" {% if filters.date_range == 'all' %}selected{% endif %}>All Time</option>
<option value="custom" {% if filters.date_range == 'custom' %}selected{% endif %}>Custom</option>
</select> </select>
</div> </div>
<div class="col-md-2"> <div class="col-md-2" id="custom-date-fields" style="display: none;">
<label for="start_date" class="form-label">Start Date</label> <label for="start_date" class="form-label">Start Date</label>
<input type="date" class="form-control" id="start_date" name="start_date" value="{{ filters.start_date }}"> <input type="date" class="form-control" id="start_date" name="start_date" value="{{ filters.start_date }}">
</div> </div>
<div class="col-md-2"> <div class="col-md-1" id="custom-time-fields" style="display: none;">
<label for="start_time" class="form-label">Start Time</label>
<input type="time" class="form-control" id="start_time" name="start_time" value="{{ filters.start_time }}">
</div>
<div class="col-md-2" id="custom-date-fields-end" style="display: none;">
<label for="end_date" class="form-label">End Date</label> <label for="end_date" class="form-label">End Date</label>
<input type="date" class="form-control" id="end_date" name="end_date" value="{{ filters.end_date }}"> <input type="date" class="form-control" id="end_date" name="end_date" value="{{ filters.end_date }}">
</div> </div>
<div class="col-md-2"> <div class="col-md-1" id="custom-time-fields-end" style="display: none;">
<label for="end_time" class="form-label">End Time</label>
<input type="time" class="form-control" id="end_time" name="end_time" value="{{ filters.end_time }}">
</div>
<div class="col-md-1">
<label for="sort_by" class="form-label">Sort By</label> <label for="sort_by" class="form-label">Sort By</label>
<select class="form-select" id="sort_by" name="sort_by"> <select class="form-select" id="sort_by" name="sort_by">
<option value="sync_timestamp" {% if filters.sort_by == 'sync_timestamp' %}selected{% endif %}>Sync Timestamp</option> <option value="sync_timestamp" {% if filters.sort_by == 'sync_timestamp' %}selected{% endif %}>Sync Timestamp</option>
...@@ -93,12 +103,13 @@ ...@@ -93,12 +103,13 @@
<thead> <thead>
<tr> <tr>
<th>Sync ID</th> <th>Sync ID</th>
<th>Client ID</th> <th>Client</th>
<th>Sync Timestamp</th> <th>Sync Timestamp</th>
<th>Date Range</th> <th>Date Range</th>
<th>Total Payin</th> <th>Total Payin</th>
<th>Total Payout</th> <th>Total Payout</th>
<th>Net Profit</th> <th>Balance</th>
<th>CAP Balance</th>
<th>Total Bets</th> <th>Total Bets</th>
<th>Total Matches</th> <th>Total Matches</th>
<th>Actions</th> <th>Actions</th>
...@@ -113,8 +124,11 @@ ...@@ -113,8 +124,11 @@
<td>{{ report.date_range }}</td> <td>{{ report.date_range }}</td>
<td class="text-end">{{ "{:,.2f}".format(report.total_payin) if report.total_payin else '0.00' }}</td> <td class="text-end">{{ "{:,.2f}".format(report.total_payin) if report.total_payin else '0.00' }}</td>
<td class="text-end">{{ "{:,.2f}".format(report.total_payout) if report.total_payout else '0.00' }}</td> <td class="text-end">{{ "{:,.2f}".format(report.total_payout) if report.total_payout else '0.00' }}</td>
<td class="text-end {% if report.net_profit >= 0 %}text-success{% else %}text-danger{% endif %}"> <td class="text-end {% if (report.total_payin - report.total_payout) >= 0 %}text-success{% else %}text-danger{% endif %}">
{{ "{:,.2f}".format(report.net_profit) if report.net_profit else '0.00' }} {{ "{:,.2f}".format(report.total_payin - report.total_payout) if report.total_payin and report.total_payout else '0.00' }}
</td>
<td class="text-end text-info">
{{ "{:,.2f}".format(report.cap_compensation_balance) if report.cap_compensation_balance else '0.00' }}
</td> </td>
<td class="text-center">{{ report.total_bets }}</td> <td class="text-center">{{ report.total_bets }}</td>
<td class="text-center">{{ report.total_matches }}</td> <td class="text-center">{{ report.total_matches }}</td>
...@@ -178,4 +192,31 @@ ...@@ -178,4 +192,31 @@
</div> </div>
</div> </div>
</div> </div>
<script>
function toggleCustomDateRange() {
var dateRange = document.getElementById('date_range').value;
var customDateFields = document.getElementById('custom-date-fields');
var customTimeFields = document.getElementById('custom-time-fields');
var customDateFieldsEnd = document.getElementById('custom-date-fields-end');
var customTimeFieldsEnd = document.getElementById('custom-time-fields-end');
if (dateRange === 'custom') {
customDateFields.style.display = 'block';
customTimeFields.style.display = 'block';
customDateFieldsEnd.style.display = 'block';
customTimeFieldsEnd.style.display = 'block';
} else {
customDateFields.style.display = 'none';
customTimeFields.style.display = 'none';
customDateFieldsEnd.style.display = 'none';
customTimeFieldsEnd.style.display = 'none';
}
}
// Initialize on page load
document.addEventListener('DOMContentLoaded', function() {
toggleCustomDateRange();
});
</script>
{% endblock %} {% endblock %}
\ No newline at end of file
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