diff --git a/models/qrcode.py b/models/qrcode.py index 58bd534..62fa794 100644 --- a/models/qrcode.py +++ b/models/qrcode.py @@ -43,6 +43,8 @@ class QRCode(base.db.Model): # 'standard' = fixed single location (existing behavior, default) # 'dynamic' = employee selects location from a list at scan time qr_type = base.db.Column(base.db.String(20), nullable=False, default='standard') + # Per-QR photo verification toggle (default: enabled) + photo_verification_enabled = base.db.Column(base.db.Boolean, nullable=False, default=True) # Relationship to style style = base.db.relationship('QRCodeStyle', backref='qr_codes') @@ -113,4 +115,4 @@ class QRCodeLocation(base.db.Model): qr_code = base.db.relationship('QRCode', backref='locations') def __repr__(self): - return f'' + return f'' \ No newline at end of file diff --git a/routes/qr_codes.py b/routes/qr_codes.py index 9030419..ac4a13c 100644 --- a/routes/qr_codes.py +++ b/routes/qr_codes.py @@ -160,6 +160,8 @@ def create_qr_code(): styles=QRCodeStyle.query.all()) # Create new QR code record first (without URL and image) + photo_verification_enabled = request.form.get('photo_verification_enabled', '1') != '0' + new_qr_code = QRCode( name=name, location=location, @@ -174,6 +176,7 @@ def create_qr_code(): coordinate_accuracy=coordinate_accuracy if has_coordinates else None, coordinates_updated_date=datetime.utcnow() if has_coordinates else None, qr_type=qr_type, # ADDED: store QR type + photo_verification_enabled=photo_verification_enabled, # NEW: Customization fields (only if columns exist) **({ 'fill_color': fill_color, @@ -220,6 +223,7 @@ def create_qr_code(): 'location_address': location_address, 'location_event': location_event, 'has_coordinates': has_coordinates, + 'photo_verification_enabled': photo_verification_enabled, 'customization': { 'fill_color': fill_color, 'back_color': back_color, @@ -514,6 +518,9 @@ def edit_qr_code(qr_id): else: qr_code.project_id = None + # Per-QR photo verification toggle + qr_code.photo_verification_enabled = request.form.get('photo_verification_enabled', '1') != '0' + # Handle QR code customization (only if columns exist) fill_color = request.form.get('fill_color', '#000000') back_color = request.form.get('back_color', '#FFFFFF') @@ -558,6 +565,11 @@ def edit_qr_code(qr_id): db.session.commit() + logger_handler.logger.info( + f"QR Code '{qr_code.name}' (ID: {qr_id}) updated by user {session.get('username', 'unknown')} — " + f"photo_verification_enabled={qr_code.photo_verification_enabled}" + ) + # Success message flash(f'QR Code "{qr_code.name}" updated successfully!', 'success') return redirect(url_for('dashboard.dashboard')) @@ -890,11 +902,12 @@ def qr_checkin(qr_url): logger_handler.logger.warning("Could not calculate location accuracy — calculation returned None") # CHECK DISTANCE THRESHOLD FOR PHOTO VERIFICATION - logger_handler.logger.debug(f"Photo verification enabled: {current_app.config.get('PHOTO_VERIFICATION_ENABLED', True)}") + logger_handler.logger.debug(f"Photo verification — global: {current_app.config.get('PHOTO_VERIFICATION_ENABLED', True)}, per-QR: {getattr(qr_code, 'photo_verification_enabled', True)}") requires_verification = False verification_photo_data = None - if current_app.config.get('PHOTO_VERIFICATION_ENABLED', True) and location_accuracy is not None and location_accuracy > current_app.config.get('DISTANCE_THRESHOLD_FOR_VERIFICATION', 0.3): + qr_photo_verification = getattr(qr_code, 'photo_verification_enabled', True) + if qr_photo_verification and current_app.config.get('PHOTO_VERIFICATION_ENABLED', True) and location_accuracy is not None and location_accuracy > current_app.config.get('DISTANCE_THRESHOLD_FOR_VERIFICATION', 0.3): logger_handler.logger.info(f"Distance ({location_accuracy:.3f} mi) exceeds verification threshold for employee {employee_id}") # Check if photo was provided @@ -1224,4 +1237,4 @@ def deactivate_qr_code(qr_id): return jsonify({ 'success': False, 'message': 'Error deactivating QR code. Please try again.' - }), 500 + }), 500 \ No newline at end of file diff --git a/templates/create_qr_code.html b/templates/create_qr_code.html index b3fcaf3..2a1469f 100644 --- a/templates/create_qr_code.html +++ b/templates/create_qr_code.html @@ -1,666 +1,656 @@ - - - - Create QR Code - QR Management System - - + - .btn-outline { - background: transparent; - color: var(--gray-600); - border: 2px solid var(--gray-300); - } + +
+
+
+

+ + Create New QR Code +

+

Generate a QR code for attendance tracking at your location

+
- .btn-outline:hover { - background: var(--gray-100); - border-color: var(--gray-400); - color: var(--gray-700); - } +
+ + + Bulk Import from Excel + +
- .error-message { - color: var(--error-color); - font-size: 0.875rem; - margin-top: 0.5rem; - } +
+ + +
+
+

+ + Basic Information +

+

Provide the basic details for your QR code

+
- .form-group.has-error input, - .form-group.has-error textarea { - border-color: var(--error-color); - } - - /* Responsive adjustments */ - @media (max-width: 768px) { - .form-row { - grid-template-columns: 1fr; - } - - .qr-preview-container { - flex-direction: column; - text-align: center; - } - - .range-input-group { - flex-direction: column; - gap: 0.5rem; - align-items: stretch; - } - - .range-value { - text-align: center; - } - } - - @media (max-width: 640px) { - .container { - padding: 0 0.5rem; - } - - .form-container { - padding: 1.5rem; - } - - .form-actions { - flex-direction: column; - } - } - - /* Animation for preview updates */ - .qr-preview { - animation: pulse 0.3s ease-in-out; - } - - @keyframes pulse { - 0% { transform: scale(1); } - 50% { transform: scale(1.05); } - 100% { transform: scale(1); } - } - - /* Toast notification styles */ - .toast { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; - } - - .toast-content { - display: flex; - align-items: center; - gap: 0.5rem; - color: var(--gray-800); - } - - .toast-content i { - font-size: 1.1rem; - } - - - -
-
-
-

- - Create New QR Code -

-

Generate a QR code for attendance tracking at your location

-
- - - - - - -
-
-

- - Basic Information -

-

Provide the basic details for your QR code

+
+ + + A unique name to identify this QR code +
+ 0/100
+
-
- - - A unique name to identify this QR code -
- 0/100 -
-
+ +
+ + + + Standard: employee checks in at one fixed location.
+ Dynamic: employee picks a location from a list when scanning. +
+
+ - -
- - - - Standard: employee checks in at one fixed location.
- Dynamic: employee picks a location from a list when scanning. -
-
- - - -
+ +
- - The name of the physical location where this QR code will be - used + + The name of the physical location where this QR code will be + used
0/100
-
+
-
- - - - - Organize your QR code by assigning it to a project - -
+
+ + + + + Organize your QR code by assigning it to a project +
+
- -
+ +

@@ -676,28 +666,17 @@ Complete Address * - - Include all address details for accurate location - identification + + Include all address details for accurate location + identification
0/500
- - - -
-
- - - Select the event type for this QR code -
+
+ +
+
+ + + Select the event type for this QR code
- -
-
-

- - QR Code Customization -

-

Customize the appearance and style of your QR code

-
+
- + + +
+
+

+ + Photo Verification +

+

Require a photo when employee check-in location is too far from the QR code

+
+
+ + + When disabled, photo verification is skipped for this QR code regardless of + distance +
+
+ + +
+
+

+ + QR Code Customization +

+

Customize the appearance and style of your QR code

+
+ + +
+ + + Choose a pre-defined style or customize manually below +
+ + +
-
- -
-
- -
- - -
- Color of the QR code modules -
- -
- -
- - -
- Background color of the QR code -
-
- - -
-
- -
- - 10px -
- Size of each QR code module (affects overall size) -
- -
- -
- - 4 modules -
- White border around the QR code -
-
- -
-
+
+ + +
+
+ +
+ + 10px +
+ Size of each QR code module (affects overall size)
- -
-

- - Live Preview -

-
-
-
- -
-
-
-
-
-
-
-
-
+
+ +
+ + 4 modules +
+ White border around the QR code +
+
+ + +
+ + + Higher levels allow QR code to work even if partially damaged +
+ + +
+

+ + Live Preview +

+
+
+
+ +
+
+
+
+
+
+
+
-
-

Sample QR Code Preview

-

Colors and styling will be applied to your actual QR code

-
+
+
+

Sample QR Code Preview

+

Colors and styling will be applied to your actual QR code

+
- - - - + + + + - -
- - - Cancel - - - -
- -
+ +
+ + + Cancel + + + +
+
+
- - - + + + - - - + } + + + + + + + + + \ No newline at end of file diff --git a/templates/edit_qr_code.html b/templates/edit_qr_code.html index cd3fdcb..88ea880 100644 --- a/templates/edit_qr_code.html +++ b/templates/edit_qr_code.html @@ -2,6 +2,29 @@ {% block title %}Edit QR Code - QR Management System{% endblock %} {% block extra_head %} +