V1.0.0.5 - Refactor app.py: Split User, Session, and Admin logic into blueprints
This commit is contained in:
90
app.py
90
app.py
@@ -16,11 +16,14 @@ from db import query_db, execute_db, get_db
|
|||||||
from blueprints.data_imports import data_imports_bp
|
from blueprints.data_imports import data_imports_bp
|
||||||
from blueprints.users import users_bp
|
from blueprints.users import users_bp
|
||||||
from blueprints.sessions import sessions_bp
|
from blueprints.sessions import sessions_bp
|
||||||
from utils import login_required, role_required
|
from blueprints.admin_locations import admin_locations_bp
|
||||||
|
from utils import login_required
|
||||||
|
|
||||||
|
# Register Blueprints
|
||||||
app.register_blueprint(data_imports_bp)
|
app.register_blueprint(data_imports_bp)
|
||||||
app.register_blueprint(users_bp)
|
app.register_blueprint(users_bp)
|
||||||
app.register_blueprint(sessions_bp)
|
app.register_blueprint(sessions_bp)
|
||||||
|
app.register_blueprint(admin_locations_bp)
|
||||||
|
|
||||||
# V1.0: Use environment variable for production, fallback to demo key for development
|
# V1.0: Use environment variable for production, fallback to demo key for development
|
||||||
app.secret_key = os.environ.get('SCANLOOK_SECRET_KEY', 'scanlook-demo-key-replace-for-production')
|
app.secret_key = os.environ.get('SCANLOOK_SECRET_KEY', 'scanlook-demo-key-replace-for-production')
|
||||||
@@ -241,91 +244,6 @@ def complete_location(location_count_id):
|
|||||||
return jsonify({'success': True, 'message': 'Bin marked as complete'})
|
return jsonify({'success': True, 'message': 'Bin marked as complete'})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/location/<int:location_count_id>/reopen', methods=['POST'])
|
|
||||||
@login_required
|
|
||||||
def reopen_location(location_count_id):
|
|
||||||
"""Reopen a completed location (admin/owner only)"""
|
|
||||||
# Check permissions
|
|
||||||
user = query_db('SELECT role FROM Users WHERE user_id = ?', [session['user_id']], one=True)
|
|
||||||
if not user or user['role'] not in ['owner', 'admin']:
|
|
||||||
return jsonify({'success': False, 'message': 'Permission denied'}), 403
|
|
||||||
|
|
||||||
# Verify location exists
|
|
||||||
loc = query_db('SELECT * FROM LocationCounts WHERE location_count_id = ?', [location_count_id], one=True)
|
|
||||||
|
|
||||||
if not loc:
|
|
||||||
return jsonify({'success': False, 'message': 'Location not found'})
|
|
||||||
|
|
||||||
# Reopen the location
|
|
||||||
execute_db('''
|
|
||||||
UPDATE LocationCounts
|
|
||||||
SET status = 'in_progress', end_timestamp = NULL
|
|
||||||
WHERE location_count_id = ?
|
|
||||||
''', [location_count_id])
|
|
||||||
|
|
||||||
return jsonify({'success': True, 'message': 'Bin reopened for counting'})
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/location/<int:location_count_id>/delete', methods=['POST'])
|
|
||||||
@login_required
|
|
||||||
def delete_location_count(location_count_id):
|
|
||||||
"""Delete all counts for a location (soft delete)"""
|
|
||||||
# Verify ownership
|
|
||||||
loc = query_db('SELECT * FROM LocationCounts WHERE location_count_id = ?', [location_count_id], one=True)
|
|
||||||
|
|
||||||
if not loc:
|
|
||||||
return jsonify({'success': False, 'message': 'Location not found'})
|
|
||||||
|
|
||||||
if loc['counted_by'] != session['user_id'] and session['role'] not in ['owner', 'admin']:
|
|
||||||
return jsonify({'success': False, 'message': 'Permission denied'})
|
|
||||||
|
|
||||||
# Soft delete all scan entries for this location
|
|
||||||
execute_db('''
|
|
||||||
UPDATE ScanEntries
|
|
||||||
SET is_deleted = 1
|
|
||||||
WHERE location_count_id = ?
|
|
||||||
''', [location_count_id])
|
|
||||||
|
|
||||||
# Delete the location count record
|
|
||||||
execute_db('''
|
|
||||||
DELETE FROM LocationCounts
|
|
||||||
WHERE location_count_id = ?
|
|
||||||
''', [location_count_id])
|
|
||||||
|
|
||||||
return jsonify({'success': True, 'message': 'Bin count deleted'})
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/location/<int:location_count_id>/scans')
|
|
||||||
@login_required
|
|
||||||
def get_location_scans(location_count_id):
|
|
||||||
"""Get all scans for a specific location (admin/owner only)"""
|
|
||||||
# Check permissions
|
|
||||||
user = query_db('SELECT role FROM Users WHERE user_id = ?', [session['user_id']], one=True)
|
|
||||||
if not user or user['role'] not in ['owner', 'admin']:
|
|
||||||
return jsonify({'success': False, 'message': 'Permission denied'}), 403
|
|
||||||
|
|
||||||
try:
|
|
||||||
scans = query_db('''
|
|
||||||
SELECT
|
|
||||||
se.*,
|
|
||||||
bic.system_bin as current_system_location,
|
|
||||||
bic.system_quantity as current_system_weight
|
|
||||||
FROM ScanEntries se
|
|
||||||
LEFT JOIN BaselineInventory_Current bic ON se.lot_number = bic.lot_number
|
|
||||||
WHERE se.location_count_id = ?
|
|
||||||
AND se.is_deleted = 0
|
|
||||||
ORDER BY se.scan_timestamp DESC
|
|
||||||
''', [location_count_id])
|
|
||||||
|
|
||||||
# Convert Row objects to dicts
|
|
||||||
scans_list = [dict(scan) for scan in scans] if scans else []
|
|
||||||
|
|
||||||
return jsonify({'success': True, 'scans': scans_list})
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
return jsonify({'success': False, 'message': str(e)})
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/count/<int:session_id>/location/<int:location_count_id>')
|
@app.route('/count/<int:session_id>/location/<int:location_count_id>')
|
||||||
@login_required
|
@login_required
|
||||||
def count_location(session_id, location_count_id):
|
def count_location(session_id, location_count_id):
|
||||||
|
|||||||
BIN
blueprints/__pycache__/admin_locations.cpython-313.pyc
Normal file
BIN
blueprints/__pycache__/admin_locations.cpython-313.pyc
Normal file
Binary file not shown.
89
blueprints/admin_locations.py
Normal file
89
blueprints/admin_locations.py
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
from flask import Blueprint, jsonify, session
|
||||||
|
from db import query_db, execute_db
|
||||||
|
from utils import login_required
|
||||||
|
|
||||||
|
admin_locations_bp = Blueprint('admin_locations', __name__)
|
||||||
|
|
||||||
|
@admin_locations_bp.route('/location/<int:location_count_id>/reopen', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def reopen_location(location_count_id):
|
||||||
|
"""Reopen a completed location (admin/owner only)"""
|
||||||
|
# Check permissions
|
||||||
|
user = query_db('SELECT role FROM Users WHERE user_id = ?', [session['user_id']], one=True)
|
||||||
|
if not user or user['role'] not in ['owner', 'admin']:
|
||||||
|
return jsonify({'success': False, 'message': 'Permission denied'}), 403
|
||||||
|
|
||||||
|
# Verify location exists
|
||||||
|
loc = query_db('SELECT * FROM LocationCounts WHERE location_count_id = ?', [location_count_id], one=True)
|
||||||
|
|
||||||
|
if not loc:
|
||||||
|
return jsonify({'success': False, 'message': 'Location not found'})
|
||||||
|
|
||||||
|
# Reopen the location
|
||||||
|
execute_db('''
|
||||||
|
UPDATE LocationCounts
|
||||||
|
SET status = 'in_progress', end_timestamp = NULL
|
||||||
|
WHERE location_count_id = ?
|
||||||
|
''', [location_count_id])
|
||||||
|
|
||||||
|
return jsonify({'success': True, 'message': 'Bin reopened for counting'})
|
||||||
|
|
||||||
|
|
||||||
|
@admin_locations_bp.route('/location/<int:location_count_id>/delete', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def delete_location_count(location_count_id):
|
||||||
|
"""Delete all counts for a location (soft delete)"""
|
||||||
|
# Verify ownership
|
||||||
|
loc = query_db('SELECT * FROM LocationCounts WHERE location_count_id = ?', [location_count_id], one=True)
|
||||||
|
|
||||||
|
if not loc:
|
||||||
|
return jsonify({'success': False, 'message': 'Location not found'})
|
||||||
|
|
||||||
|
if loc['counted_by'] != session['user_id'] and session['role'] not in ['owner', 'admin']:
|
||||||
|
return jsonify({'success': False, 'message': 'Permission denied'})
|
||||||
|
|
||||||
|
# Soft delete all scan entries for this location
|
||||||
|
execute_db('''
|
||||||
|
UPDATE ScanEntries
|
||||||
|
SET is_deleted = 1
|
||||||
|
WHERE location_count_id = ?
|
||||||
|
''', [location_count_id])
|
||||||
|
|
||||||
|
# Delete the location count record
|
||||||
|
execute_db('''
|
||||||
|
DELETE FROM LocationCounts
|
||||||
|
WHERE location_count_id = ?
|
||||||
|
''', [location_count_id])
|
||||||
|
|
||||||
|
return jsonify({'success': True, 'message': 'Bin count deleted'})
|
||||||
|
|
||||||
|
|
||||||
|
@admin_locations_bp.route('/location/<int:location_count_id>/scans')
|
||||||
|
@login_required
|
||||||
|
def get_location_scans(location_count_id):
|
||||||
|
"""Get all scans for a specific location (admin/owner only)"""
|
||||||
|
# Check permissions
|
||||||
|
user = query_db('SELECT role FROM Users WHERE user_id = ?', [session['user_id']], one=True)
|
||||||
|
if not user or user['role'] not in ['owner', 'admin']:
|
||||||
|
return jsonify({'success': False, 'message': 'Permission denied'}), 403
|
||||||
|
|
||||||
|
try:
|
||||||
|
scans = query_db('''
|
||||||
|
SELECT
|
||||||
|
se.*,
|
||||||
|
bic.system_bin as current_system_location,
|
||||||
|
bic.system_quantity as current_system_weight
|
||||||
|
FROM ScanEntries se
|
||||||
|
LEFT JOIN BaselineInventory_Current bic ON se.lot_number = bic.lot_number
|
||||||
|
WHERE se.location_count_id = ?
|
||||||
|
AND se.is_deleted = 0
|
||||||
|
ORDER BY se.scan_timestamp DESC
|
||||||
|
''', [location_count_id])
|
||||||
|
|
||||||
|
# Convert Row objects to dicts
|
||||||
|
scans_list = [dict(scan) for scan in scans] if scans else []
|
||||||
|
|
||||||
|
return jsonify({'success': True, 'scans': scans_list})
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({'success': False, 'message': str(e)})
|
||||||
Binary file not shown.
Reference in New Issue
Block a user