refactor(api): 重构数据库访问为SQLAlchemy绑定的session
- 统一移除手动创建的数据库session,统一使用models模块中的db.session - 修正项目创建接口,增加开始和结束日期的格式验证与处理 - 更新导入项目接口,使用枚举类型校验项目类型并优化异常处理 - 更新统计接口,避免多次查询假期数据,优化日期字符串处理 - 删除回滚前多余的session关闭调用,改为使用db.session.rollback() - app.py中重构数据库初始化:统一配置SQLAlchemy,动态创建数据库路径和表 - 项目模型新增开始日期和结束日期字段支持 - 添加导入批次历史记录模型支持 - 优化工具函数中日期类型提示,移除无用导入 - 更新requirements.txt依赖版本回退,确保兼容性 - 前端菜单添加导入历史导航入口,实现页面访问路由绑定
This commit is contained in:
@@ -1,35 +1,25 @@
|
||||
from flask import Blueprint, request, jsonify
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from sqlalchemy import create_engine, and_
|
||||
from backend.models.models import TimeRecord, Project, CutoffPeriod
|
||||
from backend.models.utils import *
|
||||
from sqlalchemy import and_
|
||||
from models.models import db, TimeRecord, Project, CutoffPeriod, Holiday
|
||||
from models.utils import *
|
||||
from datetime import datetime, date, timedelta
|
||||
from collections import defaultdict
|
||||
|
||||
statistics_bp = Blueprint('statistics', __name__)
|
||||
|
||||
def get_db_session():
|
||||
"""获取数据库会话"""
|
||||
engine = create_engine('sqlite:///data/timetrack.db')
|
||||
Session = sessionmaker(bind=engine)
|
||||
return Session()
|
||||
|
||||
@statistics_bp.route('/api/statistics/weekly', methods=['GET'])
|
||||
def get_weekly_statistics():
|
||||
"""获取周统计数据"""
|
||||
try:
|
||||
session = get_db_session()
|
||||
|
||||
# 获取查询参数
|
||||
period_id = request.args.get('period_id')
|
||||
start_date = request.args.get('start_date')
|
||||
end_date = request.args.get('end_date')
|
||||
start_date_str = request.args.get('start_date')
|
||||
end_date_str = request.args.get('end_date')
|
||||
|
||||
# 如果指定了周期ID,使用周期的日期范围
|
||||
if period_id:
|
||||
period = session.query(CutoffPeriod).get(int(period_id))
|
||||
period = db.session.query(CutoffPeriod).get(int(period_id))
|
||||
if not period:
|
||||
session.close()
|
||||
return jsonify({'success': False, 'error': '周期不存在'}), 404
|
||||
|
||||
start_date = period.start_date
|
||||
@@ -38,12 +28,11 @@ def get_weekly_statistics():
|
||||
period_info = period.to_dict()
|
||||
else:
|
||||
# 使用指定的日期范围
|
||||
if not start_date or not end_date:
|
||||
session.close()
|
||||
if not start_date_str or not end_date_str:
|
||||
return jsonify({'success': False, 'error': '请提供开始日期和结束日期'}), 400
|
||||
|
||||
start_date = datetime.strptime(start_date, '%Y-%m-%d').date()
|
||||
end_date = datetime.strptime(end_date, '%Y-%m-%d').date()
|
||||
start_date = datetime.strptime(start_date_str, '%Y-%m-%d').date()
|
||||
end_date = datetime.strptime(end_date_str, '%Y-%m-%d').date()
|
||||
target_hours = 40 # 默认目标工时
|
||||
period_info = {
|
||||
'period_name': f"{start_date.strftime('%m月%d日')}-{end_date.strftime('%m月%d日')}",
|
||||
@@ -53,7 +42,7 @@ def get_weekly_statistics():
|
||||
}
|
||||
|
||||
# 查询该时间范围内的所有工时记录
|
||||
records = session.query(TimeRecord).filter(
|
||||
records = db.session.query(TimeRecord).filter(
|
||||
and_(TimeRecord.date >= start_date, TimeRecord.date <= end_date)
|
||||
).order_by(TimeRecord.date).all()
|
||||
|
||||
@@ -68,6 +57,9 @@ def get_weekly_statistics():
|
||||
record_dict[record.date] = []
|
||||
record_dict[record.date].append(record)
|
||||
|
||||
# 获取时间范围内的所有假期定义,避免在循环中重复查询
|
||||
holidays_in_range = db.session.query(Holiday).all()
|
||||
|
||||
# 生成每日汇总
|
||||
while current_date <= end_date:
|
||||
day_records = record_dict.get(current_date, [])
|
||||
@@ -104,8 +96,7 @@ def get_weekly_statistics():
|
||||
}
|
||||
else:
|
||||
# 如果没有记录,生成默认记录
|
||||
holidays = session.query(Holiday).all()
|
||||
holiday_info = is_holiday(current_date, holidays)
|
||||
holiday_info = is_holiday(current_date, holidays_in_range)
|
||||
|
||||
daily_record = {
|
||||
'date': current_date.isoformat(),
|
||||
@@ -183,7 +174,6 @@ def get_weekly_statistics():
|
||||
'completion_rate': round((workday_total + holiday_total) / target_hours * 100, 1) if target_hours > 0 else 0
|
||||
}
|
||||
|
||||
session.close()
|
||||
return jsonify({'success': True, 'data': result})
|
||||
|
||||
except Exception as e:
|
||||
@@ -193,14 +183,9 @@ def get_weekly_statistics():
|
||||
def get_cutoff_periods():
|
||||
"""获取Cut-Off周期列表"""
|
||||
try:
|
||||
session = get_db_session()
|
||||
|
||||
periods = session.query(CutoffPeriod).order_by(CutoffPeriod.start_date.desc()).all()
|
||||
periods = db.session.query(CutoffPeriod).order_by(CutoffPeriod.start_date.desc()).all()
|
||||
result = [period.to_dict() for period in periods]
|
||||
|
||||
session.close()
|
||||
return jsonify({'success': True, 'data': result})
|
||||
|
||||
except Exception as e:
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
@@ -209,7 +194,6 @@ def create_cutoff_period():
|
||||
"""创建Cut-Off周期"""
|
||||
try:
|
||||
data = request.json
|
||||
session = get_db_session()
|
||||
|
||||
# 验证必填字段
|
||||
if not all(key in data for key in ['period_name', 'start_date', 'end_date']):
|
||||
@@ -235,33 +219,29 @@ def create_cutoff_period():
|
||||
month=start_date.month
|
||||
)
|
||||
|
||||
session.add(period)
|
||||
session.commit()
|
||||
db.session.add(period)
|
||||
db.session.commit()
|
||||
|
||||
result = period.to_dict()
|
||||
session.close()
|
||||
|
||||
return jsonify({'success': True, 'data': result})
|
||||
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
@statistics_bp.route('/api/statistics/periods/<int:period_id>', methods=['DELETE'])
|
||||
def delete_cutoff_period(period_id):
|
||||
"""删除Cut-Off周期"""
|
||||
try:
|
||||
session = get_db_session()
|
||||
|
||||
period = session.query(CutoffPeriod).get(period_id)
|
||||
period = db.session.query(CutoffPeriod).get(period_id)
|
||||
if not period:
|
||||
session.close()
|
||||
return jsonify({'success': False, 'error': '周期不存在'}), 404
|
||||
|
||||
session.delete(period)
|
||||
session.commit()
|
||||
session.close()
|
||||
db.session.delete(period)
|
||||
db.session.commit()
|
||||
|
||||
return jsonify({'success': True, 'message': '周期已删除'})
|
||||
|
||||
except Exception as e:
|
||||
db.session.rollback()
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
Reference in New Issue
Block a user