bemade-addons/bemade_sports_clinic/controllers/patient_injury_portal.py

809 lines
35 KiB
Python

import logging
import base64
import io
from odoo import http, fields, _
from odoo.exceptions import UserError, ValidationError
from odoo.http import request
from odoo.addons.portal.controllers.portal import CustomerPortal, pager
from .access_control_mixin import AccessControlMixin
from datetime import datetime
_logger = logging.getLogger(__name__)
class PatientInjuryPortal(CustomerPortal, AccessControlMixin):
"""Controller for all injury reporting functionality in the portal"""
# Access control methods now inherited from AccessControlMixin
@http.route(['/my/patient/injury/new'], type='http', auth='user', website=True)
def create_injury_form(self, patient_id=None, **post):
"""Show form to create a new injury report"""
if not patient_id:
return request.redirect('/my/players')
try:
patient = self._check_access_to_patient(patient_id)
except UserError as e:
return request.render('http_routing.http_error', {
'status_code': 403,
'status_message': 'Forbidden',
'error_message': str(e)
})
return_url = post.get('return_url', f'/my/player?player_id={patient_id}')
# Resolve team context
patient_teams = patient.team_ids
# Accept team context from both kwargs and request.params (GET)
team_id_param = post.get('team_id') or request.params.get('team_id')
selected_team_id = None
if team_id_param:
try:
team_id_int = int(team_id_param)
except Exception:
team_id_int = None
if team_id_int and team_id_int in patient_teams.ids:
selected_team_id = team_id_int
if not selected_team_id and len(patient_teams) == 1:
selected_team_id = patient_teams[0].id
require_team_selection = len(patient_teams) > 1 and not selected_team_id
# Check if user is a treatment professional
# Use request.env.user.has_group() directly to avoid security violations
is_treatment_prof = request.env.user.has_group('bemade_sports_clinic.group_portal_treatment_professional')
user = request.env.user
# Get treatment professionals for the multi-select field (if treatment professional)
treatment_professionals = []
parental_consent_options = None
if is_treatment_prof:
# Include both portal and internal treatment professionals
portal_tp_group = request.env.ref('bemade_sports_clinic.group_portal_treatment_professional')
internal_tp_group = request.env.ref('bemade_sports_clinic.group_sports_clinic_treatment_professional')
treatment_professionals = request.env['res.users'].search([
('groups_id', 'in', [portal_tp_group.id, internal_tp_group.id])
])
parental_consent_options = request.env['sports.patient.injury']._fields['parental_consent'].selection
values = {
'patient': patient,
'return_url': return_url,
'page_name': 'report_injury',
'is_treatment_prof': is_treatment_prof, # Pass flag to template for conditional display
'treatment_professionals': treatment_professionals,
'parental_consent_options': parental_consent_options,
'patient_teams': patient_teams,
'selected_team_id': selected_team_id,
'require_team_selection': require_team_selection,
'error': post.get('error'),
}
return request.render('bemade_sports_clinic.portal_create_injury', values)
@http.route(['/my/patient/injury/create'], type='http', auth='user', website=True, methods=['POST'])
def create_injury_submit(self, **post):
"""Process the form submission to create a new injury"""
patient_id = post.get('patient_id')
if not patient_id:
return request.redirect('/my/players')
try:
patient = self._check_access_to_patient(patient_id)
except UserError as e:
return request.render('http_routing.http_error', {
'status_code': 403,
'status_message': 'Forbidden',
'error_message': str(e)
})
# Resolve team from submission or context
patient_teams = patient.team_ids
submitted_team = post.get('team_id')
team_id = None
if submitted_team:
try:
submitted_team_int = int(submitted_team)
except Exception:
submitted_team_int = None
if submitted_team_int and submitted_team_int in patient_teams.ids:
team_id = submitted_team_int
else:
# Invalid team submitted; re-render form with error
return request.redirect(f"/my/patient/injury/new?patient_id={patient.id}&error=invalid_team")
else:
if len(patient_teams) == 1:
team_id = patient_teams[0].id
elif len(patient_teams) > 1:
# Team selection required when multiple teams and no selection provided
return request.redirect(f"/my/patient/injury/new?patient_id={patient.id}&error=team_required")
# Check if the current user is a treatment professional
is_treatment_prof = request.env.user.has_group('bemade_sports_clinic.group_portal_treatment_professional')
# Prepare values for injury creation
vals = {
'patient_id': patient.id,
'diagnosis': post.get('diagnosis', ''),
'external_notes': post.get('external_notes', ''),
'stage': 'active',
}
# Handle injury date and injury_date_na checkbox
if post.get('injury_date_na'):
vals['injury_date_na'] = True
vals['injury_date'] = False # Clear injury_date if N/A is checked
elif post.get('injury_date'):
vals['injury_date'] = post.get('injury_date')
vals['injury_date_na'] = False
# Add team_id if resolved
if team_id:
vals['team_id'] = int(team_id)
# Handle optional fields
if post.get('parental_consent'):
vals['parental_consent'] = post.get('parental_consent')
if post.get('predicted_resolution_date'):
vals['predicted_resolution_date'] = post.get('predicted_resolution_date')
# Handle internal notes for treatment professionals
if is_treatment_prof and post.get('internal_notes'):
vals['internal_notes'] = post.get('internal_notes')
# Create the injury record - portal users now have create permission
injury = request.env['sports.patient.injury'].create(vals)
# Determine if user is a coach or treatment professional
# Use request.env.user.has_group() directly to avoid security violations
is_portal_coach = request.env.user.has_group('bemade_sports_clinic.group_portal_team_coach')
is_treatment_prof = request.env.user.has_group('bemade_sports_clinic.group_portal_treatment_professional')
user = request.env.user
# Assign treatment professionals based on user role
# Handle treatment professional assignments
treatment_prof_ids = []
# If user is a treatment professional, add them by default
if is_treatment_prof:
treatment_prof_ids.append(user.id)
# Also add any additional treatment professionals selected in the form (checkbox-based)
selected_tp_ids = request.httprequest.form.getlist('treatment_professional_ids[]')
if selected_tp_ids:
# Convert to integers and add to list (avoiding duplicates)
for tp_id in selected_tp_ids:
tp_id_int = int(tp_id)
if tp_id_int not in treatment_prof_ids:
treatment_prof_ids.append(tp_id_int)
# Assign treatment professionals if any were identified
if treatment_prof_ids:
injury.write({
'treatment_professional_ids': [(6, 0, treatment_prof_ids)]
})
else:
# User is not a treatment professional
pass
# Get current treatment professionals
treatment_profs = injury.treatment_professional_ids
# Always try to assign team therapists regardless of who created the injury
# Only when a single team context is determinable
if team_id:
selected_team_id = int(team_id)
# Find therapists (head and regular) specifically for this team
team_staff = request.env['sports.team.staff'].sudo().search([
('team_id', '=', selected_team_id),
('role', 'in', ['head_therapist', 'therapist'])
])
# Collect user IDs from team staff (prefer direct user_ids relation, fallback to partner mapping)
team_tp_user_ids = set()
for staff in team_staff:
if staff.user_ids:
for u in staff.user_ids:
team_tp_user_ids.add(u.id)
else:
users = request.env['res.users'].sudo().search([('partner_id', '=', staff.partner_id.id)])
for u in users:
team_tp_user_ids.add(u.id)
if not team_tp_user_ids:
_logger.warning("No valid therapists found to assign to the injury for team %s", selected_team_id)
# Merge any team therapists with any already set/selected ones
merged_ids = set(treatment_prof_ids) | team_tp_user_ids if 'treatment_prof_ids' in locals() else team_tp_user_ids
if merged_ids:
injury.write({'treatment_professional_ids': [(6, 0, list(merged_ids))]})
else:
_logger.info(
"Skipping team-based therapist auto-assignment: patient %s has %s teams",
patient.id,
len(patient.team_ids),
)
# Handle treatment note creation if provided by treatment professional
if is_treatment_prof and post.get('treatment_note'):
treatment_note_text = post.get('treatment_note').strip()
if treatment_note_text:
try:
# Create treatment note using the controller helper to ensure correct permissions and linkage
self._add_treatment_note(injury.patient_id, treatment_note_text, injury)
_logger.info(f"Treatment note added to injury {injury.id} by user {request.env.user.id}")
except Exception as e:
_logger.error(f"Failed to create treatment note for injury {injury.id}: {str(e)}")
# Trigger recomputation of patient status based on the injury
patient._compute_is_injured()
patient._compute_stage()
return_url = f'/my/player?player_id={patient_id}'
values = {
'return_url': return_url,
}
return request.render('bemade_sports_clinic.portal_injury_created', values)
# _check_access_to_injury method now inherited from AccessControlMixin
@http.route(['/my/injury/edit'], type='http', auth='user', website=True)
def edit_injury_form(self, injury_id=None, **post):
"""Show form to edit an existing injury"""
if not injury_id:
return request.redirect('/my/players')
try:
injury = self._check_access_to_injury(injury_id)
except UserError as e:
return request.render('http_routing.http_error', {
'status_code': 403,
'status_message': 'Forbidden',
'error_message': str(e)
})
return_url = post.get('return_url', f'/my/player?player_id={injury.patient_id.id}')
# Get possible injury stages - treatment professionals can change stage
stages = []
# Use request.env.user.has_group() directly to avoid security violations
is_treatment_prof = request.env.user.has_group('bemade_sports_clinic.group_portal_treatment_professional')
user = request.env.user
if is_treatment_prof:
stage_selection = request.env['sports.patient.injury']._fields['stage'].selection
stages = [(k, v) for k, v in stage_selection]
# Get treatment professionals for the multi-select field (both portal and internal)
portal_tp_group = request.env.ref('bemade_sports_clinic.group_portal_treatment_professional')
internal_tp_group = request.env.ref('bemade_sports_clinic.group_sports_clinic_treatment_professional')
treatment_professionals = request.env['res.users'].search([
('groups_id', 'in', [portal_tp_group.id, internal_tp_group.id])
])
# Get parental consent options if treatment professional
parental_consent_options = None
if is_treatment_prof:
parental_consent_options = request.env['sports.patient.injury']._fields['parental_consent'].selection
values = {
'injury': injury,
'stages': stages,
'treatment_professionals': treatment_professionals,
'parental_consent_options': parental_consent_options,
'return_url': return_url,
'is_treatment_prof': is_treatment_prof,
'page_name': 'edit_injury',
'error': post.get('error'),
'success': post.get('success'),
}
return request.render('bemade_sports_clinic.portal_edit_injury', values)
@http.route(['/my/injury/save'], type='http', auth='user', website=True, methods=['POST'])
def edit_injury_submit(self, **post):
"""Process the form submission to update an injury"""
injury_id = post.get('injury_id')
if not injury_id:
return request.redirect('/my/players')
try:
injury = self._check_access_to_injury(injury_id)
except UserError as e:
return request.render('http_routing.http_error', {
'status_code': 403,
'status_message': 'Forbidden',
'error_message': str(e)
})
# Get user's role
# Use request.env.user.has_group() directly to avoid security violations
is_treatment_prof = request.env.user.has_group('bemade_sports_clinic.group_portal_treatment_professional')
user = request.env.user
# Prepare values for injury update
vals = {}
# Fields everyone can update
vals.update({
'diagnosis': post.get('diagnosis', injury.diagnosis or ''),
'external_notes': post.get('external_notes', injury.external_notes or ''),
})
# Handle injury date and N/A checkbox
if post.get('injury_date_na'):
vals['injury_date_na'] = True
vals['injury_date'] = False # Clear the date if N/A is checked
else:
vals['injury_date_na'] = False
if post.get('injury_date'):
vals['injury_date'] = post.get('injury_date')
# Handle resolution dates
if post.get('predicted_resolution_date'):
vals['predicted_resolution_date'] = post.get('predicted_resolution_date')
if post.get('resolution_date'):
vals['resolution_date'] = post.get('resolution_date')
# Handle treatment professionals (checkbox-based multi-select)
selected_tp_ids = request.httprequest.form.getlist('treatment_professional_ids[]')
if selected_tp_ids:
# Convert to integers and set using Odoo's many2many syntax
prof_ids = [int(pid) for pid in selected_tp_ids if pid]
vals['treatment_professional_ids'] = [(6, 0, prof_ids)]
else:
# If no checkboxes are selected, clear the treatment professionals
vals['treatment_professional_ids'] = [(6, 0, [])]
# Fields only treatment professionals can update
if is_treatment_prof:
if post.get('internal_notes'):
vals['internal_notes'] = post.get('internal_notes')
if post.get('stage'):
vals['stage'] = post.get('stage')
if post.get('parental_consent'):
vals['parental_consent'] = post.get('parental_consent')
# Update the injury
injury.sudo().write(vals)
# Add a treatment note if provided
if post.get('treatment_note') and is_treatment_prof:
# Add treatment note for injury
self._add_treatment_note(injury.patient_id, post.get('treatment_note'), injury)
# Redirect back to the edit form with success message
return_url = post.get('return_url', f'/my/injury/edit?injury_id={injury_id}')
return request.redirect(f'{return_url}&success=injury_updated')
def _add_treatment_note(self, patient, note_content, injury=None):
"""Helper method to add a treatment note to a patient, optionally linked to an injury"""
if not note_content.strip():
return False
# Validate patient parameter
# Create a new treatment note linked to patient, optionally to injury
vals = {
'patient_id': patient.id,
'note': note_content,
'date': fields.Date.today(),
'user_id': request.env.user.id,
}
# Create treatment note with prepared values
# If injury is provided, link the note to it
if injury:
vals['injury_id'] = injury.id
request.env['sports.treatment.note'].sudo().create(vals)
return True
@http.route(['/my/injury/notes'], type='http', auth='user', website=True)
def view_treatment_notes(self, injury_id=None, patient_id=None, **post):
"""View treatment notes for an injury or a patient"""
# Determine context - are we viewing injury-specific notes or all patient notes?
# At least one of injury_id or patient_id must be provided
if not injury_id and not patient_id:
return request.redirect('/my/players')
# Get user's role
is_treatment_prof = request.env.user.has_group('bemade_sports_clinic.group_portal_treatment_professional')
if injury_id:
# Injury context
try:
injury = self._check_access_to_injury(injury_id)
patient = injury.patient_id
except UserError as e:
return request.render('http_routing.http_error', {
'status_code': 403,
'status_message': 'Forbidden',
'error_message': str(e)
})
# Get notes for this injury
notes = request.env['sports.treatment.note'].sudo().search(
[('injury_id', '=', int(injury_id))],
order='date desc, id desc'
)
values = {
'injury': injury,
'notes': notes,
'patient': patient,
'is_treatment_prof': is_treatment_prof,
'page_name': 'injury_notes',
'error': post.get('error'),
'success': post.get('success'),
'context': 'injury',
}
else:
# Patient context
try:
patient = self._check_access_to_patient(patient_id)
except UserError as e:
return request.render('http_routing.http_error', {
'status_code': 403,
'status_message': 'Forbidden',
'error_message': str(e)
})
# Get all notes for this patient
notes = request.env['sports.treatment.note'].sudo().search(
[('patient_id', '=', int(patient_id))],
order='date desc, id desc'
)
values = {
'injury': None,
'notes': notes,
'patient': patient,
'is_treatment_prof': is_treatment_prof,
'page_name': 'patient_notes',
'error': post.get('error'),
'success': post.get('success'),
'context': 'patient',
}
return request.render('bemade_sports_clinic.portal_treatment_notes', values)
@http.route(['/my/injury/note/add'], type='http', auth='user', website=True, methods=['POST'])
def add_treatment_note(self, **post):
"""Add a new treatment note to a patient, optionally linked to an injury"""
# Get context - are we adding a note to an injury or just to a patient?
injury_id = post.get('injury_id')
patient_id = post.get('patient_id')
# Either injury_id or patient_id must be provided
if not injury_id and not patient_id:
return request.redirect('/my/players')
# Check if user is a treatment professional
is_treatment_prof = request.env.user.has_group('bemade_sports_clinic.group_portal_treatment_professional')
if not is_treatment_prof:
# Determine redirect URL based on context
if injury_id:
return request.redirect(f'/my/injury/notes?injury_id={injury_id}&error=permission_denied')
else:
return request.redirect(f'/my/injury/notes?patient_id={patient_id}&error=permission_denied')
# Get note content and validate
note_content = post.get('note')
if not note_content or not note_content.strip():
if injury_id:
return request.redirect(f'/my/injury/notes?injury_id={injury_id}&error=empty_note')
else:
return request.redirect(f'/my/injury/notes?patient_id={patient_id}&error=empty_note')
# Determine context and add the note
if injury_id:
# Injury context
try:
injury = self._check_access_to_injury(injury_id)
patient = injury.patient_id
self._add_treatment_note(patient, note_content, injury)
return request.redirect(f'/my/injury/notes?injury_id={injury_id}&success=note_added')
except UserError as e:
return request.render('http_routing.http_error', {
'status_code': 403,
'status_message': 'Forbidden',
'error_message': str(e)
})
else:
# Patient context
try:
patient = self._check_access_to_patient(patient_id)
except UserError as e:
return request.render('http_routing.http_error', {
'status_code': 403,
'status_message': 'Forbidden',
'error_message': str(e)
})
self._add_treatment_note(patient, note_content)
return request.redirect(f'/my/injury/notes?patient_id={patient_id}&success=note_added')
@http.route(['/my/injury/documents'], type='http', auth='user', website=True)
def view_injury_documents(self, injury_id=None, **post):
"""View documents attached to an injury"""
if not injury_id:
return request.redirect('/my/players')
try:
injury = self._check_access_to_injury(injury_id)
except UserError as e:
return request.render('http_routing.http_error', {
'status_code': 403,
'status_message': 'Forbidden',
'error_message': str(e)
})
# Get documents for this injury
documents = request.env['sports.injury.document'].sudo().search(
[('injury_id', '=', int(injury_id))],
order='create_date desc'
)
# Get user's role
is_treatment_prof = request.env.user.has_group('bemade_sports_clinic.group_portal_treatment_professional')
# Document categories (aligned with model)
categories = [
('medical', 'Medical'),
('medical_imaging', 'Medical Imaging'),
('prescription', 'Prescription'),
('other', 'Other'),
]
values = {
'injury': injury,
'documents': documents,
'patient': injury.patient_id,
'is_treatment_prof': is_treatment_prof,
'page_name': 'injury_documents',
'error': post.get('error'),
'success': post.get('success'),
'categories': categories,
}
return request.render('bemade_sports_clinic.portal_injury_documents', values)
@http.route(['/my/injury/document/upload'], type='http', auth='user', website=True, methods=['POST'])
def upload_injury_document(self, **post):
"""Upload a document for an injury"""
injury_id = post.get('injury_id')
if not injury_id:
return request.redirect('/my/players')
try:
injury = self._check_access_to_injury(injury_id)
except UserError as e:
return request.render('http_routing.http_error', {
'status_code': 403,
'status_message': 'Forbidden',
'error_message': str(e)
})
# Check if file was uploaded
attachment = post.get('attachment')
if not attachment:
return request.redirect(f'/my/injury/documents?injury_id={injury_id}&error=no_file')
# Process the file
try:
name = attachment.filename
file_content = attachment.read()
file_size = len(file_content)
# Check file size (limit to 10MB)
if file_size > 10 * 1024 * 1024: # 10MB in bytes
return request.redirect(f'/my/injury/documents?injury_id={injury_id}&error=file_too_large')
# Create the document
document = request.env['sports.injury.document'].sudo().create({
'injury_id': int(injury_id),
'patient_id': injury.patient_id.id,
'name': post.get('document_name', name),
'description': post.get('description', ''),
'category': post.get('category', 'other'),
'file_content': base64.b64encode(file_content),
'file_name': name,
'created_by_id': request.env.user.id,
})
# Redirect back to documents page with success message
return request.redirect(f'/my/injury/documents?injury_id={injury_id}&success=document_uploaded')
except Exception as e:
_logger.error(f"Error uploading document: {e}")
return request.redirect(f'/my/injury/documents?injury_id={injury_id}&error=upload_failed')
@http.route(['/my/injury/document/download/<int:document_id>'], type='http', auth='user')
def download_injury_document(self, document_id, **post):
"""Download a document attached to an injury"""
document = request.env['sports.injury.document'].sudo().browse(int(document_id))
if not document.exists():
raise request.not_found()
try:
# Prefer checking access via injury; if no injury, check via patient
if document.injury_id:
self._check_access_to_injury(document.injury_id.id)
else:
self._check_access_to_patient(document.patient_id.id)
except UserError:
raise request.not_found()
# Return the file for download
return request.make_response(
base64.b64decode(document.file_content),
headers=[
('Content-Type', 'application/octet-stream'),
('Content-Disposition', f'attachment; filename="{document.file_name}"'),
]
)
@http.route(['/my/patient/document/download/<int:document_id>'], type='http', auth='user')
def download_patient_document(self, document_id, **post):
"""Download a document linked to a patient (injury optional)."""
document = request.env['sports.injury.document'].sudo().browse(int(document_id))
if not document.exists():
raise request.not_found()
try:
# Access check based on patient (primary link)
self._check_access_to_patient(document.patient_id.id)
except UserError:
raise request.not_found()
return request.make_response(
base64.b64decode(document.file_content),
headers=[
('Content-Type', 'application/octet-stream'),
('Content-Disposition', f'attachment; filename="{document.file_name}"'),
]
)
@http.route(['/my/patient/document/upload'], type='http', auth='user', website=True, methods=['POST'])
def upload_patient_document(self, **post):
"""Upload a document directly to a patient (injury optional)."""
patient_id = post.get('patient_id')
if not patient_id:
return request.redirect('/my/players')
try:
patient = self._check_access_to_patient(patient_id)
except UserError as e:
return request.render('http_routing.http_error', {
'status_code': 403,
'status_message': 'Forbidden',
'error_message': str(e)
})
attachment = post.get('attachment')
if not attachment:
return request.redirect(f'/my/player?player_id={patient.id}&error=no_file')
try:
name = attachment.filename
file_content = attachment.read()
file_size = len(file_content)
# 10MB limit
if file_size > 10 * 1024 * 1024:
return request.redirect(f'/my/player?player_id={patient.id}&error=file_too_large')
# Create patient-linked document (injury optional)
request.env['sports.injury.document'].sudo().create({
'patient_id': patient.id,
'injury_id': int(post['injury_id']) if post.get('injury_id') else False,
'name': post.get('document_name', name),
'description': post.get('description', ''),
'category': post.get('category', 'other'),
'file_content': base64.b64encode(file_content),
'file_name': name,
'created_by_id': request.env.user.id,
})
return request.redirect(f'/my/player?player_id={patient.id}&success=document_uploaded')
except Exception as e:
_logger.error(f"Error uploading patient document: {e}")
return request.redirect(f'/my/player?player_id={patient.id}&error=upload_failed')
@http.route(['/my/injury/document/delete/<int:document_id>'], type='http', auth='user', website=True)
def delete_injury_document(self, document_id, **post):
"""Delete a document attached to an injury"""
document = request.env['sports.injury.document'].sudo().browse(int(document_id))
if not document.exists():
raise request.not_found()
try:
# Check access to the injury this document belongs to
injury = self._check_access_to_injury(document.injury_id.id)
except UserError:
raise request.not_found()
# Check if user is a treatment professional (only they can delete documents)
is_treatment_prof = request.env.user.has_group('bemade_sports_clinic.group_portal_treatment_professional')
if not is_treatment_prof:
return request.redirect(f'/my/injury/documents?injury_id={document.injury_id.id}&error=permission_denied')
# Delete the document
injury_id = document.injury_id.id
document.sudo().unlink()
# Redirect back to documents page with success message
return request.redirect(f'/my/injury/documents?injury_id={injury_id}&success=document_deleted')
@http.route(['/my/injury/verify'], type='http', auth='user', website=True, methods=['POST'])
def verify_injury(self, injury_id, **post):
"""Verify an injury (change status from unverified to active)"""
try:
injury = request.env['sports.patient.injury'].browse(int(injury_id))
# Check access - user must be a treatment professional or admin
if not (request.env.user.has_group('bemade_sports_clinic.group_portal_treatment_professional') or
request.env.user.has_group('base.group_system')):
return request.redirect('/my')
# Verify the injury
injury.action_verify_injury()
# Redirect back to the player page
return request.redirect(f'/my/player?player_id={injury.patient_id.id}')
except Exception as e:
_logger.error(f"Error verifying injury: {e}")
return request.redirect('/my')
@http.route(['/my/injury/delete'], type='http', auth='user', website=True, methods=['POST'])
def delete_injury(self, **post):
"""Delete an injury record (only for treatment professionals)"""
injury_id = post.get('injury_id')
return_url = post.get('return_url', '/my/players')
if not injury_id:
return request.redirect(return_url)
try:
injury = self._check_access_to_injury(injury_id)
except UserError as e:
return request.render('http_routing.http_error', {
'status_code': 403,
'status_message': 'Forbidden',
'error_message': str(e)
})
# Check if user is a treatment professional (only they can delete injuries)
is_treatment_prof = request.env.user.has_group('bemade_sports_clinic.group_portal_treatment_professional')
if not is_treatment_prof:
return request.redirect(f'{return_url}?error=permission_denied')
# Get patient info before deletion for redirect
patient_id = injury.patient_id.id
try:
# Delete the injury record (this will cascade delete related records)
injury.sudo().unlink()
_logger.info(f"Injury {injury_id} deleted by user {request.env.user.id}")
# Redirect back to player page with success message
return request.redirect(f'/my/player?player_id={patient_id}&success=injury_deleted')
except Exception as e:
_logger.error(f"Error deleting injury {injury_id}: {str(e)}")
return request.redirect(f'{return_url}?error=delete_failed')