Skip to content
This repository has been archived by the owner on Jan 16, 2024. It is now read-only.

Commit

Permalink
Patient listings show wrong age (#180)
Browse files Browse the repository at this point in the history
* Display current age in Patients listing

* Remove getAgeSplittedStr and getAge from Patient portal_type

* Changelog

Co-authored-by: Pau Soliva <[email protected]>
  • Loading branch information
xispa and Pau Soliva authored Apr 9, 2020
1 parent 2088e4b commit 55980f4
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 85 deletions.
2 changes: 1 addition & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ Changelog
- #163 Cannot override behavior of Patients folder when using `before_render`
- #157 Changed Base Catalog Tool


**Removed**

- #170 Removal of stale javascripts and css

**Fixed**

- #180 Fix Patient listings show wrong age
- #181 Patient historic results are not displayed
- #172 Fix sporadical errors when contacts do not have a valid email address
- #168 Cannot create Patient inside Client (content type not allowed)
Expand Down
25 changes: 16 additions & 9 deletions bika/health/browser/patients/folder_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,21 @@

import collections

from plone.app.content.browser.interfaces import IFolderContentsView
from plone.app.layout.globals.interfaces import IViewView
from zope.interface import implements

from bika.health import bikaMessageFactory as _
from bika.health.interfaces import IPatients
from bika.health.utils import get_resource_url
from bika.health.catalog import CATALOG_PATIENTS
from bika.health.interfaces import IPatients
from bika.health.permissions import AddPatient
from bika.health.utils import get_age_ymd
from bika.health.utils import get_resource_url
from bika.lims import api
from bika.lims.api import security
from bika.lims.api.security import check_permission
from bika.lims.browser.bika_listing import BikaListingView
from bika.lims.interfaces import IClient
from bika.lims.utils import get_link
from plone.app.content.browser.interfaces import IFolderContentsView
from plone.app.layout.globals.interfaces import IViewView
from zope.interface import implements
from bika.lims.api.security import check_permission


class PatientsView(BikaListingView):
Expand Down Expand Up @@ -78,7 +79,7 @@ def __init__(self, context, request):
'toggle': True,
'sortable': False}),

('getAgeSplittedStr', {
('age', {
'title': _('Age'),
'toggle': True,
'sortable': False}),
Expand Down Expand Up @@ -163,7 +164,13 @@ def folderitems(self, full_objects=False, classic=False):
return BikaListingView.folderitems(self, classic=classic)

def folderitem(self, obj, item, index):
item['getBirthDate'] = self.ulocalized_time(obj.getBirthDate)
# Date of Birth
dob = obj.getBirthDate
item['getBirthDate'] = self.ulocalized_time(dob)

# Patient's current age
item["age"] = get_age_ymd(dob)

# make the columns patient title, patient ID and client patient ID
# redirect to the Analysis Requests of the patient
ars_url = "{}/{}".format(api.get_url(obj), "analysisrequests")
Expand Down
1 change: 0 additions & 1 deletion bika/health/catalog/patient_catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
"getPrimaryReferrerUID",

# Columns without index counterpart
"getAgeSplittedStr",
"getBirthDate",
"getGender",
"getMenstrualStatus",
Expand Down
81 changes: 13 additions & 68 deletions bika/health/content/patient.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@
# Copyright 2018-2019 by it's authors.
# Some rights reserved, see README and LICENSE.

from datetime import datetime

from Products.ATContentTypes.utils import DT2dt
from Products.ATExtensions.ateapi import RecordsField
from Products.Archetypes import atapi
from Products.Archetypes.public import *
Expand All @@ -32,6 +29,7 @@
from bika.health import logger
from bika.health.config import *
from bika.health.interfaces import IPatient
from bika.health.utils import get_relative_delta
from bika.health.utils import translate_i18n as t
from bika.health.widgets import SplittedDateWidget
from bika.health.widgets.patientmenstrualstatuswidget import \
Expand Down Expand Up @@ -151,13 +149,6 @@
label=_('Age'),
),
),
ComputedField(
'AgeSplittedStr',
expression="context.getAgeSplittedStr()",
widget=ComputedWidget(
visible=False
),
),
AddressField(
'CountryState',
widget=AddressWidget(
Expand Down Expand Up @@ -923,64 +914,18 @@ def getPatientIdentifiersStr(self):
return " ".join(ids)

def getAgeSplitted(self):

if self.getBirthDate():
dob = DT2dt(self.getBirthDate()).replace(tzinfo=None)
now = datetime.today()

currentday = now.day
currentmonth = now.month
currentyear = now.year
birthday = dob.day
birthmonth = dob.month
birthyear = dob.year
ageday = currentday - birthday
agemonth = 0
ageyear = 0
months31days = [1, 3, 5, 7, 8, 10, 12]

if ageday < 0:
currentmonth -= 1
if currentmonth < 1:
currentyear -= 1
currentmonth = currentmonth + 12

dayspermonth = 30
if currentmonth in months31days:
dayspermonth = 31
elif currentmonth == 2:
dayspermonth = 28
if(currentyear % 4 == 0
and (currentyear % 100 > 0 or currentyear % 400 == 0)):
dayspermonth += 1

ageday = ageday + dayspermonth

agemonth = currentmonth - birthmonth
if agemonth < 0:
currentyear -= 1
agemonth = agemonth + 12

ageyear = currentyear - birthyear

return [{'year': ageyear,
'month': agemonth,
'day': ageday}]
else:
return [{'year': '',
'month': '',
'day': ''}]

def getAge(self):
return self.getAgeSplitted()[0]['year']

def getAgeSplittedStr(self):
splitted = self.getAgeSplitted()[0]
arr = []
arr.append(splitted['year'] and str(splitted['year']) + 'y' or '')
arr.append(splitted['month'] and str(splitted['month']) + 'm' or '')
arr.append(splitted['day'] and str(splitted['day']) + 'd' or '')
return ' '.join(arr)
"""Getter used for "AgeSplitted" schema field
"""
data = {"year": "", "month": "", "day": ""}
dob = self.getBirthDate()
if dob:
delta = get_relative_delta(dob)
data.update({
"year": delta.year,
"month": delta.month,
"day": delta.day,
})
return [data]

def getCountryState(self):
return self.getField('CountryState').get(self) \
Expand Down
31 changes: 30 additions & 1 deletion bika/health/upgrade/v01_02_003.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@
"bika_health_standard_analysis_request.css",
]

# Metadata from catalogs to remove
METADATA_TO_REMOVE = [
# AgeSplittedStr was only used in patients listing
# https://github.com/senaite/senaite.health/pull/180
(CATALOG_PATIENTS, "getAgeSplittedStr"),
]


@upgradestep(PROJECTNAME, version)
def upgrade(tool):
Expand Down Expand Up @@ -98,6 +105,9 @@ def upgrade(tool):
# https://github.com/senaite/senaite.health/pulls/172
fix_health_email_addresses(portal)

# Remove stale catalog columns
remove_stale_metadata(portal)

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

Expand Down Expand Up @@ -157,6 +167,7 @@ def fix_health_email_addresses(portal):
fix_email_address(portal, portal_types=portal_types,
catalog_id=CATALOG_PATIENTS)


def install_senaite_panic(portal):
"""Install the senaite.panic addon
"""
Expand All @@ -169,4 +180,22 @@ def install_senaite_panic(portal):
if qi.isProductInstalled(profile):
logger.info("'{}' is installed".format(profile))
return
qi.installProduct(profile)
qi.installProduct(profile)


def remove_stale_metadata(portal):
logger.info("Removing stale metadata ...")
for catalog, column in METADATA_TO_REMOVE:
del_metadata(catalog, column)
logger.info("Removing stale metadata ... [DONE]")


def del_metadata(catalog_id, column):
logger.info("Removing '{}' metadata from '{}' ..."
.format(column, catalog_id))
catalog = api.get_tool(catalog_id)
if column not in catalog.schema():
logger.info("Metadata '{}' not in catalog '{}' [SKIP]"
.format(column, catalog_id))
return
catalog.delColumn(column)
64 changes: 59 additions & 5 deletions bika/health/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,20 @@
# Copyright 2018-2019 by it's authors.
# Some rights reserved, see README and LICENSE.

from datetime import datetime

from Products.ATContentTypes.utils import DT2dt
from dateutil.relativedelta import relativedelta
from zope.i18n import translate

from bika.health import logger
from bika.health.interfaces import IPatient
from bika.lims import api
from bika.lims.api import _marker
from bika.lims.interfaces import IBatch
from bika.lims.utils import render_html_attributes, to_utf8, to_unicode
from zope.i18n import translate
from Products.Archetypes.utils import addStatusMessage

from bika.lims.utils import tmpID
from bika.lims.utils import render_html_attributes
from bika.lims.utils import to_unicode
from bika.lims.utils import to_utf8


def get_obj_from_field(instance, fieldname, default=_marker):
Expand Down Expand Up @@ -163,3 +167,53 @@ def handle_after_submit(context, request, state):
else:
status_id = "success"
return status_id


def get_age_ymd(birth_date, to_date=None):
"""Returns the age at to_date if not None. Otherwise, current age
"""
delta = get_relative_delta(birth_date, to_date)
return to_ymd(delta)


def get_relative_delta(from_date, to_date=None):
"""Returns the relative delta between two dates. If to_date is None,
compares the from_date with now
"""
from_date = to_datetime(from_date)
if not from_date:
raise TypeError("Type not supported: from_date")

to_date = to_date or datetime.now()
to_date = to_datetime(to_date)
if not to_date:
raise TypeError("Type not supported: to_date")

return relativedelta(to_date, from_date)


def to_datetime(date_value, default=None, tzinfo=None):
if isinstance(date_value, datetime):
return date_value

# Get the DateTime
date_value = api.to_date(date_value, default=None)
if not date_value:
if default is None:
return None
return to_datetime(default, tzinfo=tzinfo)

# Convert to datetime and strip
return DT2dt(date_value).replace(tzinfo=tzinfo)


def to_ymd(delta):
"""Returns a representation of a relative delta in ymd format
"""
if not isinstance(delta, relativedelta):
raise TypeError("delta parameter must be a relative_delta")

ymd = list("ymd")
diff = map(str, (delta.years, delta.months, delta.days))
age = filter(lambda it: int(it[0]), zip(diff, ymd))
return " ".join(map("".join, age))

0 comments on commit 55980f4

Please sign in to comment.