# app/blueprints/dashboard.py """ 대시보드 블루프린트 역할: - 데이터 통계 조회 (OKPOS, UPSolution, 날씨) - 주간 예보 조회 - 방문객 추이 차트 데이터 제공 """ from flask import Blueprint, render_template, jsonify, request from datetime import datetime, timedelta from sqlalchemy import select, func, desc import sys import os sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../..'))) from conf import db, db_schema dashboard_bp = Blueprint('dashboard', __name__, url_prefix='/api/dashboard') @dashboard_bp.route('/') def index(): """대시보드 페이지""" return render_template('dashboard.html') @dashboard_bp.route('/okpos-product', methods=['GET']) def get_okpos_product_stats(): """OKPOS 상품별 통계""" try: session = db.get_session() # 데이터 개수 total_records = session.query(db_schema.OkposProduct).count() # 데이터 보유 일수 earliest = session.query(func.min(db_schema.OkposProduct.data_date)).scalar() latest = session.query(func.max(db_schema.OkposProduct.data_date)).scalar() if earliest and latest: total_days = (latest - earliest).days + 1 last_date = latest.strftime('%Y-%m-%d') else: total_days = 0 last_date = None session.close() return jsonify({ 'total_records': total_records, 'total_days': total_days, 'last_date': last_date }) except Exception as e: return jsonify({'error': str(e)}), 500 @dashboard_bp.route('/okpos-receipt', methods=['GET']) def get_okpos_receipt_stats(): """OKPOS 영수증 통계""" try: session = db.get_session() total_records = session.query(db_schema.OkposReceipt).count() earliest = session.query(func.min(db_schema.OkposReceipt.receipt_date)).scalar() latest = session.query(func.max(db_schema.OkposReceipt.receipt_date)).scalar() if earliest and latest: total_days = (latest - earliest).days + 1 last_date = latest.strftime('%Y-%m-%d') else: total_days = 0 last_date = None session.close() return jsonify({ 'total_records': total_records, 'total_days': total_days, 'last_date': last_date }) except Exception as e: return jsonify({'error': str(e)}), 500 @dashboard_bp.route('/upsolution', methods=['GET']) def get_upsolution_stats(): """UPSolution 통계""" try: session = db.get_session() total_records = session.query(db_schema.Upsolution).count() earliest = session.query(func.min(db_schema.Upsolution.sales_date)).scalar() latest = session.query(func.max(db_schema.Upsolution.sales_date)).scalar() if earliest and latest: total_days = (latest - earliest).days + 1 last_date = latest.strftime('%Y-%m-%d') else: total_days = 0 last_date = None session.close() return jsonify({ 'total_records': total_records, 'total_days': total_days, 'last_date': last_date }) except Exception as e: return jsonify({'error': str(e)}), 500 @dashboard_bp.route('/weather', methods=['GET']) def get_weather_stats(): """날씨 데이터 통계""" try: session = db.get_session() total_records = session.query(db_schema.Weather).count() earliest = session.query(func.min(db_schema.Weather.date)).scalar() latest = session.query(func.max(db_schema.Weather.date)).scalar() if earliest and latest: total_days = (latest - earliest).days + 1 last_date = latest.strftime('%Y-%m-%d') else: total_days = 0 last_date = None session.close() return jsonify({ 'total_records': total_records, 'total_days': total_days, 'last_date': last_date }) except Exception as e: return jsonify({'error': str(e)}), 500 @dashboard_bp.route('/weekly-forecast', methods=['GET']) def get_weekly_forecast(): """이번주 예상 날씨 & 방문객""" try: session = db.get_session() # 오늘부터 7일간 데이터 조회 today = datetime.now().date() end_date = today + timedelta(days=6) forecast_data = [] for i in range(7): current_date = today + timedelta(days=i) day_name = ['월', '화', '수', '목', '금', '토', '일'][current_date.weekday()] # 날씨 데이터 weather = session.query(db_schema.Weather).filter( db_schema.Weather.date == current_date ).first() # 예상 방문객 (동일한 요일의 평균) same_day_visitors = session.query( func.avg(db_schema.DailyVisitor.visitors) ).filter( func.dayofweek(db_schema.DailyVisitor.visit_date) == (current_date.weekday() + 2) % 7 + 1 ).scalar() forecast_data.append({ 'date': current_date.strftime('%Y-%m-%d'), 'day': day_name, 'min_temp': weather.min_temp if weather else None, 'max_temp': weather.max_temp if weather else None, 'precipitation': weather.precipitation if weather else 0.0, 'humidity': weather.humidity if weather else None, 'expected_visitors': int(same_day_visitors) if same_day_visitors else 0 }) session.close() return jsonify({'forecast_data': forecast_data}) except Exception as e: return jsonify({'error': str(e)}), 500 @dashboard_bp.route('/visitor-trend', methods=['GET']) def get_visitor_trend(): """방문객 추이 데이터""" try: start_date_str = request.args.get('start_date') end_date_str = request.args.get('end_date') if not start_date_str or not end_date_str: return jsonify({'error': '날짜 범위를 지정하세요.'}), 400 start_date = datetime.strptime(start_date_str, '%Y-%m-%d').date() end_date = datetime.strptime(end_date_str, '%Y-%m-%d').date() session = db.get_session() visitors = session.query( db_schema.DailyVisitor.visit_date, db_schema.DailyVisitor.visitors ).filter( db_schema.DailyVisitor.visit_date.between(start_date, end_date) ).order_by(db_schema.DailyVisitor.visit_date).all() session.close() dates = [v[0].strftime('%Y-%m-%d') for v in visitors] visitor_counts = [v[1] for v in visitors] return jsonify({ 'dates': dates, 'visitors': visitor_counts }) except Exception as e: return jsonify({'error': str(e)}), 500