bemade_sports_clinic: initial commit.

This commit is contained in:
Marc Durepos 2023-10-10 21:52:42 -04:00
parent 96b77f4035
commit f0034ac447
5 changed files with 179 additions and 0 deletions

View file

@ -0,0 +1 @@
from . import models

View file

@ -0,0 +1,46 @@
#
# Bemade Inc.
#
# Copyright (C) October 2023 Bemade Inc. (<https://www.bemade.org>).
# Author: Marc Durepos (Contact : marc@bemade.org)
#
# This program is under the terms of the Odoo Proprietary License v1.0 (OPL-1)
# It is forbidden to publish, distribute, sublicense, or sell copies of the Software
# or modified copies of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
#
{
'name': 'Sports Clinic Management',
'version': '16.0.1.0.0',
'summary': 'Manage the patients of a sports medicine clinic.',
'description': """
Adds the notion of sports teams, players (patients), coaches and treatment
professionals. The core purpose of this module is to keep track of the treatment
history of players and to make it appropriately accessible to the various
involved parties (medical practitioners, clinic staff, team staff, and patients).
Internal users get access to patient data as appropriate, i.e.
treatment professionals get full access to their own patients' data, clinic
staff users get access to basic patient data needed for contacting patients, etc.
External users (portal users) can be added to give coaches and other team
personnel access to limited player data such as estimated return-to-play dates.
""",
'category': 'Services/Medical',
'author': 'Bemade Inc.',
'website': 'https://www.bemade.org',
'license': 'OPL-1',
'depends': ['base', 'mail'],
'data': [],
'demo': [],
'installable': True,
'auto_install': False,
'application': True,
}

View file

@ -0,0 +1,2 @@
from . import patient
from . import sports_team

View file

@ -0,0 +1,80 @@
from odoo import models, fields, _, api
from odoo.exceptions import ValidationError
from datetime import date
from dateutil import relativedelta
class Patient(models.Model):
_name = 'sports.patient'
first_name = fields.Char(required=True)
last_name = fields.Char(required=True)
date_of_birth = fields.Date()
age = fields.Integer(compute='_compute_age')
phone = fields.Char(unaccent=False)
email = fields.Char()
contact_ids = fields.One2many(comodel_name='sports.patient.contact',
inverse_name='patient_id', string='Patient Contacts', )
team_ids = fields.Many2many(comodel_name='res.partner',
relation='sports_team_patient_rel',
column1='patient_id',
column2='team_id',
string='Teams',
domain=[('type', '=', 'team')])
player_status = fields.Selection([
('practice', 'Practice'),
('match', 'Match'),
])
injury_ids = fields.One2many(comodel_name='sports.patient.injury',
inverse_name='patient_id',
string='Injuries')
predicted_return_date = fields.Date(compute='_compute_predicted_return_date')
@api.depends('date_of_birth')
def _compute_age(self):
for rec in self:
if not rec.date_of_birth:
rec.age = False
rec.age = relativedelta(date.today() - rec.date_of_birth).years
@api.depends('injury_ids.predicted_return_date')
def _compute_predicted_return_date(self):
for rec in self:
ongoing_injuries = rec.injury_ids.filtered(
lambda r: r.predicted_return_date > date.today()).sorted(
'predicted_return_date')
if ongoing_injuries:
rec.predicted_return_date = ongoing_injuries[-1]
else:
rec.predicted_return_date = False
class PatientContact(models.Model):
_name = 'sports.patient.contact'
sequence = fields.Integer(required=True, default=0)
name = fields.Char(unaccent=False)
contact_type = fields.Selection(selection=[
('Mother', 'mother'),
('Father', 'father'),
('other', 'Other'),
])
phone = fields.Char(unaccent=False)
patient_id = fields.Many2one(comodel_name='sports.patient', string="Patient")
class PatientInjury(models.Model):
_name = 'sports.patient.injury'
_inherit = ['mail.thread', 'mail.activity.mixin']
patient_id = fields.Many2one(comodel_name='sports.patient', string="Patient")
diagnosis = fields.Char(tracking=True)
injury_date_time = fields.Datetime(string='Date and Time of Injury')
internal_notes = fields.Html(tracking=True)
treatment_professional_ids = fields.Many2many(comodel_name='res.partner',
relation='patient_injury_treatment_pro_rel',
column1='patient_injury_id',
column2='treatment_pro_id',
string='Treatment Professionals',
domain=[
('type', '=', 'treatment_pro')], )
predicted_return_date = fields.Date(tracking=True)

View file

@ -0,0 +1,50 @@
from odoo import models, fields, api, _
from odoo.exceptions import UserError
class Partner(models.Model):
_inherit = 'res.partner'
patient_ids = fields.Many2many(comodel_name='sports.patient',
relation='sports_team_patient_rel',
column1='team_id',
column2='patient_id',
string='Players')
type = fields.Selection(selection_add=[('team', 'Sports Team'),
('treatment_pro', 'Treatment Professional'),])
staff_partner_ids = fields.Many2many(comodel_name='res.partner',
relation='sports_team_staff_partner_rel',
column1='team_id',
column2='staff_partner_id',
string='Staff')
def write(self, vals):
# Override to validate changes to the 'type' field
treatment_pros = self.filtered(lambda r: r.type == 'treatment_pro')
if treatment_pros and 'type' in vals and vals['type'] != 'treatment_pro':
injuries = self.env['sports.patient.injury'].search_count([('treatment_professional_ids', 'in', treatment_pros.ids)])
if injuries:
raise UserError(_('Partner type cannot be changed since this treatment '
'professional appears on a patient injury record.'))
teams = self.filtered(lambda r: r.type == 'team')
if teams and 'type' in vals and vals['type'] != 'team':
if teams.mapped('staff_partner_ids') or teams.mapped('patient_ids'):
raise UserError(_('Sports team is related to patients and/or staff. '
'Its type cannot be changed until these relations are '
'removed.'))
return super().write(vals)
def unlink(self):
treatment_pros = self.filtered(lambda r: r.type == 'treatment_pro')
if treatment_pros:
injuries = self.env['sports.patient.injury'].search_count([('treatment_professional_ids', 'in', treatment_pros.ids)])
if injuries:
raise UserError(_('Treatment professional cannot be deleted since they '
'appears on a patient injury record.'))
teams = self.filtered(lambda r: r.type == 'team')
if teams:
if teams.mapped('staff_partner_ids') or teams.mapped('patient_ids'):
raise UserError(_('Sports team is related to patients and/or staff. '
'Its type cannot be deleted until these relations are '
'removed. You may try archiving it instead.'))
return super().unlink()