""" Reports API endpoints. Provides endpoints for: - GET /api/reports - Get paginated list of reports - GET /api/reports/detail - Get report details - GET /api/reports/download - Download report file - POST /api/reports/delete - Delete a report """ import os from flask import jsonify, request, send_file, current_app from app.api import api_bp from app.services import login_required, get_current_user_from_context, get_accessible_reports from app.services.report_service import ReportService from app.models import Report, Task @api_bp.route('/reports', methods=['GET']) @login_required def get_reports(): """ Get paginated list of reports. Query Parameters: page: Page number (default: 1) page_size: Items per page (default: 20, max: 100) task_id: Optional filter by task ID Returns: JSON with 'data' array and 'pagination' object """ current_user = get_current_user_from_context() page = request.args.get('page', 1, type=int) # Support both pageSize (frontend) and page_size (backend convention) page_size = request.args.get('pageSize', type=int) or request.args.get('page_size', type=int) or 20 page_size = min(page_size, 100) task_id = request.args.get('task_id', type=int) # For regular users, only show their own reports user_id = None if current_user.role == 'user': user_id = current_user.id result = ReportService.get_reports( page=page, page_size=page_size, task_id=task_id, user_id=user_id ) return jsonify(result), 200 @api_bp.route('/reports/detail', methods=['GET']) @login_required def get_report_detail(): """ Get report details. Query Parameters: id: Report ID (required) Returns: JSON with report details """ current_user = get_current_user_from_context() report_id = request.args.get('id', type=int) if not report_id: return jsonify({'error': {'code': 'MISSING_PARAMETER', 'message': 'Report ID is required'}}), 400 report = ReportService.get_report_by_id(report_id) if not report: return jsonify({'error': {'code': 'NOT_FOUND', 'message': 'Report not found'}}), 404 # Check access for regular users if current_user.role == 'user': task = Task.query.get(report.task_id) if not task or task.created_by != current_user.id: return jsonify({'error': {'code': 'FORBIDDEN', 'message': 'Access denied'}}), 403 return jsonify(report.to_dict()), 200 @api_bp.route('/reports/download', methods=['GET']) @login_required def download_report(): """ Download a report file. Query Parameters: id: Report ID (required) Returns: The report file as attachment """ current_user = get_current_user_from_context() report_id = request.args.get('id', type=int) if not report_id: return jsonify({'error': {'code': 'MISSING_PARAMETER', 'message': 'Report ID is required'}}), 400 report = ReportService.get_report_by_id(report_id) if not report: return jsonify({'error': {'code': 'NOT_FOUND', 'message': 'Report not found'}}), 404 # Check access for regular users if current_user.role == 'user': task = Task.query.get(report.task_id) if not task or task.created_by != current_user.id: return jsonify({'error': {'code': 'FORBIDDEN', 'message': 'Access denied'}}), 403 # Get file path file_path = ReportService.get_report_file_path(report_id) if not file_path: return jsonify({'error': {'code': 'FILE_NOT_FOUND', 'message': 'Report file not found'}}), 404 return send_file( file_path, as_attachment=True, download_name=report.file_name, mimetype='application/vnd.openxmlformats-officedocument.wordprocessingml.document' ) @api_bp.route('/reports/delete', methods=['POST']) @login_required def delete_report(): """ Delete a report. Request Body: id: Report ID (required) Returns: JSON with success message """ current_user = get_current_user_from_context() data = request.get_json() or {} report_id = data.get('id') if not report_id: return jsonify({'error': {'code': 'MISSING_PARAMETER', 'message': 'Report ID is required'}}), 400 report = ReportService.get_report_by_id(report_id) if not report: return jsonify({'error': {'code': 'NOT_FOUND', 'message': 'Report not found'}}), 404 # Only admins can delete reports, or users can delete their own if current_user.role == 'user': task = Task.query.get(report.task_id) if not task or task.created_by != current_user.id: return jsonify({'error': {'code': 'FORBIDDEN', 'message': 'Access denied'}}), 403 success = ReportService.delete_report(report_id) if success: return jsonify({'message': 'Report deleted successfully'}), 200 else: return jsonify({'error': {'code': 'DELETE_FAILED', 'message': 'Failed to delete report'}}), 500