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

Avoid UnknownTimeZoneError when creating patient from Sample #29

Merged
merged 4 commits into from
Feb 7, 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)
------------------

- #29 Avoid UnknownTimeZoneError when creating patient from Sample
- #28 Remember age/dob selection on context
- #27 Fix cannot create samples with empty Patient ID

Expand Down
3 changes: 2 additions & 1 deletion src/senaite/patient/browser/patientfolder.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ def __init__(self, context, request):
("gender", {
"title": _("Gender"), }),
("birthdate", {
"title": _("Birthdate"), }),
"title": _("Birthdate"),
"index": "patient_birthdate"}),
))

self.review_states = [
Expand Down
1 change: 1 addition & 0 deletions src/senaite/patient/catalog/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<!-- Patient Indexes -->
<adapter name="patient_mrn" factory=".indexers.patient_mrn" />
<adapter name="patient_email" factory=".indexers.patient_email" />
<adapter name="patient_birthdate" factory=".indexers.patient_birthdate" />
<adapter name="patient_fullname" factory=".indexers.patient_fullname" />
<adapter name="patient_searchable_text" factory=".indexers.patient_searchable_text" />

Expand Down
12 changes: 10 additions & 2 deletions src/senaite/patient/catalog/indexers.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,28 @@ def patient_mrn(instance):

@indexer(IPatient)
def patient_fullname(instance):
"""Index client fullname
"""Index fullname
"""
fullname = instance.get_fullname()
return fullname


@indexer(IPatient)
def patient_email(instance):
"""Index client email
"""Index email
"""
email = instance.get_email()
return email


@indexer(IPatient)
def patient_birthdate(instance):
"""Index birthdate
"""
birthdate = instance.get_birthdate()
return birthdate


@indexer(IPatient)
def patient_searchable_text(instance):
"""Index for searchable text queries
Expand Down
1 change: 1 addition & 0 deletions src/senaite/patient/catalog/patient_catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
("patient_mrn", "", "FieldIndex"),
("patient_email", "", "FieldIndex"),
("patient_fullname", "", "FieldIndex"),
("patient_birthdate", "", "DateIndex"),
("patient_searchable_text", "", "ZCTextIndex"),
]

Expand Down
48 changes: 32 additions & 16 deletions src/senaite/patient/content/patient.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@

from six import string_types

from AccessControl import ClassSecurityInfo
from bika.lims import api
from bika.lims.api.mail import is_valid_email_address
from DateTime import DateTime
from plone.autoform import directives
from plone.dexterity.content import Container
from plone.supermodel import model
from plone.supermodel.directives import fieldset
from Products.CMFCore import permissions
from senaite.core.api import dtime
from senaite.core.schema import DatetimeField
from senaite.core.z3cform.widgets.datetimewidget import DatetimeWidget
from senaite.patient import api as patient_api
Expand Down Expand Up @@ -219,6 +221,26 @@ class Patient(Container):
"""
_catalogs = [PATIENT_CATALOG]

security = ClassSecurityInfo()

@security.private
def accessor(self, fieldname):
"""Return the field accessor for the fieldname
"""
schema = api.get_schema(self)
if fieldname not in schema:
return None
return schema[fieldname].get

@security.private
def mutator(self, fieldname):
"""Return the field mutator for the fieldname
"""
schema = api.get_schema(self)
if fieldname not in schema:
return None
return schema[fieldname].set

def Title(self):
fullname = self.get_fullname()
return fullname.encode("utf8")
Expand Down Expand Up @@ -297,22 +319,16 @@ def set_gender(self, value):
value = k
self.gender = value

@security.protected(permissions.View)
def get_birthdate(self):
if not self.birthdate:
return None
return self.birthdate
"""Returns the birthday with the field accessor
"""
accessor = self.accessor("birthdate")
return accessor(self)

@security.protected(permissions.ModifyPortalContent)
def set_birthdate(self, value):
"""Set birthdate field

Tries to convert value to datetime before set.
"""Set birthdate by the field accessor
"""
if isinstance(value, DateTime):
# convert DateTime -> datetime
value = value.asdatetime()
elif isinstance(value, string_types):
# convert string to datetime
dt = api.to_date(value, None)
if dt is not None:
value = dt.asdatetime()
self.birthdate = value
mutator = self.mutator("birthdate")
return mutator(self, value)
32 changes: 32 additions & 0 deletions src/senaite/patient/upgrade/v01_01_000.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@
# Copyright 2020-2022 by it's authors.
# Some rights reserved, see README and LICENSE.

from bika.lims import api
from senaite.core.api import dtime
from senaite.core.upgrade import upgradestep
from senaite.core.upgrade.utils import UpgradeUtils
from senaite.patient import logger
from senaite.patient.config import PATIENT_CATALOG
from senaite.patient.config import PRODUCT_NAME
from senaite.patient.setuphandlers import setup_catalogs

version = "1.1.0"

Expand All @@ -43,5 +47,33 @@ def upgrade(tool):

# -------- ADD YOUR STUFF BELOW --------

# add dateindex for birthdates
setup_catalogs(portal)

# migrate birthdates w/o time but with valid timezone
migrate_birthdates(portal)

logger.info("{0} upgraded to version {1}".format(PRODUCT_NAME, version))
return True


def migrate_birthdates(portal):
"""Migrate all birthdates from patients to be timezone aware
"""
logger.info("Migrate patient birthdate timezones ...")
catalog = api.get_tool(PATIENT_CATALOG)
results = catalog({"portal_type": "Patient"})
timezone = dtime.get_os_timezone()
for brain in results:
patient = api.get_object(brain)
birthdate = patient.birthdate
if birthdate:
# clean existing time and timezone
date = birthdate.strftime("%Y-%m-%d")
# append current OS timezone if possible
if timezone:
date = date + " %s" % timezone
patient.set_birthdate(date)
patient.reindexObject()

logger.info("Migrate patient birthdate timezones [DONE]")