from flask import request, jsonify from app import db from app.api import bp from app.models import Printer, PrintJob from app.auth.routes import token_required, admin_required from datetime import datetime @bp.route('/printers', methods=['GET']) def get_printers(): """Get all printers""" printers = Printer.query.all() result = [] for printer in printers: # Get active job for the printer if any now = datetime.utcnow() active_job = PrintJob.query.filter_by(printer_id=printer.id, aborted=False) \ .filter(PrintJob.start_at <= now) \ .filter(PrintJob.start_at.op('+')(PrintJob.duration_in_minutes * 60) > now) \ .first() printer_data = { 'id': printer.id, 'name': printer.name, 'description': printer.description, 'status': printer.status, 'is_available': printer.status == 0 and active_job is None, 'active_job': active_job.to_dict() if active_job else None } result.append(printer_data) return jsonify(result) @bp.route('/printers/', methods=['GET']) def get_printer(printer_id): """Get a specific printer""" printer = Printer.query.get_or_404(printer_id) # Get active job for the printer if any now = datetime.utcnow() active_job = PrintJob.query.filter_by(printer_id=printer.id, aborted=False) \ .filter(PrintJob.start_at <= now) \ .filter(PrintJob.start_at.op('+')(PrintJob.duration_in_minutes * 60) > now) \ .first() # Get upcoming jobs upcoming_jobs = PrintJob.query.filter_by(printer_id=printer.id, aborted=False) \ .filter(PrintJob.start_at > now) \ .order_by(PrintJob.start_at) \ .limit(5) \ .all() result = { 'id': printer.id, 'name': printer.name, 'description': printer.description, 'status': printer.status, 'is_available': printer.status == 0 and active_job is None, 'active_job': active_job.to_dict() if active_job else None, 'upcoming_jobs': [job.to_dict() for job in upcoming_jobs] } return jsonify(result) @bp.route('/printers', methods=['POST']) @admin_required def create_printer(): """Create a new printer (admin only)""" data = request.get_json() or {} required_fields = ['name', 'description'] for field in required_fields: if field not in data: return jsonify({'error': f'Missing required field: {field}'}), 400 printer = Printer( name=data['name'], description=data['description'], status=data.get('status', 0) ) db.session.add(printer) db.session.commit() return jsonify({ 'id': printer.id, 'name': printer.name, 'description': printer.description, 'status': printer.status }), 201 @bp.route('/printers/', methods=['PUT']) @admin_required def update_printer(printer_id): """Update a printer (admin only)""" printer = Printer.query.get_or_404(printer_id) data = request.get_json() or {} if 'name' in data: printer.name = data['name'] if 'description' in data: printer.description = data['description'] if 'status' in data: printer.status = data['status'] db.session.commit() return jsonify({ 'id': printer.id, 'name': printer.name, 'description': printer.description, 'status': printer.status }) @bp.route('/printers/', methods=['DELETE']) @admin_required def delete_printer(printer_id): """Delete a printer (admin only)""" printer = Printer.query.get_or_404(printer_id) # Check if the printer has active jobs now = datetime.utcnow() active_jobs = PrintJob.query.filter_by(printer_id=printer.id, aborted=False) \ .filter(PrintJob.start_at <= now) \ .filter(PrintJob.start_at.op('+')(PrintJob.duration_in_minutes * 60) > now) \ .all() if active_jobs: return jsonify({'error': 'Cannot delete printer with active jobs'}), 400 db.session.delete(printer) db.session.commit() return jsonify({'message': 'Printer deleted successfully'}) @bp.route('/printers/availability', methods=['GET']) def get_availability(): """Get availability information for all printers""" start_date = request.args.get('start_date') end_date = request.args.get('end_date') if not start_date or not end_date: return jsonify({'error': 'start_date and end_date are required'}), 400 try: start = datetime.fromisoformat(start_date.replace('Z', '+00:00')) end = datetime.fromisoformat(end_date.replace('Z', '+00:00')) except ValueError: return jsonify({'error': 'Invalid date format'}), 400 if start >= end: return jsonify({'error': 'start_date must be before end_date'}), 400 printers = Printer.query.all() result = [] for printer in printers: # Get all jobs for this printer in the date range jobs = PrintJob.query.filter_by(printer_id=printer.id, aborted=False) \ .filter( (PrintJob.start_at <= end) & (PrintJob.start_at.op('+')(PrintJob.duration_in_minutes * 60) >= start) ) \ .order_by(PrintJob.start_at) \ .all() # Convert to availability slots availability = { 'printer_id': printer.id, 'printer_name': printer.name, 'status': printer.status, 'jobs': [job.to_dict() for job in jobs] } result.append(availability) return jsonify(result)