March 17 2026: Fix bugs
This commit is contained in:
+2
-1
@@ -6,6 +6,7 @@ from app.models.audit import AuditLog
|
|||||||
from app.models.user import User
|
from app.models.user import User
|
||||||
from app.utils.decorators import admin_required
|
from app.utils.decorators import admin_required
|
||||||
from app.utils.audit import log_action, ACTION_DELETE
|
from app.utils.audit import log_action, ACTION_DELETE
|
||||||
|
from app.utils.time_utils import now_eastern
|
||||||
|
|
||||||
bp = Blueprint('audit', __name__, url_prefix='/audit')
|
bp = Blueprint('audit', __name__, url_prefix='/audit')
|
||||||
|
|
||||||
@@ -120,7 +121,7 @@ def purge():
|
|||||||
flash('Invalid purge threshold selected.', 'danger')
|
flash('Invalid purge threshold selected.', 'danger')
|
||||||
return redirect(url_for('audit.index'))
|
return redirect(url_for('audit.index'))
|
||||||
|
|
||||||
cutoff = datetime.utcnow() - timedelta(days=older_than)
|
cutoff = now_eastern() - timedelta(days=older_than)
|
||||||
deleted = AuditLog.query.filter(AuditLog.created_at < cutoff).delete()
|
deleted = AuditLog.query.filter(AuditLog.created_at < cutoff).delete()
|
||||||
db.session.flush()
|
db.session.flush()
|
||||||
|
|
||||||
|
|||||||
+41
-7
@@ -43,14 +43,47 @@ def index():
|
|||||||
.all()
|
.all()
|
||||||
)
|
)
|
||||||
|
|
||||||
# Pre-compute assignment summary per customer to avoid N+1 in template
|
customer_ids = [c.id for c in customers]
|
||||||
assignment_map = {} # user_id → list[CustomerAssignment]
|
|
||||||
scope_map = {} # user_id → list[int] facility IDs
|
|
||||||
|
|
||||||
|
# ── Single bulk query for all assignments ─────────────────────────────
|
||||||
|
# Replaces per-customer CustomerAssignment.query.filter_by(user_id=...) loop
|
||||||
|
all_assignments = (
|
||||||
|
CustomerAssignment.query
|
||||||
|
.filter(CustomerAssignment.user_id.in_(customer_ids))
|
||||||
|
.all()
|
||||||
|
) if customer_ids else []
|
||||||
|
|
||||||
|
assignment_map = {c.id: [] for c in customers}
|
||||||
|
for a in all_assignments:
|
||||||
|
assignment_map[a.user_id].append(a)
|
||||||
|
|
||||||
|
# ── Single bulk query for all active facilities in assigned projects ──
|
||||||
|
# Resolves facility scope for every customer without repeated DB round-trips.
|
||||||
|
from collections import defaultdict
|
||||||
|
assigned_project_ids = {a.project_id for a in all_assignments}
|
||||||
|
|
||||||
|
project_facilities_map = defaultdict(list) # project_id → [facility_id, ...]
|
||||||
|
if assigned_project_ids:
|
||||||
|
proj_facs = (
|
||||||
|
Facility.query
|
||||||
|
.filter(
|
||||||
|
Facility.project_id.in_(assigned_project_ids),
|
||||||
|
Facility.active == True,
|
||||||
|
)
|
||||||
|
.all()
|
||||||
|
)
|
||||||
|
for f in proj_facs:
|
||||||
|
project_facilities_map[f.project_id].append(f.id)
|
||||||
|
|
||||||
|
scope_map = {} # user_id → sorted list[int] facility IDs
|
||||||
for customer in customers:
|
for customer in customers:
|
||||||
assignments = CustomerAssignment.query.filter_by(user_id=customer.id).all()
|
ids = set()
|
||||||
assignment_map[customer.id] = assignments
|
for a in assignment_map[customer.id]:
|
||||||
scope_map[customer.id] = get_customer_scope(customer) or []
|
if a.facility_id:
|
||||||
|
ids.add(a.facility_id)
|
||||||
|
else:
|
||||||
|
ids.update(project_facilities_map.get(a.project_id, []))
|
||||||
|
scope_map[customer.id] = sorted(ids)
|
||||||
|
|
||||||
# All active projects for the assignment modal
|
# All active projects for the assignment modal
|
||||||
projects = Project.query.filter_by(active=True).order_by(Project.name).all()
|
projects = Project.query.filter_by(active=True).order_by(Project.name).all()
|
||||||
@@ -386,8 +419,9 @@ def bulk_import():
|
|||||||
facility_id = fac_id or None,
|
facility_id = fac_id or None,
|
||||||
)
|
)
|
||||||
db.session.add(assign)
|
db.session.add(assign)
|
||||||
|
db.session.flush() # populate assign.id before audit log
|
||||||
created_assign += 1
|
created_assign += 1
|
||||||
log_action(ACTION_CREATE, 'CustomerAssignment', 0,
|
log_action(ACTION_CREATE, 'CustomerAssignment', assign.id,
|
||||||
f'{uname} → project_id={proj_id}',
|
f'{uname} → project_id={proj_id}',
|
||||||
f'facility_id={fac_id}; source=bulk_import')
|
f'facility_id={fac_id}; source=bulk_import')
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -55,8 +55,7 @@ def _compute_next_send(frequency: str, from_dt: datetime = None) -> datetime:
|
|||||||
if frequency == 'daily':
|
if frequency == 'daily':
|
||||||
return (now + timedelta(days=1)).replace(hour=7, minute=0, second=0, microsecond=0)
|
return (now + timedelta(days=1)).replace(hour=7, minute=0, second=0, microsecond=0)
|
||||||
if frequency == 'weekly':
|
if frequency == 'weekly':
|
||||||
days_ahead = 7 - now.weekday() # next Monday
|
return (now + timedelta(weeks=1)).replace(hour=7, minute=0, second=0, microsecond=0)
|
||||||
return (now + timedelta(days=days_ahead)).replace(hour=7, minute=0, second=0, microsecond=0)
|
|
||||||
# monthly: first of next month
|
# monthly: first of next month
|
||||||
if now.month == 12:
|
if now.month == 12:
|
||||||
return now.replace(year=now.year + 1, month=1, day=1, hour=7, minute=0, second=0, microsecond=0)
|
return now.replace(year=now.year + 1, month=1, day=1, hour=7, minute=0, second=0, microsecond=0)
|
||||||
|
|||||||
@@ -108,6 +108,8 @@ def rename_template(template_id):
|
|||||||
template.frequency = new_frequency
|
template.frequency = new_frequency
|
||||||
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
log_action(ACTION_UPDATE, 'Template', template.id, template.name,
|
||||||
|
f'frequency={template.frequency}; via=rename')
|
||||||
flash(f'Template "{template.name}" updated successfully.', 'success')
|
flash(f'Template "{template.name}" updated successfully.', 'success')
|
||||||
return redirect(url_for('templates.index'))
|
return redirect(url_for('templates.index'))
|
||||||
|
|
||||||
@@ -258,6 +260,8 @@ def save_form_schema(template_id):
|
|||||||
|
|
||||||
template.form_schema = sanitised
|
template.form_schema = sanitised
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
log_action(ACTION_UPDATE, 'Template', template.id, template.name,
|
||||||
|
f'form_schema saved; field_count={len(sanitised)}')
|
||||||
|
|
||||||
return jsonify({'success': True, 'field_count': len(sanitised)})
|
return jsonify({'success': True, 'field_count': len(sanitised)})
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -112,7 +112,7 @@ def send_sla_alerts():
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
open_issues = Issue.query.filter(
|
open_issues = Issue.query.filter(
|
||||||
Issue.status.in_(['open', 'in_progress'])
|
Issue.status.in_(['open', 'in_progress', 'pending_verification'])
|
||||||
).all()
|
).all()
|
||||||
|
|
||||||
admins = User.query.filter_by(role='admin').all()
|
admins = User.query.filter_by(role='admin').all()
|
||||||
|
|||||||
Reference in New Issue
Block a user