bemade_sports_clinic iteration 3 progress on fields and views.

This commit is contained in:
Marc Durepos 2023-10-28 17:20:22 -04:00
parent e951c23346
commit 1a287d1452
4 changed files with 230 additions and 137 deletions

View file

@ -45,8 +45,26 @@ class Patient(models.Model):
inverse_name='patient_id',
string='Injuries', )
injured_since = fields.Date(compute='_compute_is_injured')
predicted_return_date = fields.Date()
predicted_return_date = fields.Date(tracking=True)
return_date = fields.Date(tracking=True,
help="When the player was cleared by medical staff to "
"return to match play.")
is_injured = fields.Boolean(compute="_compute_is_injured")
stage = fields.Selection(
selection=[('no_play', 'Injured'), ('practice_ok', 'Cleared for Practice'), ('healthy', 'Cleared to Play')],
compute='_compute_stage')
last_consultation_date = fields.Date()
@api.depends('match_status', 'practice_status')
def _compute_stage(self):
for rec in self:
if rec.match_status == 'yes' and rec.practice_status == 'yes':
rec.stage = 'healthy'
elif rec.match_status == 'no' and rec.practice_status == 'no_contact':
rec.stage = 'practice_ok'
else:
rec.stage = 'no_play'
@api.depends('date_of_birth')
def _compute_age(self):
@ -68,8 +86,8 @@ class Patient(models.Model):
rec.is_injured = rec.practice_status != 'yes' or rec.match_status != 'yes'
if rec.is_injured:
rec.injured_since = \
rec.injury_ids.filtered(lambda r: not r.is_resolved).sorted(
'injury_date_time')[0].injury_date_time
rec.injury_ids.filtered(lambda r: not r.stage == 'resolved').sorted(
'injury_date_time')[0].injury_date_time
else:
rec.injured_since = False
@ -83,6 +101,16 @@ class Patient(models.Model):
'context': self._context,
}
def action_consulted_today(self):
self.ensure_one() # should just be called from form view
self.last_consultation_date = date.today()
return {
'view_mode': 'form',
'res_model': 'sports.patient',
'context': self._context,
'res_id': self.id,
}
class PatientContact(models.Model):
_name = 'sports.patient.contact'
@ -114,6 +142,7 @@ class PatientInjury(models.Model):
injury_date_time = fields.Datetime(string='Date and Time of Injury', required=True,
default=datetime.now())
internal_notes = fields.Html(tracking=True)
external_notes = fields.Html(tracking=True)
treatment_professional_ids = fields.Many2many(comodel_name='res.users',
relation='patient_injury_treatment_pro_rel',
column1='patient_injury_id',
@ -123,7 +152,18 @@ class PatientInjury(models.Model):
('is_treatment_professional', '=',
True)], tracking=True)
predicted_resolution_date = fields.Date(tracking=True)
is_resolved = fields.Boolean(tracking=True, required=True, default=False)
resolution_date = fields.Date(tracking=True,
help="The date when the injury was actually resolved.")
stage = fields.Selection(selection=[('active', 'Active'), ('resolved', 'Resolved')], tracking=True, required=True,
default='active', readonly=False)
@api.constrains('stage')
def constrain_stage_on_resolution_date(self):
for rec in self:
if rec.stage == 'resolved' and not rec.resolution_date:
raise ValidationError(_('Cannot set an injury as resolved without setting the resolution date first.'))
def write(self, vals):
super().write(vals)

View file

@ -64,6 +64,10 @@ class TeamStaff(models.Model):
('trainer', 'Trainer'),
('other', 'Other')
], required=True)
phone = fields.Char(related='partner_id.phone', readonly=False)
name = fields.Char(related='partner_id.name', readonly=False)
parent_id = fields.Many2one(related='partner_id.parent_id', readonly=False, string="Organization")
email = fields.Char(related='parent_id.email', readonly=False)
_sql_constraints = [('team_staff_unique', 'unique(team_id, partner_id)',
'Each partner can only be related to a given team once.')]
@ -76,3 +80,8 @@ class TeamStaff(models.Model):
raise ValidationError(_("A team can have only one head coach."))
if len(team.staff_ids.filtered(lambda r: r.role == 'head_trainer')) > 1:
raise ValidationError(_("A team can have only one head trainer."))
@api.onchange('phone')
def _onchange_phone_validation(self):
if self.phone:
self.phone = self.partner_id._phone_format(self.phone, force_format='INTERNATIONAL')

View file

@ -12,6 +12,8 @@
<field name="date_of_birth" widget="date"/>
<field name="email" widget="email"/>
<field name="phone" widget="phone"/>
<field name="predicted_return_date"/>
<field name="return_date"/>
<filter name="groupby_team_ids" context="{'group_by': 'team_ids'}"/>
</search>
</field>
@ -24,7 +26,7 @@
decoration-danger="match_status == 'no'
and practice_status == 'no'"
decoration-warning="match_status == 'no'
and practice_status == 'no_contact'">
and practice_status != 'no'">
<field name="first_name"/>
<field name="last_name"/>
<field name="date_of_birth"/>
@ -33,12 +35,13 @@
<field name="match_status"/>
<field name="practice_status"/>
<field name="predicted_return_date" widget="date"/>
<field name="return_date" widget="date"/>
<field name="activity_ids" widget="list_activity"/>
</tree>
</field>
</record>
<record id="sports_patient_view_list_embedded" model="ir.ui.view">
<field name="name">sports.patient.view.list</field>
<field name="name">sports.patient.view.list.embedded</field>
<field name="model">sports.patient</field>
<field name="arch" type="xml">
<tree string="Patients" multi_edit="True" editable="bottom"
@ -52,12 +55,13 @@
<field name="age"/>
<field name="team_ids" widget="many2many_tags"/>
<field name="match_status"
/>
/>
<field name="practice_status"/>
<field name="predicted_return_date" widget="date"/>
<field name="return_date" widget="date"/>
<field name="activity_ids" widget="list_activity"/>
<button name="action_view_patient_form" type="object"
class="fa fa-arrow-right" title="Details"/>
title="Details" string="Details"/>
</tree>
</field>
</record>
@ -66,17 +70,26 @@
<field name="model">sports.patient</field>
<field name="arch" type="xml">
<form>
<header></header>
<header>
<field name="stage" widget="statusbar" options="{'clickable': '1'}" />
</header>
<sheet>
<div class="oe_button_box"></div>
<div class="oe_title"><h1>Patient Record</h1></div>
<group>
<group>
<group col="3">
<separator string="Patient Information"/>
<field name="first_name"/>
<field name="last_name"/>
<field name="date_of_birth"/>
<field name="age"/>
<field name="first_name" colspan="3"/>
<field name="last_name" colspan="3"/>
<field name="date_of_birth" colspan="3"/>
<field name="age" colspan="3"/>
<label for="last_consultation_date" colspan="1"/>
<span colspan="2">
<field name="last_consultation_date" widget="date" class="oe_inline"/>
<button type="object" name="action_consulted_today"
class="fa fa-refresh" title="Set to Today's Date"/>
</span>
</group>
<group>
<separator string="Team Information"/>
@ -85,6 +98,7 @@
<field name="match_status"/>
<field name="practice_status"/>
<field name="predicted_return_date"/>
<field name="return_date"/>
</group>
<notebook>
<page string="Injuries">
@ -117,20 +131,29 @@
<field name="model">sports.patient.injury</field>
<field name="arch" type="xml">
<form>
<header></header>
<header>
<field name="stage" widget="statusbar" options="{'clickable': '1'}"/>
</header>
<sheet>
<div class="oe_title">
<h1>
<field name="patient_name"/>
Injury Details for
<field name="patient_name" class="oe_inline"/>
</h1>
</div>
<group>
<field name="injury_date_time"/>
<field name="diagnosis"/>
<field name="internal_notes"/>
<field name="treatment_professional_ids"
widget="many2many_tags_avatar"/>
<field name="predicted_resolution_date"/>
<group>
<field name="injury_date_time"/>
<field name="diagnosis"/>
<field name="predicted_resolution_date"/>
<field name="resolution_date"/>
</group>
<group>
<field name="internal_notes" widget="html"/>
<field name="external_notes" widget="html"/>
<field name="treatment_professional_ids"
widget="many2many_tags_avatar"/>
</group>
</group>
</sheet>
<div class="oe_chatter">
@ -150,11 +173,12 @@
<field name="injury_date_time" widget="datetime"/>
<field name="diagnosis"/>
<field name="predicted_resolution_date" widget="date"/>
<field name="resolution_date" widget="date"/>
<field name="treatment_professional_ids"
widget="many2many_avatar_user"/>
<field name="activity_ids" widget="list_activity"/>
<button name="action_view_injury_form" type="object"
class="fa fa-arrow-right" title="Details"/>
title="Details" string="Details"/>
</tree>
</field>
</record>

View file

@ -1,122 +1,142 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data>
<record id="teams_view_search" model="ir.ui.view">
<field name="name">teams.view.search</field>
<field name="model">sports.team</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="parent_id" string="Parent Organization"/>
<field name="head_coach_id"/>
<field name="head_trainer_id"/>
<filter name="groupby_parent_id"
context="{'group_by': 'parent_id'}"/>
<filter name="groupby_head_coach_id"
context="{'group_by': 'head_coach_id'}"/>
<filter name="groupby_head_trainer_id"
context="{'group_by': 'head_trainer_id'}"/>
</search>
</field>
</record>
<record id="sports_team_view_kanban" model="ir.ui.view">
<field name="name">sports.team.view.kanban</field>
<field name="model">sports.team</field>
<field name="arch" type="xml">
<kanban default_group_by="parent_id" default_order="name"
group_create="false" group_delete="false" archivable="false">
<field name="name"/>
<field name="parent_id"/>
<field name="head_coach_name"/>
<field name="head_trainer_name"/>
<field name="injured_count"/>
<field name="healthy_count"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_content oe_kanban_global_click">
<div>
<strong class="o_kanban_record_title">
<span><field name="name"/></span>
</strong>
</div>
<div>
<span class="o_kanban_record_subtitle">
<field name="parent_id"/>
<record id="teams_view_search" model="ir.ui.view">
<field name="name">teams.view.search</field>
<field name="model">sports.team</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="parent_id" string="Parent Organization"/>
<field name="head_coach_id"/>
<field name="head_trainer_id"/>
<filter name="groupby_parent_id"
context="{'group_by': 'parent_id'}"/>
<filter name="groupby_head_coach_id"
context="{'group_by': 'head_coach_id'}"/>
<filter name="groupby_head_trainer_id"
context="{'group_by': 'head_trainer_id'}"/>
</search>
</field>
</record>
<record id="sports_team_view_kanban" model="ir.ui.view">
<field name="name">sports.team.view.kanban</field>
<field name="model">sports.team</field>
<field name="arch" type="xml">
<kanban default_group_by="parent_id" default_order="name"
group_create="false" group_delete="false" archivable="false">
<field name="name"/>
<field name="parent_id"/>
<field name="head_coach_name"/>
<field name="head_trainer_name"/>
<field name="injured_count"/>
<field name="healthy_count"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_content oe_kanban_global_click">
<div>
<strong class="o_kanban_record_title">
<span><field name="name"/></span>
</strong>
</div>
<div>
<span class="o_kanban_record_subtitle">
<field name="parent_id"/>
</span>
</div>
<div>
<span>Head coach: <field
name="head_coach_name"/></span>
</div>
<div>
<span>Head trainer: <field
name="head_trainer_name"/></span>
</div>
<div class="o_kanban_record_bottom">
<div class="oe_kanban_bottom_left">
<span class="text-success">Healthy:
<field name="healthy_count"/>
</span>
</div>
<div>
<span>Head coach: <field
name="head_coach_name"/></span>
</div>
<div>
<span>Head trainer: <field
name="head_trainer_name"/></span>
</div>
<div class="o_kanban_record_bottom">
<div class="oe_kanban_bottom_left">
<span class="text-success">Healthy:
<field name="healthy_count"/>
</span>
</div>
<div class="oe_kanban_bottom_right">
<span t-attf-class="{{record.injured_count.value != 0 ? 'text-danger' : ''}}">
Injured:
<field name="injured_count"/>
</span>
</div>
<div class="oe_kanban_bottom_right">
<span t-attf-class="{{record.injured_count.value != 0 ? 'text-danger' : ''}}">
Injured:
<field name="injured_count"/>
</span>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="sports_team_view_list" model="ir.ui.view">
<field name="name">sports.team.view.list</field>
<field name="model">sports.team</field>
<field name="arch" type="xml">
<tree string="Sports Teams">
<field name="name"/>
<field name="parent_id"/>
<field name="head_coach_id"/>
<field name="head_trainer_id"/>
<field name="player_count"/>
<field name="injured_count"/>
</tree>
</field>
</record>
<record id="sports_team_view_form" model="ir.ui.view">
<field name="name">sports.team.view.form</field>
<field name="model">sports.team</field>
<field name="arch" type="xml">
<form>
<header></header>
<sheet>
<div class="oe_button_box"></div>
<div class="oe_title"><h1><field name="name"/></h1></div>
<group string="Team Information">
<group>
<field name="parent_id"/>
<field name="player_count"/>
<field name="injured_count"/>
</group>
<group>
<field name="staff_ids">
<tree>
<field name="sequence" widget="handle"/>
<field name="partner_id"/>
<field name="role"/>
</tree>
</field>
</group>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="sports_team_view_list" model="ir.ui.view">
<field name="name">sports.team.view.list</field>
<field name="model">sports.team</field>
<field name="arch" type="xml">
<tree string="Sports Teams">
<field name="name"/>
<field name="parent_id"/>
<field name="head_coach_id"/>
<field name="head_trainer_id"/>
<field name="player_count"/>
<field name="injured_count"/>
</tree>
</field>
</record>
<record id="sports_team_view_form" model="ir.ui.view">
<field name="name">sports.team.view.form</field>
<field name="model">sports.team</field>
<field name="arch" type="xml">
<form>
<field name="id" invisible="1"/>
<header></header>
<sheet>
<div class="oe_button_box"></div>
<div class="oe_title"><h1><field name="name"/></h1></div>
<group string="Team Information">
<group>
<field name="parent_id"/>
<field name="player_count"/>
<field name="injured_count"/>
</group>
<separator string="Players"/>
<field name="patient_ids" nolabel="1"
context="{'tree_view_ref': 'bemade_sports_clinic.sports_patient_view_list_embedded'}"/>
</sheet>
</form>
</field>
</record>
</data>
<group>
<field name="staff_ids">
<tree>
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="role"/>
<field name="phone" widget="phone"/>
</tree>
</field>
</group>
</group>
<separator string="Players"/>
<field name="patient_ids" nolabel="1"
context="{'tree_view_ref': 'bemade_sports_clinic.sports_patient_view_list_embedded'}"/>
</sheet>
</form>
</field>
</record>
<record id="sports_team_staff_view_form" model="ir.ui.view">
<field name="name">sports.team.staff.view.form</field>
<field name="model">sports.team.staff</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<group>
<field name="name"/>
<field name="parent_id"/>
<field name="role"/>
</group>
<group>
<field name="phone" widget="phone"/>
<field name="email" widget="email"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
</odoo>