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 set additional named phone numbers #54

Merged
merged 10 commits into from
Oct 19, 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 @@ -5,6 +5,7 @@ Changelog
1.4.0 (unreleased)
------------------

- #54 Allow to set additional named phone numbers
- #55 Optional MRN in Patient Add/Edit forms
- #53 Add patient marital status

Expand Down
153 changes: 79 additions & 74 deletions src/senaite/patient/content/patient.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@
from senaite.core.behaviors import IClientShareable
from senaite.core.schema import AddressField
from senaite.core.schema import DatetimeField
from senaite.core.schema import PhoneField
from senaite.core.schema.addressfield import OTHER_ADDRESS
from senaite.core.schema.addressfield import PHYSICAL_ADDRESS
from senaite.core.schema.addressfield import POSTAL_ADDRESS
from senaite.core.schema.fields import DataGridField
from senaite.core.schema.fields import DataGridRow
from senaite.core.z3cform.widgets.datagrid import DataGridWidgetFactory
from senaite.core.z3cform.widgets.datetimewidget import DatetimeWidget
from senaite.core.z3cform.widgets.phone import PhoneWidgetFactory
from senaite.patient import api as patient_api
from senaite.patient import messageFactory as _
from senaite.patient.catalog import PATIENT_CATALOG
Expand All @@ -46,71 +48,15 @@
from senaite.patient.interfaces import IPatient
from z3c.form.interfaces import NO_VALUE
from zope import schema
from zope.interface import Interface
from zope.interface import Invalid
from zope.interface import implementer
from zope.interface import invariant


class IIdentifiersSchema(Interface):
"""Schema definition for identifier records field
"""

key = schema.Choice(
title=_("Type"),
description=_(
u"The type of identifier that holds the ID"
),
source="senaite.patient.vocabularies.identifiers",
required=True,
)

value = schema.TextLine(
title=_(u"ID"),
description=_(
u"The identification number of the selected identifier"
),
required=True,
)


class IAdditionalEmailSchema(Interface):
"""Schema definition for additional emails field
"""

name = schema.TextLine(
title=_("Name"),
description=_(u"Private, Work, Other etc."),
required=True,
)

email = schema.TextLine(
title=_(u"Email"),
description=_(u"Email address"),
required=True,
)


class IRaceSchema(Interface):
"""Schema definition for patient race
"""
race = schema.Choice(
title=_("Race"),
description=_(u""),
source="senaite.patient.vocabularies.races",
required=False,
)


class IEthnicitySchema(Interface):
"""Schema definition for patient ethnicity
"""
ethnicity = schema.Choice(
title=_("Ethnicity"),
description=_(u""),
source="senaite.patient.vocabularies.ethnicities",
required=False,
)
from .schema import IAdditionalEmailSchema
from .schema import IAdditionalPhoneNumbersSchema
from .schema import IEthnicitySchema
from .schema import IIdentifiersSchema
from .schema import IRaceSchema


class IPatientSchema(model.Schema):
Expand All @@ -137,9 +83,14 @@ class IPatientSchema(model.Schema):

# contact fieldset
fieldset(
"contact",
label=u"Contact",
fields=["email", "additional_emails", "phone", "mobile"])
"email_and_phone",
label=u"Email and Phone",
fields=[
"email",
"additional_emails",
"phone",
"additional_phone_numbers",
])

# address fieldset
fieldset(
Expand Down Expand Up @@ -272,7 +223,7 @@ class IPatientSchema(model.Schema):
email = schema.TextLine(
title=_(
u"label_primary_patient_email",
default=u"Primary Email"
default=u"Primary Email Address"
),
description=_(
u"description_patient_primary_email",
Expand All @@ -289,7 +240,7 @@ class IPatientSchema(model.Schema):
additional_emails = DataGridField(
title=_(
u"label_patient_additional_emails",
default=u"Additional Emails"),
default=u"Additional Email Addresses"),
description=_(
u"description_patient_additional_emails",
default=u"Additional email addresses for this patient"
Expand All @@ -302,16 +253,36 @@ class IPatientSchema(model.Schema):
default=[],
)

phone = schema.TextLine(
title=_(u"label_patient_phone", default=u"Phone"),
description=_(u"Patient phone number"),
# primary phone number
directives.widget("phone", PhoneWidgetFactory)
phone = PhoneField(
title=_(
u"label_patient_primary_phone",
default=u"Primary Phone Number",),
description=_(
u"description_patient_primary_phone",
u"Primary phone number for this patient"),
required=False,
)

mobile = schema.TextLine(
title=_(u"label_patient_mobile", default=u"Mobile"),
description=_(u"Patient mobile phone number"),
# additional phone numbers
directives.widget(
"additional_phone_numbers",
DataGridWidgetFactory,
allow_reorder=True,
auto_append=True)
additional_phone_numbers = DataGridField(
title=_(u"label_patient_additional_phone_numbers",
default=u"Additional Phone Numbers"),
description=_(
u"description_patient_additional_phone_numbers",
u"Additional phone numbers for this patient"),
value_type=DataGridRow(
title=u"Phone",
schema=IAdditionalPhoneNumbersSchema),
required=False,
missing_value=[],
default=[],
)

# Address
Expand Down Expand Up @@ -643,17 +614,21 @@ def getFullname(self):
parts = [self.getFirstname(), self.getMiddlename(), self.getLastname()]
return " ".join(filter(None, parts))

###
# EMAIL AND PHONE
###

@security.protected(permissions.View)
def getEmail(self):
"""Returns the email with the field accessor
"""Get email with the field accessor
"""
accessor = self.accessor("email")
value = accessor(self) or ""
return value.encode("utf-8")

@security.protected(permissions.ModifyPortalContent)
def setEmail(self, value):
"""Set email by the field accessor
"""Set email by the field mutator
"""
if not isinstance(value, string_types):
value = u""
Expand All @@ -674,6 +649,36 @@ def setAdditionalEmails(self, value):
mutator = self.mutator("additional_emails")
mutator(self, value)

@security.protected(permissions.View)
def getPhone(self):
"""Get phone by the field accessor
"""
accessor = self.accessor("phone")
return accessor(self) or ""

@security.protected(permissions.ModifyPortalContent)
def setPhone(self, value):
"""Set phone by the field mutator
"""
if not isinstance(value, string_types):
value = u""
mutator = self.mutator("phone")
mutator(self, api.safe_unicode(value.strip()))

@security.protected(permissions.View)
def getAdditionalPhoneNumbers(self):
"""Get additional phone numbers by the field accessor
"""
accessor = self.accessor("additional_phone_numbers")
return accessor(self) or []

@security.protected(permissions.ModifyPortalContent)
def setAdditionalPhoneNumbers(self, value):
"""Set additional phone numbers by the field mutator
"""
mutator = self.mutator("additional_phone_numbers")
mutator(self, value)

@security.protected(permissions.View)
def getSex(self):
"""Returns the sex with the field accessor
Expand Down
119 changes: 119 additions & 0 deletions src/senaite/patient/content/schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# -*- coding: utf-8 -*-

from plone.autoform import directives
from senaite.core.schema import PhoneField
from senaite.core.z3cform.widgets.phone import PhoneWidgetFactory
from senaite.patient import messageFactory as _
from zope import schema
from zope.interface import Interface


class IIdentifiersSchema(Interface):
"""Schema definition for identifiers field
"""
key = schema.Choice(
title=_(
u"label_patient_identifiers_key",
default=u"Type",
),
description=_(
u"description_patient_identifiers_key",
default=u"The type of identifier that holds the ID",
),
source="senaite.patient.vocabularies.identifiers",
required=True,
)

value = schema.TextLine(
title=_(
u"label_patient_identifiers_value",
default=u"ID",
),
description=_(
u"description_patient_identifiers_value",
default=u"The identification number of the selected identifier",
),
required=True,
)


class IAdditionalEmailSchema(Interface):
"""Schema definition for additional emails field
"""
name = schema.TextLine(
title=_(
u"label_patient_additional_emails_name",
default="Name"
),
description=_(
u"description_patient_additional_emails_name",
default=u"Private, Work, Other etc.",
),
required=True,
)

email = schema.TextLine(
title=_(
u"label_patient_additional_emails_email",
default=u"Email",
),
description=_(
u"description_patient_additional_emails_email",
default=u"Email address"),
required=True,
)


class IAdditionalPhoneNumbersSchema(Interface):
"""Schema definition for additional phone numbers field
"""
name = schema.TextLine(
title=_(
u"label_patient_additional_phone_numbers_name",
default="Name",
),
description=_(
u"description_patient_additional_phone_numbers_name",
default=u"Private, Work, Other etc."
),
required=True,
)

directives.widget("phone", PhoneWidgetFactory)
phone = PhoneField(
title=_(
u"label_patient_additional_phone_numbers_phone",
default=u"Phone",
),
description=_(
u"description_patient_additional_phone_numbers_phone",
default=u"Phone Number",
),
required=True,
)


class IRaceSchema(Interface):
"""Schema definition for patient race
"""
race = schema.Choice(
title=_(
u"label_patient_race",
default=u"Race",
),
source="senaite.patient.vocabularies.races",
required=False,
)


class IEthnicitySchema(Interface):
"""Schema definition for patient ethnicity
"""
ethnicity = schema.Choice(
title=_(
u"label_patient_ethnicity",
default=u"Ethnicity",
),
source="senaite.patient.vocabularies.ethnicities",
required=False,
)
2 changes: 1 addition & 1 deletion src/senaite/patient/profiles/default/metadata.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
dependencies before installing this add-on own profile.
-->
<metadata>
<version>1401</version>
<version>1402</version>

<!-- Be sure to install the following dependencies if not yet installed -->
<dependencies>
Expand Down
Loading