242 lines
10 KiB
Python
242 lines
10 KiB
Python
|
|
import logging
|
||
|
|
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 datetime import timedelta
|
||
|
|
|
||
|
|
_logger = logging.getLogger(__name__)
|
||
|
|
|
||
|
|
|
||
|
|
class TaskManagementPortal(CustomerPortal):
|
||
|
|
"""Controller for task management functionality in the portal"""
|
||
|
|
|
||
|
|
def _check_access_to_task_model(self, model_name, record_id):
|
||
|
|
"""Verify the user has access to the record"""
|
||
|
|
user = request.env.user
|
||
|
|
record = request.env[model_name].browse(int(record_id))
|
||
|
|
|
||
|
|
# Check if user is a treatment professional
|
||
|
|
is_treatment_prof = user.has_group('bemade_sports_clinic.group_sports_clinic_treatment_professional')
|
||
|
|
|
||
|
|
# Check if record exists
|
||
|
|
if not record.exists():
|
||
|
|
raise UserError(_('Record not found.'))
|
||
|
|
|
||
|
|
# For patient records, check team access
|
||
|
|
if model_name == 'sports.patient':
|
||
|
|
patient_id_int = int(record_id)
|
||
|
|
accessible_teams = request.env['sports.team'].search([
|
||
|
|
('staff_ids.user_id', '=', user.id),
|
||
|
|
('patient_ids', 'in', patient_id_int)
|
||
|
|
])
|
||
|
|
|
||
|
|
if not accessible_teams and not is_treatment_prof:
|
||
|
|
raise UserError(_('You do not have access to this patient.'))
|
||
|
|
|
||
|
|
# For injury records, check team access through the patient
|
||
|
|
elif model_name == 'sports.patient.injury':
|
||
|
|
patient = record.patient_id
|
||
|
|
team = record.team_id
|
||
|
|
|
||
|
|
if team:
|
||
|
|
is_team_staff = team.staff_ids.filtered(
|
||
|
|
lambda s: user.partner_id in s.user_ids.partner_id
|
||
|
|
)
|
||
|
|
|
||
|
|
if not is_team_staff and not is_treatment_prof:
|
||
|
|
raise UserError(_('You do not have access to this injury.'))
|
||
|
|
else:
|
||
|
|
raise UserError(_('This injury is not associated with a team.'))
|
||
|
|
|
||
|
|
return record
|
||
|
|
|
||
|
|
@http.route(['/my/activities'], type='http', auth='user', website=True)
|
||
|
|
def view_activities(self, **kw):
|
||
|
|
"""Display list of activities assigned to the current user"""
|
||
|
|
user = request.env.user
|
||
|
|
partner = user.partner_id
|
||
|
|
|
||
|
|
# Get all activities assigned to this user
|
||
|
|
activities = request.env['mail.activity'].search([
|
||
|
|
('user_id', '=', user.id),
|
||
|
|
('res_model', 'in', ['sports.patient', 'sports.patient.injury']),
|
||
|
|
], order='date_deadline asc')
|
||
|
|
|
||
|
|
# Group activities by model
|
||
|
|
patient_activities = activities.filtered(lambda a: a.res_model == 'sports.patient')
|
||
|
|
injury_activities = activities.filtered(lambda a: a.res_model == 'sports.patient.injury')
|
||
|
|
|
||
|
|
# Get activity types for filtering
|
||
|
|
activity_types = request.env['mail.activity.type'].search([])
|
||
|
|
|
||
|
|
values = {
|
||
|
|
'activities': activities,
|
||
|
|
'patient_activities': patient_activities,
|
||
|
|
'injury_activities': injury_activities,
|
||
|
|
'activity_types': activity_types,
|
||
|
|
'page_name': 'activities',
|
||
|
|
}
|
||
|
|
|
||
|
|
return request.render('bemade_sports_clinic.portal_my_activities', values)
|
||
|
|
|
||
|
|
@http.route(['/my/activity/create'], type='http', auth='user', website=True)
|
||
|
|
def create_activity_form(self, model=None, res_id=None, **kw):
|
||
|
|
"""Display form to create a new activity"""
|
||
|
|
# Validate model and res_id
|
||
|
|
valid_models = ['sports.patient', 'sports.patient.injury']
|
||
|
|
if model not in valid_models or not res_id:
|
||
|
|
return request.redirect('/my/activities')
|
||
|
|
|
||
|
|
try:
|
||
|
|
record = self._check_access_to_task_model(model, res_id)
|
||
|
|
except UserError as e:
|
||
|
|
return request.render('portal.403', {'error': str(e)})
|
||
|
|
|
||
|
|
# Get activity types
|
||
|
|
activity_types = request.env['mail.activity.type'].search([])
|
||
|
|
|
||
|
|
# Get users that can be assigned to activities
|
||
|
|
domain = []
|
||
|
|
|
||
|
|
# If this is an injury record, filter by team staff
|
||
|
|
if model == 'sports.patient.injury':
|
||
|
|
team = record.team_id
|
||
|
|
if team:
|
||
|
|
domain = [('partner_id', 'in', team.staff_ids.mapped('partner_id').ids)]
|
||
|
|
|
||
|
|
# Only treatment professionals can see and assign all users
|
||
|
|
is_treatment_prof = request.env.user.has_group('bemade_sports_clinic.group_sports_clinic_treatment_professional')
|
||
|
|
if not is_treatment_prof:
|
||
|
|
domain.append(('id', '=', request.env.user.id))
|
||
|
|
|
||
|
|
assignable_users = request.env['res.users'].search(domain)
|
||
|
|
|
||
|
|
# Prepare record name for display
|
||
|
|
record_name = record.name if hasattr(record, 'name') else record.display_name
|
||
|
|
|
||
|
|
# Default return URL
|
||
|
|
if model == 'sports.patient':
|
||
|
|
return_url = f'/my/player?player_id={res_id}'
|
||
|
|
else: # sports.patient.injury
|
||
|
|
return_url = f'/my/player?player_id={record.patient_id.id}'
|
||
|
|
|
||
|
|
values = {
|
||
|
|
'activity_types': activity_types,
|
||
|
|
'assignable_users': assignable_users,
|
||
|
|
'record': record,
|
||
|
|
'record_name': record_name,
|
||
|
|
'model': model,
|
||
|
|
'res_id': res_id,
|
||
|
|
'default_user_id': request.env.user.id,
|
||
|
|
'return_url': kw.get('return_url', return_url),
|
||
|
|
'page_name': 'create_activity',
|
||
|
|
}
|
||
|
|
|
||
|
|
return request.render('bemade_sports_clinic.portal_create_activity', values)
|
||
|
|
|
||
|
|
@http.route(['/my/activity/save'], type='http', auth='user', website=True, methods=['POST'])
|
||
|
|
def create_activity_submit(self, **post):
|
||
|
|
"""Process form submission to create a new activity"""
|
||
|
|
model = post.get('model')
|
||
|
|
res_id = post.get('res_id')
|
||
|
|
|
||
|
|
# Validate model and res_id
|
||
|
|
valid_models = ['sports.patient', 'sports.patient.injury']
|
||
|
|
if model not in valid_models or not res_id:
|
||
|
|
return request.redirect('/my/activities')
|
||
|
|
|
||
|
|
try:
|
||
|
|
record = self._check_access_to_task_model(model, res_id)
|
||
|
|
except UserError as e:
|
||
|
|
return request.render('portal.403', {'error': str(e)})
|
||
|
|
|
||
|
|
# Validate required fields
|
||
|
|
activity_type_id = post.get('activity_type_id')
|
||
|
|
summary = post.get('summary')
|
||
|
|
user_id = post.get('user_id')
|
||
|
|
date_deadline = post.get('date_deadline')
|
||
|
|
|
||
|
|
if not activity_type_id or not summary or not user_id or not date_deadline:
|
||
|
|
return_url = post.get('return_url', '/my/activities')
|
||
|
|
return request.redirect(f'{return_url}&error=missing_fields')
|
||
|
|
|
||
|
|
# Check if the assigned user is valid
|
||
|
|
is_treatment_prof = request.env.user.has_group('bemade_sports_clinic.group_sports_clinic_treatment_professional')
|
||
|
|
assigned_user = request.env['res.users'].browse(int(user_id))
|
||
|
|
|
||
|
|
# Only treatment professionals can assign to other users
|
||
|
|
if not is_treatment_prof and assigned_user.id != request.env.user.id:
|
||
|
|
return_url = post.get('return_url', '/my/activities')
|
||
|
|
return request.redirect(f'{return_url}&error=invalid_user')
|
||
|
|
|
||
|
|
# Create the activity
|
||
|
|
vals = {
|
||
|
|
'activity_type_id': int(activity_type_id),
|
||
|
|
'summary': summary,
|
||
|
|
'note': post.get('note', ''),
|
||
|
|
'user_id': int(user_id),
|
||
|
|
'date_deadline': date_deadline,
|
||
|
|
'res_model_id': request.env['ir.model']._get_id(model),
|
||
|
|
'res_id': int(res_id),
|
||
|
|
}
|
||
|
|
|
||
|
|
activity = request.env['mail.activity'].sudo().create(vals)
|
||
|
|
|
||
|
|
# Redirect to the return URL or activities page
|
||
|
|
return_url = post.get('return_url', '/my/activities')
|
||
|
|
return request.redirect(f'{return_url}&success=activity_created')
|
||
|
|
|
||
|
|
@http.route(['/my/activity/complete'], type='http', auth='user', website=True, methods=['POST'])
|
||
|
|
def complete_activity(self, activity_id, **post):
|
||
|
|
"""Mark an activity as done"""
|
||
|
|
activity = request.env['mail.activity'].browse(int(activity_id))
|
||
|
|
|
||
|
|
# Check if the activity exists and belongs to the current user
|
||
|
|
if not activity.exists() or activity.user_id != request.env.user:
|
||
|
|
return request.redirect('/my/activities')
|
||
|
|
|
||
|
|
# Add feedback if provided
|
||
|
|
feedback = post.get('feedback', '')
|
||
|
|
|
||
|
|
# Mark the activity as done
|
||
|
|
activity.sudo().action_feedback(feedback=feedback)
|
||
|
|
|
||
|
|
# Redirect to activities page
|
||
|
|
return request.redirect('/my/activities')
|
||
|
|
|
||
|
|
@http.route(['/my/activity/cancel'], type='http', auth='user', website=True, methods=['POST'])
|
||
|
|
def cancel_activity(self, activity_id, **post):
|
||
|
|
"""Cancel an activity"""
|
||
|
|
activity = request.env['mail.activity'].browse(int(activity_id))
|
||
|
|
|
||
|
|
# Check if the activity exists and belongs to the current user
|
||
|
|
if not activity.exists() or activity.user_id != request.env.user:
|
||
|
|
return request.redirect('/my/activities')
|
||
|
|
|
||
|
|
# Cancel the activity
|
||
|
|
activity.sudo().unlink()
|
||
|
|
|
||
|
|
# Redirect to activities page
|
||
|
|
return request.redirect('/my/activities')
|
||
|
|
|
||
|
|
@http.route(['/my/activity/reschedule'], type='http', auth='user', website=True, methods=['POST'])
|
||
|
|
def reschedule_activity(self, activity_id, **post):
|
||
|
|
"""Reschedule an activity to a new date"""
|
||
|
|
activity = request.env['mail.activity'].browse(int(activity_id))
|
||
|
|
|
||
|
|
# Check if the activity exists and belongs to the current user
|
||
|
|
if not activity.exists() or activity.user_id != request.env.user:
|
||
|
|
return request.redirect('/my/activities')
|
||
|
|
|
||
|
|
# Get new deadline
|
||
|
|
new_deadline = post.get('new_deadline')
|
||
|
|
if not new_deadline:
|
||
|
|
return request.redirect('/my/activities')
|
||
|
|
|
||
|
|
# Update the deadline
|
||
|
|
activity.sudo().write({'date_deadline': new_deadline})
|
||
|
|
|
||
|
|
# Redirect to activities page
|
||
|
|
return request.redirect('/my/activities')
|