# app.py (Full updated code) from flask import Flask, render_template, request, redirect, url_for, session, flash, abort, send_file, make_response, send_from_directory, jsonify from flask_sqlalchemy import SQLAlchemy from werkzeug.security import generate_password_hash, check_password_hash from werkzeug.utils import secure_filename from datetime import datetime, date import os import json import razorpay from io import BytesIO from reportlab.pdfgen import canvas from reportlab.lib.pagesizes import letter import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.mime.application import MIMEApplication import requests from flask import jsonify app = Flask(__name__) app.config['SECRET_KEY'] = 'your_secret_key' app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///hospital.db' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['RAZORPAY_KEY_ID'] = 'rzp_test_RPURGWwDtViv9P' # Enter your Razorpay key here app.config['RAZORPAY_KEY_SECRET'] = 'gHB7AScqU12PUikgM7Fibsu3' # Enter your Razorpay secret here app.config['UPLOAD_FOLDER'] = 'uploads' app.config['SENDER_EMAIL'] = 'harshvardhandhane13@gmail.com' app.config['SENDER_PASSWORD'] = 'ipde veha zmzs hhlb' # Add to app.config after existing configs app.config['OPENROUTER_API_KEY'] = "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" app.config['OPENROUTER_URL'] = "https://openrouter.ai/api/v1/chat/completions" app.config['MODEL'] = "openai/gpt-oss-20b:free" db = SQLAlchemy(app) razorpay_client = razorpay.Client(auth=(app.config['RAZORPAY_KEY_ID'], app.config['RAZORPAY_KEY_SECRET'])) def send_email(to_email, subject, body, pdf_buffer=None): msg = MIMEMultipart() msg['From'] = app.config['SENDER_EMAIL'] msg['To'] = to_email msg['Subject'] = subject msg.attach(MIMEText(body, 'plain')) if pdf_buffer: pdf_buffer.seek(0) attach = MIMEApplication(pdf_buffer.getvalue(), _subtype='pdf') attach.add_header('Content-Disposition', 'attachment', filename='bill.pdf') msg.attach(attach) try: server = smtplib.SMTP('smtp.gmail.com', 587) server.starttls() server.login(app.config['SENDER_EMAIL'], app.config['SENDER_PASSWORD']) text = msg.as_string() server.sendmail(app.config['SENDER_EMAIL'], to_email, text) server.quit() return True except Exception as e: print(f"Email send failed: {e}") return False def generate_booking_bill_pdf(booking, bed, room): buffer = BytesIO() p = canvas.Canvas(buffer, pagesize=letter) p.drawString(100, 750, "Hospital Bill") y = 700 p.drawString(100, y, f"Patient Name: {booking.patient_name}") y -= 20 p.drawString(100, y, f"Age: {booking.age}") y -= 20 p.drawString(100, y, f"Contact: {booking.contact_number}") y -= 20 p.drawString(100, y, f"Check-in Date: {booking.check_in_date}") y -= 20 p.drawString(100, y, f"Estimated Stay: {booking.estimated_stay} days") y -= 20 p.drawString(100, y, f"Room: {room.name}") y -= 20 p.drawString(100, y, f"Bed: {bed.bed_number}") y -= 20 p.drawString(100, y, f"Price per day: ₹{room.price_per_bed}") y -= 20 p.drawString(100, y, f"Total Amount: ₹{room.price_per_bed * booking.estimated_stay}") p.save() return buffer def generate_appointment_bill_pdf(appointment, time_slot): buffer = BytesIO() p = canvas.Canvas(buffer, pagesize=letter) p.drawString(100, 750, "Appointment Bill") y = 700 p.drawString(100, y, f"Patient Name: {appointment.patient.name}") y -= 20 p.drawString(100, y, f"Doctor Name: {appointment.doctor.name}") y -= 20 p.drawString(100, y, f"Appointment Date: {appointment.appointment_date}") y -= 20 p.drawString(100, y, f"Time Slot: {time_slot.start_time} - {time_slot.end_time}") y -= 20 p.drawString(100, y, f"Amount: ₹{time_slot.price}") p.save() return buffer def generate_ambulance_bill_pdf(booking, vehicle): buffer = BytesIO() p = canvas.Canvas(buffer, pagesize=letter) p.drawString(100, 750, "Ambulance Bill") y = 700 p.drawString(100, y, f"Patient Name: {booking.patient.name}") y -= 20 p.drawString(100, y, f"Vehicle: {vehicle.name}") y -= 20 p.drawString(100, y, f"Numberplate: {vehicle.numberplate}") y -= 20 p.drawString(100, y, f"Use Type: {booking.use_type}") if booking.location_link: y -= 20 p.drawString(100, y, f"Location Link: {booking.location_link}") y -= 20 p.drawString(100, y, f"Amount: ₹{booking.amount}") p.save() return buffer def generate_nurse_bill_pdf(booking, nurse): buffer = BytesIO() p = canvas.Canvas(buffer, pagesize=letter) p.drawString(100, 750, "Nurse Booking Bill") y = 700 p.drawString(100, y, f"Patient Name: {booking.patient.name}") y -= 20 p.drawString(100, y, f"Nurse Name: {nurse.name}") y -= 20 p.drawString(100, y, f"Duration Type: {booking.duration_type}") y -= 20 p.drawString(100, y, f"Location: {booking.location}") y -= 20 p.drawString(100, y, f"Amount: ₹{booking.amount}") p.save() return buffer def generate_canteen_bill_pdf(order): buffer = BytesIO() p = canvas.Canvas(buffer, pagesize=letter) p.drawString(100, 750, "Canteen Bill") y = 700 p.drawString(100, y, f"Patient Name: {order.patient.name}") y -= 20 p.drawString(100, y, f"Order ID: {order.id}") y -= 20 p.drawString(100, y, f"Date: {order.created_at.strftime('%Y-%m-%d %H:%M')}") if order.room_id: room = Room.query.get(order.room_id) y -= 20 p.drawString(100, y, f"Delivery Room: {room.name}") if order.bed_id: bed = Bed.query.get(order.bed_id) y -= 20 p.drawString(100, y, f"Delivery Bed: {bed.bed_number}") y -= 20 total = 0 for item in order.items: p.drawString(100, y, f"{item.item.name} x {item.quantity}: ₹{item.item.price * item.quantity}") y -= 20 total += item.item.price * item.quantity p.drawString(100, y, f"Total Amount: ₹{total}") p.save() return buffer # Add this function after the generate_canteen_bill_pdf function def call_openrouter(messages): headers = { "Authorization": f"Bearer {app.config['OPENROUTER_API_KEY']}", "Content-Type": "application/json", "HTTP-Referer": url_for('index', _external=True), # Optional, for OpenRouter "X-Title": "Hospital AI Bot" # Optional } data = { "model": app.config['MODEL'], "messages": messages, "max_tokens": 500, "temperature": 0.7 } try: response = requests.post(app.config['OPENROUTER_URL'], headers=headers, json=data) if response.status_code == 200: return response.json()['choices'][0]['message']['content'] else: print(f"OpenRouter error: {response.text}") return "Sorry, I'm having trouble responding right now. Please try again." except Exception as e: print(f"OpenRouter call failed: {e}") return "Sorry, I'm having trouble connecting. Please try again." # Models (unchanged from provided) class Hospital(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100), nullable=False) username = db.Column(db.String(50), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) mobile = db.Column(db.String(20), nullable=False) password = db.Column(db.String(255), nullable=False) info= db.Column(db.Text, nullable=True) class Doctor(db.Model): id = db.Column(db.Integer, primary_key=True) hospital_id = db.Column(db.Integer, db.ForeignKey('hospital.id'), nullable=False) name = db.Column(db.String(100), nullable=False) username = db.Column(db.String(50), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) mobile = db.Column(db.String(20), nullable=False) password = db.Column(db.String(255), nullable=False) info = db.Column(db.Text, nullable=True) # Professional Information qualifications = db.Column(db.Text, nullable=True) specializations = db.Column(db.Text, nullable=True) practice_years = db.Column(db.Integer, nullable=True) additional_links = db.Column(db.Text, nullable=True) practice_location = db.Column(db.String(255), nullable=True) time_slots = db.relationship('TimeSlot', backref='doctor', lazy=True, cascade="all, delete-orphan") medical_records = db.relationship('MedicalRecord', backref='doctor', lazy=True, cascade="all, delete-orphan") appointments = db.relationship('Appointment', backref='doctor', lazy=True, cascade="all, delete-orphan") doctor_reviews = db.relationship('DoctorReview', backref='doctor', lazy=True, cascade="all, delete-orphan") class TimeSlot(db.Model): id = db.Column(db.Integer, primary_key=True) doctor_id = db.Column(db.Integer, db.ForeignKey('doctor.id'), nullable=False) start_time = db.Column(db.String(5), nullable=False) # e.g., '09:00' end_time = db.Column(db.String(5), nullable=False) # e.g., '10:00' price = db.Column(db.Float, nullable=False) appointments = db.relationship('Appointment', backref='time_slot', lazy=True) class Appointment(db.Model): id = db.Column(db.Integer, primary_key=True) doctor_id = db.Column(db.Integer, db.ForeignKey('doctor.id'), nullable=False) patient_id = db.Column(db.Integer, db.ForeignKey('patient.id'), nullable=False) appointment_date = db.Column(db.Date, nullable=False) time_slot_id = db.Column(db.Integer, db.ForeignKey('time_slot.id'), nullable=False) status = db.Column(db.String(20), default='pending') created_at = db.Column(db.DateTime, default=datetime.utcnow) class MedicalRecord(db.Model): id = db.Column(db.Integer, primary_key=True) doctor_id = db.Column(db.Integer, db.ForeignKey('doctor.id'), nullable=False) patient_name = db.Column(db.String(100), nullable=False) age = db.Column(db.Integer, nullable=False) mobile = db.Column(db.String(20), nullable=False) medical_condition = db.Column(db.Text, nullable=True) file_path = db.Column(db.String(255), nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow) class Ambulance(db.Model): id = db.Column(db.Integer, primary_key=True) hospital_id = db.Column(db.Integer, db.ForeignKey('hospital.id'), nullable=False) name = db.Column(db.String(100), nullable=False) username = db.Column(db.String(50), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) mobile = db.Column(db.String(20), nullable=False) password = db.Column(db.String(255), nullable=False) info = db.Column(db.Text, nullable=True) status = db.Column(db.String(20), default='available') # available, on duty, under maintenance vehicles = db.relationship('AmbulanceVehicle', backref='ambulance', lazy=True, cascade="all, delete-orphan") bookings = db.relationship('AmbulanceBooking', backref='ambulance', lazy=True, cascade="all, delete-orphan") reviews = db.relationship('AmbulanceReview', backref='ambulance', lazy=True, cascade="all, delete-orphan") class AmbulanceVehicle(db.Model): id = db.Column(db.Integer, primary_key=True) ambulance_id = db.Column(db.Integer, db.ForeignKey('ambulance.id'), nullable=False) name = db.Column(db.String(100), nullable=False) numberplate = db.Column(db.String(50), nullable=False) cost_price = db.Column(db.Float, nullable=False) medical_support = db.Column(db.Text, nullable=True) image_path = db.Column(db.String(255), nullable=True) bookings = db.relationship('AmbulanceBooking', backref='vehicle', lazy=True) class AmbulanceBooking(db.Model): id = db.Column(db.Integer, primary_key=True) ambulance_id = db.Column(db.Integer, db.ForeignKey('ambulance.id'), nullable=False) vehicle_id = db.Column(db.Integer, db.ForeignKey('ambulance_vehicle.id'), nullable=False) patient_id = db.Column(db.Integer, db.ForeignKey('patient.id'), nullable=False) status = db.Column(db.String(20), default='pending') payment_status = db.Column(db.String(20), default='unpaid') use_type = db.Column(db.String(20), nullable=False) # emergency or normal location_link = db.Column(db.Text, nullable=True) # patient's for emergency, ambulance's for normal live_location_link = db.Column(db.Text, nullable=True) # ambulance's live link for normal amount = db.Column(db.Float, nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow) class AmbulanceReview(db.Model): id = db.Column(db.Integer, primary_key=True) ambulance_id = db.Column(db.Integer, db.ForeignKey('ambulance.id'), nullable=False) patient_id = db.Column(db.Integer, db.ForeignKey('patient.id'), nullable=False) rating = db.Column(db.Integer, nullable=False) text = db.Column(db.Text, nullable=True) created_at = db.Column(db.DateTime, default=datetime.utcnow) class Nurse(db.Model): id = db.Column(db.Integer, primary_key=True) hospital_id = db.Column(db.Integer, db.ForeignKey('hospital.id'), nullable=False) name = db.Column(db.String(100), nullable=False) username = db.Column(db.String(50), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) mobile = db.Column(db.String(20), nullable=False) password = db.Column(db.String(255), nullable=False) info = db.Column(db.Text, nullable=True) availability_locations = db.Column(db.String(50), nullable=True) # e.g., 'home,hospital' status = db.Column(db.String(20), default='available') # available, booked bookings = db.relationship('NurseBooking', backref='nurse', lazy=True, cascade="all, delete-orphan") nurse_reviews = db.relationship('NurseReview', backref='nurse', lazy=True, cascade="all, delete-orphan") rates = db.relationship('NurseRate', backref='nurse', lazy=True, cascade="all, delete-orphan") class NurseRate(db.Model): id = db.Column(db.Integer, primary_key=True) nurse_id = db.Column(db.Integer, db.ForeignKey('nurse.id'), nullable=False) rate_type = db.Column(db.String(50), nullable=False) # 'per_hour_home', 'per_hour_hospital', 'per_day_home', 'per_day_hospital' price = db.Column(db.Float, nullable=False) class NurseBooking(db.Model): id = db.Column(db.Integer, primary_key=True) nurse_id = db.Column(db.Integer, db.ForeignKey('nurse.id'), nullable=False) patient_id = db.Column(db.Integer, db.ForeignKey('patient.id'), nullable=False) status = db.Column(db.String(20), default='pending') # pending, accepted, paid, rejected duration_type = db.Column(db.String(20), nullable=False) # 'per_hour', 'per_day' location = db.Column(db.String(20), nullable=False) # 'home', 'hospital' amount = db.Column(db.Float, nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow) class NurseReview(db.Model): id = db.Column(db.Integer, primary_key=True) nurse_id = db.Column(db.Integer, db.ForeignKey('nurse.id'), nullable=False) patient_id = db.Column(db.Integer, db.ForeignKey('patient.id'), nullable=False) rating = db.Column(db.Integer, nullable=False) text = db.Column(db.Text, nullable=True) created_at = db.Column(db.DateTime, default=datetime.utcnow) class Canteen(db.Model): id = db.Column(db.Integer, primary_key=True) hospital_id = db.Column(db.Integer, db.ForeignKey('hospital.id'), nullable=False) name = db.Column(db.String(100), nullable=False) username = db.Column(db.String(50), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) mobile = db.Column(db.String(20), nullable=False) password = db.Column(db.String(255), nullable=False) info = db.Column(db.Text, nullable=True) categories = db.relationship('CanteenCategory', backref='canteen', lazy=True, cascade="all, delete-orphan") orders = db.relationship('CanteenOrder', backref='canteen', lazy=True, cascade="all, delete-orphan") reviews = db.relationship('CanteenReview', backref='canteen', lazy=True, cascade="all, delete-orphan") class CanteenCategory(db.Model): id = db.Column(db.Integer, primary_key=True) canteen_id = db.Column(db.Integer, db.ForeignKey('canteen.id'), nullable=False) name = db.Column(db.String(100), nullable=False) items = db.relationship('CanteenItem', backref='category', lazy=True, cascade="all, delete-orphan") class CanteenItem(db.Model): id = db.Column(db.Integer, primary_key=True) category_id = db.Column(db.Integer, db.ForeignKey('canteen_category.id'), nullable=False) name = db.Column(db.String(100), nullable=False) price = db.Column(db.Float, nullable=False) class CanteenOrder(db.Model): __tablename__ = 'canteen_order' id = db.Column(db.Integer, primary_key=True) canteen_id = db.Column(db.Integer, db.ForeignKey('canteen.id'), nullable=False) patient_id = db.Column(db.Integer, db.ForeignKey('patient.id'), nullable=False) room_id = db.Column(db.Integer, db.ForeignKey('room.id'), nullable=True) # New field bed_id = db.Column(db.Integer, db.ForeignKey('bed.id'), nullable=True) # New field status = db.Column(db.String(20), default='pending') # pending, accepted, paid, preparing, out_for_delivery, delivered payment_status = db.Column(db.String(20), default='unpaid') created_at = db.Column(db.DateTime, default=datetime.utcnow) items = db.relationship('CanteenOrderItem', backref='order', lazy=True, cascade="all, delete-orphan") class CanteenOrderItem(db.Model): __tablename__ = 'canteen_order_item' id = db.Column(db.Integer, primary_key=True) order_id = db.Column(db.Integer, db.ForeignKey('canteen_order.id'), nullable=False) item_id = db.Column(db.Integer, db.ForeignKey('canteen_item.id'), nullable=False) quantity = db.Column(db.Integer, nullable=False) item = db.relationship('CanteenItem') class CanteenReview(db.Model): id = db.Column(db.Integer, primary_key=True) canteen_id = db.Column(db.Integer, db.ForeignKey('canteen.id'), nullable=False) patient_id = db.Column(db.Integer, db.ForeignKey('patient.id'), nullable=False) rating = db.Column(db.Integer, nullable=False) text = db.Column(db.Text, nullable=True) created_at = db.Column(db.DateTime, default=datetime.utcnow) class Patient(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100), nullable=False) username = db.Column(db.String(50), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) mobile = db.Column(db.String(20), nullable=False) password = db.Column(db.String(255), nullable=False) info = db.Column(db.Text, nullable=True) appointments = db.relationship('Appointment', backref='patient', lazy=True, cascade="all, delete-orphan") reviews = db.relationship('Review', backref='patient', lazy=True, cascade="all, delete-orphan") doctor_reviews = db.relationship('DoctorReview', backref='patient', lazy=True, cascade="all, delete-orphan") ambulance_bookings = db.relationship('AmbulanceBooking', backref='patient', lazy=True, cascade="all, delete-orphan") ambulance_reviews = db.relationship('AmbulanceReview', backref='patient', lazy=True, cascade="all, delete-orphan") nurse_bookings = db.relationship('NurseBooking', backref='patient', lazy=True, cascade="all, delete-orphan") nurse_reviews = db.relationship('NurseReview', backref='patient', lazy=True, cascade="all, delete-orphan") canteen_orders = db.relationship('CanteenOrder', backref='patient', lazy=True, cascade="all, delete-orphan") canteen_reviews = db.relationship('CanteenReview', backref='patient', lazy=True, cascade="all, delete-orphan") class Room(db.Model): id = db.Column(db.Integer, primary_key=True) hospital_id = db.Column(db.Integer, db.ForeignKey('hospital.id'), nullable=False) name = db.Column(db.String(100), nullable=False) num_beds = db.Column(db.Integer, nullable=False) price_per_bed = db.Column(db.Float, nullable=False) description = db.Column(db.Text, nullable=True) beds = db.relationship('Bed', backref='room', lazy=True, cascade="all, delete-orphan") reviews = db.relationship('Review', backref='room', lazy=True, cascade="all, delete-orphan") class Bed(db.Model): id = db.Column(db.Integer, primary_key=True) room_id = db.Column(db.Integer, db.ForeignKey('room.id'), nullable=False) bed_number = db.Column(db.Integer, nullable=False) status = db.Column(db.String(20), default='available') position = db.Column(db.String(50), nullable=True) bookings = db.relationship('Booking', backref='bed', lazy=True, cascade="all, delete-orphan") class Booking(db.Model): id = db.Column(db.Integer, primary_key=True) bed_id = db.Column(db.Integer, db.ForeignKey('bed.id'), nullable=False) patient_id = db.Column(db.Integer, db.ForeignKey('patient.id'), nullable=False) status = db.Column(db.String(20), default='pending') patient_name = db.Column(db.String(100)) contact_number = db.Column(db.String(20)) age = db.Column(db.Integer) medical_condition = db.Column(db.Text) estimated_stay = db.Column(db.Integer) check_in_date = db.Column(db.Date, nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow) class Review(db.Model): id = db.Column(db.Integer, primary_key=True) room_id = db.Column(db.Integer, db.ForeignKey('room.id'), nullable=False) patient_id = db.Column(db.Integer, db.ForeignKey('patient.id'), nullable=False) rating = db.Column(db.Integer, nullable=False) text = db.Column(db.Text, nullable=True) created_at = db.Column(db.DateTime, default=datetime.utcnow) class DoctorReview(db.Model): id = db.Column(db.Integer, primary_key=True) doctor_id = db.Column(db.Integer, db.ForeignKey('doctor.id'), nullable=False) patient_id = db.Column(db.Integer, db.ForeignKey('patient.id'), nullable=False) rating = db.Column(db.Integer, nullable=False) text = db.Column(db.Text, nullable=True) created_at = db.Column(db.DateTime, default=datetime.utcnow) # Create database with app.app_context(): db.create_all() @app.route('/uploads/') def uploaded_file(filename): return send_from_directory(app.config['UPLOAD_FOLDER'], filename) # Routes (all existing + updated for canteen) @app.route('/') def index(): return render_template('index.html') # Hospital Admin Routes (unchanged) @app.route('/admin/login', methods=['GET', 'POST']) def admin_login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] hospital = Hospital.query.filter_by(username=username).first() if hospital and check_password_hash(hospital.password, password): session['admin_user_id'] = hospital.id return redirect(url_for('admin_dashboard')) flash('Invalid username or password') return render_template('admin_login.html') @app.route('/admin/register', methods=['GET', 'POST']) def admin_register(): if request.method == 'POST': name = request.form['name'] username = request.form['username'] email = request.form['email'] mobile = request.form['mobile'] password = request.form['password'] confirm_password = request.form['confirm_password'] if password != confirm_password: flash('Passwords do not match') return render_template('admin_register.html') if Hospital.query.filter_by(username=username).first() or Hospital.query.filter_by(email=email).first(): flash('Username or email already exists') return render_template('admin_register.html') hashed_password = generate_password_hash(password) new_hospital = Hospital(name=name, username=username, email=email, mobile=mobile, password=hashed_password) db.session.add(new_hospital) db.session.commit() return redirect(url_for('admin_login')) return render_template('admin_register.html') @app.route('/admin/dashboard', methods=['GET', 'POST']) def admin_dashboard(): if 'admin_user_id' not in session: return redirect(url_for('admin_login')) hospital = Hospital.query.get(session['admin_user_id']) if request.method == 'POST' and 'edit' in request.form: hospital.name = request.form['name'] hospital.mobile = request.form['mobile'] hospital.email = request.form['email'] hospital.info = request.form['info'] db.session.commit() flash('Details updated') return render_template('admin_dashboard.html', hospital=hospital) @app.route('/admin/doctors', methods=['GET', 'POST']) def admin_doctors(): if 'admin_user_id' not in session: return redirect(url_for('admin_login')) hospital_id = session['admin_user_id'] doctors = Doctor.query.filter_by(hospital_id=hospital_id).all() if request.method == 'POST' and 'add' in request.form: name = request.form['name'] username = request.form['username'] email = request.form['email'] mobile = request.form['mobile'] password = request.form['password'] confirm_password = request.form['confirm_password'] if password != confirm_password: flash('Passwords do not match') return render_template('admin_doctors.html', doctors=doctors) if Doctor.query.filter_by(username=username).first() or Doctor.query.filter_by(email=email).first(): flash('Username or email already exists') return render_template('admin_doctors.html', doctors=doctors) hashed_password = generate_password_hash(password) new_doctor = Doctor(hospital_id=hospital_id, name=name, username=username, email=email, mobile=mobile, password=hashed_password) db.session.add(new_doctor) db.session.commit() flash('Doctor added') return redirect(url_for('admin_doctors')) return render_template('admin_doctors.html', doctors=doctors) @app.route('/admin/doctors/edit/', methods=['GET', 'POST']) def admin_edit_doctor(doctor_id): if 'admin_user_id' not in session: return redirect(url_for('admin_login')) doctor = Doctor.query.get_or_404(doctor_id) if doctor.hospital_id != session['admin_user_id']: return redirect(url_for('admin_doctors')) if request.method == 'POST': doctor.name = request.form['name'] doctor.mobile = request.form['mobile'] doctor.email = request.form['email'] db.session.commit() flash('Doctor updated') return redirect(url_for('admin_doctors')) return render_template('admin_edit_doctor.html', doctor=doctor) @app.route('/admin/doctors/remove/') def admin_remove_doctor(doctor_id): if 'admin_user_id' not in session: return redirect(url_for('admin_login')) doctor = Doctor.query.get_or_404(doctor_id) if doctor.hospital_id != session['admin_user_id']: return redirect(url_for('admin_doctors')) db.session.delete(doctor) db.session.commit() flash('Doctor removed') return redirect(url_for('admin_doctors')) # Ambulance Admin Routes (unchanged) @app.route('/admin/ambulances', methods=['GET', 'POST']) def admin_ambulances(): if 'admin_user_id' not in session: return redirect(url_for('admin_login')) hospital_id = session['admin_user_id'] ambulances = Ambulance.query.filter_by(hospital_id=hospital_id).all() if request.method == 'POST' and 'add' in request.form: name = request.form['name'] username = request.form['username'] email = request.form['email'] mobile = request.form['mobile'] password = request.form['password'] confirm_password = request.form['confirm_password'] if password != confirm_password: flash('Passwords do not match') return render_template('admin_ambulances.html', ambulances=ambulances) if Ambulance.query.filter_by(username=username).first() or Ambulance.query.filter_by(email=email).first(): flash('Username or email already exists') return render_template('admin_ambulances.html', ambulances=ambulances) hashed_password = generate_password_hash(password) new_ambulance = Ambulance(hospital_id=hospital_id, name=name, username=username, email=email, mobile=mobile, password=hashed_password) db.session.add(new_ambulance) db.session.commit() flash('Ambulance added') return redirect(url_for('admin_ambulances')) return render_template('admin_ambulances.html', ambulances=ambulances) @app.route('/admin/ambulances/edit/', methods=['GET', 'POST']) def admin_edit_ambulance(ambulance_id): if 'admin_user_id' not in session: return redirect(url_for('admin_login')) ambulance = Ambulance.query.get_or_404(ambulance_id) if ambulance.hospital_id != session['admin_user_id']: return redirect(url_for('admin_ambulances')) if request.method == 'POST': ambulance.name = request.form['name'] ambulance.mobile = request.form['mobile'] ambulance.email = request.form['email'] db.session.commit() flash('Ambulance updated') return redirect(url_for('admin_ambulances')) return render_template('admin_edit_ambulance.html', ambulance=ambulance) @app.route('/admin/ambulances/remove/') def admin_remove_ambulance(ambulance_id): if 'admin_user_id' not in session: return redirect(url_for('admin_login')) ambulance = Ambulance.query.get_or_404(ambulance_id) if ambulance.hospital_id != session['admin_user_id']: return redirect(url_for('admin_ambulances')) db.session.delete(ambulance) db.session.commit() flash('Ambulance removed') return redirect(url_for('admin_ambulances')) # Nurse (unchanged) @app.route('/admin/nurses', methods=['GET', 'POST']) def admin_nurses(): if 'admin_user_id' not in session: return redirect(url_for('admin_login')) hospital_id = session['admin_user_id'] nurses = Nurse.query.filter_by(hospital_id=hospital_id).all() if request.method == 'POST' and 'add' in request.form: name = request.form['name'] username = request.form['username'] email = request.form['email'] mobile = request.form['mobile'] password = request.form['password'] confirm_password = request.form['confirm_password'] if password != confirm_password: flash('Passwords do not match') return render_template('admin_nurses.html', nurses=nurses) if Nurse.query.filter_by(username=username).first() or Nurse.query.filter_by(email=email).first(): flash('Username or email already exists') return render_template('admin_nurses.html', nurses=nurses) hashed_password = generate_password_hash(password) new_nurse = Nurse(hospital_id=hospital_id, name=name, username=username, email=email, mobile=mobile, password=hashed_password) db.session.add(new_nurse) db.session.commit() flash('Nurse added') return redirect(url_for('admin_nurses')) return render_template('admin_nurses.html', nurses=nurses) @app.route('/admin/nurses/edit/', methods=['GET', 'POST']) def admin_edit_nurse(nurse_id): if 'admin_user_id' not in session: return redirect(url_for('admin_login')) nurse = Nurse.query.get_or_404(nurse_id) if nurse.hospital_id != session['admin_user_id']: return redirect(url_for('admin_nurses')) if request.method == 'POST': nurse.name = request.form['name'] nurse.mobile = request.form['mobile'] nurse.email = request.form['email'] db.session.commit() flash('Nurse updated') return redirect(url_for('admin_nurses')) return render_template('admin_edit_nurse.html', nurse=nurse) @app.route('/admin/nurses/remove/') def admin_remove_nurse(nurse_id): if 'admin_user_id' not in session: return redirect(url_for('admin_login')) nurse = Nurse.query.get_or_404(nurse_id) if nurse.hospital_id != session['admin_user_id']: return redirect(url_for('admin_nurses')) db.session.delete(nurse) db.session.commit() flash('Nurse removed') return redirect(url_for('admin_nurses')) # Canteen (updated) @app.route('/admin/canteens', methods=['GET', 'POST']) def admin_canteens(): if 'admin_user_id' not in session: return redirect(url_for('admin_login')) hospital_id = session['admin_user_id'] canteens = Canteen.query.filter_by(hospital_id=hospital_id).all() if request.method == 'POST' and 'add' in request.form: name = request.form['name'] username = request.form['username'] email = request.form['email'] mobile = request.form['mobile'] password = request.form['password'] confirm_password = request.form['confirm_password'] if password != confirm_password: flash('Passwords do not match') return render_template('admin_canteens.html', canteens=canteens) if Canteen.query.filter_by(username=username).first() or Canteen.query.filter_by(email=email).first(): flash('Username or email already exists') return render_template('admin_canteens.html', canteens=canteens) hashed_password = generate_password_hash(password) new_canteen = Canteen(hospital_id=hospital_id, name=name, username=username, email=email, mobile=mobile, password=hashed_password) db.session.add(new_canteen) db.session.commit() flash('Canteen added') return redirect(url_for('admin_canteens')) return render_template('admin_canteens.html', canteens=canteens) @app.route('/admin/canteens/edit/', methods=['GET', 'POST']) def admin_edit_canteen(canteen_id): if 'admin_user_id' not in session: return redirect(url_for('admin_login')) canteen = Canteen.query.get_or_404(canteen_id) if canteen.hospital_id != session['admin_user_id']: return redirect(url_for('admin_canteens')) if request.method == 'POST': canteen.name = request.form['name'] canteen.mobile = request.form['mobile'] canteen.email = request.form['email'] db.session.commit() flash('Canteen updated') return redirect(url_for('admin_canteens')) return render_template('admin_edit_canteen.html', canteen=canteen) @app.route('/admin/canteens/remove/') def admin_remove_canteen(canteen_id): if 'admin_user_id' not in session: return redirect(url_for('admin_login')) canteen = Canteen.query.get_or_404(canteen_id) if canteen.hospital_id != session['admin_user_id']: return redirect(url_for('admin_canteens')) db.session.delete(canteen) db.session.commit() flash('Canteen removed') return redirect(url_for('admin_canteens')) # Admin Rooms Management (unchanged) @app.route('/admin/rooms', methods=['GET', 'POST']) def admin_rooms(): if 'admin_user_id' not in session: return redirect(url_for('admin_login')) hospital_id = session['admin_user_id'] rooms = Room.query.filter_by(hospital_id=hospital_id).all() bookings = Booking.query.join(Bed).join(Room).filter(Room.hospital_id == hospital_id).all() active_bookings = [b for b in bookings if b.status == 'pending'] history_bookings = [b for b in bookings if b.status in ['accepted', 'rejected', 'cancelled']] confirmed_bookings = [b for b in bookings if b.status == 'paid'] if request.method == 'POST' and 'create_room' in request.form: name = request.form['name'] num_beds = int(request.form['num_beds']) price_per_bed = float(request.form['price_per_bed']) description = request.form.get('description') layout_json = request.form['layout'] layout = json.loads(layout_json) new_room = Room(hospital_id=hospital_id, name=name, num_beds=num_beds, price_per_bed=price_per_bed, description=description) db.session.add(new_room) db.session.commit() for item in layout: bed = Bed(room_id=new_room.id, bed_number=item['number'], position=f"{item['left']},{item['top']}") db.session.add(bed) db.session.commit() flash('Room created') return redirect(url_for('admin_rooms')) return render_template('admin_rooms.html', rooms=rooms, active_bookings=active_bookings, history_bookings=history_bookings, confirmed_bookings=confirmed_bookings) @app.route('/admin/rooms/edit/', methods=['GET', 'POST']) def admin_edit_room(room_id): if 'admin_user_id' not in session: return redirect(url_for('admin_login')) room = Room.query.get_or_404(room_id) if room.hospital_id != session['admin_user_id']: abort(403) reviews = Review.query.filter_by(room_id=room_id).order_by(Review.created_at.desc()).all() if request.method == 'POST': room.name = request.form['name'] room.price_per_bed = float(request.form['price_per_bed']) room.description = request.form.get('description') layout_json = request.form['layout'] layout = json.loads(layout_json) beds = Bed.query.filter_by(room_id=room_id).order_by(Bed.bed_number).all() for i, item in enumerate(layout): beds[i].position = f"{item['left']},{item['top']}" db.session.commit() flash('Room updated') return redirect(url_for('admin_rooms')) beds = Bed.query.filter_by(room_id=room_id).order_by(Bed.bed_number).all() initial_layout = [] for bed in beds: left, top = bed.position.split(',') if bed.position else ('0px', '0px') initial_layout.append({'id': bed.id, 'number': bed.bed_number, 'status': bed.status, 'left': left, 'top': top}) return render_template('admin_edit_room.html', room=room, initial_layout=json.dumps(initial_layout), reviews=reviews) @app.route('/admin/rooms/delete/') def admin_delete_room(room_id): if 'admin_user_id' not in session: return redirect(url_for('admin_login')) room = Room.query.get_or_404(room_id) if room.hospital_id != session['admin_user_id']: abort(403) db.session.delete(room) db.session.commit() flash('Room deleted') return redirect(url_for('admin_rooms')) @app.route('/admin/accept_booking/') def admin_accept_booking(booking_id): if 'admin_user_id' not in session: return redirect(url_for('admin_login')) booking = Booking.query.get_or_404(booking_id) bed = Bed.query.get(booking.bed_id) room = Room.query.get(bed.room_id) if room.hospital_id != session['admin_user_id']: abort(403) booking.status = 'accepted' db.session.commit() flash('Booking accepted') # Send email to patient patient = Patient.query.get(booking.patient_id) if patient and patient.email: subject = "Bed Booking Request Accepted" body = f"Dear {patient.name},\n\nYour bed booking request has been accepted. Please pay the bill to confirm.\n\nBest regards,\nHospital Team" send_email(patient.email, subject, body) return redirect(url_for('admin_rooms')) @app.route('/admin/reject_booking/') def admin_reject_booking(booking_id): if 'admin_user_id' not in session: return redirect(url_for('admin_login')) booking = Booking.query.get_or_404(booking_id) bed = Bed.query.get(booking.bed_id) room = Room.query.get(bed.room_id) if room.hospital_id != session['admin_user_id']: abort(403) booking.status = 'rejected' db.session.commit() flash('Booking rejected') # Send email to patient patient = Patient.query.get(booking.patient_id) if patient and patient.email: subject = "Bed Booking Request Rejected" body = f"Dear {patient.name},\n\nYour bed booking request has been rejected.\n\nBest regards,\nHospital Team" send_email(patient.email, subject, body) return redirect(url_for('admin_rooms')) @app.route('/admin/room//unbook_bed/') def admin_unbook_bed(room_id, bed_id): if 'admin_user_id' not in session: return redirect(url_for('admin_login')) bed = Bed.query.get_or_404(bed_id) if bed.room_id != room_id: abort(404) room = Room.query.get(room_id) if room.hospital_id != session['admin_user_id']: abort(403) if bed.status == 'booked': booking = Booking.query.filter_by(bed_id=bed_id, status='paid').first() if booking: booking.status = 'cancelled' # Send email to patient for cancellation patient = Patient.query.get(booking.patient_id) if patient and patient.email: subject = "Bed Booking Cancelled" body = f"Dear {patient.name},\n\nYour bed booking has been cancelled by admin.\n\nBest regards,\nHospital Team" send_email(patient.email, subject, body) bed.status = 'available' db.session.commit() flash('Bed unbooked') return redirect(url_for('admin_edit_room', room_id=room_id)) @app.route('/admin/delete_review/') def admin_delete_review(review_id): if 'admin_user_id' not in session: return redirect(url_for('admin_login')) review = Review.query.get_or_404(review_id) room = review.room if room.hospital_id != session['admin_user_id']: abort(403) db.session.delete(review) db.session.commit() flash('Review deleted') return redirect(url_for('admin_edit_room', room_id=room.id)) # Doctor Routes (unchanged) @app.route('/doctor/login', methods=['GET', 'POST']) def doctor_login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] doctor = Doctor.query.filter_by(username=username).first() if doctor and check_password_hash(doctor.password, password): session['doctor_user_id'] = doctor.id return redirect(url_for('doctor_dashboard')) flash('Invalid username or password') return render_template('doctor_login.html') @app.route('/doctor/dashboard', methods=['GET', 'POST']) def doctor_dashboard(): if 'doctor_user_id' not in session: return redirect(url_for('doctor_login')) doctor = db.session.get(Doctor, session['doctor_user_id']) if request.method == 'POST' and 'edit' in request.form: doctor.name = request.form['name'] doctor.mobile = request.form['mobile'] doctor.email = request.form['email'] doctor.info = request.form['info'] doctor.qualifications = request.form['qualifications'] doctor.specializations = request.form['specializations'] doctor.practice_years = int(request.form['practice_years']) doctor.additional_links = request.form['additional_links'] doctor.practice_location = request.form['practice_location'] db.session.commit() flash('Details updated') return render_template('doctor_dashboard.html', doctor=doctor) @app.route('/doctor/manage_appointments', methods=['GET', 'POST']) def doctor_manage_appointments(): if 'doctor_user_id' not in session: return redirect(url_for('doctor_login')) doctor_id = session['doctor_user_id'] time_slots = TimeSlot.query.filter_by(doctor_id=doctor_id).all() if request.method == 'POST': start_time = request.form['start_time'] end_time = request.form['end_time'] price = float(request.form['price']) new_slot = TimeSlot(doctor_id=doctor_id, start_time=start_time, end_time=end_time, price=price) db.session.add(new_slot) db.session.commit() flash('Time slot added') return redirect(url_for('doctor_manage_appointments')) return render_template('manage_appointments.html', time_slots=time_slots) @app.route('/doctor/delete_slot/') def doctor_delete_slot(slot_id): if 'doctor_user_id' not in session: return redirect(url_for('doctor_login')) slot = TimeSlot.query.get_or_404(slot_id) if slot.doctor_id != session['doctor_user_id']: abort(403) db.session.delete(slot) db.session.commit() flash('Time slot deleted') return redirect(url_for('doctor_manage_appointments')) @app.route('/doctor/appointments') def doctor_appointments(): if 'doctor_user_id' not in session: return redirect(url_for('doctor_login')) doctor_id = session['doctor_user_id'] today = date.today() # Join with TimeSlot to access time_slot information appointments = db.session.query(Appointment).join(TimeSlot).filter( Appointment.doctor_id == doctor_id, Appointment.appointment_date == today, Appointment.status == 'paid' ).all() return render_template('doctor_appointments.html', appointments=appointments, today_date=today) @app.route('/doctor/medical_records', methods=['GET', 'POST']) def doctor_medical_records(): if 'doctor_user_id' not in session: return redirect(url_for('doctor_login')) doctor_id = session['doctor_user_id'] search = request.args.get('search', '') if search: records = MedicalRecord.query.filter_by(doctor_id=doctor_id).filter(MedicalRecord.patient_name.like(f'%{search}%')).all() else: records = MedicalRecord.query.filter_by(doctor_id=doctor_id).all() if request.method == 'POST': patient_name = request.form['patient_name'] age = int(request.form['age']) mobile = request.form['mobile'] medical_condition = request.form.get('medical_condition') file = request.files['file'] if file and file.filename.endswith('.pdf'): folder = os.path.join(app.config['UPLOAD_FOLDER'], f'doctor_{doctor_id}') os.makedirs(folder, exist_ok=True) filename = secure_filename(file.filename) file_path = os.path.join(folder, filename) file.save(file_path) new_record = MedicalRecord(doctor_id=doctor_id, patient_name=patient_name, age=age, mobile=mobile, medical_condition=medical_condition, file_path=file_path) db.session.add(new_record) db.session.commit() flash('Medical record added') else: flash('Invalid file') return redirect(url_for('doctor_medical_records')) return render_template('medical_records.html', records=records, search=search) @app.route('/doctor/delete_record/') def doctor_delete_record(record_id): if 'doctor_user_id' not in session: return redirect(url_for('doctor_login')) record = MedicalRecord.query.get_or_404(record_id) if record.doctor_id != session['doctor_user_id']: abort(403) if os.path.exists(record.file_path): os.remove(record.file_path) db.session.delete(record) db.session.commit() flash('Medical record deleted') return redirect(url_for('doctor_medical_records')) @app.route('/doctor/download_record/') def doctor_download_record(record_id): if 'doctor_user_id' not in session: return redirect(url_for('doctor_login')) record = MedicalRecord.query.get_or_404(record_id) if record.doctor_id != session['doctor_user_id']: abort(403) return send_file(record.file_path, as_attachment=False) @app.route('/doctor/manage_reviews') def doctor_manage_reviews(): if 'doctor_user_id' not in session: return redirect(url_for('doctor_login')) doctor_id = session['doctor_user_id'] reviews = DoctorReview.query.filter_by(doctor_id=doctor_id).order_by(DoctorReview.created_at.desc()).all() return render_template('doctor_manage_reviews.html', reviews=reviews) @app.route('/doctor/delete_review/') def doctor_delete_review(review_id): if 'doctor_user_id' not in session: return redirect(url_for('doctor_login')) review = DoctorReview.query.get_or_404(review_id) if review.doctor_id != session['doctor_user_id']: abort(403) db.session.delete(review) db.session.commit() flash('Review deleted') return redirect(url_for('doctor_manage_reviews')) # Ambulance Routes (unchanged) @app.route('/ambulance/login', methods=['GET', 'POST']) def ambulance_login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] ambulance = Ambulance.query.filter_by(username=username).first() if ambulance and check_password_hash(ambulance.password, password): session['ambulance_user_id'] = ambulance.id return redirect(url_for('ambulance_dashboard')) flash('Invalid username or password') return render_template('ambulance_login.html') @app.route('/ambulance/dashboard', methods=['GET', 'POST']) def ambulance_dashboard(): if 'ambulance_user_id' not in session: return redirect(url_for('ambulance_login')) ambulance = Ambulance.query.get(session['ambulance_user_id']) if request.method == 'POST' and 'edit' in request.form: ambulance.name = request.form['name'] ambulance.mobile = request.form['mobile'] ambulance.email = request.form['email'] ambulance.info = request.form['info'] ambulance.status = request.form['status'] db.session.commit() flash('Details updated') return render_template('ambulance_dashboard.html', ambulance=ambulance) @app.route('/ambulance/vehicles', methods=['GET', 'POST']) def ambulance_vehicles(): if 'ambulance_user_id' not in session: return redirect(url_for('ambulance_login')) ambulance_id = session['ambulance_user_id'] vehicles = AmbulanceVehicle.query.filter_by(ambulance_id=ambulance_id).all() if request.method == 'POST' and 'add' in request.form: name = request.form['name'] numberplate = request.form['numberplate'] cost_price = float(request.form['cost_price']) medical_support = request.form.get('medical_support') file = request.files['image'] image_path = None if file and file.filename != '': folder = os.path.join(app.config['UPLOAD_FOLDER'], f'ambulance_{ambulance_id}/vehicles') os.makedirs(folder, exist_ok=True) filename = secure_filename(file.filename) image_path = os.path.join(folder, filename) file.save(image_path) new_vehicle = AmbulanceVehicle(ambulance_id=ambulance_id, name=name, numberplate=numberplate, cost_price=cost_price, medical_support=medical_support, image_path=image_path) db.session.add(new_vehicle) db.session.commit() flash('Vehicle added') return redirect(url_for('ambulance_vehicles')) return render_template('ambulance_vehicles.html', vehicles=vehicles) @app.route('/ambulance/edit_vehicle/', methods=['GET', 'POST']) def ambulance_edit_vehicle(vehicle_id): if 'ambulance_user_id' not in session: return redirect(url_for('ambulance_login')) vehicle = AmbulanceVehicle.query.get_or_404(vehicle_id) if vehicle.ambulance_id != session['ambulance_user_id']: abort(403) if request.method == 'POST': vehicle.name = request.form['name'] vehicle.numberplate = request.form['numberplate'] vehicle.cost_price = float(request.form['cost_price']) vehicle.medical_support = request.form.get('medical_support') file = request.files['image'] if file and file.filename != '': if vehicle.image_path and os.path.exists(vehicle.image_path): os.remove(vehicle.image_path) folder = os.path.join(app.config['UPLOAD_FOLDER'], f'ambulance_{session["ambulance_user_id"]}/vehicles') os.makedirs(folder, exist_ok=True) filename = secure_filename(file.filename) vehicle.image_path = os.path.join(folder, filename) file.save(vehicle.image_path) db.session.commit() flash('Vehicle updated') return redirect(url_for('ambulance_vehicles')) return render_template('ambulance_edit_vehicle.html', vehicle=vehicle) @app.route('/ambulance/delete_vehicle/') def ambulance_delete_vehicle(vehicle_id): if 'ambulance_user_id' not in session: return redirect(url_for('ambulance_login')) vehicle = AmbulanceVehicle.query.get_or_404(vehicle_id) if vehicle.ambulance_id != session['ambulance_user_id']: abort(403) if vehicle.image_path and os.path.exists(vehicle.image_path): os.remove(vehicle.image_path) db.session.delete(vehicle) db.session.commit() flash('Vehicle deleted') return redirect(url_for('ambulance_vehicles')) @app.route('/ambulance/bookings') def ambulance_bookings(): if 'ambulance_user_id' not in session: return redirect(url_for('ambulance_login')) ambulance_id = session['ambulance_user_id'] bookings = AmbulanceBooking.query.filter_by(ambulance_id=ambulance_id).all() pending_bookings = [b for b in bookings if b.status == 'pending'] accepted_bookings = [b for b in bookings if b.status == 'accepted'] paid_bookings = [b for b in bookings if b.status == 'paid'] return render_template('ambulance_bookings.html', pending_bookings=pending_bookings, accepted_bookings=accepted_bookings, paid_bookings=paid_bookings) @app.route('/ambulance/accept_booking/', methods=['GET', 'POST']) def ambulance_accept_booking(booking_id): if 'ambulance_user_id' not in session: return redirect(url_for('ambulance_login')) booking = AmbulanceBooking.query.get_or_404(booking_id) if booking.ambulance_id != session['ambulance_user_id']: abort(403) if request.method == 'POST': live_location_link = request.form['live_location_link'] booking.live_location_link = live_location_link patient = booking.patient vehicle = booking.vehicle if booking.use_type == 'emergency': booking.status = 'paid' subject = "Ambulance is on the Way" body = f"Dear {patient.name},\n\nAmbulance is on the way. Here is the live location: {live_location_link}\n\nBest regards,\nAmbulance Team" send_email(patient.email, subject, body) else: booking.status = 'accepted' pdf_buffer = generate_ambulance_bill_pdf(booking, vehicle) subject = "Ambulance Booking Accepted" body = f"Dear {patient.name},\n\nYour ambulance booking request has been accepted. Please pay the bill to confirm.\nLive Location Link: {live_location_link}\n\nBest regards,\nAmbulance Team" send_email(patient.email, subject, body, pdf_buffer) db.session.commit() flash('Booking accepted and email sent') return redirect(url_for('ambulance_bookings')) return render_template('ambulance_accept_booking.html', booking=booking) @app.route('/ambulance/share_live_location/', methods=['GET', 'POST']) def ambulance_share_live_location(booking_id): if 'ambulance_user_id' not in session: return redirect(url_for('ambulance_login')) booking = AmbulanceBooking.query.get_or_404(booking_id) if booking.ambulance_id != session['ambulance_user_id'] or booking.status not in ['accepted', 'paid']: abort(403) if request.method == 'POST': live_location_link = request.form['live_location_link'] booking.live_location_link = live_location_link patient = booking.patient subject = "Ambulance Live Location Updated" body = f"Dear {patient.name},\n\nThe live location for your ambulance booking has been updated. Live Location Link: {live_location_link}\n\nBest regards,\nAmbulance Team" send_email(patient.email, subject, body) db.session.commit() flash('Live location shared and email sent') return redirect(url_for('ambulance_bookings')) return render_template('ambulance_share_live_location.html', booking=booking) @app.route('/ambulance/reject_booking/') def ambulance_reject_booking(booking_id): if 'ambulance_user_id' not in session: return redirect(url_for('ambulance_login')) booking = AmbulanceBooking.query.get_or_404(booking_id) if booking.ambulance_id != session['ambulance_user_id']: abort(403) patient = booking.patient booking.status = 'rejected' if booking.payment_status == 'paid': body = f"Dear {patient.name},\n\nYour ambulance booking request has been rejected. Refund will be sent soon.\n\nBest regards,\nAmbulance Team" else: body = f"Dear {patient.name},\n\nYour ambulance booking request has been rejected.\n\nBest regards,\nAmbulance Team" send_email(patient.email, "Ambulance Booking Rejected", body) db.session.commit() flash('Booking rejected') return redirect(url_for('ambulance_bookings')) @app.route('/ambulance/reviews') def ambulance_reviews(): if 'ambulance_user_id' not in session: return redirect(url_for('ambulance_login')) ambulance_id = session['ambulance_user_id'] reviews = AmbulanceReview.query.filter_by(ambulance_id=ambulance_id).order_by(AmbulanceReview.created_at.desc()).all() return render_template('ambulance_reviews.html', reviews=reviews) @app.route('/ambulance/delete_review/') def ambulance_delete_review(review_id): if 'ambulance_user_id' not in session: return redirect(url_for('ambulance_login')) review = AmbulanceReview.query.get_or_404(review_id) if review.ambulance_id != session['ambulance_user_id']: abort(403) db.session.delete(review) db.session.commit() flash('Review deleted') return redirect(url_for('ambulance_reviews')) # Nurse Routes (unchanged) @app.route('/nurse/login', methods=['GET', 'POST']) def nurse_login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] nurse = Nurse.query.filter_by(username=username).first() if nurse and check_password_hash(nurse.password, password): session['nurse_user_id'] = nurse.id return redirect(url_for('nurse_dashboard')) flash('Invalid username or password') return render_template('nurse_login.html') @app.route('/nurse/dashboard', methods=['GET', 'POST']) def nurse_dashboard(): if 'nurse_user_id' not in session: return redirect(url_for('nurse_login')) nurse = Nurse.query.get(session['nurse_user_id']) if request.method == 'POST' and 'edit' in request.form: nurse.name = request.form['name'] nurse.mobile = request.form['mobile'] nurse.email = request.form['email'] nurse.info = request.form['info'] db.session.commit() flash('Details updated') elif request.method == 'POST' and 'update_status' in request.form: nurse.status = request.form['status'] db.session.commit() flash('Status updated') return render_template('nurse_dashboard.html', nurse=nurse) @app.route('/nurse/set_price', methods=['GET', 'POST']) def nurse_set_price(): if 'nurse_user_id' not in session: return redirect(url_for('nurse_login')) nurse = Nurse.query.get(session['nurse_user_id']) rates = NurseRate.query.filter_by(nurse_id=session['nurse_user_id']).all() if request.method == 'POST': if 'add_rate' in request.form: rate_type = request.form['rate_type'] price = float(request.form['price']) existing = NurseRate.query.filter_by(nurse_id=session['nurse_user_id'], rate_type=rate_type).first() if existing: existing.price = price else: new_rate = NurseRate(nurse_id=session['nurse_user_id'], rate_type=rate_type, price=price) db.session.add(new_rate) db.session.commit() flash('Rate added/updated') elif 'edit_rate' in request.form: rate_id = int(request.form['rate_id']) price = float(request.form['price']) rate = NurseRate.query.get_or_404(rate_id) if rate.nurse_id != session['nurse_user_id']: abort(403) rate.price = price db.session.commit() flash('Rate updated') elif 'delete_rate' in request.form: rate_id = int(request.form['rate_id']) rate = NurseRate.query.get_or_404(rate_id) if rate.nurse_id != session['nurse_user_id']: abort(403) db.session.delete(rate) db.session.commit() flash('Rate deleted') elif 'update_availability' in request.form: availability = ','.join(request.form.getlist('availability')) nurse.availability_locations = availability db.session.commit() flash('Availability updated') return redirect(url_for('nurse_set_price')) return render_template('nurse_set_price.html', nurse=nurse, rates=rates) @app.route('/nurse/patient_requests') def nurse_patient_requests(): if 'nurse_user_id' not in session: return redirect(url_for('nurse_login')) nurse_id = session['nurse_user_id'] bookings = NurseBooking.query.filter_by(nurse_id=nurse_id).all() pending_bookings = [b for b in bookings if b.status == 'pending'] accepted_bookings = [b for b in bookings if b.status == 'accepted'] paid_bookings = [b for b in bookings if b.status == 'paid'] return render_template('nurse_patient_requests.html', pending_bookings=pending_bookings, accepted_bookings=accepted_bookings, paid_bookings=paid_bookings) @app.route('/nurse/accept_booking/') def nurse_accept_booking(booking_id): if 'nurse_user_id' not in session: return redirect(url_for('nurse_login')) booking = NurseBooking.query.get_or_404(booking_id) if booking.nurse_id != session['nurse_user_id']: abort(403) booking.status = 'accepted' nurse = booking.nurse patient = booking.patient nurse.status = 'booked' db.session.commit() flash('Booking accepted') # Send email to patient if patient and patient.email: subject = "Nurse Booking Request Accepted" body = f"Dear {patient.name},\n\nYour request for Nurse {nurse.name} ({booking.duration_type} at {booking.location}) has been accepted. Please pay the bill to confirm.\n\nBest regards,\nHospital Team" send_email(patient.email, subject, body) return redirect(url_for('nurse_patient_requests')) @app.route('/nurse/reject_booking/') def nurse_reject_booking(booking_id): if 'nurse_user_id' not in session: return redirect(url_for('nurse_login')) booking = NurseBooking.query.get_or_404(booking_id) if booking.nurse_id != session['nurse_user_id']: abort(403) patient = booking.patient nurse = booking.nurse booking.status = 'rejected' db.session.commit() flash('Booking rejected') # Send email to patient if patient and patient.email: subject = "Nurse Booking Request Rejected" body = f"Dear {patient.name},\n\nYour request for Nurse {nurse.name} ({booking.duration_type} at {booking.location}) has been rejected.\n\nBest regards,\nHospital Team" send_email(patient.email, subject, body) return redirect(url_for('nurse_patient_requests')) @app.route('/nurse/manage_reviews') def nurse_manage_reviews(): if 'nurse_user_id' not in session: return redirect(url_for('nurse_login')) nurse_id = session['nurse_user_id'] reviews = NurseReview.query.filter_by(nurse_id=nurse_id).order_by(NurseReview.created_at.desc()).all() return render_template('nurse_manage_reviews.html', reviews=reviews) @app.route('/nurse/delete_review/') def nurse_delete_review(review_id): if 'nurse_user_id' not in session: return redirect(url_for('nurse_login')) review = NurseReview.query.get_or_404(review_id) if review.nurse_id != session['nurse_user_id']: abort(403) db.session.delete(review) db.session.commit() flash('Review deleted') return redirect(url_for('nurse_manage_reviews')) # Add these routes after the existing patient_edit_nurse_review and patient_delete_nurse_review routes # (around line 1400-1500, after the nurse review routes and before canteen routes) @app.route('/patient/add_doctor_review/', methods=['POST']) def patient_add_doctor_review(doctor_id): if 'patient_user_id' not in session: return redirect(url_for('patient_login')) doctor = Doctor.query.get_or_404(doctor_id) rating = int(request.form['rating']) text = request.form.get('text') new_review = DoctorReview(doctor_id=doctor_id, patient_id=session['patient_user_id'], rating=rating, text=text) db.session.add(new_review) db.session.commit() flash('Review added') return redirect(url_for('patient_doctor', doctor_id=doctor_id)) @app.route('/patient/edit_doctor_review/', methods=['POST']) def patient_edit_doctor_review(review_id): if 'patient_user_id' not in session: return redirect(url_for('patient_login')) review = DoctorReview.query.get_or_404(review_id) if review.patient_id != session['patient_user_id']: abort(403) review.rating = int(request.form['rating']) review.text = request.form.get('text') db.session.commit() flash('Review updated') return redirect(url_for('patient_doctor', doctor_id=review.doctor_id)) @app.route('/patient/delete_doctor_review/') def patient_delete_doctor_review(review_id): if 'patient_user_id' not in session: return redirect(url_for('patient_login')) review = DoctorReview.query.get_or_404(review_id) if review.patient_id != session['patient_user_id']: abort(403) doctor_id = review.doctor_id db.session.delete(review) db.session.commit() flash('Review deleted') return redirect(url_for('patient_doctor', doctor_id=doctor_id)) # Canteen Routes (updated with new features and status emails) @app.route('/canteen/login', methods=['GET', 'POST']) def canteen_login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] canteen = Canteen.query.filter_by(username=username).first() if canteen and check_password_hash(canteen.password, password): session['canteen_user_id'] = canteen.id return redirect(url_for('canteen_dashboard')) flash('Invalid username or password') return render_template('canteen_login.html') @app.route('/canteen/dashboard', methods=['GET', 'POST']) def canteen_dashboard(): if 'canteen_user_id' not in session: return redirect(url_for('canteen_login')) canteen = Canteen.query.get(session['canteen_user_id']) if request.method == 'POST' and 'edit' in request.form: canteen.name = request.form['name'] canteen.mobile = request.form['mobile'] canteen.email = request.form['email'] canteen.info = request.form['info'] db.session.commit() flash('Details updated') # Get preparing orders for dashboard preparing_orders = CanteenOrder.query.filter_by(canteen_id=session['canteen_user_id'], status='preparing').all() return render_template('canteen_dashboard.html', canteen=canteen, preparing_orders=preparing_orders) @app.route('/canteen/menu_management', methods=['GET', 'POST']) def canteen_menu_management(): if 'canteen_user_id' not in session: return redirect(url_for('canteen_login')) canteen_id = session['canteen_user_id'] categories = CanteenCategory.query.filter_by(canteen_id=canteen_id).all() if request.method == 'POST': if 'add_category' in request.form: name = request.form['name'] new_category = CanteenCategory(canteen_id=canteen_id, name=name) db.session.add(new_category) db.session.commit() flash('Category added') elif 'edit_category' in request.form: category_id = int(request.form['category_id']) name = request.form['name'] category = CanteenCategory.query.get_or_404(category_id) if category.canteen_id != canteen_id: abort(403) category.name = name db.session.commit() flash('Category updated') elif 'delete_category' in request.form: category_id = int(request.form['category_id']) category = CanteenCategory.query.get_or_404(category_id) if category.canteen_id != canteen_id: abort(403) db.session.delete(category) db.session.commit() flash('Category deleted') elif 'add_item' in request.form: category_id = int(request.form['category_id']) name = request.form['name'] price = float(request.form['price']) new_item = CanteenItem(category_id=category_id, name=name, price=price) db.session.add(new_item) db.session.commit() flash('Item added') elif 'edit_item' in request.form: item_id = int(request.form['item_id']) name = request.form['name'] price = float(request.form['price']) item = CanteenItem.query.get_or_404(item_id) item.name = name item.price = price db.session.commit() flash('Item updated') elif 'delete_item' in request.form: item_id = int(request.form['item_id']) item = CanteenItem.query.get_or_404(item_id) db.session.delete(item) db.session.commit() flash('Item deleted') return redirect(url_for('canteen_menu_management')) return render_template('canteen_menu_management.html', categories=categories) @app.route('/canteen/orders') def canteen_orders(): if 'canteen_user_id' not in session: return redirect(url_for('canteen_login')) canteen_id = session['canteen_user_id'] orders = CanteenOrder.query.filter_by(canteen_id=canteen_id).all() # Pre-load room and bed data for all orders orders_with_details = [] for order in orders: order_dict = { 'order': order, 'room': None, 'bed': None } if order.room_id: order_dict['room'] = Room.query.get(order.room_id) if order.bed_id: order_dict['bed'] = Bed.query.get(order.bed_id) orders_with_details.append(order_dict) # Filter orders by status with their details pending_orders = [od for od in orders_with_details if od['order'].status == 'pending'] accepted_orders = [od for od in orders_with_details if od['order'].status == 'accepted'] paid_orders = [od for od in orders_with_details if od['order'].status == 'paid'] delivered_orders = [od for od in orders_with_details if od['order'].status == 'delivered'] preparing_orders = [od for od in orders_with_details if od['order'].status == 'preparing'] out_for_delivery_orders = [od for od in orders_with_details if od['order'].status == 'out_for_delivery'] return render_template('canteen_orders.html', pending_orders=pending_orders, accepted_orders=accepted_orders, paid_orders=paid_orders, delivered_orders=delivered_orders, preparing_orders=preparing_orders, out_for_delivery_orders=out_for_delivery_orders) @app.route('/canteen/accept_order/') def canteen_accept_order(order_id): if 'canteen_user_id' not in session: return redirect(url_for('canteen_login')) order = CanteenOrder.query.get_or_404(order_id) if order.canteen_id != session['canteen_user_id']: abort(403) order.status = 'accepted' db.session.commit() patient = order.patient total_amount = sum(item.item.price * item.quantity for item in order.items) subject = "Your Canteen Order is Accepted" body = f"Dear {patient.name},\n\nYour canteen order has been accepted. Total: ₹{total_amount}\nItems:\n" for item in order.items: body += f"- {item.item.name} x {item.quantity} = ₹{item.item.price * item.quantity}\n" body += "\nPlease pay the bill to confirm.\n\nBest regards,\nCanteen Team" send_email(patient.email, subject, body) flash('Order accepted') return redirect(url_for('canteen_orders')) @app.route('/canteen/reject_order/') def canteen_reject_order(order_id): if 'canteen_user_id' not in session: return redirect(url_for('canteen_login')) order = CanteenOrder.query.get_or_404(order_id) if order.canteen_id != session['canteen_user_id']: abort(403) order.status = 'rejected' db.session.commit() patient = order.patient subject = "Your Canteen Order is Rejected" body = f"Dear {patient.name},\n\nYour canteen order has been rejected. Please place another order or call.\n\nBest regards,\nCanteen Team" send_email(patient.email, subject, body) flash('Order rejected') return redirect(url_for('canteen_orders')) @app.route('/canteen/update_status/', methods=['GET', 'POST']) def canteen_update_status(order_id): if 'canteen_user_id' not in session: return redirect(url_for('canteen_login')) order = CanteenOrder.query.get_or_404(order_id) if order.canteen_id != session['canteen_user_id']: abort(403) # Pre-load room and bed data for this order room = None bed = None if order.room_id: room = Room.query.get(order.room_id) if order.bed_id: bed = Bed.query.get(order.bed_id) if request.method == 'POST': new_status = request.form['status'] patient = order.patient total_amount = sum(item.item.price * item.quantity for item in order.items) if new_status == 'preparing': order.status = 'preparing' subject = "Your Order is Being Prepared" body = f"Dear {patient.name},\n\nYour order is being prepared. Total: ₹{total_amount}\n\nBest regards,\nCanteen Team" send_email(patient.email, subject, body) elif new_status == 'out_for_delivery': order.status = 'out_for_delivery' subject = "Your Food is Out for Delivery" body = f"Dear {patient.name},\n\nYour food order is out for delivery. Total: ₹{total_amount}\n\nBest regards,\nCanteen Team" send_email(patient.email, subject, body) elif new_status == 'delivered': order.status = 'delivered' subject = "Your Order is Delivered Successfully" body = f"Dear {patient.name},\n\nYour order is delivered successfully. Total: ₹{total_amount}\n\nBest regards,\nCanteen Team" send_email(patient.email, subject, body) db.session.commit() flash('Status updated') return redirect(url_for('canteen_orders')) return render_template('canteen_update_status.html', order=order, room=room, bed=bed) @app.route('/canteen/update_statuses') def canteen_update_statuses(): if 'canteen_user_id' not in session: return redirect(url_for('canteen_login')) canteen_id = session['canteen_user_id'] orders = CanteenOrder.query.filter_by(canteen_id=canteen_id).filter( CanteenOrder.status.in_(['accepted', 'paid', 'preparing', 'out_for_delivery']) ).order_by(CanteenOrder.created_at.desc()).all() # Pre-load room and bed data for all orders orders_with_details = [] for order in orders: order_dict = { 'order': order, 'room': None, 'bed': None } if order.room_id: order_dict['room'] = Room.query.get(order.room_id) if order.bed_id: order_dict['bed'] = Bed.query.get(order.bed_id) orders_with_details.append(order_dict) return render_template('canteen_update_statuses.html', orders=orders_with_details) @app.route('/canteen/manage_reviews') def canteen_manage_reviews(): if 'canteen_user_id' not in session: return redirect(url_for('canteen_login')) canteen_id = session['canteen_user_id'] reviews = CanteenReview.query.filter_by(canteen_id=canteen_id).order_by(CanteenReview.created_at.desc()).all() return render_template('canteen_manage_reviews.html', reviews=reviews) @app.route('/canteen/delete_review/', methods=['POST']) def canteen_delete_review(review_id): if 'canteen_user_id' not in session: return redirect(url_for('canteen_login')) review = CanteenReview.query.get_or_404(review_id) if review.canteen_id != session['canteen_user_id']: abort(403) db.session.delete(review) db.session.commit() flash('Review deleted') return redirect(url_for('canteen_manage_reviews')) # Patient Routes (updated with canteen features) @app.route('/patient/login', methods=['GET', 'POST']) def patient_login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] patient = Patient.query.filter_by(username=username).first() if patient and check_password_hash(patient.password, password): session['patient_user_id'] = patient.id return redirect(url_for('patient_dashboard')) flash('Invalid username or password') return render_template('patient_login.html') @app.route('/patient/register', methods=['GET', 'POST']) def patient_register(): if request.method == 'POST': name = request.form['name'] username = request.form['username'] email = request.form['email'] mobile = request.form['mobile'] password = request.form['password'] confirm_password = request.form['confirm_password'] if password != confirm_password: flash('Passwords do not match') return render_template('patient_register.html') if Patient.query.filter_by(username=username).first() or Patient.query.filter_by(email=email).first(): flash('Username or email already exists') return render_template('patient_register.html') hashed_password = generate_password_hash(password) new_patient = Patient(name=name, username=username, email=email, mobile=mobile, password=hashed_password) db.session.add(new_patient) db.session.commit() return redirect(url_for('patient_login')) return render_template('patient_register.html') @app.route('/patient/dashboard', methods=['GET', 'POST']) def patient_dashboard(): if 'patient_user_id' not in session: return redirect(url_for('patient_login')) patient = Patient.query.get(session['patient_user_id']) hospitals = Hospital.query.all() bookings = Booking.query.filter_by(patient_id=session['patient_user_id']).all() pending_requests = [b for b in bookings if b.status == 'pending'] accepted_unpaid = [b for b in bookings if b.status == 'accepted'] history_bookings = [b for b in bookings if b.status in ['paid', 'rejected']] # Join appointments with time_slots to access time_slot information appointments = db.session.query(Appointment).join(TimeSlot).filter( Appointment.patient_id == session['patient_user_id'] ).all() history_appointments = [a for a in appointments if a.status == 'paid'] # Ambulance ambulance_pending = AmbulanceBooking.query.filter_by(patient_id=session['patient_user_id'], status='pending').all() ambulance_notifications = AmbulanceBooking.query.filter_by(patient_id=session['patient_user_id'], status='accepted').all() ambulance_history = AmbulanceBooking.query.filter_by(patient_id=session['patient_user_id'], status='paid').all() # Nurse nurse_pending = NurseBooking.query.filter_by(patient_id=session['patient_user_id'], status='pending').all() nurse_notifications = NurseBooking.query.filter_by(patient_id=session['patient_user_id'], status='accepted').all() nurse_history = NurseBooking.query.filter_by(patient_id=session['patient_user_id'], status='paid').all() # Canteen canteen_orders = CanteenOrder.query.filter_by(patient_id=session['patient_user_id']).all() canteen_pending = [o for o in canteen_orders if o.status == 'pending'] canteen_notifications = [o for o in canteen_orders if o.status == 'accepted'] canteen_history = [o for o in canteen_orders if o.status in ['paid', 'delivered', 'preparing', 'out_for_delivery']] if request.method == 'POST' and 'edit' in request.form: patient.name = request.form['name'] patient.mobile = request.form['mobile'] patient.email = request.form['email'] patient.info = request.form['info'] db.session.commit() flash('Details updated') return render_template('patient_dashboard.html', patient=patient, hospitals=hospitals, pending_requests=pending_requests, accepted_unpaid=accepted_unpaid, history_bookings=history_bookings, history_appointments=history_appointments, ambulance_pending=ambulance_pending, ambulance_notifications=ambulance_notifications, ambulance_history=ambulance_history, nurse_pending=nurse_pending, nurse_notifications=nurse_notifications, nurse_history=nurse_history, canteen_pending=canteen_pending, canteen_notifications=canteen_notifications, canteen_history=canteen_history) @app.route('/patient/hospital/') def patient_hospital(hospital_id): if 'patient_user_id' not in session: return redirect(url_for('patient_login')) hospital = Hospital.query.get_or_404(hospital_id) doctors = Doctor.query.filter_by(hospital_id=hospital_id).all() ambulances = Ambulance.query.filter_by(hospital_id=hospital_id).all() nurses = Nurse.query.filter_by(hospital_id=hospital_id).all() canteens = Canteen.query.filter_by(hospital_id=hospital_id).all() rooms = Room.query.filter_by(hospital_id=hospital_id).all() return render_template('patient_hospital.html', hospital=hospital, doctors=doctors, ambulances=ambulances, nurses=nurses, canteens=canteens, rooms=rooms) @app.route('/patient/canteen/') def patient_canteen(canteen_id): if 'patient_user_id' not in session: return redirect(url_for('patient_login')) canteen = Canteen.query.get_or_404(canteen_id) categories = CanteenCategory.query.filter_by(canteen_id=canteen_id).all() reviews = CanteenReview.query.filter_by(canteen_id=canteen_id).order_by(CanteenReview.created_at.desc()).all() # Get rooms and beds for the canteen's hospital hospital_id = canteen.hospital_id rooms = Room.query.filter_by(hospital_id=hospital_id).all() # Build a JSON-serializable map: keys as strings -> list of simple dicts beds_by_room = {} for room in rooms: beds = Bed.query.filter_by(room_id=room.id).all() beds_by_room[str(room.id)] = [ { "id": b.id, "bed_number": b.bed_number, "status": b.status } for b in beds ] return render_template('patient_canteen.html', canteen=canteen, categories=categories, reviews=reviews, rooms=rooms, beds_by_room=beds_by_room) @app.route('/patient/submit_canteen_order/', methods=['POST']) def patient_submit_canteen_order(canteen_id): if 'patient_user_id' not in session: return redirect(url_for('patient_login')) # selected_items may be an empty string; ensure it becomes a dict selected_items_raw = request.form.get('selected_items', '') try: selected_items = json.loads(selected_items_raw) if selected_items_raw else {} except Exception: selected_items = {} # room_id/bed_id come from