nordabiz/blueprints/admin/routes_competitors.py
Maciej Pienczyn 02696c59a4
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
feat: Add new services, scripts, and competitor dashboard
- google_places_service.py: Google Places API integration
- competitor_monitoring_service.py: Competitor tracking service
- scripts/competitor_monitor_cron.py, scripts/generate_audit_report.py
- blueprints/admin/routes_competitors.py, templates/admin/competitor_dashboard.html

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 12:00:54 +01:00

158 lines
5.1 KiB
Python

"""
Admin Competitor Monitoring Routes
===================================
Dashboard for viewing and managing competitor tracking.
"""
import logging
from datetime import datetime, timedelta
from flask import render_template, request, jsonify, redirect, url_for
from flask_login import login_required, current_user
from . import bp
from database import (
SessionLocal, Company, CompanyCompetitor, CompetitorSnapshot,
GBPAudit, SystemRole
)
from utils.decorators import role_required
logger = logging.getLogger(__name__)
@bp.route('/competitors')
@login_required
@role_required(SystemRole.OFFICE_MANAGER)
def admin_competitors():
"""
Admin dashboard for competitor monitoring overview.
Displays:
- List of companies with active competitor tracking
- Competitor count per company
- Recent changes detected
"""
db = SessionLocal()
try:
# Get companies that have competitors tracked
companies_with_competitors = (
db.query(Company, db.query(CompanyCompetitor)
.filter(CompanyCompetitor.company_id == Company.id,
CompanyCompetitor.is_active == True)
.count().label('competitor_count'))
.filter(Company.status == 'active')
.all()
)
# Simpler approach: get all active competitors grouped by company
competitors = db.query(CompanyCompetitor).filter(
CompanyCompetitor.is_active == True
).all()
# Group by company
company_ids = set(c.company_id for c in competitors)
companies = db.query(Company).filter(
Company.id.in_(company_ids),
Company.status == 'active'
).all() if company_ids else []
company_data = []
for company in companies:
company_competitors = [c for c in competitors if c.company_id == company.id]
# Get GBP audit for this company (for comparison)
gbp_audit = db.query(GBPAudit).filter(
GBPAudit.company_id == company.id
).order_by(GBPAudit.audit_date.desc()).first()
company_data.append({
'company': company,
'competitor_count': len(company_competitors),
'competitors': company_competitors,
'gbp_audit': gbp_audit,
})
# Get recent snapshots with changes (last 30 days)
thirty_days_ago = datetime.now() - timedelta(days=30)
recent_changes = db.query(CompetitorSnapshot).filter(
CompetitorSnapshot.snapshot_date >= thirty_days_ago.date(),
CompetitorSnapshot.changes != None
).order_by(CompetitorSnapshot.snapshot_date.desc()).limit(20).all()
return render_template('admin/competitor_dashboard.html',
company_data=company_data,
recent_changes=recent_changes,
total_companies=len(company_data),
total_competitors=len(competitors),
)
finally:
db.close()
@bp.route('/competitors/<int:company_id>')
@login_required
@role_required(SystemRole.OFFICE_MANAGER)
def admin_competitor_detail(company_id):
"""
Detailed competitor view for a specific company.
Shows:
- Company's GBP metrics vs competitors
- Competitor list with current metrics
- Timeline of changes
"""
db = SessionLocal()
try:
company = db.query(Company).get(company_id)
if not company:
return redirect(url_for('admin.admin_competitors'))
# Get company's own GBP audit
gbp_audit = db.query(GBPAudit).filter(
GBPAudit.company_id == company.id
).order_by(GBPAudit.audit_date.desc()).first()
# Get competitors
competitors = db.query(CompanyCompetitor).filter(
CompanyCompetitor.company_id == company.id,
CompanyCompetitor.is_active == True
).all()
# Get latest snapshots for each competitor
competitor_data = []
for comp in competitors:
latest_snapshot = db.query(CompetitorSnapshot).filter(
CompetitorSnapshot.competitor_id == comp.id
).order_by(CompetitorSnapshot.snapshot_date.desc()).first()
competitor_data.append({
'competitor': comp,
'latest_snapshot': latest_snapshot,
})
# Get all snapshots with changes (for timeline)
competitor_ids = [c.id for c in competitors]
timeline = []
if competitor_ids:
timeline = db.query(CompetitorSnapshot).filter(
CompetitorSnapshot.competitor_id.in_(competitor_ids),
CompetitorSnapshot.changes != None
).order_by(CompetitorSnapshot.snapshot_date.desc()).limit(30).all()
return render_template('admin/competitor_dashboard.html',
company=company,
gbp_audit=gbp_audit,
competitor_data=competitor_data,
timeline=timeline,
detail_view=True,
total_companies=0,
total_competitors=len(competitors),
company_data=[],
recent_changes=[],
)
finally:
db.close()