qwerrewq / utils.py
SuriRaja's picture
Upload 21 files
c6ad4a0 verified
Raw
History Blame Contribute Delete
6.87 kB
import os
import uuid
from datetime import datetime
from flask import Response, current_app
from PIL import Image
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle
from reportlab.lib import colors
from io import BytesIO
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}
def allowed_file(filename):
"""Check if the uploaded file has an allowed extension."""
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
def save_uploaded_image(file):
"""Save an uploaded image file with a unique filename."""
if not file:
return None
# Generate unique filename
filename = str(uuid.uuid4()) + '.' + file.filename.rsplit('.', 1)[1].lower()
filepath = os.path.join(current_app.config['UPLOAD_FOLDER'], filename)
# Save and optimize the image
try:
image = Image.open(file.stream)
# Convert RGBA to RGB if necessary
if image.mode in ('RGBA', 'LA'):
background = Image.new('RGB', image.size, (255, 255, 255))
background.paste(image, mask=image.split()[-1] if image.mode == 'RGBA' else None)
image = background
# Resize if image is too large (max 1920px on longest side)
max_size = 1920
if max(image.size) > max_size:
image.thumbnail((max_size, max_size), Image.Resampling.LANCZOS)
# Save with optimization
image.save(filepath, optimize=True, quality=85)
except Exception as e:
current_app.logger.error(f"Error processing image: {e}")
# Fallback to direct save
file.seek(0)
file.save(filepath)
return filename
def generate_treatment_pdf(treatment_plan):
"""Generate a PDF for the treatment plan."""
buffer = BytesIO()
doc = SimpleDocTemplate(buffer, pagesize=letter)
# Styles
styles = getSampleStyleSheet()
title_style = ParagraphStyle(
'CustomTitle',
parent=styles['Heading1'],
fontSize=18,
spaceAfter=30,
textColor=colors.HexColor('#0F766E')
)
heading_style = ParagraphStyle(
'CustomHeading',
parent=styles['Heading2'],
fontSize=14,
spaceBefore=20,
spaceAfter=10,
textColor=colors.HexColor('#1E40AF')
)
# Build the PDF content
content = []
# Header
content.append(Paragraph("Doctor's Sidekick - Treatment Plan", title_style))
content.append(Spacer(1, 20))
# Patient and plan information
patient_info = [
['Patient:', treatment_plan.patient.full_name],
['Patient ID:', treatment_plan.patient.patient_id],
['Date of Birth:', treatment_plan.patient.date_of_birth.strftime('%B %d, %Y')],
['Plan Date:', treatment_plan.created_at.strftime('%B %d, %Y')],
['Created By:', treatment_plan.created_by.full_name]
]
patient_table = Table(patient_info, colWidths=[1.5*inch, 4*inch])
patient_table.setStyle(TableStyle([
('ALIGN', (0, 0), (-1, -1), 'LEFT'),
('FONTNAME', (0, 0), (0, -1), 'Helvetica-Bold'),
('FONTSIZE', (0, 0), (-1, -1), 12),
('BOTTOMPADDING', (0, 0), (-1, -1), 6),
]))
content.append(patient_table)
content.append(Spacer(1, 30))
# Diagnosis
content.append(Paragraph("Diagnosis", heading_style))
content.append(Paragraph(treatment_plan.diagnosis or "Not specified", styles['Normal']))
content.append(Spacer(1, 15))
# Medications
if treatment_plan.medications:
content.append(Paragraph("Medications", heading_style))
content.append(Paragraph(treatment_plan.medications, styles['Normal']))
content.append(Spacer(1, 15))
# Instructions
if treatment_plan.instructions:
content.append(Paragraph("Instructions", heading_style))
content.append(Paragraph(treatment_plan.instructions, styles['Normal']))
content.append(Spacer(1, 15))
# Duration and Follow-up
if treatment_plan.duration or treatment_plan.follow_up_date:
content.append(Paragraph("Treatment Details", heading_style))
if treatment_plan.duration:
content.append(Paragraph(f"<b>Duration:</b> {treatment_plan.duration}", styles['Normal']))
if treatment_plan.follow_up_date:
content.append(Paragraph(
f"<b>Follow-up Date:</b> {treatment_plan.follow_up_date.strftime('%B %d, %Y')}",
styles['Normal']
))
content.append(Spacer(1, 15))
# Additional Notes
if treatment_plan.notes:
content.append(Paragraph("Additional Notes", heading_style))
content.append(Paragraph(treatment_plan.notes, styles['Normal']))
# Footer
content.append(Spacer(1, 50))
footer_style = ParagraphStyle(
'Footer',
parent=styles['Normal'],
fontSize=10,
textColor=colors.grey,
alignment=1 # Center alignment
)
content.append(Paragraph(
f"Generated on {datetime.now().strftime('%B %d, %Y at %I:%M %p')}",
footer_style
))
# Build PDF
doc.build(content)
# Return PDF as response
buffer.seek(0)
return Response(
buffer.getvalue(),
mimetype='application/pdf',
headers={
'Content-Disposition': f'attachment; filename=treatment_plan_{treatment_plan.id}.pdf'
}
)
def calculate_age(birth_date):
"""Calculate age from birth date."""
today = datetime.now().date()
return today.year - birth_date.year - ((today.month, today.day) < (birth_date.month, birth_date.day))
def format_phone_number(phone):
"""Format phone number for display."""
if not phone:
return ""
# Remove all non-digit characters
digits = ''.join(filter(str.isdigit, phone))
# Format as (XXX) XXX-XXXX for 10-digit numbers
if len(digits) == 10:
return f"({digits[:3]}) {digits[3:6]}-{digits[6:]}"
return phone
def get_dashboard_stats():
"""Get statistics for the dashboard."""
from models import Patient, Visit, Inventory
from datetime import date, timedelta
today = date.today()
week_ago = today - timedelta(days=7)
stats = {
'total_patients': Patient.query.count(),
'new_patients_week': Patient.query.filter(Patient.created_at >= week_ago).count(),
'visits_today': Visit.query.filter(Visit.visit_date >= today).count(),
'low_stock_items': Inventory.query.filter(
Inventory.current_stock <= Inventory.min_threshold
).count()
}
return stats