Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to share patients across clients #38

Merged
merged 8 commits into from
Jun 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Changelog
1.1.0 (unreleased)
------------------

- #37 Allow client users to create samples and patients
- #36 Do not display Patient root folder to users other than lab contact
- #35 Integrate new DX address field for patients
- #34 Fix UnicodeDecodeError when storing Patients with special characters
Expand Down
7 changes: 7 additions & 0 deletions src/senaite/patient/browser/controlpanel.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ class IPatientControlPanel(Interface):
default=False,
)

share_patients = schema.Bool(
title=_(u"Share patient on sample creation"),
description=_(u"If selected, patients created or referred on sample "
u"creation will automatically be shared across users "
u"from same client the sample belongs to")
)

@invariant
def validate_identifiers(data):
"""Checks if the keyword is unique and valid
Expand Down
8 changes: 4 additions & 4 deletions src/senaite/patient/content/patient.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
# Copyright 2020-2022 by it's authors.
# Some rights reserved, see README and LICENSE.

from six import string_types

from AccessControl import ClassSecurityInfo
from bika.lims import api
from bika.lims.api.mail import is_valid_email_address
Expand All @@ -28,6 +26,7 @@
from plone.supermodel import model
from plone.supermodel.directives import fieldset
from Products.CMFCore import permissions
from senaite.core.behaviors import IClientShareable
from senaite.core.schema import AddressField
from senaite.core.schema import DatetimeField
from senaite.core.schema.addressfield import OTHER_ADDRESS
Expand All @@ -42,10 +41,11 @@
from senaite.patient.catalog import PATIENT_CATALOG
from senaite.patient.config import GENDERS
from senaite.patient.interfaces import IPatient
from six import string_types
from zope import schema
from zope.interface import implementer
from zope.interface import Interface
from zope.interface import Invalid
from zope.interface import implementer
from zope.interface import invariant


Expand Down Expand Up @@ -280,7 +280,7 @@ def validate_email(data):
raise Invalid(_("Patient email is invalid"))


@implementer(IPatient, IPatientSchema)
@implementer(IPatient, IPatientSchema, IClientShareable)
class Patient(Container):
"""Results Interpretation Template content
"""
Expand Down
9 changes: 8 additions & 1 deletion src/senaite/patient/profiles/default/rolemap.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,35 @@
<role name="Manager"/>
</permission>

<!-- Field permissions -->
<!-- Permissions for Sample fields
User who creates the object (Owner) has all rights granted by default
-->
<permission name="senaite.patient: Field: Edit MRN" acquire="False">
<role name="Owner"/>
<role name="LabClerk"/>
<role name="LabManager"/>
<role name="Manager"/>
</permission>
<permission name="senaite.patient: Field: Edit Fullname" acquire="False">
<role name="Owner"/>
<role name="LabClerk"/>
<role name="LabManager"/>
<role name="Manager"/>
</permission>
<permission name="senaite.patient: Field: Edit Date of Birth" acquire="False">
<role name="Owner"/>
<role name="LabClerk"/>
<role name="LabManager"/>
<role name="Manager"/>
</permission>
<permission name="senaite.patient: Field: Edit Gender" acquire="False">
<role name="Owner"/>
<role name="LabClerk"/>
<role name="LabManager"/>
<role name="Manager"/>
</permission>
<permission name="senaite.patient: Field: Edit Address" acquire="False">
<role name="Owner"/>
<role name="LabClerk"/>
<role name="LabManager"/>
<role name="Manager"/>
Expand Down
1 change: 1 addition & 0 deletions src/senaite/patient/profiles/default/types/Patient.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
<element value="bika.lims.interfaces.IAutoGenerateID"/>
<element value="bika.lims.interfaces.IMultiCatalogBehavior"/>
<element value="plone.app.referenceablebehavior.referenceable.IReferenceable" />
<element value="senaite.core.behaviors.IClientShareableBehavior" />
</property>

<!-- Action aliases -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
i18n:domain="senaite.patient">

<!-- PLONE permissions -->
<permission>Add portal content</permission>
<permission>Access contents information</permission>
<permission>Delete objects</permission>
<permission>List folder contents</permission>
Expand All @@ -21,6 +22,7 @@
<permission-map name="Access contents information" acquired="False">
<!-- All except Anonymous and Client -->
<permission-role>Analyst</permission-role>
<permission-role>ClientGuest</permission-role>
<permission-role>LabClerk</permission-role>
<permission-role>LabManager</permission-role>
<permission-role>Preserver</permission-role>
Expand All @@ -29,12 +31,14 @@
<permission-role>SamplingCoordinator</permission-role>
<!-- Plone roles -->
<permission-role>Manager</permission-role>
<permission-role>Owner</permission-role>
<permission-role>Site Administrator</permission-role>
</permission-map>
<permission-map name="Delete objects" acquired="False" />
<permission-map name="List folder contents" acquired="False">
<!-- All except Anonymous and Client -->
<permission-role>Analyst</permission-role>
<permission-role>ClientGuest</permission-role>
<permission-role>LabClerk</permission-role>
<permission-role>LabManager</permission-role>
<permission-role>Preserver</permission-role>
Expand All @@ -45,14 +49,25 @@
<permission-role>Manager</permission-role>
<permission-role>Site Administrator</permission-role>
</permission-map>
<permission-map name="Add portal content" acquired="False">
<permission-role>Client</permission-role>
<permission-role>LabClerk</permission-role>
<permission-role>LabManager</permission-role>
<!-- Plone roles -->
<permission-role>Manager</permission-role>
</permission-map>
<permission-map name="Modify portal content" acquired="False">
<permission-role>LabClerk</permission-role>
<permission-role>LabManager</permission-role>
<!-- Plone roles -->
<permission-role>Manager</permission-role>
<permission-role>Owner</permission-role>
</permission-map>
<permission-map name="View" acquired="False">
<!-- All except Anonymous and Client -->
<!-- All except Anonymous -->
<permission-role>Analyst</permission-role>
<permission-role>Client</permission-role>
<permission-role>ClientGuest</permission-role>
<permission-role>LabClerk</permission-role>
<permission-role>LabManager</permission-role>
<permission-role>Preserver</permission-role>
Expand All @@ -61,6 +76,7 @@
<permission-role>SamplingCoordinator</permission-role>
<!-- Plone roles -->
<permission-role>Manager</permission-role>
<permission-role>Owner</permission-role>
<permission-role>Site Administrator</permission-role>
</permission-map>
</state>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,22 @@
<permission-map name="Delete objects" acquired="True" />
<permission-map name="List folder contents" acquired="True" />
<permission-map name="Modify portal content" acquired="True" />
<permission-map name="View" acquired="True" />

<permission-map name="View" acquired="False">
<!-- All except Anonymous and Client -->
<permission-role>Analyst</permission-role>
<permission-role>ClientGuest</permission-role>
<permission-role>LabClerk</permission-role>
<permission-role>LabManager</permission-role>
<permission-role>Preserver</permission-role>
<permission-role>RegulatoryInspector</permission-role>
<permission-role>Sampler</permission-role>
<permission-role>SamplingCoordinator</permission-role>
<!-- Plone roles -->
<permission-role>Manager</permission-role>
<permission-role>Owner</permission-role>
<permission-role>Site Administrator</permission-role>
</permission-map>
<!-- senaite.patient permissions -->
<permission-map name="senaite.patient: Field: Edit MRN" acquired="True" />
<permission-map name="senaite.patient: Field: Edit ID" acquired="True" />
Expand Down
14 changes: 14 additions & 0 deletions src/senaite/patient/subscribers/analysisrequest.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
# Some rights reserved, see README and LICENSE.

from bika.lims import api
from senaite.core.behaviors import IClientShareableBehavior
from senaite.patient import api as patient_api
from senaite.patient import check_installed
from senaite.patient import logger
Expand All @@ -39,6 +40,19 @@ def on_object_created(instance, event):
email = patient.getEmail()
add_cc_email(instance, email)

# share patient with sample's client users if necessary
reg_key = "senaite.patient.share_patients"
if api.get_registry_record(reg_key, default=False):
client_uid = api.get_uid(instance.getClient())
behavior = IClientShareableBehavior(patient)
# Note we get Raw clients because if current user is a Client, she/he
# does not have enough privileges to wake-up clients other than the one
# she/he belongs to. Still, we need to keep the rest of shared clients
client_uids = behavior.getRawClients() or []
if client_uid not in client_uids:
client_uids.append(client_uid)
behavior.setClients(client_uids)


@check_installed(None)
def on_object_edited(instance, event):
Expand Down
2 changes: 1 addition & 1 deletion src/senaite/patient/tests/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def setUpPloneSite(self, portal):
SIMPLE_FIXTURE = SimpleTestLayer()
SIMPLE_TESTING = FunctionalTesting(
bases=(SIMPLE_FIXTURE, ),
name="senaite.storage:SimpleTesting"
name="senaite.patient:SimpleTesting"
)


Expand Down
42 changes: 21 additions & 21 deletions src/senaite/patient/tests/doctests/PatientWorkflow.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Get the mapped workflow and status of the patient folder:
>>> patients = portal.patients

>>> api.get_workflows_for(patients)
('senaite_one_state_workflow',)
('senaite_patient_folder_workflow',)

>>> api.get_workflow_status_of(patients)
'active'
Expand Down Expand Up @@ -117,23 +117,23 @@ Field permission in **active** state:

>>> from senaite.patient.permissions import FieldEditMRN
>>> get_roles_for_permission(FieldEditMRN, patient)
['LabClerk', 'LabManager', 'Manager']
['LabClerk', 'LabManager', 'Manager', 'Owner']

>>> from senaite.patient.permissions import FieldEditFullName
>>> get_roles_for_permission(FieldEditFullName, patient)
['LabClerk', 'LabManager', 'Manager']
['LabClerk', 'LabManager', 'Manager', 'Owner']

>>> from senaite.patient.permissions import FieldEditGender
>>> get_roles_for_permission(FieldEditGender, patient)
['LabClerk', 'LabManager', 'Manager']
['LabClerk', 'LabManager', 'Manager', 'Owner']

>>> from senaite.patient.permissions import FieldEditDateOfBirth
>>> get_roles_for_permission(FieldEditDateOfBirth, patient)
['LabClerk', 'LabManager', 'Manager']
['LabClerk', 'LabManager', 'Manager', 'Owner']

>>> from senaite.patient.permissions import FieldEditAddress
>>> get_roles_for_permission(FieldEditAddress, patient)
['LabClerk', 'LabManager', 'Manager']
['LabClerk', 'LabManager', 'Manager', 'Owner']

Deactivating the patient

Expand Down Expand Up @@ -183,23 +183,23 @@ All patient fields are editable in `sample_due`:

>>> from senaite.patient.permissions import FieldEditMRN
>>> get_roles_for_permission(FieldEditMRN, sample)
['LabClerk', 'LabManager', 'Manager']
['LabClerk', 'LabManager', 'Manager', 'Owner']

>>> from senaite.patient.permissions import FieldEditFullName
>>> get_roles_for_permission(FieldEditFullName, sample)
['LabClerk', 'LabManager', 'Manager']
['LabClerk', 'LabManager', 'Manager', 'Owner']

>>> from senaite.patient.permissions import FieldEditGender
>>> get_roles_for_permission(FieldEditGender, sample)
['LabClerk', 'LabManager', 'Manager']
['LabClerk', 'LabManager', 'Manager', 'Owner']

>>> from senaite.patient.permissions import FieldEditDateOfBirth
>>> get_roles_for_permission(FieldEditDateOfBirth, sample)
['LabClerk', 'LabManager', 'Manager']
['LabClerk', 'LabManager', 'Manager', 'Owner']

>>> from senaite.patient.permissions import FieldEditAddress
>>> get_roles_for_permission(FieldEditAddress, sample)
['LabClerk', 'LabManager', 'Manager']
['LabClerk', 'LabManager', 'Manager', 'Owner']

Receive the sample:

Expand All @@ -211,23 +211,23 @@ All patient fields are editable in `sample_received`:

>>> from senaite.patient.permissions import FieldEditMRN
>>> get_roles_for_permission(FieldEditMRN, sample)
['LabClerk', 'LabManager', 'Manager']
['LabClerk', 'LabManager', 'Manager', 'Owner']

>>> from senaite.patient.permissions import FieldEditFullName
>>> get_roles_for_permission(FieldEditFullName, sample)
['LabClerk', 'LabManager', 'Manager']
['LabClerk', 'LabManager', 'Manager', 'Owner']

>>> from senaite.patient.permissions import FieldEditGender
>>> get_roles_for_permission(FieldEditGender, sample)
['LabClerk', 'LabManager', 'Manager']
['LabClerk', 'LabManager', 'Manager', 'Owner']

>>> from senaite.patient.permissions import FieldEditDateOfBirth
>>> get_roles_for_permission(FieldEditDateOfBirth, sample)
['LabClerk', 'LabManager', 'Manager']
['LabClerk', 'LabManager', 'Manager', 'Owner']

>>> from senaite.patient.permissions import FieldEditAddress
>>> get_roles_for_permission(FieldEditAddress, sample)
['LabClerk', 'LabManager', 'Manager']
['LabClerk', 'LabManager', 'Manager', 'Owner']

Set results and submit:

Expand All @@ -248,23 +248,23 @@ All patient fields are editable in `to_be_verified`:

>>> from senaite.patient.permissions import FieldEditMRN
>>> get_roles_for_permission(FieldEditMRN, sample)
['LabClerk', 'LabManager', 'Manager']
['LabClerk', 'LabManager', 'Manager', 'Owner']

>>> from senaite.patient.permissions import FieldEditFullName
>>> get_roles_for_permission(FieldEditFullName, sample)
['LabClerk', 'LabManager', 'Manager']
['LabClerk', 'LabManager', 'Manager', 'Owner']

>>> from senaite.patient.permissions import FieldEditGender
>>> get_roles_for_permission(FieldEditGender, sample)
['LabClerk', 'LabManager', 'Manager']
['LabClerk', 'LabManager', 'Manager', 'Owner']

>>> from senaite.patient.permissions import FieldEditDateOfBirth
>>> get_roles_for_permission(FieldEditDateOfBirth, sample)
['LabClerk', 'LabManager', 'Manager']
['LabClerk', 'LabManager', 'Manager', 'Owner']

>>> from senaite.patient.permissions import FieldEditAddress
>>> get_roles_for_permission(FieldEditAddress, sample)
['LabClerk', 'LabManager', 'Manager']
['LabClerk', 'LabManager', 'Manager', 'Owner']

Verify the results:

Expand Down
Loading