Merge branch '16.0' into 17.0
Forward port of latest updates.
This commit is contained in:
commit
4baef176fb
23 changed files with 1361 additions and 320 deletions
|
|
@ -18,7 +18,7 @@
|
||||||
#
|
#
|
||||||
{
|
{
|
||||||
'name': 'Sports Clinic Management',
|
'name': 'Sports Clinic Management',
|
||||||
'version': '17.0.1.5.2',
|
'version': '17.0.1.6.2',
|
||||||
'summary': 'Manage the patients of a sports medicine clinic.',
|
'summary': 'Manage the patients of a sports medicine clinic.',
|
||||||
'description': """
|
'description': """
|
||||||
Adds the notion of sports teams, players (patients), coaches and treatment
|
Adds the notion of sports teams, players (patients), coaches and treatment
|
||||||
|
|
@ -33,25 +33,31 @@
|
||||||
External users (portal users) can be added to give coaches and other team
|
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.
|
personnel access to limited player data such as estimated return-to-play dates.
|
||||||
""",
|
""",
|
||||||
'category': 'Services/Medical',
|
"category": "Services/Medical",
|
||||||
'author': 'Bemade Inc.',
|
"author": "Bemade Inc.",
|
||||||
'website': 'https://www.bemade.org',
|
"website": "https://www.bemade.org",
|
||||||
'license': 'OPL-1',
|
"license": "OPL-1",
|
||||||
'depends': ['portal', 'contacts'],
|
"depends": ["portal", "contacts"],
|
||||||
'data': [
|
"external_dependencies": {
|
||||||
'security/sports_clinic_groups.xml',
|
"python": [
|
||||||
'security/ir.model.access.csv',
|
"openupgradelib",
|
||||||
'security/sports_clinic_rules.xml',
|
],
|
||||||
'data/sports_clinic_data.xml',
|
},
|
||||||
'views/sports_team_views.xml',
|
"data": [
|
||||||
'views/sports_clinic_menus.xml',
|
"security/sports_clinic_groups.xml",
|
||||||
'views/sports_patient_injury_views.xml',
|
"security/ir.model.access.csv",
|
||||||
'views/sports_patient_views.xml',
|
"security/sports_clinic_rules.xml",
|
||||||
'views/sports_clinic_portal_views.xml',
|
"data/sports_clinic_data.xml",
|
||||||
'views/res_partner_views.xml',
|
"views/sports_team_views.xml",
|
||||||
|
"views/sports_clinic_menus.xml",
|
||||||
|
"views/sports_patient_injury_views.xml",
|
||||||
|
"views/sports_patient_views.xml",
|
||||||
|
"views/sports_clinic_portal_views.xml",
|
||||||
|
"views/res_partner_views.xml",
|
||||||
|
"views/res_users_views.xml",
|
||||||
],
|
],
|
||||||
'demo': ['data/demo/sports_clinic_demo_data.xml'],
|
"demo": ["data/demo/sports_clinic_demo_data.xml"],
|
||||||
'installable': True,
|
"installable": True,
|
||||||
'auto_install': False,
|
"auto_install": False,
|
||||||
'application': True,
|
"application": True,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,8 @@ class TeamStaffPortal(CustomerPortal):
|
||||||
@classmethod
|
@classmethod
|
||||||
def _prepare_teams_domain(cls):
|
def _prepare_teams_domain(cls):
|
||||||
user = http.request.env.user
|
user = http.request.env.user
|
||||||
partner = http.request.env.user.partner_id
|
|
||||||
return [
|
return [
|
||||||
('staff_ids', 'in', partner.team_staff_rel_ids.ids),
|
('staff_ids.user_ids', 'in', user.id),
|
||||||
]
|
]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Odoo Server 16.0\n"
|
"Project-Id-Version: Odoo Server 16.0\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2024-02-21 00:52+0000\n"
|
"POT-Creation-Date: 2024-09-05 18:11+0000\n"
|
||||||
"PO-Revision-Date: 2024-02-21 00:52+0000\n"
|
"PO-Revision-Date: 2024-09-05 18:11+0000\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
|
|
@ -15,15 +15,98 @@ msgstr ""
|
||||||
"Content-Transfer-Encoding: \n"
|
"Content-Transfer-Encoding: \n"
|
||||||
"Plural-Forms: \n"
|
"Plural-Forms: \n"
|
||||||
|
|
||||||
|
#. module: bemade_sports_clinic
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/bemade_sports_clinic/models/patient_injury.py:0
|
||||||
|
#: code:addons/bemade_sports_clinic/models/patient_injury.py:0
|
||||||
|
#, python-format
|
||||||
|
msgid " Diagnosis: %s."
|
||||||
|
msgstr " Diagnostic : %s."
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model_terms:ir.ui.view,arch_db:bemade_sports_clinic.portal_my_home
|
#: model_terms:ir.ui.view,arch_db:bemade_sports_clinic.portal_my_home
|
||||||
msgid "/my/players"
|
msgid "/my/players"
|
||||||
msgstr ""
|
msgstr "/my/players"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model_terms:ir.ui.view,arch_db:bemade_sports_clinic.portal_my_home
|
#: model_terms:ir.ui.view,arch_db:bemade_sports_clinic.portal_my_home
|
||||||
msgid "/my/teams"
|
msgid "/my/teams"
|
||||||
|
msgstr "/my/teams"
|
||||||
|
|
||||||
|
#. module: bemade_sports_clinic
|
||||||
|
#: model:mail.template,body_html:bemade_sports_clinic.mail_template_patient_new_internal_note
|
||||||
|
msgid ""
|
||||||
|
"<p>A new internal note has been posted to the record for <t t-out=\"object.name\"></t>'s.\n"
|
||||||
|
" </p>\n"
|
||||||
|
" <div>\n"
|
||||||
|
" <p><strong>New Note: </strong></p>\n"
|
||||||
|
" <div><t t-out=\"object.team_info_notes\"></t></div>\n"
|
||||||
|
" </div>\n"
|
||||||
|
" "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"<p>Une nouvelle note interne a été ajouté au dossier pour <t t-out=\"object.name\">."
|
||||||
|
" </p>\n"
|
||||||
|
" <div>\n"
|
||||||
|
" <p><strong>Nouvelle note : </strong></p>\n"
|
||||||
|
" <div><t t-out=\"object.team_info_notes\"></t></div>\n"
|
||||||
|
" </div>\n"
|
||||||
|
" "
|
||||||
|
|
||||||
|
#. module: bemade_sports_clinic
|
||||||
|
#: model:mail.template,body_html:bemade_sports_clinic.mail_template_patient_injury_new_internal_note
|
||||||
|
msgid ""
|
||||||
|
"<p>A new internal note has been posted to the injury record for <t t-out=\"object.patient_name\"></t>'s injury<t t-if=\"object.diagnosis\">with\n"
|
||||||
|
" the diagnosis of <strong t-out=\"object.diagnosis\"></strong></t>.\n"
|
||||||
|
" </p>\n"
|
||||||
|
" <div>\n"
|
||||||
|
" <p><strong>New Note: </strong></p>\n"
|
||||||
|
" <div><t t-out=\"object.internal_notes\"></t></div>\n"
|
||||||
|
" </div>\n"
|
||||||
|
" "
|
||||||
|
msgstr ""
|
||||||
|
"<p>Une nouvelle note interne a été publiée dans le dossier du patient <t t-out=\"object.patient_name\"></t><t t-if=\"object.diagnosis\">avec\n"
|
||||||
|
" pour la blessure <strong t-out=\"object.diagnosis\"></strong></t>.\n"
|
||||||
|
" </p>\n"
|
||||||
|
" <div>\n"
|
||||||
|
" <p><strong>Nouvelle note : </strong></p>\n"
|
||||||
|
" <div><t t-out=\"object.internal_notes\"></t></div>\n"
|
||||||
|
" </div>\n"
|
||||||
|
" "
|
||||||
|
|
||||||
|
#. module: bemade_sports_clinic
|
||||||
|
#: model:mail.template,body_html:bemade_sports_clinic.mail_template_patient_status_update
|
||||||
|
msgid ""
|
||||||
|
"<p>An update has been posted to the record for <t t-out=\"object.name\"></t>'s. Click\n"
|
||||||
|
" <a t-attf-href=\"{{ user.company_id.website }}/my/players\">here</a> to view the details.\n"
|
||||||
|
" </p>\n"
|
||||||
|
" "
|
||||||
|
msgstr ""
|
||||||
|
"<p>Une mise à jour a été publiée dans le dossier de <t t-out=\"object.name\"></t>'s. Cliquez\n"
|
||||||
|
" <a t-attf-href=\"{{ user.company_id.website }}/my/players\">ici</a> pour les détails.\n"
|
||||||
|
" </p>\n"
|
||||||
|
" "
|
||||||
|
|
||||||
|
#. module: bemade_sports_clinic
|
||||||
|
#: model:mail.template,body_html:bemade_sports_clinic.mail_template_patient_injury_status_update
|
||||||
|
msgid ""
|
||||||
|
"<p>An update has been posted to the injury record for <t t-out=\"object.patient_name\"></t>'s injury<t t-if=\"object.diagnosis\">with\n"
|
||||||
|
" the diagnosis of <strong t-out=\"object.diagnosis\"></strong></t>. Click\n"
|
||||||
|
" <a t-attf-href=\"{{ user.company_id.website }}/my/player?player_id={{ object.patient_id.id }}\">here</a> to view the injury details.\n"
|
||||||
|
" </p>\n"
|
||||||
|
" "
|
||||||
|
msgstr ""
|
||||||
|
"<p>Une mise à jour a été publiée par rapport à la blessure de <t t-out=\"object.patient_name\"></t><t t-if=\"object.diagnosis\">avec\n"
|
||||||
|
" avec le diagnostic <strong t-out=\"object.diagnosis\"></strong></t>. Cliquez\n"
|
||||||
|
" <a t-attf-href=\"{{ user.company_id.website }}/my/player?player_id={{ object.patient_id.id }}\">ici</a> pour voir les détails de la blessure.\n"
|
||||||
|
" </p>\n"
|
||||||
|
" "
|
||||||
|
|
||||||
|
#. module: bemade_sports_clinic
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/bemade_sports_clinic/models/patient_injury.py:0
|
||||||
|
#, python-format
|
||||||
|
msgid "A new injury was created for this patient."
|
||||||
|
msgstr "Une nouvelle blessure a été créée pour ce patient."
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#. odoo-python
|
#. odoo-python
|
||||||
|
|
@ -39,9 +122,15 @@ msgstr "Une équipe ne peut avoir qu'un seul entraineur chef."
|
||||||
msgid "A team can have only one head therapist."
|
msgid "A team can have only one head therapist."
|
||||||
msgstr "Une équipe ne peut avoir qu'un seul thérapeute en chef."
|
msgstr "Une équipe ne peut avoir qu'un seul thérapeute en chef."
|
||||||
|
|
||||||
|
#. module: bemade_sports_clinic
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_res_users__accessible_team_ids
|
||||||
|
msgid "Accessible Sports Teams"
|
||||||
|
msgstr "Équipes accessibles"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_needaction
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_needaction
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_needaction
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_needaction
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__message_needaction
|
||||||
msgid "Action Needed"
|
msgid "Action Needed"
|
||||||
msgstr "Action requise"
|
msgstr "Action requise"
|
||||||
|
|
||||||
|
|
@ -69,24 +158,28 @@ msgstr "Nombre de blessures actives"
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__activity_ids
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__activity_ids
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__activity_ids
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__activity_ids
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__activity_ids
|
||||||
msgid "Activities"
|
msgid "Activities"
|
||||||
msgstr "Activités"
|
msgstr "Activités"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__activity_exception_decoration
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__activity_exception_decoration
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__activity_exception_decoration
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__activity_exception_decoration
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__activity_exception_decoration
|
||||||
msgid "Activity Exception Decoration"
|
msgid "Activity Exception Decoration"
|
||||||
msgstr "Décoration d'activité en exception"
|
msgstr "Décoration d'activité en exception"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__activity_state
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__activity_state
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__activity_state
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__activity_state
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__activity_state
|
||||||
msgid "Activity State"
|
msgid "Activity State"
|
||||||
msgstr "État de l'activité"
|
msgstr "État de l'activité"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__activity_type_icon
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__activity_type_icon
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__activity_type_icon
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__activity_type_icon
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__activity_type_icon
|
||||||
msgid "Activity Type Icon"
|
msgid "Activity Type Icon"
|
||||||
msgstr "Icône du type d'activité"
|
msgstr "Icône du type d'activité"
|
||||||
|
|
||||||
|
|
@ -105,9 +198,22 @@ msgstr "Âge"
|
||||||
msgid "Allergies"
|
msgid "Allergies"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: bemade_sports_clinic
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__allowed_user_ids
|
||||||
|
msgid "Allowed Users"
|
||||||
|
msgstr "Utilisateurs autorisés"
|
||||||
|
|
||||||
|
#. module: bemade_sports_clinic
|
||||||
|
#. odoo-python
|
||||||
|
#: code:addons/bemade_sports_clinic/models/patient_injury.py:0
|
||||||
|
#, python-format
|
||||||
|
msgid "An injury was deleted."
|
||||||
|
msgstr "Une blessure a été supprimée."
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_attachment_count
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_attachment_count
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_attachment_count
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_attachment_count
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__message_attachment_count
|
||||||
msgid "Attachment Count"
|
msgid "Attachment Count"
|
||||||
msgstr "Nombre de pièces jointes"
|
msgstr "Nombre de pièces jointes"
|
||||||
|
|
||||||
|
|
@ -121,6 +227,11 @@ msgstr "Ville"
|
||||||
msgid "Coach"
|
msgid "Coach"
|
||||||
msgstr "Entraîneur"
|
msgstr "Entraîneur"
|
||||||
|
|
||||||
|
#. module: bemade_sports_clinic
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__parental_consent
|
||||||
|
msgid "Consent for Disclosure to Parent"
|
||||||
|
msgstr "Consentement pour divulgation au parent"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model,name:bemade_sports_clinic.model_res_partner
|
#: model:ir.model,name:bemade_sports_clinic.model_res_partner
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__partner_id
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__partner_id
|
||||||
|
|
@ -200,6 +311,11 @@ msgstr "Nom pour affichage"
|
||||||
msgid "Doctor"
|
msgid "Doctor"
|
||||||
msgstr "Docteur"
|
msgstr "Docteur"
|
||||||
|
|
||||||
|
#. module: bemade_sports_clinic
|
||||||
|
#: model:ir.model,name:bemade_sports_clinic.model_mail_followers
|
||||||
|
msgid "Document Followers"
|
||||||
|
msgstr "Abonnés au document"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.constraint,message:bemade_sports_clinic.constraint_sports_team_staff_team_staff_unique
|
#: model:ir.model.constraint,message:bemade_sports_clinic.constraint_sports_team_staff_team_staff_unique
|
||||||
msgid "Each partner can only be related to a given team once."
|
msgid "Each partner can only be related to a given team once."
|
||||||
|
|
@ -242,18 +358,21 @@ msgstr "Prénom"
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_follower_ids
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_follower_ids
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_follower_ids
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_follower_ids
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__message_follower_ids
|
||||||
msgid "Followers"
|
msgid "Followers"
|
||||||
msgstr "Abonnés"
|
msgstr "Abonnés"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_partner_ids
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_partner_ids
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_partner_ids
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_partner_ids
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__message_partner_ids
|
||||||
msgid "Followers (Partners)"
|
msgid "Followers (Partners)"
|
||||||
msgstr "Abonnés (partenaires)"
|
msgstr "Abonnés (partenaires)"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient__activity_type_icon
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient__activity_type_icon
|
||||||
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient_injury__activity_type_icon
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient_injury__activity_type_icon
|
||||||
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_team__activity_type_icon
|
||||||
msgid "Font awesome icon e.g. fa-tasks"
|
msgid "Font awesome icon e.g. fa-tasks"
|
||||||
msgstr "Icône Font Awesome ex. fa-tasks"
|
msgstr "Icône Font Awesome ex. fa-tasks"
|
||||||
|
|
||||||
|
|
@ -265,6 +384,7 @@ msgstr "Donner accès au portail"
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__has_message
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__has_message
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__has_message
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__has_message
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__has_message
|
||||||
msgid "Has Message"
|
msgid "Has Message"
|
||||||
msgstr "A un message"
|
msgstr "A un message"
|
||||||
|
|
||||||
|
|
@ -317,18 +437,21 @@ msgstr ""
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__activity_exception_icon
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__activity_exception_icon
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__activity_exception_icon
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__activity_exception_icon
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__activity_exception_icon
|
||||||
msgid "Icon"
|
msgid "Icon"
|
||||||
msgstr "Icône"
|
msgstr "Icône"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient__activity_exception_icon
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient__activity_exception_icon
|
||||||
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient_injury__activity_exception_icon
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient_injury__activity_exception_icon
|
||||||
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_team__activity_exception_icon
|
||||||
msgid "Icon to indicate an exception activity."
|
msgid "Icon to indicate an exception activity."
|
||||||
msgstr "Icône pour indiquer une activité en exception."
|
msgstr "Icône pour indiquer une activité en exception."
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient__message_needaction
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient__message_needaction
|
||||||
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient_injury__message_needaction
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient_injury__message_needaction
|
||||||
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_team__message_needaction
|
||||||
msgid "If checked, new messages require your attention."
|
msgid "If checked, new messages require your attention."
|
||||||
msgstr "Si coché, des nouveaux messages nécessitent votre attention."
|
msgstr "Si coché, des nouveaux messages nécessitent votre attention."
|
||||||
|
|
||||||
|
|
@ -337,6 +460,8 @@ msgstr "Si coché, des nouveaux messages nécessitent votre attention."
|
||||||
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient__message_has_sms_error
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient__message_has_sms_error
|
||||||
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient_injury__message_has_error
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient_injury__message_has_error
|
||||||
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient_injury__message_has_sms_error
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient_injury__message_has_sms_error
|
||||||
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_team__message_has_error
|
||||||
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_team__message_has_sms_error
|
||||||
msgid "If checked, some messages have a delivery error."
|
msgid "If checked, some messages have a delivery error."
|
||||||
msgstr "Si coché, certains messages ont une erreur de livraison."
|
msgstr "Si coché, certains messages ont une erreur de livraison."
|
||||||
|
|
||||||
|
|
@ -345,7 +470,8 @@ msgstr "Si coché, certains messages ont une erreur de livraison."
|
||||||
#: code:addons/bemade_sports_clinic/models/patient_injury.py:0
|
#: code:addons/bemade_sports_clinic/models/patient_injury.py:0
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "If injury date is not set, the N/A box must be checked."
|
msgid "If injury date is not set, the N/A box must be checked."
|
||||||
msgstr "Sa la date de la blessure n'est pas remplie, la case S/O doit être cochée."
|
msgstr ""
|
||||||
|
"Sa la date de la blessure n'est pas remplie, la case S/O doit être cochée."
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields.selection,name:bemade_sports_clinic.selection__sports_patient__stage__no_play
|
#: model:ir.model.fields.selection,name:bemade_sports_clinic.selection__sports_patient__stage__no_play
|
||||||
|
|
@ -384,6 +510,16 @@ msgstr "Détails des blessures pour"
|
||||||
msgid "Injury Record for"
|
msgid "Injury Record for"
|
||||||
msgstr "Historique des blessures pour"
|
msgstr "Historique des blessures pour"
|
||||||
|
|
||||||
|
#. module: bemade_sports_clinic
|
||||||
|
#: model:mail.template,subject:bemade_sports_clinic.mail_template_patient_new_internal_note
|
||||||
|
msgid "Internal Note Updated for Patient {{ object.name}}"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#. module: bemade_sports_clinic
|
||||||
|
#: model:mail.template,subject:bemade_sports_clinic.mail_template_patient_injury_new_internal_note
|
||||||
|
msgid "Internal Note Updated for Patient {{ object.patient_name }}"
|
||||||
|
msgstr "Note interne mise à jour pour le patient {{ object.patient_name }}"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__internal_notes
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__internal_notes
|
||||||
msgid "Internal Notes"
|
msgid "Internal Notes"
|
||||||
|
|
@ -404,6 +540,7 @@ msgstr "Combinaison invalide des statuts de match et de pratique."
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_is_follower
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_is_follower
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_is_follower
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_is_follower
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__message_is_follower
|
||||||
msgid "Is Follower"
|
msgid "Is Follower"
|
||||||
msgstr "Est abonné"
|
msgstr "Est abonné"
|
||||||
|
|
||||||
|
|
@ -461,6 +598,7 @@ msgstr "Dernière mise à jour le"
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_main_attachment_id
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_main_attachment_id
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_main_attachment_id
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_main_attachment_id
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__message_main_attachment_id
|
||||||
msgid "Main Attachment"
|
msgid "Main Attachment"
|
||||||
msgstr "Pièce jointe principale"
|
msgstr "Pièce jointe principale"
|
||||||
|
|
||||||
|
|
@ -474,12 +612,14 @@ msgstr "Statut match"
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_has_error
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_has_error
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_has_error
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_has_error
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__message_has_error
|
||||||
msgid "Message Delivery error"
|
msgid "Message Delivery error"
|
||||||
msgstr "Erreur de livraison du message"
|
msgstr "Erreur de livraison du message"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_ids
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_ids
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_ids
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_ids
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__message_ids
|
||||||
msgid "Messages"
|
msgid "Messages"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
@ -498,6 +638,7 @@ msgstr "Mère"
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__my_activity_date_deadline
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__my_activity_date_deadline
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__my_activity_date_deadline
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__my_activity_date_deadline
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__my_activity_date_deadline
|
||||||
msgid "My Activity Deadline"
|
msgid "My Activity Deadline"
|
||||||
msgstr "Date limite de mon activité"
|
msgstr "Date limite de mon activité"
|
||||||
|
|
||||||
|
|
@ -521,18 +662,21 @@ msgstr "Nom"
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__activity_date_deadline
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__activity_date_deadline
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__activity_date_deadline
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__activity_date_deadline
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__activity_date_deadline
|
||||||
msgid "Next Activity Deadline"
|
msgid "Next Activity Deadline"
|
||||||
msgstr "Échéance de la prochaine activité"
|
msgstr "Échéance de la prochaine activité"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__activity_summary
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__activity_summary
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__activity_summary
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__activity_summary
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__activity_summary
|
||||||
msgid "Next Activity Summary"
|
msgid "Next Activity Summary"
|
||||||
msgstr "Résumé de la prochaine activité"
|
msgstr "Résumé de la prochaine activité"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__activity_type_id
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__activity_type_id
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__activity_type_id
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__activity_type_id
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__activity_type_id
|
||||||
msgid "Next Activity Type"
|
msgid "Next Activity Type"
|
||||||
msgstr "Type de la prochaine activité"
|
msgstr "Type de la prochaine activité"
|
||||||
|
|
||||||
|
|
@ -552,24 +696,28 @@ msgstr ""
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_needaction_counter
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_needaction_counter
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_needaction_counter
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_needaction_counter
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__message_needaction_counter
|
||||||
msgid "Number of Actions"
|
msgid "Number of Actions"
|
||||||
msgstr "Nombre d'actions"
|
msgstr "Nombre d'actions"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_has_error_counter
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_has_error_counter
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_has_error_counter
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_has_error_counter
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__message_has_error_counter
|
||||||
msgid "Number of errors"
|
msgid "Number of errors"
|
||||||
msgstr "Nombre d'erreurs"
|
msgstr "Nombre d'erreurs"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient__message_needaction_counter
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient__message_needaction_counter
|
||||||
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient_injury__message_needaction_counter
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient_injury__message_needaction_counter
|
||||||
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_team__message_needaction_counter
|
||||||
msgid "Number of messages requiring action"
|
msgid "Number of messages requiring action"
|
||||||
msgstr "Nombre de messages nécessitant une action"
|
msgstr "Nombre de messages nécessitant une action"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient__message_has_error_counter
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient__message_has_error_counter
|
||||||
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient_injury__message_has_error_counter
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient_injury__message_has_error_counter
|
||||||
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_team__message_has_error_counter
|
||||||
msgid "Number of messages with delivery error"
|
msgid "Number of messages with delivery error"
|
||||||
msgstr "Nombre de messages avec une erreur de livraison"
|
msgstr "Nombre de messages avec une erreur de livraison"
|
||||||
|
|
||||||
|
|
@ -608,11 +756,6 @@ msgstr "Équipe détenue"
|
||||||
msgid "Parent Organization"
|
msgid "Parent Organization"
|
||||||
msgstr "Organisation parente"
|
msgstr "Organisation parente"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__parental_consent
|
|
||||||
msgid "Consent for Disclosure to Parent"
|
|
||||||
msgstr "Consentement pour divulgation au parent"
|
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model,name:bemade_sports_clinic.model_sports_patient
|
#: model:ir.model,name:bemade_sports_clinic.model_sports_patient
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_res_partner__patient_ids
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_res_partner__patient_ids
|
||||||
|
|
@ -633,9 +776,16 @@ msgid "Patient Contacts"
|
||||||
msgstr "Contacts du patient"
|
msgstr "Contacts du patient"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:mail.message.subtype,name:bemade_sports_clinic.subtype_patient_update
|
#: model:mail.message.subtype,name:bemade_sports_clinic.subtype_patient_external_update
|
||||||
msgid "Patient File Update"
|
#: model:mail.message.subtype,name:bemade_sports_clinic.subtype_patient_injury_external_update
|
||||||
msgstr "Mise à jour du dossier du patient"
|
msgid "Patient File Update (External)"
|
||||||
|
msgstr "Mise à jour du dossier patient (externe)"
|
||||||
|
|
||||||
|
#. module: bemade_sports_clinic
|
||||||
|
#: model:mail.message.subtype,name:bemade_sports_clinic.subtype_patient_injury_internal_update
|
||||||
|
#: model:mail.message.subtype,name:bemade_sports_clinic.subtype_patient_internal_update
|
||||||
|
msgid "Patient File Update (Internal)"
|
||||||
|
msgstr "Mise à jour du dossier patient (interne)"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model_terms:ir.ui.view,arch_db:bemade_sports_clinic.sports_patient_view_form
|
#: model_terms:ir.ui.view,arch_db:bemade_sports_clinic.sports_patient_view_form
|
||||||
|
|
@ -653,9 +803,9 @@ msgid "Patient Injury History"
|
||||||
msgstr "Historique des blessures du patient"
|
msgstr "Historique des blessures du patient"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:mail.message.subtype,name:bemade_sports_clinic.subtype_patient_injury_update
|
#: model:mail.template,subject:bemade_sports_clinic.mail_template_patient_injury_status_update
|
||||||
msgid "Patient Injury Status Update"
|
msgid "Patient Injury Status Update for {{ object.patient_name }}"
|
||||||
msgstr "Mise à jour du statut de la blessure d'un patient"
|
msgstr "Mise à jour du dossier de la blessure de {{ object.patient_name }}"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model_terms:ir.ui.view,arch_db:bemade_sports_clinic.sports_patient_view_form
|
#: model_terms:ir.ui.view,arch_db:bemade_sports_clinic.sports_patient_view_form
|
||||||
|
|
@ -667,21 +817,24 @@ msgstr "Téléphone et courriel du patient"
|
||||||
msgid "Patient Record"
|
msgid "Patient Record"
|
||||||
msgstr "Dossier du patient"
|
msgstr "Dossier du patient"
|
||||||
|
|
||||||
|
#. module: bemade_sports_clinic
|
||||||
|
#: model:mail.template,name:bemade_sports_clinic.mail_template_patient_injury_new_internal_note
|
||||||
|
#: model:mail.template,name:bemade_sports_clinic.mail_template_patient_injury_status_update
|
||||||
|
#: model:mail.template,name:bemade_sports_clinic.mail_template_patient_new_internal_note
|
||||||
|
#: model:mail.template,name:bemade_sports_clinic.mail_template_patient_status_update
|
||||||
|
msgid "Patient Status Update"
|
||||||
|
msgstr "Mise à jour sur le patient"
|
||||||
|
|
||||||
|
#. module: bemade_sports_clinic
|
||||||
|
#: model:mail.template,subject:bemade_sports_clinic.mail_template_patient_status_update
|
||||||
|
msgid "Patient Status Update for {{ object.name}}"
|
||||||
|
msgstr "Mise à jour pour le patient {{ object.name }}"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model_terms:ir.ui.view,arch_db:bemade_sports_clinic.sports_patient_view_form
|
#: model_terms:ir.ui.view,arch_db:bemade_sports_clinic.sports_patient_view_form
|
||||||
msgid "Patient's Contacts"
|
msgid "Patient's Contacts"
|
||||||
msgstr "Contacts du patient"
|
msgstr "Contacts du patient"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
|
||||||
#: model:mail.message.subtype,description:bemade_sports_clinic.subtype_patient_update
|
|
||||||
msgid "Patient's file has been updated."
|
|
||||||
msgstr "Le dossier du patient a été mis à jour."
|
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
|
||||||
#: model:mail.message.subtype,description:bemade_sports_clinic.subtype_patient_injury_update
|
|
||||||
msgid "Patient's injury was updated."
|
|
||||||
msgstr "Le dossier de la blessure du patient a été mis à jour."
|
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.actions.act_window,name:bemade_sports_clinic.action_view_patient
|
#: model:ir.actions.act_window,name:bemade_sports_clinic.action_view_patient
|
||||||
#: model:ir.ui.menu,name:bemade_sports_clinic.sports_clinic_patients
|
#: model:ir.ui.menu,name:bemade_sports_clinic.sports_clinic_patients
|
||||||
|
|
@ -749,6 +902,7 @@ msgstr "Résolu"
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__activity_user_id
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__activity_user_id
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__activity_user_id
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__activity_user_id
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__activity_user_id
|
||||||
msgid "Responsible User"
|
msgid "Responsible User"
|
||||||
msgstr "Utilisateur responsable"
|
msgstr "Utilisateur responsable"
|
||||||
|
|
||||||
|
|
@ -770,6 +924,7 @@ msgstr "Rôle"
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_has_sms_error
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__message_has_sms_error
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_has_sms_error
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__message_has_sms_error
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__message_has_sms_error
|
||||||
msgid "SMS Delivery error"
|
msgid "SMS Delivery error"
|
||||||
msgstr "Erreur de livraison SMS"
|
msgstr "Erreur de livraison SMS"
|
||||||
|
|
||||||
|
|
@ -836,6 +991,7 @@ msgstr "État"
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient__activity_state
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient__activity_state
|
||||||
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient_injury__activity_state
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient_injury__activity_state
|
||||||
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_team__activity_state
|
||||||
msgid ""
|
msgid ""
|
||||||
"Status based on activities\n"
|
"Status based on activities\n"
|
||||||
"Overdue: Due date is already passed\n"
|
"Overdue: Due date is already passed\n"
|
||||||
|
|
@ -932,7 +1088,8 @@ msgstr "Cette équipe n'a pu être trouvée."
|
||||||
#: code:addons/bemade_sports_clinic/models/res_partner.py:0
|
#: code:addons/bemade_sports_clinic/models/res_partner.py:0
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "To change a patient's name, change it from the patient form."
|
msgid "To change a patient's name, change it from the patient form."
|
||||||
msgstr "Pour changer le nom d'un patient, changez le à partir du formulaire patient."
|
msgstr ""
|
||||||
|
"Pour changer le nom d'un patient, changez le à partir du formulaire patient."
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model_terms:ir.ui.view,arch_db:bemade_sports_clinic.portal_my_teams
|
#: model_terms:ir.ui.view,arch_db:bemade_sports_clinic.portal_my_teams
|
||||||
|
|
@ -952,6 +1109,7 @@ msgstr "Professionnels de la santé"
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient__activity_exception_decoration
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient__activity_exception_decoration
|
||||||
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient_injury__activity_exception_decoration
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient_injury__activity_exception_decoration
|
||||||
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_team__activity_exception_decoration
|
||||||
msgid "Type of the exception activity on record."
|
msgid "Type of the exception activity on record."
|
||||||
msgstr "Type d'exception de l'activité enregistrée."
|
msgstr "Type d'exception de l'activité enregistrée."
|
||||||
|
|
||||||
|
|
@ -960,6 +1118,11 @@ msgstr "Type d'exception de l'activité enregistrée."
|
||||||
msgid "User"
|
msgid "User"
|
||||||
msgstr "Utilisateur"
|
msgstr "Utilisateur"
|
||||||
|
|
||||||
|
#. module: bemade_sports_clinic
|
||||||
|
#: model_terms:ir.ui.view,arch_db:bemade_sports_clinic.sports_team_view_form
|
||||||
|
msgid "User Access"
|
||||||
|
msgstr "Accès utilisateur"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team_staff__user_ids
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team_staff__user_ids
|
||||||
msgid "Users"
|
msgid "Users"
|
||||||
|
|
@ -973,12 +1136,14 @@ msgstr "Site web"
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__website_message_ids
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__website_message_ids
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__website_message_ids
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient_injury__website_message_ids
|
||||||
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_team__website_message_ids
|
||||||
msgid "Website Messages"
|
msgid "Website Messages"
|
||||||
msgstr "Messages du site web"
|
msgstr "Messages du site web"
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient__website_message_ids
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient__website_message_ids
|
||||||
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient_injury__website_message_ids
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_patient_injury__website_message_ids
|
||||||
|
#: model:ir.model.fields,help:bemade_sports_clinic.field_sports_team__website_message_ids
|
||||||
msgid "Website communication history"
|
msgid "Website communication history"
|
||||||
msgstr "Historique de communication du site web"
|
msgstr "Historique de communication du site web"
|
||||||
|
|
||||||
|
|
@ -994,8 +1159,8 @@ msgid ""
|
||||||
"Whether the patient has given their consent to share injury details with "
|
"Whether the patient has given their consent to share injury details with "
|
||||||
"their parents."
|
"their parents."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Indique si le patient a donné son consentement pour que les détails de la blessure soient partagés avec "
|
"Indique si le patient a donné son consentement pour que les détails de la "
|
||||||
"ses parents."
|
"blessure soient partagés avec ses parents."
|
||||||
|
|
||||||
#. module: bemade_sports_clinic
|
#. module: bemade_sports_clinic
|
||||||
#: model:ir.model.fields.selection,name:bemade_sports_clinic.selection__sports_patient__match_status__yes
|
#: model:ir.model.fields.selection,name:bemade_sports_clinic.selection__sports_patient__match_status__yes
|
||||||
|
|
@ -1023,3 +1188,13 @@ msgstr "Vos équipes"
|
||||||
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__zip
|
#: model:ir.model.fields,field_description:bemade_sports_clinic.field_sports_patient__zip
|
||||||
msgid "Zip"
|
msgid "Zip"
|
||||||
msgstr "Code postal"
|
msgstr "Code postal"
|
||||||
|
|
||||||
|
#. module: bemade_sports_clinic
|
||||||
|
#: model_terms:ir.ui.view,arch_db:bemade_sports_clinic.portal_my_home
|
||||||
|
msgid "players_count"
|
||||||
|
msgstr "players_count"
|
||||||
|
|
||||||
|
#. module: bemade_sports_clinic
|
||||||
|
#: model_terms:ir.ui.view,arch_db:bemade_sports_clinic.portal_my_home
|
||||||
|
msgid "teams_count"
|
||||||
|
msgstr "teams_count"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
from odoo import api, SUPERUSER_ID
|
||||||
|
|
||||||
|
|
||||||
|
def migrate(cr, version):
|
||||||
|
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||||
|
env["sports.team"].search([])._allow_access_for_staff_internal_users()
|
||||||
|
cr.execute('CREATE EXTENSION IF NOT EXISTS "unaccent"')
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
from odoo import api, SUPERUSER_ID
|
||||||
|
|
||||||
|
|
||||||
|
def migrate(cr, version):
|
||||||
|
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||||
|
env["sports.patient"].search([]).recompute_followers()
|
||||||
23
bemade_sports_clinic/migrations/16.0.1.7.0/post-migrate.py
Normal file
23
bemade_sports_clinic/migrations/16.0.1.7.0/post-migrate.py
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
""" Patient access revised to make the team staff relationship central to
|
||||||
|
access. Everything is calculated from there. Inverse functions deal with
|
||||||
|
sports.team.staff records instead of having a separate table for storing
|
||||||
|
access rights."""
|
||||||
|
|
||||||
|
from odoo import api, SUPERUSER_ID, Command
|
||||||
|
|
||||||
|
|
||||||
|
def migrate(cr, version):
|
||||||
|
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||||
|
rules = (
|
||||||
|
env.ref("bemade_sports_clinic.restrict_staff_access_to_teams")
|
||||||
|
+ env.ref("bemade_sports_clinic.restrict_staff_access_to_team_injuries")
|
||||||
|
+ env.ref("bemade_sports_clinic.restrict_staff_access_to_team_players")
|
||||||
|
)
|
||||||
|
rules.write({
|
||||||
|
"groups": [Command.link(env.ref("base.group_user").id)]
|
||||||
|
})
|
||||||
|
env.ref("bemade_sports_clinic.group_sports_clinic_user").write({
|
||||||
|
"implied_ids": [Command.link(env.ref("base.group_partner_manager").id)]
|
||||||
|
})
|
||||||
|
cr.execute("DROP TABLE sports_team_res_users_rel")
|
||||||
|
# Check the groups are OK
|
||||||
10
bemade_sports_clinic/migrations/16.0.1.7.0/pre-migrate.py
Normal file
10
bemade_sports_clinic/migrations/16.0.1.7.0/pre-migrate.py
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import openupgradelib.openupgrade as ou
|
||||||
|
from odoo import SUPERUSER_ID, api
|
||||||
|
|
||||||
|
def migrate(cr, version):
|
||||||
|
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||||
|
ou.delete_records_safely_by_xml_id(env, [
|
||||||
|
"bemade_sports_clinic.restrict_team_access_to_allowed_internal_users",
|
||||||
|
"bemade_sports_clinic.restrict_patient_access_to_allowed_internal_users",
|
||||||
|
"bemade_sports_clinic.restrict_injury_access_to_allowed_internal_users",
|
||||||
|
])
|
||||||
|
|
@ -3,105 +3,113 @@ from odoo.exceptions import ValidationError
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
from odoo.addons.phone_validation.tools import phone_validation
|
from odoo.addons.phone_validation.tools import phone_validation
|
||||||
from typing import Set, Tuple
|
import logging
|
||||||
|
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
external_tracking_fields = {
|
external_tracking_fields = {
|
||||||
'last_consultation_date',
|
"last_consultation_date",
|
||||||
'match_status',
|
"match_status",
|
||||||
'practice_status',
|
"practice_status",
|
||||||
'predicted_return_date',
|
"predicted_return_date",
|
||||||
'return_date',
|
"return_date",
|
||||||
}
|
}
|
||||||
|
|
||||||
internal_tracking_fields = {
|
internal_tracking_fields = {
|
||||||
'team_info_notes',
|
"team_info_notes",
|
||||||
'age',
|
"age",
|
||||||
'date_of_birth',
|
"date_of_birth",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Patient(models.Model):
|
class Patient(models.Model):
|
||||||
_name = 'sports.patient'
|
_name = "sports.patient"
|
||||||
_description = "Patient"
|
_description = "Patient"
|
||||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
_inherit = ["mail.thread", "mail.activity.mixin"]
|
||||||
_order = 'last_name, first_name'
|
_order = "last_name, first_name"
|
||||||
|
|
||||||
# res.partner fields
|
# res.partner fields
|
||||||
partner_id = fields.Many2one(comodel_name='res.partner', string='Contact', ondelete='restrict', compute_sudo=True)
|
partner_id = fields.Many2one(
|
||||||
|
comodel_name="res.partner",
|
||||||
|
string="Contact",
|
||||||
|
ondelete="restrict",
|
||||||
|
compute_sudo=True,
|
||||||
|
)
|
||||||
first_name = fields.Char(required=True, tracking=True)
|
first_name = fields.Char(required=True, tracking=True)
|
||||||
last_name = fields.Char(required=True, tracking=True)
|
last_name = fields.Char(required=True, tracking=True)
|
||||||
name = fields.Char(related='partner_id.name', compute="_compute_name", compute_sudo=True)
|
name = fields.Char(
|
||||||
phone = fields.Char(related='partner_id.phone', readonly=False)
|
related="partner_id.name",
|
||||||
mobile = fields.Char(related='partner_id.mobile', readonly=False)
|
)
|
||||||
street = fields.Char(related='partner_id.street', readonly=False)
|
phone = fields.Char(related="partner_id.phone", readonly=False)
|
||||||
street2 = fields.Char(related='partner_id.street2', readonly=False)
|
mobile = fields.Char(related="partner_id.mobile", readonly=False)
|
||||||
city = fields.Char(related='partner_id.city', readonly=False)
|
street = fields.Char(related="partner_id.street", readonly=False)
|
||||||
state_id = fields.Many2one(related='partner_id.state_id', readonly=False)
|
street2 = fields.Char(related="partner_id.street2", readonly=False)
|
||||||
zip = fields.Char(related='partner_id.zip', readonly=False)
|
city = fields.Char(related="partner_id.city", readonly=False)
|
||||||
country_id = fields.Many2one(related='partner_id.country_id', readonly=False)
|
state_id = fields.Many2one(related="partner_id.state_id", readonly=False)
|
||||||
email = fields.Char(related='partner_id.email', readonly=False)
|
zip = fields.Char(related="partner_id.zip", readonly=False)
|
||||||
|
country_id = fields.Many2one(related="partner_id.country_id", readonly=False)
|
||||||
|
email = fields.Char(related="partner_id.email", readonly=False)
|
||||||
|
|
||||||
# Patient fields
|
# Patient fields
|
||||||
date_of_birth = fields.Date(
|
date_of_birth = fields.Date(
|
||||||
groups="bemade_sports_clinic.group_sports_clinic_treatment_professional",
|
groups="bemade_sports_clinic.group_sports_clinic_treatment_professional",
|
||||||
tracking=True)
|
tracking=True,
|
||||||
|
)
|
||||||
age = fields.Integer(
|
age = fields.Integer(
|
||||||
compute='_compute_age',
|
compute="_compute_age",
|
||||||
groups="bemade_sports_clinic.group_sports_clinic_treatment_professional"
|
groups="bemade_sports_clinic.group_sports_clinic_treatment_professional",
|
||||||
)
|
)
|
||||||
contact_ids = fields.One2many(
|
contact_ids = fields.One2many(
|
||||||
comodel_name='sports.patient.contact',
|
comodel_name="sports.patient.contact",
|
||||||
inverse_name='patient_id',
|
inverse_name="patient_id",
|
||||||
string='Patient Contacts',
|
string="Patient Contacts",
|
||||||
groups="bemade_sports_clinic.group_sports_clinic_user"
|
groups="bemade_sports_clinic.group_sports_clinic_user",
|
||||||
)
|
)
|
||||||
team_ids = fields.Many2many(
|
team_ids = fields.Many2many(
|
||||||
comodel_name='sports.team',
|
comodel_name="sports.team",
|
||||||
relation='sports_team_patient_rel',
|
relation="sports_team_patient_rel",
|
||||||
column1='patient_id',
|
column1="patient_id",
|
||||||
column2='team_id',
|
column2="team_id",
|
||||||
string='Teams',
|
string="Teams",
|
||||||
)
|
)
|
||||||
match_status = fields.Selection( # Selection rather than bool for easy expansion later
|
match_status = fields.Selection(
|
||||||
|
# Selection rather than bool for easy expansion later
|
||||||
selection=[
|
selection=[
|
||||||
('yes', 'Yes'),
|
("yes", "Yes"),
|
||||||
('no', 'No'),
|
("no", "No"),
|
||||||
],
|
],
|
||||||
required=True,
|
required=True,
|
||||||
default='yes',
|
default="yes",
|
||||||
tracking=True)
|
tracking=True,
|
||||||
|
)
|
||||||
practice_status = fields.Selection(
|
practice_status = fields.Selection(
|
||||||
selection=[
|
selection=[("yes", "Yes"), ("no_contact", "Yes, no contact"), ("no", "No")],
|
||||||
('yes', 'Yes'),
|
|
||||||
('no_contact', 'Yes, no contact'),
|
|
||||||
('no', 'No')
|
|
||||||
],
|
|
||||||
tracking=True,
|
tracking=True,
|
||||||
required=True,
|
required=True,
|
||||||
default='yes',
|
default="yes",
|
||||||
)
|
)
|
||||||
injury_ids = fields.One2many(
|
injury_ids = fields.One2many(
|
||||||
comodel_name='sports.patient.injury',
|
comodel_name="sports.patient.injury",
|
||||||
inverse_name='patient_id',
|
inverse_name="patient_id",
|
||||||
string='Injuries',
|
string="Injuries",
|
||||||
)
|
)
|
||||||
injured_since = fields.Date(compute='_compute_is_injured')
|
injured_since = fields.Date(compute="_compute_is_injured")
|
||||||
predicted_return_date = fields.Date(tracking=True)
|
predicted_return_date = fields.Date(tracking=True)
|
||||||
return_date = fields.Date(
|
return_date = fields.Date(
|
||||||
tracking=True,
|
tracking=True,
|
||||||
help="When the player was cleared by medical staff to "
|
help="When the player was cleared by medical staff to " "return to match play.",
|
||||||
"return to match play."
|
|
||||||
)
|
)
|
||||||
is_injured = fields.Boolean(compute="_compute_is_injured")
|
is_injured = fields.Boolean(compute="_compute_is_injured")
|
||||||
stage = fields.Selection(
|
stage = fields.Selection(
|
||||||
selection=[
|
selection=[
|
||||||
('no_play', 'Injured'),
|
("no_play", "Injured"),
|
||||||
('practice_ok', 'Practice OK'),
|
("practice_ok", "Practice OK"),
|
||||||
('healthy', 'Play OK')
|
("healthy", "Play OK"),
|
||||||
],
|
],
|
||||||
compute='_compute_stage')
|
compute="_compute_stage",
|
||||||
|
)
|
||||||
last_consultation_date = fields.Date(tracking=True)
|
last_consultation_date = fields.Date(tracking=True)
|
||||||
active_injury_count = fields.Integer(compute='_compute_active_injury_count')
|
active_injury_count = fields.Integer(compute="_compute_active_injury_count")
|
||||||
allergies = fields.Text()
|
allergies = fields.Text()
|
||||||
team_info_notes = fields.Html(
|
team_info_notes = fields.Html(
|
||||||
string="Notes",
|
string="Notes",
|
||||||
|
|
@ -110,55 +118,92 @@ class Patient(models.Model):
|
||||||
|
|
||||||
def default_get(self, fields_list):
|
def default_get(self, fields_list):
|
||||||
res = super().default_get(fields_list)
|
res = super().default_get(fields_list)
|
||||||
if 'team_ids' in fields_list and 'params' in self.env.context \
|
if (
|
||||||
and self.env.context.get('params')['model'] == 'sports.team':
|
"team_ids" in fields_list
|
||||||
team = self.env['sports.team'].browse(self.env.context.get('params')['id'])
|
and "params" in self.env.context
|
||||||
|
and self.env.context.get("params")["model"] == "sports.team"
|
||||||
|
):
|
||||||
|
team = self.env["sports.team"].browse(self.env.context.get("params")["id"])
|
||||||
team_ids = [Command.set([team.id])]
|
team_ids = [Command.set([team.id])]
|
||||||
if team_ids:
|
if team_ids:
|
||||||
res.update({'team_ids': team_ids})
|
res.update({"team_ids": team_ids})
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def write(self, values):
|
||||||
|
res = super().write(values)
|
||||||
|
if "team_ids" in values:
|
||||||
|
self.sudo().recompute_followers()
|
||||||
|
if "first_name" in values or "last_name" in values:
|
||||||
|
self._recompute_name()
|
||||||
|
return res
|
||||||
|
|
||||||
|
def _recompute_name(self):
|
||||||
|
for rec in self:
|
||||||
|
rec.partner_id.with_context(patient_update=True).name = (
|
||||||
|
rec._get_name_from_first_and_last(rec.first_name, rec.last_name)
|
||||||
|
)
|
||||||
|
|
||||||
@api.model_create_multi
|
@api.model_create_multi
|
||||||
def create(self, vals_list):
|
def create(self, vals_list):
|
||||||
for row in vals_list:
|
for row in vals_list:
|
||||||
if 'partner_id' not in row:
|
if "partner_id" not in row:
|
||||||
row['partner_id'] = self.env['res.partner'].create({
|
row["partner_id"] = (
|
||||||
'name': self._get_name_from_first_and_last(row['first_name'], row['last_name'])
|
self.env["res.partner"]
|
||||||
}).id
|
.create(
|
||||||
return super().create(vals_list)
|
{
|
||||||
|
"name": self._get_name_from_first_and_last(
|
||||||
|
row["first_name"], row["last_name"]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.id
|
||||||
|
)
|
||||||
|
res = super().create(vals_list)
|
||||||
|
res.sudo().recompute_followers()
|
||||||
|
return res
|
||||||
|
|
||||||
@api.constrains('match_status', 'practice_status')
|
@api.constrains("match_status", "practice_status")
|
||||||
def constrain_match_and_practice_status(self):
|
def constrain_match_and_practice_status(self):
|
||||||
""" Avoid invalid combinations of match and practice status:
|
"""Avoid invalid combinations of match and practice status:
|
||||||
- Yes (match), No (practice)
|
- Yes (match), No (practice)
|
||||||
- Yes (match), No Contact (practice)
|
- Yes (match), No Contact (practice)
|
||||||
"""
|
"""
|
||||||
# combinations of (match_status, practice_status) that are valid
|
# combinations of (match_status, practice_status) that are valid
|
||||||
valid_combinations = [('yes', 'yes'), ('no', 'yes'), ('no', 'no_contact'), ('no', 'no')]
|
valid_combinations = [
|
||||||
|
("yes", "yes"),
|
||||||
|
("no", "yes"),
|
||||||
|
("no", "no_contact"),
|
||||||
|
("no", "no"),
|
||||||
|
]
|
||||||
for rec in self:
|
for rec in self:
|
||||||
if (rec.match_status, rec.practice_status) not in valid_combinations:
|
if (rec.match_status, rec.practice_status) not in valid_combinations:
|
||||||
raise ValidationError(_("Invalid combination of match and practice status."))
|
raise ValidationError(
|
||||||
|
_("Invalid combination of match and practice status.")
|
||||||
|
)
|
||||||
|
|
||||||
@api.depends('injury_ids.stage')
|
@api.depends("injury_ids.stage")
|
||||||
def _compute_active_injury_count(self):
|
def _compute_active_injury_count(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
rec.active_injury_count = len(rec.injury_ids.filtered(lambda r: r.stage == 'active'))
|
rec.active_injury_count = len(
|
||||||
|
rec.injury_ids.filtered(lambda r: r.stage == "active")
|
||||||
|
)
|
||||||
|
|
||||||
@api.depends('match_status', 'practice_status')
|
@api.depends("match_status", "practice_status")
|
||||||
def _compute_stage(self):
|
def _compute_stage(self):
|
||||||
stage_map = {
|
stage_map = {
|
||||||
('yes', 'yes'): 'healthy',
|
("yes", "yes"): "healthy",
|
||||||
('no', 'yes'): 'practice_ok',
|
("no", "yes"): "practice_ok",
|
||||||
('no', 'no_contact'): 'practice_ok',
|
("no", "no_contact"): "practice_ok",
|
||||||
('no', 'no'): 'no_play',
|
("no", "no"): "no_play",
|
||||||
}
|
}
|
||||||
for rec in self:
|
for rec in self:
|
||||||
|
# not a valid combination, will be caught by constraint if save is attempted
|
||||||
if (rec.match_status, rec.practice_status) not in stage_map:
|
if (rec.match_status, rec.practice_status) not in stage_map:
|
||||||
rec.stage = False # not a valid combination, will be caught by constraint if save is attempted
|
rec.stage = False
|
||||||
continue
|
continue
|
||||||
rec.stage = stage_map[(rec.match_status, rec.practice_status)]
|
rec.stage = stage_map[(rec.match_status, rec.practice_status)]
|
||||||
|
|
||||||
@api.depends('date_of_birth')
|
@api.depends("date_of_birth")
|
||||||
def _compute_age(self):
|
def _compute_age(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
if not rec.date_of_birth:
|
if not rec.date_of_birth:
|
||||||
|
|
@ -166,56 +211,60 @@ class Patient(models.Model):
|
||||||
else:
|
else:
|
||||||
rec.age = relativedelta(date.today(), rec.date_of_birth).years
|
rec.age = relativedelta(date.today(), rec.date_of_birth).years
|
||||||
|
|
||||||
@api.depends('first_name', 'last_name')
|
|
||||||
def _compute_name(self):
|
|
||||||
for rec in self:
|
|
||||||
rec.name = self._get_name_from_first_and_last(rec.first_name, rec.last_name)
|
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _get_name_from_first_and_last(self, first_name, last_name):
|
def _get_name_from_first_and_last(self, first_name, last_name):
|
||||||
return ((first_name or "") + " " + (last_name or "")).strip()
|
names = []
|
||||||
|
if first_name:
|
||||||
|
names.append(first_name)
|
||||||
|
if last_name:
|
||||||
|
names.append(last_name)
|
||||||
|
return " ".join(names)
|
||||||
|
|
||||||
@api.depends('practice_status', 'match_status', 'injury_ids.injury_date')
|
@api.depends("practice_status", "match_status", "injury_ids.injury_date")
|
||||||
def _compute_is_injured(self):
|
def _compute_is_injured(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
rec.is_injured = rec.practice_status != 'yes' or rec.match_status != 'yes'
|
rec.is_injured = rec.practice_status != "yes" or rec.match_status != "yes"
|
||||||
if rec.is_injured:
|
if rec.is_injured:
|
||||||
unresolved_injuries = rec.injury_ids.filtered(lambda r: not r.stage == 'resolved')
|
unresolved_injuries = rec.injury_ids.filtered(
|
||||||
rec.injured_since = unresolved_injuries and unresolved_injuries[0].injury_date
|
lambda r: not r.stage == "resolved"
|
||||||
|
)
|
||||||
|
rec.injured_since = (
|
||||||
|
unresolved_injuries and unresolved_injuries[0].injury_date
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
rec.injured_since = False
|
rec.injured_since = False
|
||||||
|
|
||||||
def action_view_patient_form(self):
|
def action_view_patient_form(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
return {
|
return {
|
||||||
'type': 'ir.actions.act_window',
|
"type": "ir.actions.act_window",
|
||||||
'view_mode': 'form',
|
"view_mode": "form",
|
||||||
'res_model': 'sports.patient',
|
"res_model": "sports.patient",
|
||||||
'res_id': self.id,
|
"res_id": self.id,
|
||||||
'context': self._context,
|
"context": self._context,
|
||||||
}
|
}
|
||||||
|
|
||||||
def action_consulted_today(self):
|
def action_consulted_today(self):
|
||||||
self.ensure_one() # should just be called from form view
|
self.ensure_one() # should just be called from form view
|
||||||
self.last_consultation_date = date.today()
|
self.last_consultation_date = date.today()
|
||||||
return {
|
return {
|
||||||
'view_mode': 'form',
|
"view_mode": "form",
|
||||||
'res_model': 'sports.patient',
|
"res_model": "sports.patient",
|
||||||
'context': self._context,
|
"context": self._context,
|
||||||
'res_id': self.id,
|
"res_id": self.id,
|
||||||
}
|
}
|
||||||
|
|
||||||
@api.onchange('mobile', 'country_id')
|
@api.onchange("mobile", "country_id")
|
||||||
def _onchange_mobile_validation(self):
|
def _onchange_mobile_validation(self):
|
||||||
if self.mobile:
|
if self.mobile:
|
||||||
self.mobile = self._phone_format(self.mobile, force_format="INTERNATIONAL")
|
self.mobile = self._phone_format(self.mobile, force_format="INTERNATIONAL")
|
||||||
|
|
||||||
@api.onchange('phone', 'country_id')
|
@api.onchange("phone", "country_id")
|
||||||
def _onchange_phone_validation(self):
|
def _onchange_phone_validation(self):
|
||||||
if self.phone:
|
if self.phone:
|
||||||
self.phone = self._phone_format(self.phone, force_format="INTERNATIONAL")
|
self.phone = self._phone_format(self.phone, force_format="INTERNATIONAL")
|
||||||
|
|
||||||
def _phone_format(self, number, force_format='E164'):
|
def _phone_format(self, number, force_format="E164"):
|
||||||
country = self.country_id or self.env.company.country_id
|
country = self.country_id or self.env.company.country_id
|
||||||
if not country or not number:
|
if not country or not number:
|
||||||
return number
|
return number
|
||||||
|
|
@ -224,11 +273,11 @@ class Patient(models.Model):
|
||||||
country.code if country else None,
|
country.code if country else None,
|
||||||
country.phone_code if country else None,
|
country.phone_code if country else None,
|
||||||
force_format=force_format,
|
force_format=force_format,
|
||||||
raise_exception=False
|
raise_exception=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _track_subtype(self, init_values):
|
def _track_subtype(self, init_values):
|
||||||
return self.env.ref('mail.mt_note')
|
return self.env.ref("mail.mt_note")
|
||||||
|
|
||||||
def _track_template(self, changes):
|
def _track_template(self, changes):
|
||||||
res = super()._track_template(changes)
|
res = super()._track_template(changes)
|
||||||
|
|
@ -237,18 +286,47 @@ class Patient(models.Model):
|
||||||
if external:
|
if external:
|
||||||
first_external_field = (external_tracking_fields & params).pop()
|
first_external_field = (external_tracking_fields & params).pop()
|
||||||
res[first_external_field] = (
|
res[first_external_field] = (
|
||||||
self.env.ref('bemade_sports_clinic.mail_template_patient_status_update'), {
|
self.env.ref(
|
||||||
'auto_delete_message': False,
|
"bemade_sports_clinic.mail_template_patient_status_update"
|
||||||
'subtype_id': self.env.ref('bemade_sports_clinic.subtype_patient_external_update').id,
|
),
|
||||||
'email_layout_xmlid': 'mail.mail_notification_light',
|
{
|
||||||
}
|
"auto_delete_message": False,
|
||||||
|
"subtype_id": self.env.ref(
|
||||||
|
"bemade_sports_clinic.subtype_patient_external_update"
|
||||||
|
).id,
|
||||||
|
"email_layout_xmlid": "mail.mail_notification_light",
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if 'team_info_notes' in changes:
|
if "team_info_notes" in changes:
|
||||||
res['team_info_notes'] = (
|
res["team_info_notes"] = (
|
||||||
self.env.ref('bemade_sports_clinic.mail_template_patient_new_internal_note'), {
|
self.env.ref(
|
||||||
'auto_delete_message': False,
|
"bemade_sports_clinic.mail_template_patient_new_internal_note"
|
||||||
'subtype_id': self.env.ref('bemade_sports_clinic.subtype_patient_internal_update').id,
|
),
|
||||||
'email_layout_xmlid': 'mail.mail_notification_light',
|
{
|
||||||
}
|
"auto_delete_message": False,
|
||||||
|
"subtype_id": self.env.ref(
|
||||||
|
"bemade_sports_clinic.subtype_patient_internal_update"
|
||||||
|
).id,
|
||||||
|
"email_layout_xmlid": "mail.mail_notification_light",
|
||||||
|
},
|
||||||
)
|
)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def recompute_followers(self):
|
||||||
|
"""Recompute the followers for this patient (and its injuries) based on the
|
||||||
|
changes to a specific team's staff members. Ignoring manually unsubscribed
|
||||||
|
followers, the set of followers should be the set of staff on all teams the
|
||||||
|
patient is part of."""
|
||||||
|
for patient in self:
|
||||||
|
patient = patient.sudo()
|
||||||
|
current_followers = patient.message_partner_ids
|
||||||
|
future_followers = patient.team_ids.mapped("staff_ids").mapped("partner_id")
|
||||||
|
removed_followers = current_followers - future_followers
|
||||||
|
if removed_followers:
|
||||||
|
_logger.debug(f"{self} unsubscribing {removed_followers}")
|
||||||
|
patient.message_unsubscribe(removed_followers.ids)
|
||||||
|
patient.injury_ids.message_unsubscribe(removed_followers.ids)
|
||||||
|
if future_followers:
|
||||||
|
_logger.debug(f"{self} subscribing {future_followers}")
|
||||||
|
patient.message_subscribe(future_followers.ids)
|
||||||
|
patient.injury_ids.message_subscribe(future_followers.ids)
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,13 @@ class PatientContact(models.Model):
|
||||||
_description = "Emergency or other contacts for a patient."
|
_description = "Emergency or other contacts for a patient."
|
||||||
|
|
||||||
sequence = fields.Integer(required=True, default=0)
|
sequence = fields.Integer(required=True, default=0)
|
||||||
name = fields.Char(unaccent=False)
|
name = fields.Char(unaccent=True)
|
||||||
contact_type = fields.Selection(selection=[
|
contact_type = fields.Selection(selection=[
|
||||||
('mother', 'Mother'),
|
('mother', 'Mother'),
|
||||||
('father', 'Father'),
|
('father', 'Father'),
|
||||||
('other', 'Other'),
|
('other', 'Other'),
|
||||||
], required=True)
|
], required=True)
|
||||||
mobile = fields.Char(unaccent=False, required=True)
|
mobile = fields.Char(unaccent=False)
|
||||||
# TODO: add email here and on views
|
# TODO: add email here and on views
|
||||||
patient_id = fields.Many2one(comodel_name='sports.patient', string='Patient')
|
patient_id = fields.Many2one(comodel_name='sports.patient', string='Patient')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,132 +2,138 @@ from odoo import models, fields, api, _
|
||||||
from datetime import datetime, date
|
from datetime import datetime, date
|
||||||
import pytz
|
import pytz
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
from typing import Set, Tuple
|
import logging
|
||||||
|
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
external_tracking_fields = {
|
external_tracking_fields = {
|
||||||
'diagnosis',
|
"diagnosis",
|
||||||
'predicted_resolution_date',
|
"predicted_resolution_date",
|
||||||
'resolution_date',
|
"resolution_date",
|
||||||
'external_notes',
|
"external_notes",
|
||||||
}
|
}
|
||||||
|
|
||||||
# Include only fields not already included in external_tracking_fields here
|
# Include only fields not already included in external_tracking_fields here
|
||||||
internal_tracking_fields = {
|
internal_tracking_fields = {
|
||||||
'internal_notes',
|
"internal_notes",
|
||||||
'parental_consent',
|
"parental_consent",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class PatientInjury(models.Model):
|
class PatientInjury(models.Model):
|
||||||
_name = 'sports.patient.injury'
|
_name = "sports.patient.injury"
|
||||||
_description = "Patient Injury"
|
_description = "Patient Injury"
|
||||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
_inherit = ["mail.thread", "mail.activity.mixin"]
|
||||||
_rec_name = 'diagnosis'
|
_rec_name = "diagnosis"
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _today(self):
|
def _today(self):
|
||||||
"""Get the current date in the user's time zone."""
|
"""Get the current date in the user's time zone."""
|
||||||
return datetime.now(pytz.timezone(self.env.user.tz or 'GMT'))
|
return datetime.now(pytz.timezone(self.env.user.tz or "GMT"))
|
||||||
|
|
||||||
# TODO: Find a way to improve notifications send about tracking injury details
|
# TODO: Find a way to improve notifications send about tracking injury details
|
||||||
# TODO: Add field consentement_parental = fields.Selection(oui, non, non-applicable)
|
# TODO: Add field consentement_parental = fields.Selection(oui, non, non-applicable)
|
||||||
|
|
||||||
patient_id = fields.Many2one(
|
patient_id = fields.Many2one(
|
||||||
comodel_name='sports.patient',
|
comodel_name="sports.patient",
|
||||||
string="Patient",
|
string="Patient",
|
||||||
readonly=True,
|
readonly=True,
|
||||||
required=True
|
required=True,
|
||||||
|
ondelete="cascade",
|
||||||
)
|
)
|
||||||
patient_name = fields.Char(related="patient_id.name")
|
patient_name = fields.Char(related="patient_id.name")
|
||||||
diagnosis = fields.Char(tracking=True)
|
diagnosis = fields.Char(tracking=True)
|
||||||
|
|
||||||
injury_date = fields.Date(
|
injury_date = fields.Date(
|
||||||
string='Date of Injury',
|
string="Date of Injury",
|
||||||
default=_today,
|
default=_today,
|
||||||
)
|
)
|
||||||
injury_date_na = fields.Boolean(string="N/A", default=False)
|
injury_date_na = fields.Boolean(string="N/A", default=False)
|
||||||
internal_notes = fields.Html(tracking=True)
|
internal_notes = fields.Html(tracking=True)
|
||||||
external_notes = fields.Html(tracking=True)
|
external_notes = fields.Html(tracking=True)
|
||||||
treatment_professional_ids = fields.Many2many(
|
treatment_professional_ids = fields.Many2many(
|
||||||
comodel_name='res.users',
|
comodel_name="res.users",
|
||||||
relation='patient_injury_treatment_pro_rel',
|
relation="patient_injury_treatment_pro_rel",
|
||||||
column1='patient_injury_id',
|
column1="patient_injury_id",
|
||||||
column2='treatment_pro_id', string='Treatment Professionals',
|
column2="treatment_pro_id",
|
||||||
domain=[
|
string="Treatment Professionals",
|
||||||
('is_treatment_professional', '=',
|
domain=[("is_treatment_professional", "=", True)],
|
||||||
True)], tracking=True
|
tracking=True,
|
||||||
)
|
)
|
||||||
predicted_resolution_date = fields.Date(tracking=True)
|
predicted_resolution_date = fields.Date(tracking=True)
|
||||||
resolution_date = fields.Date(
|
resolution_date = fields.Date(
|
||||||
tracking=True,
|
tracking=True, help="The date when the injury was actually resolved."
|
||||||
help="The date when the injury was actually resolved."
|
)
|
||||||
|
stage = fields.Selection(
|
||||||
|
selection=[("active", "Active"), ("resolved", "Resolved")],
|
||||||
|
compute="_compute_stage",
|
||||||
)
|
)
|
||||||
stage = fields.Selection(selection=[('active', 'Active'), ('resolved', 'Resolved')], compute='_compute_stage')
|
|
||||||
parental_consent = fields.Selection(
|
parental_consent = fields.Selection(
|
||||||
string="Consent for Disclosure to Parent",
|
string="Consent for Disclosure to Parent",
|
||||||
selection=[
|
selection=[("yes", "Yes"), ("no", "No"), ("na", "N/A")],
|
||||||
('yes', 'Yes'),
|
|
||||||
('no', 'No'),
|
|
||||||
('na', 'N/A')
|
|
||||||
],
|
|
||||||
help="Whether the patient has given their consent to share injury details with their parents.",
|
help="Whether the patient has given their consent to share injury details with their parents.",
|
||||||
tracking=True,
|
tracking=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
@api.constrains('injury_date_na', 'injury_date')
|
@api.constrains("injury_date_na", "injury_date")
|
||||||
def constrain_date_blank_only_if_na(self):
|
def constrain_date_blank_only_if_na(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
if not rec.injury_date_na and not rec.injury_date:
|
if not rec.injury_date_na and not rec.injury_date:
|
||||||
raise ValidationError(_("If injury date is not set, the N/A box must be checked."))
|
raise ValidationError(
|
||||||
|
_("If injury date is not set, the N/A box must be checked.")
|
||||||
|
)
|
||||||
|
|
||||||
@api.onchange('injury_date_na')
|
@api.onchange("injury_date_na")
|
||||||
def _onchange_injury_date_na(self):
|
def _onchange_injury_date_na(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
if rec.injury_date_na:
|
if rec.injury_date_na:
|
||||||
rec.injury_date = None
|
rec.injury_date = None
|
||||||
|
|
||||||
@api.onchange('injury_date')
|
@api.onchange("injury_date")
|
||||||
def _onchange_injury_date(self):
|
def _onchange_injury_date(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
if rec.injury_date:
|
if rec.injury_date:
|
||||||
rec.injury_date_na = False
|
rec.injury_date_na = False
|
||||||
|
|
||||||
@api.depends('resolution_date')
|
@api.depends("resolution_date")
|
||||||
def _compute_stage(self):
|
def _compute_stage(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
if rec.resolution_date and rec.resolution_date <= date.today():
|
if rec.resolution_date and rec.resolution_date <= date.today():
|
||||||
rec.stage = 'resolved'
|
rec.stage = "resolved"
|
||||||
else:
|
else:
|
||||||
rec.stage = 'active'
|
rec.stage = "active"
|
||||||
|
|
||||||
def write(self, vals):
|
|
||||||
super().write(vals)
|
|
||||||
if 'treatment_professional_ids' in vals:
|
|
||||||
to_subscribe = (self.treatment_professional_ids.mapped('partner_id')
|
|
||||||
- self.message_follower_ids.mapped('partner_id'))
|
|
||||||
self.message_subscribe(to_subscribe.ids)
|
|
||||||
|
|
||||||
@api.model_create_multi
|
@api.model_create_multi
|
||||||
def create(self, vals_list):
|
def create(self, vals_list):
|
||||||
res = super().create(vals_list)
|
res = super().create(vals_list)
|
||||||
for rec in res:
|
for rec in res.sudo():
|
||||||
to_subscribe = (rec.treatment_professional_ids.mapped('partner_id')
|
rec.message_subscribe(rec.patient_id.message_partner_ids)
|
||||||
- rec.message_follower_ids.mapped('partner_id'))
|
msg_body = _("A new injury was created for this patient.")
|
||||||
rec.message_subscribe(to_subscribe.ids)
|
if rec.diagnosis:
|
||||||
|
msg_body += _(" Diagnosis: %s." % rec.diagnosis)
|
||||||
|
rec.patient_id.message_post(body=msg_body, message_type="comment")
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def unlink(self):
|
||||||
|
for rec in self:
|
||||||
|
msg_body = _("An injury was deleted.")
|
||||||
|
if rec.diagnosis:
|
||||||
|
msg_body += _(" Diagnosis: %s." % rec.diagnosis)
|
||||||
|
rec.patient_id.message_post(body=msg_body, message_type="comment")
|
||||||
|
return super().unlink()
|
||||||
|
|
||||||
def action_view_injury_form(self):
|
def action_view_injury_form(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
return {
|
return {
|
||||||
'type': 'ir.actions.act_window',
|
"type": "ir.actions.act_window",
|
||||||
'view_mode': 'form',
|
"view_mode": "form",
|
||||||
'res_model': 'sports.patient.injury',
|
"res_model": "sports.patient.injury",
|
||||||
'res_id': self.id,
|
"res_id": self.id,
|
||||||
'context': self._context,
|
"context": self._context,
|
||||||
}
|
}
|
||||||
|
|
||||||
def _track_subtype(self, init_values):
|
def _track_subtype(self, init_values):
|
||||||
return self.env.ref('mail.mt_note')
|
return self.env.ref("mail.mt_note")
|
||||||
|
|
||||||
def _track_template(self, changes):
|
def _track_template(self, changes):
|
||||||
res = super()._track_template(changes)
|
res = super()._track_template(changes)
|
||||||
|
|
@ -136,18 +142,34 @@ class PatientInjury(models.Model):
|
||||||
if external:
|
if external:
|
||||||
first_external_field = (external_tracking_fields & params).pop()
|
first_external_field = (external_tracking_fields & params).pop()
|
||||||
res[first_external_field] = (
|
res[first_external_field] = (
|
||||||
self.env.ref('bemade_sports_clinic.mail_template_patient_injury_status_update'), {
|
self.env.ref(
|
||||||
'auto_delete_message': False,
|
"bemade_sports_clinic.mail_template_patient_injury_status_update"
|
||||||
'subtype_id': self.env.ref('bemade_sports_clinic.subtype_patient_injury_external_update').id,
|
),
|
||||||
'email_layout_xmlid': 'mail.mail_notification_light',
|
{
|
||||||
}
|
"auto_delete_message": False,
|
||||||
|
"subtype_id": self.env.ref(
|
||||||
|
"bemade_sports_clinic.subtype_patient_injury_external_update"
|
||||||
|
).id,
|
||||||
|
"email_layout_xmlid": "mail.mail_notification_light",
|
||||||
|
},
|
||||||
)
|
)
|
||||||
if 'internal_notes' in changes:
|
if "internal_notes" in changes:
|
||||||
res['internal_notes'] = (
|
res["internal_notes"] = (
|
||||||
self.env.ref('bemade_sports_clinic.mail_template_patient_injury_new_internal_note'), {
|
self.env.ref(
|
||||||
'auto_delete_message': False,
|
"bemade_sports_clinic.mail_template_patient_injury_new_internal_note"
|
||||||
'subtype_id': self.env.ref('bemade_sports_clinic.subtype_patient_injury_internal_update').id,
|
),
|
||||||
'email_layout_xmlid': 'mail.mail_notification_light',
|
{
|
||||||
}
|
"auto_delete_message": False,
|
||||||
|
"subtype_id": self.env.ref(
|
||||||
|
"bemade_sports_clinic.subtype_patient_injury_internal_update"
|
||||||
|
).id,
|
||||||
|
"email_layout_xmlid": "mail.mail_notification_light",
|
||||||
|
},
|
||||||
)
|
)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@api.model_create_multi
|
||||||
|
def create(self, vals_list):
|
||||||
|
res = super().create(vals_list)
|
||||||
|
res.patient_id.recompute_followers()
|
||||||
|
return res
|
||||||
|
|
|
||||||
|
|
@ -4,25 +4,54 @@ from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
|
|
||||||
class Partner(models.Model):
|
class Partner(models.Model):
|
||||||
_inherit = 'res.partner'
|
_inherit = "res.partner"
|
||||||
|
|
||||||
owned_team_ids = fields.One2many(comodel_name='sports.team',
|
owned_team_ids = fields.One2many(
|
||||||
inverse_name='parent_id')
|
comodel_name="sports.team", inverse_name="parent_id"
|
||||||
staff_ids = fields.One2many(comodel_name='sports.team.staff',
|
)
|
||||||
inverse_name='team_id')
|
staff_ids = fields.One2many(
|
||||||
team_staff_rel_ids = fields.One2many(comodel_name='sports.team.staff',
|
comodel_name="sports.team.staff", inverse_name="team_id"
|
||||||
inverse_name='partner_id',
|
)
|
||||||
string='Teams Served',
|
team_staff_rel_ids = fields.One2many(
|
||||||
help='The teams this person works for.')
|
comodel_name="sports.team.staff",
|
||||||
teams_served_ids = fields.One2many(comodel_name='sports.team', compute='_compute_teams_served')
|
inverse_name="partner_id",
|
||||||
patient_ids = fields.One2many(comodel_name='sports.patient', inverse_name='partner_id')
|
string="Employer(s)",
|
||||||
|
help="The teams this person works for.",
|
||||||
|
)
|
||||||
|
teams_served_ids = fields.One2many(
|
||||||
|
comodel_name="sports.team",
|
||||||
|
compute="_compute_teams_served",
|
||||||
|
inverse="_inverse_teams_served",
|
||||||
|
)
|
||||||
|
patient_ids = fields.One2many(
|
||||||
|
comodel_name="sports.patient", inverse_name="partner_id"
|
||||||
|
)
|
||||||
|
|
||||||
def write(self, vals):
|
def write(self, vals):
|
||||||
if self.patient_ids and 'name' in vals:
|
if (
|
||||||
raise ValidationError(_("To change a patient's name, change it from the patient form."))
|
self.patient_ids
|
||||||
|
and "name" in vals
|
||||||
|
and not self._context.get("patient_update")
|
||||||
|
):
|
||||||
|
raise ValidationError(
|
||||||
|
_("To change a patient's name, change it from the patient form.")
|
||||||
|
)
|
||||||
return super().write(vals)
|
return super().write(vals)
|
||||||
|
|
||||||
@api.depends('team_staff_rel_ids.team_id')
|
@api.depends("team_staff_rel_ids.team_id")
|
||||||
def _compute_teams_served(self):
|
def _compute_teams_served(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
rec.teams_served_ids = rec.team_staff_rel_ids.mapped('team_id')
|
rec.teams_served_ids = rec.team_staff_rel_ids.mapped("team_id")
|
||||||
|
|
||||||
|
@api.depends("team_staff_rel_ids.team_id")
|
||||||
|
def _inverse_teams_served(self):
|
||||||
|
for rec in self:
|
||||||
|
for staff in rec.team_staff_rel_ids:
|
||||||
|
if staff.team_id not in rec.teams_served_ids:
|
||||||
|
staff.unlink()
|
||||||
|
served_teams = rec.team_staff_rel_ids.mapped("team_id")
|
||||||
|
for team in rec.teams_served_ids:
|
||||||
|
if team not in served_teams:
|
||||||
|
raise UserError(
|
||||||
|
_("To add a staff member to a team, use the team view.")
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,45 @@
|
||||||
from odoo import models, fields, api, _
|
from odoo import models, fields, api, _, Command
|
||||||
|
|
||||||
|
|
||||||
class User(models.Model):
|
class User(models.Model):
|
||||||
_inherit = 'res.users'
|
_inherit = "res.users"
|
||||||
|
|
||||||
is_treatment_professional = fields.Boolean(
|
is_treatment_professional = fields.Boolean(
|
||||||
compute="_compute_is_treatment_professional", store=True)
|
compute="_compute_is_treatment_professional", store=True
|
||||||
|
)
|
||||||
|
|
||||||
@api.depends('groups_id')
|
accessible_team_ids = fields.Many2many(
|
||||||
|
comodel_name="sports.team",
|
||||||
|
compute="_compute_accessible_team_ids",
|
||||||
|
inverse="_inverse_accessible_team_ids",
|
||||||
|
)
|
||||||
|
|
||||||
|
@api.depends("groups_id")
|
||||||
def _compute_is_treatment_professional(self):
|
def _compute_is_treatment_professional(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
rec.is_treatment_professional = rec.has_group(
|
rec.is_treatment_professional = rec.has_group(
|
||||||
'bemade_sports_clinic.group_sports_clinic_treatment_professional')
|
"bemade_sports_clinic.group_sports_clinic_treatment_professional"
|
||||||
|
)
|
||||||
|
|
||||||
|
def _compute_accessible_team_ids(self):
|
||||||
|
for rec in self:
|
||||||
|
rec.accessible_team_ids = rec.partner_id.teams_served_ids
|
||||||
|
|
||||||
|
def _inverse_accessible_team_ids(self):
|
||||||
|
for rec in self:
|
||||||
|
removed_teams = rec.partner_id.teams_served_ids - rec.accessible_team_ids
|
||||||
|
added_teams = rec.accessible_team_ids - rec.partner_id.teams_served_ids
|
||||||
|
removed_teams = rec.partner_id.teams_served_ids.filtered(
|
||||||
|
lambda team: team in removed_teams
|
||||||
|
)
|
||||||
|
removed_teams.remove_access(self)
|
||||||
|
self.env["sports.team.staff"].create(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"team_id": team.id,
|
||||||
|
"partner_id": rec.partner_id.id,
|
||||||
|
"role": "other",
|
||||||
|
}
|
||||||
|
for team in added_teams
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -5,105 +5,240 @@ from odoo.exceptions import ValidationError
|
||||||
class SportsTeam(models.Model):
|
class SportsTeam(models.Model):
|
||||||
_name = "sports.team"
|
_name = "sports.team"
|
||||||
_description = "Sports Team"
|
_description = "Sports Team"
|
||||||
|
_inherit = ["mail.thread", "mail.activity.mixin"]
|
||||||
|
|
||||||
name = fields.Char()
|
name = fields.Char()
|
||||||
patient_ids = fields.Many2many(comodel_name='sports.patient',
|
patient_ids = fields.Many2many(
|
||||||
relation='sports_team_patient_rel',
|
comodel_name="sports.patient",
|
||||||
column1='team_id',
|
relation="sports_team_patient_rel",
|
||||||
column2='patient_id',
|
column1="team_id",
|
||||||
string='Players')
|
column2="patient_id",
|
||||||
|
string="Players",
|
||||||
|
tracking=True,
|
||||||
|
)
|
||||||
player_count = fields.Integer(compute="_compute_player_counts")
|
player_count = fields.Integer(compute="_compute_player_counts")
|
||||||
injured_count = fields.Integer(compute="_compute_player_counts")
|
injured_count = fields.Integer(compute="_compute_player_counts")
|
||||||
healthy_count = fields.Integer(compute="_compute_player_counts")
|
healthy_count = fields.Integer(compute="_compute_player_counts")
|
||||||
parent_id = fields.Many2one(comodel_name='res.partner', string='Parent Organization',
|
parent_id = fields.Many2one(
|
||||||
ondelete='restrict')
|
comodel_name="res.partner",
|
||||||
staff_ids = fields.One2many(comodel_name='sports.team.staff',
|
string="Parent Organization",
|
||||||
inverse_name='team_id')
|
ondelete="restrict",
|
||||||
head_coach_id = fields.Many2one(comodel_name='res.partner',
|
tracking=True,
|
||||||
compute='_compute_head_coach',
|
)
|
||||||
store=True)
|
staff_ids = fields.One2many(
|
||||||
head_coach_name = fields.Char(related='head_coach_id.name')
|
comodel_name="sports.team.staff",
|
||||||
head_therapist_id = fields.Many2one(comodel_name='res.partner',
|
inverse_name="team_id",
|
||||||
compute='_compute_head_therapist',
|
tracking=True,
|
||||||
store=True)
|
)
|
||||||
head_therapist_name = fields.Char(related='head_therapist_id.name')
|
head_coach_id = fields.Many2one(
|
||||||
|
comodel_name="res.partner",
|
||||||
|
compute="_compute_head_coach",
|
||||||
|
store=True,
|
||||||
|
)
|
||||||
|
head_coach_name = fields.Char(
|
||||||
|
related="head_coach_id.name",
|
||||||
|
string="Head Coach Name",
|
||||||
|
)
|
||||||
|
head_therapist_id = fields.Many2one(
|
||||||
|
comodel_name="res.partner",
|
||||||
|
compute="_compute_head_therapist",
|
||||||
|
store=True,
|
||||||
|
string="Head Therapist",
|
||||||
|
)
|
||||||
|
head_therapist_name = fields.Char(
|
||||||
|
related="head_therapist_id.name",
|
||||||
|
string="Head Therapist Name",
|
||||||
|
)
|
||||||
website = fields.Char()
|
website = fields.Char()
|
||||||
|
allowed_user_ids = fields.Many2many(
|
||||||
|
comodel_name="res.users",
|
||||||
|
compute="_compute_allowed_user_ids",
|
||||||
|
inverse="_inverse_allowed_user_ids",
|
||||||
|
)
|
||||||
|
|
||||||
@api.depends('patient_ids.is_injured')
|
def write(self, vals):
|
||||||
|
previous_patient_ids = self.sudo().patient_ids
|
||||||
|
res = super().write(vals)
|
||||||
|
if "staff_ids" in vals or "patient_ids" in vals:
|
||||||
|
(self.sudo().patient_ids | previous_patient_ids).recompute_followers()
|
||||||
|
return res
|
||||||
|
|
||||||
|
@api.model_create_multi
|
||||||
|
def create(self, vals_list):
|
||||||
|
res = super().create(vals_list)
|
||||||
|
for index, rec in enumerate(res):
|
||||||
|
if "staff_ids" in vals_list[index]:
|
||||||
|
rec.sudo().patient_ids.recompute_followers()
|
||||||
|
return res
|
||||||
|
|
||||||
|
def unlink(self):
|
||||||
|
to_recompute = self.patient_ids
|
||||||
|
res = super().unlink()
|
||||||
|
to_recompute.recompute_followers()
|
||||||
|
return res
|
||||||
|
|
||||||
|
@api.depends("patient_ids.is_injured")
|
||||||
def _compute_player_counts(self):
|
def _compute_player_counts(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
rec.player_count = len(rec.patient_ids)
|
rec.player_count = len(rec.patient_ids)
|
||||||
rec.injured_count = len(rec.patient_ids.filtered(lambda p: p.is_injured))
|
rec.injured_count = len(rec.patient_ids.filtered(lambda p: p.is_injured))
|
||||||
rec.healthy_count = rec.player_count - rec.injured_count
|
rec.healthy_count = rec.player_count - rec.injured_count
|
||||||
|
|
||||||
@api.depends('staff_ids.role')
|
@api.depends("staff_ids.role")
|
||||||
def _compute_head_coach(self):
|
def _compute_head_coach(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
staff = rec.staff_ids.filtered(lambda r: r.role == 'head_coach')
|
staff = rec.staff_ids.filtered(lambda r: r.role == "head_coach")
|
||||||
rec.head_coach_id = staff.partner_id if staff else False
|
rec.head_coach_id = staff.partner_id if staff else False
|
||||||
|
|
||||||
@api.depends('staff_ids.role')
|
@api.depends("staff_ids.role")
|
||||||
def _compute_head_therapist(self):
|
def _compute_head_therapist(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
staff = rec.staff_ids.filtered(lambda r: r.role == 'head_therapist')
|
staff = rec.staff_ids.filtered(lambda r: r.role == "head_therapist")
|
||||||
rec.head_therapist_id = staff.partner_id if staff else False
|
rec.head_therapist_id = staff.partner_id if staff else False
|
||||||
|
|
||||||
|
def _compute_allowed_user_ids(self):
|
||||||
|
for rec in self:
|
||||||
|
rec.allowed_user_ids = rec.staff_ids.user_ids
|
||||||
|
|
||||||
|
def _inverse_allowed_user_ids(self):
|
||||||
|
for rec in self:
|
||||||
|
removed_staff = rec.staff_ids.filtered(
|
||||||
|
lambda staff: staff.user_ids not in rec.allowed_user_ids
|
||||||
|
)
|
||||||
|
added_users = rec.allowed_user_ids - rec.staff_ids.user_ids
|
||||||
|
removed_staff.unlink()
|
||||||
|
self.env["sports.team.staff"].create(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"team_id": rec.id,
|
||||||
|
"partner_id": user.partner_id.id,
|
||||||
|
"role": "other",
|
||||||
|
}
|
||||||
|
for user in added_users
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
def remove_access(self, user):
|
||||||
|
self.staff_ids.filtered(lambda staff: user in staff.user_ids).unlink()
|
||||||
|
|
||||||
|
|
||||||
class TeamStaff(models.Model):
|
class TeamStaff(models.Model):
|
||||||
_name = "sports.team.staff"
|
_name = "sports.team.staff"
|
||||||
_description = "Sports Team Staff"
|
_description = "Sports Team Staff"
|
||||||
|
|
||||||
sequence = fields.Integer()
|
sequence = fields.Integer()
|
||||||
team_id = fields.Many2one(comodel_name='sports.team', string='Team', required=True)
|
team_id = fields.Many2one(
|
||||||
partner_id = fields.Many2one(comodel_name='res.partner', string='Staff Member',
|
comodel_name="sports.team",
|
||||||
required=True, domain=[('is_company', '=', False)])
|
string="Team",
|
||||||
role = fields.Selection(selection=[
|
required=True,
|
||||||
('head_coach', 'Head Coach'),
|
ondelete="cascade",
|
||||||
('head_therapist', 'Head Therapist'),
|
)
|
||||||
('coach', 'Coach'),
|
partner_id = fields.Many2one(
|
||||||
('therapist', 'Therapist'),
|
comodel_name="res.partner",
|
||||||
('doctor', 'Doctor'),
|
string="Staff Member",
|
||||||
('other', 'Other')
|
required=True,
|
||||||
], required=True)
|
domain=[("is_company", "=", False)],
|
||||||
mobile = fields.Char(related='partner_id.mobile', readonly=False)
|
ondelete="cascade",
|
||||||
name = fields.Char(related='partner_id.name', readonly=False)
|
)
|
||||||
parent_id = fields.Many2one(related='partner_id.parent_id', readonly=False, string="Organization",
|
active = fields.Boolean(related="partner_id.active")
|
||||||
domain=[('is_company', '=', True)])
|
role = fields.Selection(
|
||||||
email = fields.Char(related='partner_id.email', readonly=False)
|
selection=[
|
||||||
user_ids = fields.One2many(related='partner_id.user_ids', readonly=True)
|
("head_coach", "Head Coach"),
|
||||||
has_portal_access = fields.Boolean(compute='_compute_has_portal_access', compute_sudo=True)
|
("head_therapist", "Head Therapist"),
|
||||||
|
("coach", "Coach"),
|
||||||
|
("therapist", "Therapist"),
|
||||||
|
("doctor", "Doctor"),
|
||||||
|
("other", "Other"),
|
||||||
|
],
|
||||||
|
required=True,
|
||||||
|
)
|
||||||
|
mobile = fields.Char(related="partner_id.mobile", readonly=False)
|
||||||
|
name = fields.Char(related="partner_id.name", readonly=False)
|
||||||
|
parent_id = fields.Many2one(
|
||||||
|
related="partner_id.parent_id",
|
||||||
|
readonly=False,
|
||||||
|
string="Organization",
|
||||||
|
domain=[("is_company", "=", True)],
|
||||||
|
)
|
||||||
|
email = fields.Char(related="partner_id.email", readonly=False)
|
||||||
|
user_ids = fields.One2many(related="partner_id.user_ids", readonly=True)
|
||||||
|
has_portal_access = fields.Boolean(
|
||||||
|
compute="_compute_has_portal_access", compute_sudo=True
|
||||||
|
)
|
||||||
|
|
||||||
_sql_constraints = [('team_staff_unique', 'unique(team_id, partner_id)',
|
_sql_constraints = [
|
||||||
'Each partner can only be related to a given team once.')]
|
(
|
||||||
|
"team_staff_unique",
|
||||||
|
"unique(team_id, partner_id)",
|
||||||
|
"Each partner can only be related to a given team once.",
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
@api.constrains('role')
|
@api.constrains("role")
|
||||||
def _constrain_role(self):
|
def _constrain_role(self):
|
||||||
teams = self.mapped('team_id')
|
teams = self.mapped("team_id")
|
||||||
for team in teams:
|
for team in teams:
|
||||||
if len(team.staff_ids.filtered(lambda r: r.role == 'head_coach')) > 1:
|
if len(team.staff_ids.filtered(lambda r: r.role == "head_coach")) > 1:
|
||||||
raise ValidationError(_("A team can have only one head coach."))
|
raise ValidationError(_("A team can have only one head coach."))
|
||||||
if len(team.staff_ids.filtered(lambda r: r.role == 'head_therapist')) > 1:
|
if len(team.staff_ids.filtered(lambda r: r.role == "head_therapist")) > 1:
|
||||||
raise ValidationError(_("A team can have only one head therapist."))
|
raise ValidationError(_("A team can have only one head therapist."))
|
||||||
|
|
||||||
@api.onchange('mobile')
|
@api.onchange("mobile")
|
||||||
def _onchange_mobile_validation(self):
|
def _onchange_mobile_validation(self):
|
||||||
if self.mobile:
|
if self.mobile:
|
||||||
self.mobile = self.partner_id._phone_format(self.mobile, force_format='INTERNATIONAL')
|
self.mobile = self.partner_id._phone_format(
|
||||||
|
self.mobile, force_format="INTERNATIONAL"
|
||||||
|
)
|
||||||
|
|
||||||
@api.depends('user_ids', 'user_ids.groups_id')
|
@api.depends("user_ids", "user_ids.groups_id")
|
||||||
def _compute_has_portal_access(self):
|
def _compute_has_portal_access(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
rec.has_portal_access = bool(rec.user_ids.filtered(lambda r: r.has_group('base.group_portal'))) or bool(
|
rec.has_portal_access = (
|
||||||
rec.user_ids.filtered(lambda r: r.has_group('base.group_user'))) or bool(rec.partner_id.signup_token)
|
bool(rec.user_ids.filtered(lambda r: r.has_group("base.group_portal")))
|
||||||
|
or bool(rec.user_ids.filtered(lambda r: r.has_group("base.group_user")))
|
||||||
|
or bool(rec.partner_id.signup_token)
|
||||||
|
)
|
||||||
|
|
||||||
def action_revoke_portal_access(self):
|
def action_revoke_portal_access(self):
|
||||||
group_portal = self.env.ref('base.group_portal')
|
group_portal = self.env.ref("base.group_portal")
|
||||||
group_public = self.env.ref('base.group_public')
|
group_public = self.env.ref("base.group_public")
|
||||||
self.user_ids.write(
|
self.user_ids.write(
|
||||||
{'groups_id': [Command.unlink(group_portal.id), Command.link(group_public.id)], 'active': False})
|
{
|
||||||
|
"groups_id": [
|
||||||
|
Command.unlink(group_portal.id),
|
||||||
|
Command.link(group_public.id),
|
||||||
|
],
|
||||||
|
"active": False,
|
||||||
|
}
|
||||||
|
)
|
||||||
# Remove the signup token, so it cannot be used
|
# Remove the signup token, so it cannot be used
|
||||||
self.partner_id.sudo().signup_token = False
|
self.partner_id.sudo().signup_token = False
|
||||||
|
|
||||||
def action_grant_portal_access(self):
|
def action_grant_portal_access(self):
|
||||||
wiz = self.env['portal.wizard'].create({'partner_ids': [(4, self.partner_id.id)]})
|
wiz = self.env["portal.wizard"].create(
|
||||||
|
{"partner_ids": [(4, self.partner_id.id)]}
|
||||||
|
)
|
||||||
return wiz._action_open_modal()
|
return wiz._action_open_modal()
|
||||||
|
|
||||||
|
@api.model_create_multi
|
||||||
|
def create(self, vals_list):
|
||||||
|
res = super().create(vals_list)
|
||||||
|
res.team_id.mapped("patient_ids").recompute_followers()
|
||||||
|
return res
|
||||||
|
|
||||||
|
def unlink(self):
|
||||||
|
patients = self.team_id.mapped("patient_ids")
|
||||||
|
res = super().unlink()
|
||||||
|
patients.recompute_followers()
|
||||||
|
return res
|
||||||
|
|
||||||
|
def write(self, values):
|
||||||
|
if "team_id" in values:
|
||||||
|
to_recompute = self.env["sports.patient"]
|
||||||
|
for rec in self:
|
||||||
|
if rec.team_id.id != values["team_id"]:
|
||||||
|
to_recompute |= rec.team_id.patient_ids
|
||||||
|
res = super().write(values)
|
||||||
|
to_recompute.recompute_followers()
|
||||||
|
return res
|
||||||
|
return super().write(values)
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,20 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
<data noupdate="1">
|
<data>
|
||||||
<record id="module_category_sports_clinic_management" model="ir.module.category">
|
<record id="module_category_sports_clinic_management" model="ir.module.category">
|
||||||
<field name="name">Sports Medicine Clinic Management</field>
|
<field name="name">Sports Medicine Clinic Management</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="group_sports_clinic_user" model="res.groups">
|
<record id="group_sports_clinic_user" model="res.groups">
|
||||||
<field name="name">Internal User</field>
|
<field name="name">Internal User</field>
|
||||||
<field name="category_id" ref="module_category_sports_clinic_management"/>
|
<field name="category_id" ref="module_category_sports_clinic_management"/>
|
||||||
|
<field name="implied_ids" eval="[
|
||||||
|
Command.set(
|
||||||
|
[
|
||||||
|
ref('base.group_user'),
|
||||||
|
ref('base.group_partner_manager'),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
]"/>
|
||||||
</record>
|
</record>
|
||||||
<record id="group_sports_clinic_treatment_professional" model="res.groups">
|
<record id="group_sports_clinic_treatment_professional" model="res.groups">
|
||||||
<field name="name">Treatment Professional</field>
|
<field name="name">Treatment Professional</field>
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,111 @@
|
||||||
<odoo>
|
<odoo>
|
||||||
<data noupdate="1">
|
<data noupdate="1">
|
||||||
<!-- Refuse access to patient records that are not part of staff user's teams -->
|
<!-- Refuse access to patient records that are not part of staff user's teams -->
|
||||||
<record id="restrict_team_access_to_team_players" model="ir.rule">
|
<record id="restrict_staff_access_to_team_players" model="ir.rule">
|
||||||
<field name="name">Restrict Team Staff Access to Their Players Only</field>
|
<field name="name">Restrict Team Staff Access to Their Players Only</field>
|
||||||
<field name="model_id" ref="model_sports_patient"/>
|
<field name="model_id" ref="model_sports_patient"/>
|
||||||
<field name="groups" eval="[(6, 0, [ref('base.group_portal')])]"/>
|
<field name="groups"
|
||||||
|
eval="[(6, 0, [ref('base.group_portal'), ref('base.group_user')])]"/>
|
||||||
|
<field name="perm_create" eval="True"/>
|
||||||
|
<field name="perm_write" eval="True"/>
|
||||||
|
<field name="perm_read" eval="True"/>
|
||||||
|
<field name="perm_unlink" eval="True"/>
|
||||||
<field name="domain_force">
|
<field name="domain_force">
|
||||||
[('id', 'in',
|
[('team_ids.staff_ids.user_ids', 'in', user.id)]
|
||||||
user.partner_id.team_staff_rel_ids.team_id.patient_ids.ids)]
|
</field>
|
||||||
|
</record>
|
||||||
|
<record id="restrict_staff_access_to_teams" model="ir.rule">
|
||||||
|
<field name="name">Restrict Team Staff Access to Their Teams Only</field>
|
||||||
|
<field name="model_id" ref="model_sports_team"/>
|
||||||
|
<field name="groups"
|
||||||
|
eval="[(6, 0, [ref('base.group_portal'), ref('base.group_user')])]"/>
|
||||||
|
<field name="perm_create" eval="True"/>
|
||||||
|
<field name="perm_write" eval="True"/>
|
||||||
|
<field name="perm_read" eval="True"/>
|
||||||
|
<field name="perm_unlink" eval="True"/>
|
||||||
|
<field name="domain_force">
|
||||||
|
[('staff_ids.user_ids', 'in', user.id)]
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
<record id="restrict_staff_access_to_team_injuries" model="ir.rule">
|
||||||
|
<field name="name">Restrict Team Staff Access to Their Teams Only</field>
|
||||||
|
<field name="model_id" ref="model_sports_patient_injury"/>
|
||||||
|
<field name="groups"
|
||||||
|
eval="[(6, 0, [ref('base.group_portal'), ref('base.group_user')])]"/>
|
||||||
|
<field name="perm_create" eval="True"/>
|
||||||
|
<field name="perm_write" eval="True"/>
|
||||||
|
<field name="perm_read" eval="True"/>
|
||||||
|
<field name="perm_unlink" eval="True"/>
|
||||||
|
<field name="domain_force">
|
||||||
|
[('patient_id.team_ids.staff_ids.user_ids', 'in', user.id)]
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
<record id="restrict_patient_contact_access_to_allowed_internal_users"
|
||||||
|
model="ir.rule">
|
||||||
|
<field name="name">Restrict Patient Contact Access to Allowed Internal
|
||||||
|
Users
|
||||||
|
</field>
|
||||||
|
<field name="model_id" ref="model_sports_patient_contact"/>
|
||||||
|
<field name="groups" eval="[(6, 0, [ref('base.group_user')])]"/>
|
||||||
|
<field name="perm_create" eval="True"/>
|
||||||
|
<field name="perm_write" eval="True"/>
|
||||||
|
<field name="perm_read" eval="True"/>
|
||||||
|
<field name="perm_unlink" eval="True"/>
|
||||||
|
<field name="domain_force">
|
||||||
|
[('patient_id.team_ids.staff_ids.user_ids', 'in', user.id)]
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
<record id="allow_team_access_to_admins" model="ir.rule">
|
||||||
|
<field name="name">Allow Team Access to Administrators</field>
|
||||||
|
<field name="model_id" ref="model_sports_team"/>
|
||||||
|
<field name="groups"
|
||||||
|
eval="[(6, 0, [ref('base.group_system'), ref('bemade_sports_clinic.group_sports_clinic_admin')])]"/>
|
||||||
|
<field name="perm_create" eval="True"/>
|
||||||
|
<field name="perm_write" eval="True"/>
|
||||||
|
<field name="perm_read" eval="True"/>
|
||||||
|
<field name="perm_unlink" eval="True"/>
|
||||||
|
<field name="domain_force">
|
||||||
|
[(1, '=', 1)]
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
<record id="allow_patient_access_to_admins" model="ir.rule">
|
||||||
|
<field name="name">Allow Patient Access to Administrators</field>
|
||||||
|
<field name="model_id" ref="model_sports_patient"/>
|
||||||
|
<field name="groups"
|
||||||
|
eval="[(6, 0, [ref('base.group_system'), ref('bemade_sports_clinic.group_sports_clinic_admin')])]"/>
|
||||||
|
<field name="perm_create" eval="True"/>
|
||||||
|
<field name="perm_write" eval="True"/>
|
||||||
|
<field name="perm_read" eval="True"/>
|
||||||
|
<field name="perm_unlink" eval="True"/>
|
||||||
|
<field name="domain_force">
|
||||||
|
[(1, '=', 1)]
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
<record id="allow_injury_access_to_admins" model="ir.rule">
|
||||||
|
<field name="name">Allow Injury Access to Administrators</field>
|
||||||
|
<field name="model_id" ref="model_sports_patient_injury"/>
|
||||||
|
<field name="groups"
|
||||||
|
eval="[(6, 0, [ref('base.group_system'), ref('bemade_sports_clinic.group_sports_clinic_admin')])]"/>
|
||||||
|
<field name="perm_create" eval="True"/>
|
||||||
|
<field name="perm_write" eval="True"/>
|
||||||
|
<field name="perm_read" eval="True"/>
|
||||||
|
<field name="perm_unlink" eval="True"/>
|
||||||
|
<field name="domain_force">
|
||||||
|
[(1, '=', 1)]
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
<record id="allow_patient_contact_access_to_admins" model="ir.rule">
|
||||||
|
<field name="name">Allow Sports Patient Contact Access to Administrators
|
||||||
|
</field>
|
||||||
|
<field name="model_id" ref="model_sports_patient_contact"/>
|
||||||
|
<field name="groups"
|
||||||
|
eval="[(6, 0, [ref('base.group_system'), ref('bemade_sports_clinic.group_sports_clinic_admin')])]"/>
|
||||||
|
<field name="perm_create" eval="True"/>
|
||||||
|
<field name="perm_write" eval="True"/>
|
||||||
|
<field name="perm_read" eval="True"/>
|
||||||
|
<field name="perm_unlink" eval="True"/>
|
||||||
|
<field name="domain_force">
|
||||||
|
[(1, '=', 1)]
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
</data>
|
</data>
|
||||||
|
|
|
||||||
3
bemade_sports_clinic/tests/__init__.py
Normal file
3
bemade_sports_clinic/tests/__init__.py
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
from . import test_patient
|
||||||
|
from . import test_rights
|
||||||
|
from . import test_users
|
||||||
222
bemade_sports_clinic/tests/test_patient.py
Normal file
222
bemade_sports_clinic/tests/test_patient.py
Normal file
|
|
@ -0,0 +1,222 @@
|
||||||
|
from odoo.tests import TransactionCase, tagged, Form
|
||||||
|
from odoo import fields, Command
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
|
||||||
|
@tagged("-at_install", "post_install")
|
||||||
|
class TestPatient(TransactionCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super().setUpClass()
|
||||||
|
organization = cls.env["res.partner"].create(
|
||||||
|
{"name": "Test Org"},
|
||||||
|
)
|
||||||
|
team1 = cls.env["sports.team"].create(
|
||||||
|
{
|
||||||
|
"name": "Test team",
|
||||||
|
"parent_id": organization.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
coach = cls.env["sports.team.staff"].create(
|
||||||
|
{
|
||||||
|
"partner_id": cls.env["res.partner"]
|
||||||
|
.create(
|
||||||
|
{
|
||||||
|
"name": "Test Coach",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.id,
|
||||||
|
"team_id": team1.id,
|
||||||
|
"role": "head_coach",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
patient1 = cls.env["sports.patient"].create(
|
||||||
|
{
|
||||||
|
"first_name": "Test",
|
||||||
|
"last_name": "Patient 1",
|
||||||
|
"team_ids": [Command.set(team1.ids)],
|
||||||
|
"date_of_birth": fields.Date.today() - timedelta(days=18 * 365),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
patient1_injury = cls.env["sports.patient.injury"].create(
|
||||||
|
{
|
||||||
|
"patient_id": patient1.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
patient2 = cls.env["sports.patient"].create(
|
||||||
|
{
|
||||||
|
"first_name": "Test",
|
||||||
|
"last_name": "Patient2",
|
||||||
|
"team_ids": [Command.set(team1.ids)],
|
||||||
|
"date_of_birth": fields.Date.today() - timedelta(days=21 * 365),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
patient2_injury = cls.env["sports.patient.injury"].create(
|
||||||
|
{
|
||||||
|
"patient_id": patient2.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
(
|
||||||
|
cls.organization,
|
||||||
|
cls.team1,
|
||||||
|
cls.coach,
|
||||||
|
cls.patient1,
|
||||||
|
cls.patient1_injury,
|
||||||
|
cls.patient2,
|
||||||
|
cls.patient2_injury,
|
||||||
|
) = (
|
||||||
|
organization,
|
||||||
|
team1,
|
||||||
|
coach,
|
||||||
|
patient1,
|
||||||
|
patient1_injury,
|
||||||
|
patient2,
|
||||||
|
patient2_injury,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_adding_staff_adds_follower_to_patient_and_injury(self):
|
||||||
|
therapist = self.env["sports.team.staff"].create(
|
||||||
|
{
|
||||||
|
"team_id": self.team1.id,
|
||||||
|
"partner_id": self.env["res.partner"]
|
||||||
|
.create(
|
||||||
|
{"name": "Tester"},
|
||||||
|
)
|
||||||
|
.id,
|
||||||
|
"role": "therapist",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
therapist = therapist.partner_id
|
||||||
|
self.assertIn(therapist, self.patient1.message_partner_ids)
|
||||||
|
self.assertIn(therapist, self.patient2.message_partner_ids)
|
||||||
|
self.assertIn(therapist, self.patient1_injury.message_partner_ids)
|
||||||
|
self.assertIn(therapist, self.patient2_injury.message_partner_ids)
|
||||||
|
|
||||||
|
def test_removing_staff_removes_follower_from_patient_and_injury(self):
|
||||||
|
coach = self.coach.partner_id
|
||||||
|
self.team1.staff_ids = False
|
||||||
|
self.assertNotIn(coach, self.patient1.message_partner_ids)
|
||||||
|
self.assertNotIn(coach, self.patient1_injury.message_partner_ids)
|
||||||
|
self.assertNotIn(coach, self.patient2.message_partner_ids)
|
||||||
|
self.assertNotIn(coach, self.patient2_injury.message_partner_ids)
|
||||||
|
|
||||||
|
def test_deleting_team_removes_follower_from_patient_and_injury(self):
|
||||||
|
coach = self.coach.partner_id
|
||||||
|
self.team1.unlink()
|
||||||
|
self.assertNotIn(coach, self.patient1.message_partner_ids)
|
||||||
|
self.assertNotIn(coach, self.patient1_injury.message_partner_ids)
|
||||||
|
self.assertNotIn(coach, self.patient2.message_partner_ids)
|
||||||
|
self.assertNotIn(coach, self.patient2_injury.message_partner_ids)
|
||||||
|
|
||||||
|
def test_adding_second_team_subscribes_new_staff(self):
|
||||||
|
team2, therapist, coach = self._generate_second_team_and_staff()
|
||||||
|
|
||||||
|
team2.patient_ids = self.patient1
|
||||||
|
|
||||||
|
self.assertIn(therapist, self.patient1.message_partner_ids)
|
||||||
|
self.assertIn(coach, self.patient1.message_partner_ids)
|
||||||
|
self.assertIn(therapist, self.patient1_injury.message_partner_ids)
|
||||||
|
self.assertIn(coach, self.patient1_injury.message_partner_ids)
|
||||||
|
self.assertEqual(len(self.patient1_injury.message_partner_ids), 2)
|
||||||
|
self.assertEqual(len(self.patient1.message_partner_ids), 2)
|
||||||
|
|
||||||
|
def test_creating_patient_in_team_assigns_followers(self):
|
||||||
|
patient = self.env["sports.patient"].create(
|
||||||
|
{
|
||||||
|
"first_name": "Test",
|
||||||
|
"last_name": "Patient",
|
||||||
|
"date_of_birth": fields.Date.today() - timedelta(days=365 * 20),
|
||||||
|
"team_ids": [(6, 0, self.team1.ids)],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
cp_id = self.coach.partner_id
|
||||||
|
self.assertIn(cp_id, patient.message_partner_ids)
|
||||||
|
|
||||||
|
injury = self.env["sports.patient.injury"].create(
|
||||||
|
{
|
||||||
|
"patient_id": patient.id,
|
||||||
|
"diagnosis": "Something",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.assertIn(cp_id, injury.message_partner_ids)
|
||||||
|
|
||||||
|
def test_removing_second_team_correctly_adjusts_staff(self):
|
||||||
|
"""Tests both removing from the team side and from the patient side."""
|
||||||
|
team2, therapist, coach = self._generate_second_team_and_staff()
|
||||||
|
self.patient1.write({"team_ids": [Command.link(team2.id)]})
|
||||||
|
self.assertIn(self.patient1, team2.patient_ids)
|
||||||
|
self.assertIn(therapist, self.patient1.message_partner_ids)
|
||||||
|
|
||||||
|
team2.write({"patient_ids": [Command.unlink(self.patient1.id)]})
|
||||||
|
|
||||||
|
self.assertNotIn(self.patient1, team2.patient_ids)
|
||||||
|
self.assertEqual(self.patient1.message_partner_ids, coach)
|
||||||
|
self.assertEqual(self.patient1_injury.message_partner_ids, coach)
|
||||||
|
|
||||||
|
self.patient1.write({"team_ids": [Command.link(team2.id)]})
|
||||||
|
|
||||||
|
self.assertIn(self.patient1, team2.patient_ids)
|
||||||
|
self.assertIn(therapist, self.patient1.message_partner_ids)
|
||||||
|
|
||||||
|
self.patient1.write({"team_ids": [Command.unlink(team2.id)]})
|
||||||
|
|
||||||
|
self.assertNotIn(self.patient1, team2.patient_ids)
|
||||||
|
self.assertEqual(self.patient1.message_partner_ids, coach)
|
||||||
|
self.assertEqual(self.patient1_injury.message_partner_ids, coach)
|
||||||
|
|
||||||
|
def test_adding_patient_injury_sets_followers(self):
|
||||||
|
injury2 = self.env["sports.patient.injury"].create(
|
||||||
|
{
|
||||||
|
"patient_id": self.patient1.id,
|
||||||
|
"diagnosis": "some other injury",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(injury2.message_partner_ids, self.coach.partner_id)
|
||||||
|
|
||||||
|
def _generate_second_team_and_staff(self):
|
||||||
|
team2 = self.env["sports.team"].create(
|
||||||
|
{
|
||||||
|
"parent_id": self.organization.id,
|
||||||
|
"name": "Test team 2",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
therapist = (
|
||||||
|
self.env["sports.team.staff"]
|
||||||
|
.create(
|
||||||
|
{
|
||||||
|
"team_id": team2.id,
|
||||||
|
"partner_id": self.env["res.partner"]
|
||||||
|
.create(
|
||||||
|
{"name": "Tester"},
|
||||||
|
)
|
||||||
|
.id,
|
||||||
|
"role": "therapist",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.partner_id
|
||||||
|
)
|
||||||
|
coach = (
|
||||||
|
self.env["sports.team.staff"]
|
||||||
|
.create(
|
||||||
|
{
|
||||||
|
"team_id": team2.id,
|
||||||
|
"partner_id": self.coach.partner_id.id,
|
||||||
|
"role": "coach",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.partner_id
|
||||||
|
)
|
||||||
|
return team2, therapist, coach
|
||||||
|
|
||||||
|
def test_changing_patient_name_changes_on_partner(self):
|
||||||
|
new_last_name = "New last name"
|
||||||
|
new_first_name = "New first name"
|
||||||
|
with Form(self.patient1) as patient:
|
||||||
|
patient.last_name = new_last_name
|
||||||
|
patient.first_name = new_first_name
|
||||||
|
self.assertEqual(
|
||||||
|
self.patient1.partner_id.name, " ".join([new_first_name, new_last_name])
|
||||||
|
)
|
||||||
114
bemade_sports_clinic/tests/test_rights.py
Normal file
114
bemade_sports_clinic/tests/test_rights.py
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
from odoo.tests import TransactionCase, Form, tagged
|
||||||
|
from odoo.fields import Date
|
||||||
|
from datetime import timedelta
|
||||||
|
from odoo.exceptions import AccessError
|
||||||
|
from odoo import Command
|
||||||
|
import logging
|
||||||
|
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@tagged("-at_install", "post_install")
|
||||||
|
class TestRights(TransactionCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super().setUpClass()
|
||||||
|
# Create one admin user
|
||||||
|
cls.admin_user = cls.env["res.users"].create(
|
||||||
|
{
|
||||||
|
"name": "Admin User",
|
||||||
|
"login": "sports_admin",
|
||||||
|
"password": "sports_admin",
|
||||||
|
"groups_id": [
|
||||||
|
Command.set(
|
||||||
|
cls.env.ref(
|
||||||
|
"bemade_sports_clinic.group_sports_clinic_admin"
|
||||||
|
).ids,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
# Create one treatment professional user
|
||||||
|
cls.treatment_professional_user = cls.env["res.users"].create(
|
||||||
|
{
|
||||||
|
"name": "Treatment Professional User",
|
||||||
|
"login": "treatment_professional",
|
||||||
|
"password": "treatment_professional",
|
||||||
|
"groups_id": [
|
||||||
|
Command.set(
|
||||||
|
cls.env.ref(
|
||||||
|
"bemade_sports_clinic.group_sports_clinic_treatment_professional"
|
||||||
|
).ids,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
# _logger.info(
|
||||||
|
# f"Treatment Pro Groups: "
|
||||||
|
# f"{cls.treatment_professional_user.groups_id.mapped('name')}"
|
||||||
|
# )
|
||||||
|
|
||||||
|
def test_treatment_pro_has_access_only_to_staffed_teams(self):
|
||||||
|
"""A treatment professional should only have access to teams and,
|
||||||
|
by extension, patients for which they are a team staff member."""
|
||||||
|
team, patients = self._generate_team_with_patient(self.admin_user)
|
||||||
|
with self.assertRaises(AccessError):
|
||||||
|
Form(
|
||||||
|
self.env["sports.team"]
|
||||||
|
.with_user(self.treatment_professional_user)
|
||||||
|
.browse(team.id)
|
||||||
|
)
|
||||||
|
with self.assertRaises(AccessError):
|
||||||
|
Form(
|
||||||
|
self.env["sports.patient"]
|
||||||
|
.with_user(self.treatment_professional_user)
|
||||||
|
.browse(patients[0].id)
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_treatment_pro_can_remove_patient_from_team(self):
|
||||||
|
team, patients = self._generate_team_with_patient(self.admin_user)
|
||||||
|
self.env["sports.team.staff"].with_user(self.admin_user).create(
|
||||||
|
{
|
||||||
|
"team_id": team.id,
|
||||||
|
"partner_id": self.treatment_professional_user.partner_id.id,
|
||||||
|
"role": "head_therapist",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
# Test removing the patient since we are team staff
|
||||||
|
# Should not throw an error...
|
||||||
|
with Form(team.with_user(self.treatment_professional_user)) as team:
|
||||||
|
team.patient_ids.remove(index=0)
|
||||||
|
self.assertEqual(len(team.patient_ids), 1)
|
||||||
|
|
||||||
|
def _generate_team_with_patient(self, user=None):
|
||||||
|
user = user or self.env.user
|
||||||
|
team = (
|
||||||
|
self.env["sports.team"]
|
||||||
|
.with_user(user)
|
||||||
|
.create(
|
||||||
|
{
|
||||||
|
"name": "Test Team",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
patients = (
|
||||||
|
self.env["sports.patient"]
|
||||||
|
.with_user(user)
|
||||||
|
.create(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"first_name": "Test",
|
||||||
|
"last_name": "Patient One",
|
||||||
|
"date_of_birth": Date.today() - timedelta(days=-365 * 18),
|
||||||
|
"team_ids": [(6, 0, team.ids)],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"first_name": "Test",
|
||||||
|
"last_name": "Patient Two",
|
||||||
|
"date_of_birth": Date.today() - timedelta(days=-365 * 18),
|
||||||
|
"team_ids": [(6, 0, team.ids)],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return team, patients
|
||||||
35
bemade_sports_clinic/tests/test_users.py
Normal file
35
bemade_sports_clinic/tests/test_users.py
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
from odoo.tests import TransactionCase, tagged, Form
|
||||||
|
from odoo import Command
|
||||||
|
|
||||||
|
|
||||||
|
@tagged("-at_install", "post_install")
|
||||||
|
class TestUsers(TransactionCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
super().setUpClass()
|
||||||
|
|
||||||
|
def test_add_team_access_to_user(self):
|
||||||
|
user = self.env["res.users"].create(
|
||||||
|
{
|
||||||
|
"name": "test",
|
||||||
|
"login": "test",
|
||||||
|
"password": "test",
|
||||||
|
"groups_id": [
|
||||||
|
Command.set(
|
||||||
|
self.env.ref(
|
||||||
|
"bemade_sports_clinic.group_sports_clinic_treatment_professional"
|
||||||
|
).ids
|
||||||
|
)
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
team = self.env["sports.team"].create(
|
||||||
|
{
|
||||||
|
"name": "Test",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertNotIn(user, team.staff_ids.user_ids)
|
||||||
|
user.write({"accessible_team_ids": [Command.link(team.id)]})
|
||||||
|
# user._inverse_accessible_team_ids()
|
||||||
|
self.assertIn(user, team.staff_ids.user_ids)
|
||||||
|
|
@ -8,7 +8,16 @@
|
||||||
<page name="contact_addresses" position="after">
|
<page name="contact_addresses" position="after">
|
||||||
<page name="Teams">
|
<page name="Teams">
|
||||||
<field invisible="is_company == False" name="owned_team_ids" string="Teams"/>
|
<field invisible="is_company == False" name="owned_team_ids" string="Teams"/>
|
||||||
<field invisible="is_company == True" name="teams_served_ids" string="Teams Served"/>
|
<field invisible="is_company == True" name="teams_served_ids" string="Teams Served">
|
||||||
|
<tree editable="bottom" create="False" delete="True">
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="parent_id"/>
|
||||||
|
<field name="head_coach_id"/>
|
||||||
|
<field name="head_therapist_id"/>
|
||||||
|
<field name="player_count"/>
|
||||||
|
<field name="injured_count"/>
|
||||||
|
</tree>
|
||||||
|
</field>
|
||||||
</page>
|
</page>
|
||||||
</page></field>
|
</page></field>
|
||||||
</record>
|
</record>
|
||||||
|
|
|
||||||
16
bemade_sports_clinic/views/res_users_views.xml
Normal file
16
bemade_sports_clinic/views/res_users_views.xml
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<record id="view_users_form_inherit" model="ir.ui.view">
|
||||||
|
<field name="name">view.users.form.inherit</field>
|
||||||
|
<field name="inherit_id" ref="base.view_users_form"/>
|
||||||
|
<field name="model">res.users</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<page name="preferences" position="before">
|
||||||
|
<page name="Sports Team Access"
|
||||||
|
groups="base.group_system,bemade_sports_clinic.group_sports_clinic_admin">
|
||||||
|
<field name="accessible_team_ids" widget="many2many_checkboxes"/>
|
||||||
|
</page>
|
||||||
|
</page>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
|
|
@ -128,7 +128,7 @@
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<ul class="list-unstyled">
|
<ul class="list-unstyled">
|
||||||
<t t-foreach="player.team_ids" t-as="team">
|
<t t-foreach="player.sudo().team_ids" t-as="team">
|
||||||
<li>
|
<li>
|
||||||
<a t-attf-href="/my/team?team_id={{ team.id }}"
|
<a t-attf-href="/my/team?team_id={{ team.id }}"
|
||||||
t-field="team.name"/>
|
t-field="team.name"/>
|
||||||
|
|
|
||||||
|
|
@ -117,10 +117,25 @@
|
||||||
</tree></field>
|
</tree></field>
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
<separator string="Players"/>
|
<notebook>
|
||||||
<field context="{'tree_view_ref': 'bemade_sports_clinic.sports_patient_view_list_embedded'}" name="patient_ids" nolabel="1"/>
|
<page name="players" string="Players">
|
||||||
|
<field name="patient_ids" nolabel="1"
|
||||||
|
context="{'tree_view_ref': 'bemade_sports_clinic.sports_patient_view_list_embedded'}"/>
|
||||||
|
</page>
|
||||||
|
<page name="user_access"
|
||||||
|
string="User Access"
|
||||||
|
groups="bemade_sports_clinic.group_sports_clinic_admin,base.group_system">
|
||||||
|
<field name="allowed_user_ids"/>
|
||||||
|
</page>
|
||||||
|
</notebook>
|
||||||
</sheet>
|
</sheet>
|
||||||
</form></field>
|
<div class="oe_chatter">
|
||||||
|
<field name="message_follower_ids" widget="mail_followers"/>
|
||||||
|
<field name="activity_ids" widget="mail_activity"/>
|
||||||
|
<field name="message_ids" widget="mail_thread"/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
</record>
|
</record>
|
||||||
<record id="sports_team_staff_view_form" model="ir.ui.view">
|
<record id="sports_team_staff_view_form" model="ir.ui.view">
|
||||||
<field name="name">sports.team.staff.view.form</field>
|
<field name="name">sports.team.staff.view.form</field>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue