Add QR code configuration section to admin dashboard

- Add new QR code settings section in admin/configurations page
- QR codes disabled by default in database on creation
- Include size, error correction level, and display options
- Add API endpoints for QR code configuration management
- Update barcode settings to be enabled by default
- Add JavaScript handlers for QR code settings with validation
- Create database migration for QR code configuration settings
parent 4d37119a
......@@ -1542,7 +1542,7 @@ class Migration_021_AddBarcodeConfiguration(DatabaseMigration):
barcode_configs = [
{
'key': 'barcode.enabled',
'value': 'false',
'value': 'true',
'value_type': 'bool',
'description': 'Enable barcode generation for betting tickets',
'is_system': False
......@@ -1628,6 +1628,100 @@ class Migration_021_AddBarcodeConfiguration(DatabaseMigration):
logger.error(f"Failed to remove barcode configuration: {e}")
return False
class Migration_022_AddQRCodeConfiguration(DatabaseMigration):
"""Add QR code configuration settings for betting system"""
def __init__(self):
super().__init__("022", "Add QR code configuration settings for betting system")
def up(self, db_manager) -> bool:
"""Add QR code configuration to configuration table"""
try:
with db_manager.engine.connect() as conn:
# Add QR code configuration settings
qrcode_configs = [
{
'key': 'qrcode.enabled',
'value': 'false',
'value_type': 'bool',
'description': 'Enable QR code generation for betting tickets',
'is_system': False
},
{
'key': 'qrcode.size',
'value': '200',
'value_type': 'int',
'description': 'QR code image size in pixels (square)',
'is_system': False
},
{
'key': 'qrcode.error_correction',
'value': 'M',
'value_type': 'string',
'description': 'QR code error correction level: L, M, Q, H',
'is_system': False
},
{
'key': 'qrcode.show_on_thermal',
'value': 'true',
'value_type': 'bool',
'description': 'Show QR code on thermal printed receipts',
'is_system': False
},
{
'key': 'qrcode.show_on_verification',
'value': 'true',
'value_type': 'bool',
'description': 'Show QR code on bet verification pages',
'is_system': False
}
]
for config in qrcode_configs:
# Check if configuration already exists
result = conn.execute(text("""
SELECT COUNT(*) FROM configuration WHERE key = :key
"""), {'key': config['key']})
exists = result.scalar() > 0
if not exists:
conn.execute(text("""
INSERT INTO configuration
(key, value, value_type, description, is_system, created_at, updated_at)
VALUES (:key, :value, :value_type, :description, :is_system, datetime('now'), datetime('now'))
"""), config)
logger.info(f"Added QR code configuration: {config['key']} = {config['value']}")
else:
logger.info(f"QR code configuration already exists: {config['key']}")
conn.commit()
logger.info("QR code configuration settings added successfully")
return True
except Exception as e:
logger.error(f"Failed to add QR code configuration: {e}")
return False
def down(self, db_manager) -> bool:
"""Remove QR code configuration settings"""
try:
with db_manager.engine.connect() as conn:
# Remove all QR code-related configurations
conn.execute(text("""
DELETE FROM configuration
WHERE key LIKE 'qrcode.%'
"""))
conn.commit()
logger.info("QR code configuration settings removed")
return True
except Exception as e:
logger.error(f"Failed to remove QR code configuration: {e}")
return False
# Registry of all migrations in order
MIGRATIONS: List[DatabaseMigration] = [
Migration_001_InitialSchema(),
......@@ -1651,6 +1745,7 @@ MIGRATIONS: List[DatabaseMigration] = [
Migration_019_AddPaidFieldToBets(),
Migration_020_FixBetDetailsForeignKey(),
Migration_021_AddBarcodeConfiguration(),
Migration_022_AddQRCodeConfiguration(),
]
......
......@@ -265,6 +265,13 @@ def configuration():
barcode_show_on_thermal = main_bp.db_manager.get_config_value('barcode.show_on_thermal', True) if main_bp.db_manager else True
barcode_show_on_verification = main_bp.db_manager.get_config_value('barcode.show_on_verification', True) if main_bp.db_manager else True
# Load QR code configuration from database
qrcode_enabled = main_bp.db_manager.get_config_value('qrcode.enabled', False) if main_bp.db_manager else False
qrcode_size = main_bp.db_manager.get_config_value('qrcode.size', 200) if main_bp.db_manager else 200
qrcode_error_correction = main_bp.db_manager.get_config_value('qrcode.error_correction', 'M') if main_bp.db_manager else 'M'
qrcode_show_on_thermal = main_bp.db_manager.get_config_value('qrcode.show_on_thermal', True) if main_bp.db_manager else True
qrcode_show_on_verification = main_bp.db_manager.get_config_value('qrcode.show_on_verification', True) if main_bp.db_manager else True
config_data.update({
# General settings
'app_name': general_config.get('app_name', 'MbetterClient'),
......@@ -301,7 +308,14 @@ def configuration():
'barcode_width': barcode_width,
'barcode_height': barcode_height,
'barcode_show_on_thermal': barcode_show_on_thermal,
'barcode_show_on_verification': barcode_show_on_verification
'barcode_show_on_verification': barcode_show_on_verification,
# QR code settings
'qrcode_enabled': qrcode_enabled,
'qrcode_size': qrcode_size,
'qrcode_error_correction': qrcode_error_correction,
'qrcode_show_on_thermal': qrcode_show_on_thermal,
'qrcode_show_on_verification': qrcode_show_on_verification
})
except Exception as e:
logger.warning(f"Error loading configuration values: {e}")
......@@ -4379,6 +4393,89 @@ def set_barcode_settings():
return jsonify({"error": str(e)}), 500
# QR Code Settings API routes
@api_bp.route('/qrcode-settings')
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def get_qrcode_settings():
"""Get QR code configuration"""
try:
if api_bp.db_manager:
settings = {
'enabled': api_bp.db_manager.get_config_value('qrcode.enabled', False),
'size': api_bp.db_manager.get_config_value('qrcode.size', 200),
'error_correction': api_bp.db_manager.get_config_value('qrcode.error_correction', 'M'),
'show_on_thermal': api_bp.db_manager.get_config_value('qrcode.show_on_thermal', True),
'show_on_verification': api_bp.db_manager.get_config_value('qrcode.show_on_verification', True)
}
else:
# Default settings
settings = {
'enabled': False,
'size': 200,
'error_correction': 'M',
'show_on_thermal': True,
'show_on_verification': True
}
return jsonify({
"success": True,
"settings": settings
})
except Exception as e:
logger.error(f"API get QR code settings error: {e}")
return jsonify({"error": str(e)}), 500
@api_bp.route('/qrcode-settings', methods=['POST'])
@api_bp.auth_manager.require_auth if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
@api_bp.auth_manager.require_admin if hasattr(api_bp, 'auth_manager') and api_bp.auth_manager else login_required
def set_qrcode_settings():
"""Set QR code configuration (admin only)"""
try:
data = request.get_json() or {}
enabled = data.get('enabled', False)
size = data.get('size', 200)
error_correction = data.get('error_correction', 'M')
show_on_thermal = data.get('show_on_thermal', True)
show_on_verification = data.get('show_on_verification', True)
# Validation
valid_error_levels = ['L', 'M', 'Q', 'H']
if error_correction not in valid_error_levels:
return jsonify({"error": f"Invalid error correction level. Must be one of: {', '.join(valid_error_levels)}"}), 400
if not isinstance(size, int) or size < 100 or size > 500:
return jsonify({"error": "Size must be an integer between 100 and 500"}), 400
if api_bp.db_manager:
# Save QR code configuration to database
api_bp.db_manager.set_config_value('qrcode.enabled', enabled)
api_bp.db_manager.set_config_value('qrcode.size', size)
api_bp.db_manager.set_config_value('qrcode.error_correction', error_correction)
api_bp.db_manager.set_config_value('qrcode.show_on_thermal', show_on_thermal)
api_bp.db_manager.set_config_value('qrcode.show_on_verification', show_on_verification)
logger.info(f"QR code settings updated - enabled: {enabled}, size: {size}, error_correction: {error_correction}")
return jsonify({
"success": True,
"message": f"QR code settings updated: {'enabled' if enabled else 'disabled'}",
"settings": {
"enabled": enabled,
"size": size,
"error_correction": error_correction,
"show_on_thermal": show_on_thermal,
"show_on_verification": show_on_verification
}
})
else:
return jsonify({"error": "Database manager not available"}), 500
except Exception as e:
logger.error(f"API set QR code settings error: {e}")
return jsonify({"error": str(e)}), 500
@api_bp.route('/barcode/<uuid:bet_id>')
def generate_bet_barcode(bet_id):
"""Generate barcode image for bet verification - no authentication required"""
......
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