← Back to team overview

oship-dev team mailing list archive

[Branch ~oship-dev/oship/devel] Rev 532: Added Lab Request Demo

 

------------------------------------------------------------
revno: 532
committer: Tim Cook <timothywayne.cook@xxxxxxxxx>
branch nick: oship
timestamp: Thu 2011-01-27 23:13:23 -0200
message:
  Added Lab Request Demo
added:
  src/labrequest/
  src/labrequest/setup.py
  src/labrequest/src/
  src/labrequest/src/labrequest/
  src/labrequest/src/labrequest/__init__.py
  src/labrequest/src/labrequest/app.py
  src/labrequest/src/labrequest/app_templates/
  src/labrequest/src/labrequest/app_templates/cuffsize.pt
  src/labrequest/src/labrequest/app_templates/deviceinfo.pt
  src/labrequest/src/labrequest/app_templates/encounterpagetitle.pt
  src/labrequest/src/labrequest/app_templates/encounterview.pt
  src/labrequest/src/labrequest/app_templates/footertext.pt
  src/labrequest/src/labrequest/app_templates/info.pt
  src/labrequest/src/labrequest/app_templates/korotkoffsound.pt
  src/labrequest/src/labrequest/app_templates/locationofmeasurement.pt
  src/labrequest/src/labrequest/app_templates/lrmain.pt
  src/labrequest/src/labrequest/app_templates/methodofmeasuring.pt
  src/labrequest/src/labrequest/app_templates/newpatient.pt
  src/labrequest/src/labrequest/app_templates/pagetitle.pt
  src/labrequest/src/labrequest/app_templates/patientinfo.pt
  src/labrequest/src/labrequest/app_templates/patientshead.pt
  src/labrequest/src/labrequest/configure.zcml
  src/labrequest/src/labrequest/forms.py
  src/labrequest/src/labrequest/interfaces.py
  src/labrequest/src/labrequest/locales/
  src/labrequest/src/labrequest/static/
  src/labrequest/src/labrequest/static/README.txt
  src/labrequest/src/labrequest/static/css/
  src/labrequest/src/labrequest/static/css/lrmain.css
  src/labrequest/src/labrequest/tests/
  src/labrequest/src/labrequest/tests/__init__.py
  src/labrequest/src/labrequest/tests/oshipunittest.py
  src/labrequest/src/labrequest/tests/test_patient.py
modified:
  buildout.cfg
  etc/site.zcml.in
  src/oship.openehr.rm/src/oship/openehr/rm/common/archetyped/__init__.py
  src/oship.openehr.rm/src/oship/openehr/rm/datatypes/quantity/datetime/__init__.py


--
lp:oship
https://code.launchpad.net/~oship-dev/oship/devel

Your team OSHIP Development Team is subscribed to branch lp:oship.
To unsubscribe from this branch go to https://code.launchpad.net/~oship-dev/oship/devel/+edit-subscription
=== modified file 'buildout.cfg'
--- buildout.cfg	2010-12-20 19:50:27 +0000
+++ buildout.cfg	2011-01-28 01:13:23 +0000
@@ -13,6 +13,7 @@
     src/dsedemo
     src/sdmx-hd
     src/connect
+    src/labrequest
 
 parts =
     app
@@ -67,6 +68,7 @@
     dsedemo
     sdmx-hd
     connect
+    labrequest
 #    psyco
 #    uncomment above if you want psyco support(it works only for 32bit architecture).
 

=== modified file 'etc/site.zcml.in'
--- etc/site.zcml.in	2010-12-20 19:50:27 +0000
+++ etc/site.zcml.in	2011-01-28 01:13:23 +0000
@@ -6,6 +6,7 @@
   <include package="oship.openehr.rm" />
   <include package="bptrack" />
   <include package="dsedemo" />
+  <include package="labrequest" />
 
     <configure i18n_domain="oship">
 

=== added directory 'src/labrequest'
=== added file 'src/labrequest/setup.py'
--- src/labrequest/setup.py	1970-01-01 00:00:00 +0000
+++ src/labrequest/setup.py	2011-01-28 01:13:23 +0000
@@ -0,0 +1,25 @@
+from setuptools import setup, find_packages
+
+version = '0.1'
+
+setup(name='labrequest',
+      version=version,
+      description="OSHIP",
+      long_description=""" """,
+      # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=[],
+      keywords="EHR,Person,Lab Request",
+      author="OSHIP Development Team",
+      author_email="oship-dev@xxxxxxxxxxxxxxxxxxx",
+      url="http://www.oship.org";,
+      license="MPL1.1",
+      package_dir={'': 'src'},
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok',
+                        'oship.openehr.rm',
+                        'z3c.testsetup',
+                        ],
+      )

=== added directory 'src/labrequest/src'
=== added directory 'src/labrequest/src/labrequest'
=== added file 'src/labrequest/src/labrequest/__init__.py'
=== added file 'src/labrequest/src/labrequest/app.py'
--- src/labrequest/src/labrequest/app.py	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/app.py	2011-01-28 01:13:23 +0000
@@ -0,0 +1,241 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+# Copyright (c) 2007, Timothy W. Cook and Contributors. All rights reserved.
+# Redistribution and use are governed by the Mozilla Public License Version 1.1 - see docs/OSHIP-LICENSE.txt
+#
+# Use and/or redistribution of this file assumes you have read and accepted the
+# terms of the license.
+##############################################################################
+
+
+__author__  = u'Timothy Cook <timothywayne.cook@xxxxxxxxx>'
+__docformat__ = u'plaintext'
+__contributors__ = u'<name> <email address>'
+
+
+import uuid
+from datetime import datetime
+
+import grok
+from grok import index
+
+from zope.i18nmessageid import MessageFactory
+from zope.schema import TextLine,Datetime
+from zope.interface import Interface
+from oship.app import OSHIP
+from oship.openehr.rm.datatypes.text import DvText 
+from oship.openehr.rm.demographic import Person
+from oship.openehr.rm.datatypes.quantity.datetime import DvDate
+from oship.openehr.rm.data_structures.item_structure import ItemTree
+from oship.openehr.rm.data_structures.item_structure.representation import Element
+
+_ = MessageFactory('oship')
+
+
+class LabRequest(grok.Application, grok.Container):
+    pass
+
+grok.context(LabRequest)
+
+class Index(grok.View):
+
+    def render(self):
+        try:
+            self.context['demographics'] = grok.Container() # demographics space
+            self.context['clinical'] = grok.Container() # clinical space
+        except:
+            pass
+
+
+        self.redirect(self.application_url()+"/lrmain")
+
+# Main view
+class LRMain(grok.View):
+    pass
+
+
+
+# Setup Viewletmanagers
+class Header(grok.ViewletManager):
+    grok.name('header')
+
+class Patients(grok.ViewletManager):
+    grok.name('patients')
+
+class InfoArea(grok.ViewletManager):
+    grok.name('infoarea')
+
+class Footer(grok.ViewletManager):
+    grok.name('footer')
+
+# Define the viewlets
+class PageTitle(grok.Viewlet):
+    grok.viewletmanager(Header)
+    grok.order(1)
+
+class FooterText(grok.Viewlet):
+    grok.viewletmanager(Footer)
+    grok.order(1)
+
+class PatientsHead(grok.Viewlet):
+    grok.viewletmanager(Patients)
+    grok.order(1)
+
+class PatientsList(grok.Viewlet):
+    grok.viewletmanager(Patients)
+    grok.order(2)
+
+
+    def render(self):
+        """
+        Here we create the patient listing along with a URL to their record in the clinical folder that
+        points to the ehrview class so that we can list all of their previous entries as well as prepare
+        to create a new entry.
+        """
+        names = []
+        retstr = '<ul>'
+        keylist = self.context['demographics'].keys()
+        for x in keylist:
+            # create a tuple to append to the names list that also includes the ehrurl.
+            sname = self.context['demographics'][x].surName
+            gname = self.context['demographics'][x].givenName
+            dob = self.context['demographics'][x].dob
+            fname = gname+" "+sname
+            # To get the url we have to use the parent view, then strip off that name and add the clinical container
+            # and each patient's record number (ehrid). Send the full name so we can display it in the ehrview.
+            ehrurl=self.view.url().strip('/bpmain')+'/encounterview?ehrid='+self.context['demographics'][x].ehrid+'&fname='+fname+'&dob='+datetime.strftime(dob,"%Y/%m/%d")
+
+            names.append((sname,gname,ehrurl))
+
+        # create the display string to return to the interface.
+        for y in names:
+            retstr+= '<li><a href="'+y[2]+'">'+y[0]+','+y[1]+'</a> '+'</li>'
+
+        retstr+='</ul>'
+
+        if retstr == '<ul></ul>':
+            retstr = "You haven't added any patients to this system. Please use the Add patient Form."
+
+        return retstr
+
+
+
+
+class NewPatient(grok.Viewlet):
+    grok.viewletmanager(InfoArea)
+    grok.order(1)
+
+
+class Info(grok.Viewlet):
+    grok.viewletmanager(InfoArea)
+    grok.order(2)
+        
+
+
+
+#class AddPatient(grok.View):
+    #"""
+    #This view is called, as the action attribute, from the patient add form in newpatient.pt
+    #It creates a Person obj where the patient id and ehr id are created from a UUID.
+    #These are used as the unique identifiers for the records in both the demographics and clinical containers.
+    #"""
+    
+    #def render(self):
+        #patid, __name__ = unicode(uuid.uuid4())
+        #ehrid = unicode(uuid.uuid4())
+        #name = rtrim(self.request.form['surName']) + ',' + rtrim(self.request.form['givenName'])
+        #person_obj = Person(details=ItemTree(Element(DvDate(self.request.form['dob']))),
+                     #identities=PartyIdentity(details=ItemTree(items=Element(DvText(name)))))
+        
+        #self.context['demographics'][patid] = person_obj
+        #self.context['clinical'][ehrid] = Ehr()
+        #self.context['clinical'][ehrid]['created'] = datetime.now()
+        #self.context['clinical'][ehrid]['system'] = u'OSHIP'
+
+        #self.redirect(self.application_url()+"/lrmain") # now redirect to the main page
+
+#class PatientIndex(grok.Indexes):
+    #grok.site(OSHIP)
+    #grok.name('patients_catalog')
+    #surname = grok.index.Field(attribute='surName')
+
+
+#class PatientSearchResults(grok.View):
+
+    #def render(self):
+        #return "Searches are yet to be implemented"
+
+
+
+# define a simple EHR container; not using the openEHR specs
+class Ehr(grok.Container):
+    """
+    The container for each individual's clinical data.
+    """
+    pass
+
+
+
+# here is where the BP Encounter begins
+class EncounterView(grok.View):
+    grok.context( LabRequest)
+    pass
+
+
+class EncounterHeader(grok.ViewletManager):
+    grok.name('encounterheader')
+
+class BPForm(grok.ViewletManager):
+    grok.name('bpform')
+
+class EncounterFooter(grok.ViewletManager):
+    grok.name('encounterfooter')
+
+#Encounter viewlets
+class EncounterPageTitle(grok.Viewlet):
+    grok.viewletmanager(EncounterHeader)
+    grok.order(1)
+
+class PatientInfo(grok.Viewlet):
+    grok.viewletmanager(EncounterHeader)
+    grok.order(2)
+
+#we begin the viewlets for the blood pressure archetype form here
+class DeviceInfo(grok.Viewlet):
+    grok.viewletmanager(BPForm)
+    grok.order(1)
+
+class Korotkoffsound(grok.Viewlet):
+    grok.viewletmanager(BPForm)
+    grok.order(2)
+
+class MethodofMeasuring(grok.Viewlet):
+    grok.viewletmanager(BPForm)
+    grok.order(3)
+
+class LocationofMeasurement(grok.Viewlet):
+    grok.viewletmanager(BPForm)
+    grok.order(4)
+
+class CuffSize(grok.Viewlet):
+    grok.viewletmanager(BPForm)
+    grok.order(5)
+
+
+class AddBP(grok.View):
+    grok.context(LabRequest)
+    """
+    This view is called, as the action attribute, from the addbp form in the ehrindex.pt template.
+    The first thing we do is create an instance of EncounterV1, then add the instance of
+    BloodPressureV1 to the content attribute:
+    encounter=EncounterV1()
+    Get the attributes from the blood pressure input form and create the bloodpressure instance (bp)
+
+    encounter.content=bp
+
+    """
+    def render(self):
+        return "Nothing happening here yet."
+
+
+

=== added directory 'src/labrequest/src/labrequest/app_templates'
=== added file 'src/labrequest/src/labrequest/app_templates/cuffsize.pt'
--- src/labrequest/src/labrequest/app_templates/cuffsize.pt	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/app_templates/cuffsize.pt	2011-01-28 01:13:23 +0000
@@ -0,0 +1,10 @@
+<p />Cuff Size:
+<select name="cuffsize">
+<option value="at0015">Adult</option>
+<option value="at0016">Large Adult</option>
+<option value="at0017">Paediatric/Child</option>
+<option value="at1008">Adult Thigh</option>
+<option value="at1009">Neonatal</option>
+<option value="at1018">Infant</option>
+<option value="at1019">Small Adult</option>
+</select>

=== added file 'src/labrequest/src/labrequest/app_templates/deviceinfo.pt'
--- src/labrequest/src/labrequest/app_templates/deviceinfo.pt	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/app_templates/deviceinfo.pt	2011-01-28 01:13:23 +0000
@@ -0,0 +1,13 @@
+Device Information:<br />
+Serviced By:<input type="text" name="at0011" length="30" value=""  />
+Date/Time Calibrated: <input type="text" name="at0010" length="19" value="'yyyy-??-??T??:??:??'" />
+Date/Time Serviced: <input type="text" name="at0009" length="19" value="'yyyy-??-??T??:??:??'" /><br />
+Manufacturer Details:<br />
+Serial Number: <input type="text" name="at0006" length="30" value=""  />
+Model: <input type="text" name="at0005" length="30" value=""  />
+Manufacturer: <input type="text" name="at0003" length="30" value=""  />
+<br />
+Description: <input type="text" name="at0002" length="30" value=""  />
+Name: <input type="text" name="at0001" length="30" value=""  />
+
+<hr />

=== added file 'src/labrequest/src/labrequest/app_templates/encounterpagetitle.pt'
--- src/labrequest/src/labrequest/app_templates/encounterpagetitle.pt	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/app_templates/encounterpagetitle.pt	2011-01-28 01:13:23 +0000
@@ -0,0 +1,4 @@
+<h1 align="center">OSHIP BP Tracker Demo - Encounter</h1>
+<div align="right" style="color: blue; font-family: courier, fixed, monospace; "><a tal:attributes="href python:view.url('bpmain')">Return to Main Page</a></div>
+
+

=== added file 'src/labrequest/src/labrequest/app_templates/encounterview.pt'
--- src/labrequest/src/labrequest/app_templates/encounterview.pt	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/app_templates/encounterview.pt	2011-01-28 01:13:23 +0000
@@ -0,0 +1,29 @@
+<html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en"
+    xmlns:tal="http://xml.zope.org/namespaces/tal";
+    xmlns:i18n="http://xml.zope.org/namespaces/i18n";
+    lang="en"
+    i18n:domain="oship">
+<head>
+<link rel="stylesheet" type="text/css"  tal:attributes="href static/css/bpencounter.css" />
+<title>Blood Pressure Tracker EHR -- OSHIP 1.0x Demo</title>
+</head>
+
+<body>
+
+<div id="encounterheader">
+    <tal:encounterheader content="structure provider:encounterheader" />
+</div>
+
+<div id="bpform">
+    <form name="addbp" tal:attributes="action python:view.url('addbp')" method="POST">
+    <tal:bpform content="structure provider:bpform" />
+    <p />
+    <input  type="submit" name="add-bp" value="Add BP Entry" />
+</form>
+</div>
+
+<div id="encounterfooter">
+    <tal:encounterfooter content="structure provider:encounterfooter" />
+</div>
+
+</body></html>
\ No newline at end of file

=== added file 'src/labrequest/src/labrequest/app_templates/footertext.pt'
--- src/labrequest/src/labrequest/app_templates/footertext.pt	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/app_templates/footertext.pt	2011-01-28 01:13:23 +0000
@@ -0,0 +1,2 @@
+<h3 align="center"> Copyright 2009-2011, Timothy W. Cook  </h3>
+

=== added file 'src/labrequest/src/labrequest/app_templates/info.pt'
--- src/labrequest/src/labrequest/app_templates/info.pt	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/app_templates/info.pt	2011-01-28 01:13:23 +0000
@@ -0,0 +1,15 @@
+<hr size="2" width="100%" color="black" />
+<div align="center">This is a DEMO application for developers!</div>
+<hr size="2" width="100%" color="black" />
+<p>
+It is intended to demonstrate how to create applications using OSHIP based on openEHR fundamentals.<br />
+This application is not robust enough to actually use for real patient information and there are no security checks.
+</p>
+<p>
+To Use the demo:<br />
+Add a few patients and then click on a patient name.  It will open a new page for their Lab Request.
+</p>
+
+<p>
+See the project page on <a href="http://launchpad.net/oship";>Launchpad</a> for more information. 
+</p>
\ No newline at end of file

=== added file 'src/labrequest/src/labrequest/app_templates/korotkoffsound.pt'
--- src/labrequest/src/labrequest/app_templates/korotkoffsound.pt	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/app_templates/korotkoffsound.pt	2011-01-28 01:13:23 +0000
@@ -0,0 +1,5 @@
+Korotkoff Sound: 
+<select name="ksound">
+<option value="at1011">Fifth</option>
+<option value="at1012">Fourth</option>
+<br />

=== added file 'src/labrequest/src/labrequest/app_templates/locationofmeasurement.pt'
--- src/labrequest/src/labrequest/app_templates/locationofmeasurement.pt	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/app_templates/locationofmeasurement.pt	2011-01-28 01:13:23 +0000
@@ -0,0 +1,12 @@
+<p />Location of measurement:
+<select name="locationofmeasurement">
+<option value="at0025">Right arm</option>
+<option value="at0026">Left arm</option>
+<option value="at0027">Right thigh</option>
+<option value="at0028">Left thigh</option>
+<option value="at1020">Right wrist</option>
+<option value="at1021">Left wrist</option>
+<option value="at1026">Finger</option>
+<option value="at1031">Right ankle</option>
+<option value="at1032">Left ankle</option>
+</select>
\ No newline at end of file

=== added file 'src/labrequest/src/labrequest/app_templates/lrmain.pt'
--- src/labrequest/src/labrequest/app_templates/lrmain.pt	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/app_templates/lrmain.pt	2011-01-28 01:13:23 +0000
@@ -0,0 +1,29 @@
+<html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en"
+    xmlns:tal="http://xml.zope.org/namespaces/tal";
+    xmlns:i18n="http://xml.zope.org/namespaces/i18n";
+    lang="en"
+    i18n:domain="oship">
+<head>
+<link rel="stylesheet" type="text/css"  tal:attributes="href static/css/lrmain.css" />
+<title>Lab Request Demo</title>
+</head>
+
+<body>
+<div id="header">
+    <tal:header content="structure provider:header" />
+</div>
+
+<div id="infoarea">
+   <tal:infoarea content="structure provider:infoarea" />
+</div>
+
+<div id="patients">
+   <tal:patients content="structure provider:patients" />
+</div>
+
+
+<div id="footer">
+    <tal:footer content="structure provider:footer" />
+</div>
+
+</body></html>
\ No newline at end of file

=== added file 'src/labrequest/src/labrequest/app_templates/methodofmeasuring.pt'
--- src/labrequest/src/labrequest/app_templates/methodofmeasuring.pt	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/app_templates/methodofmeasuring.pt	2011-01-28 01:13:23 +0000
@@ -0,0 +1,7 @@
+<p />Method of measuring:
+<select name="methodofmeasuring">
+<option value="at1040">Invasive</option>
+<option value="at1039">Machine</option>
+<option value="at1037">Palpation</option>
+<option value="at1036">Auscultation</option>
+</select>
\ No newline at end of file

=== added file 'src/labrequest/src/labrequest/app_templates/newpatient.pt'
--- src/labrequest/src/labrequest/app_templates/newpatient.pt	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/app_templates/newpatient.pt	2011-01-28 01:13:23 +0000
@@ -0,0 +1,14 @@
+<form tal:attributes="action python:view.url('addpatient')" method="POST">
+<table border="2" width="100%" >
+<caption><strong><span style="font-size: larger;">Add a New Patient</span></strong></caption>
+<th>Surname</th><th>Given Name</th><th>Date of Birth</th>
+
+<tr>
+<td><input type="text" name="surName" size="35"  /></td>
+<td><input type="text" name="givenName" size="35" /></td>
+<td><input type="text" name="dob" size="10" value="yyyy/mm/dd" /></td>
+</tr>
+
+</table>
+<input  type="submit" name="addpatient" value="Add Patient" />
+</form>

=== added file 'src/labrequest/src/labrequest/app_templates/pagetitle.pt'
--- src/labrequest/src/labrequest/app_templates/pagetitle.pt	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/app_templates/pagetitle.pt	2011-01-28 01:13:23 +0000
@@ -0,0 +1,3 @@
+<h1 align="center">OSHIP Lab Request Demo</h1>
+
+

=== added file 'src/labrequest/src/labrequest/app_templates/patientinfo.pt'
--- src/labrequest/src/labrequest/app_templates/patientinfo.pt	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/app_templates/patientinfo.pt	2011-01-28 01:13:23 +0000
@@ -0,0 +1,5 @@
+<div id="patientinfo" align="center">
+Name: <span tal:content="python:request['fname']">Full Name</span>
+&nbsp;&nbsp;&nbsp;DOB:  <span tal:content="python:request['dob']">Date of Birth</span>
+</div>
+

=== added file 'src/labrequest/src/labrequest/app_templates/patientshead.pt'
--- src/labrequest/src/labrequest/app_templates/patientshead.pt	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/app_templates/patientshead.pt	2011-01-28 01:13:23 +0000
@@ -0,0 +1,8 @@
+<b align="center">Patient List</b><br />
+Search:
+<form action="." tal:attributes="action request/URL" method="post"
+      class="edit-form" enctype="multipart/form-data">
+      <input type="text" name="search" value="Enter a Surname" size="15">
+      <input type="submit" name="search-submit" value=">>">
+</form>
+

=== added file 'src/labrequest/src/labrequest/configure.zcml'
--- src/labrequest/src/labrequest/configure.zcml	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/configure.zcml	2011-01-28 01:13:23 +0000
@@ -0,0 +1,8 @@
+<configure xmlns="http://namespaces.zope.org/zope";
+           xmlns:i18n="http://namespaces.zope.org/i18n";
+           xmlns:grok="http://namespaces.zope.org/grok";>
+  <include package="grok" />
+  <includeDependencies package="."/>
+  <grok:grok package="." />
+  <i18n:registerTranslations directory="locales"/>
+</configure>

=== added file 'src/labrequest/src/labrequest/forms.py'
--- src/labrequest/src/labrequest/forms.py	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/forms.py	2011-01-28 01:13:23 +0000
@@ -0,0 +1,14 @@
+import grok
+from interfaces import IPatient
+from app import LabRequest
+
+
+class AddPatient(grok.AddForm):
+
+    grok.context(LabRequest)
+    form_fields = grok.AutoFields(IPatient)
+
+    @grok.action(u"Add Patient")
+    def add_patient(self, **data):
+        person = Person(**data)
+        self.context['person1'] = person

=== added file 'src/labrequest/src/labrequest/interfaces.py'
--- src/labrequest/src/labrequest/interfaces.py	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/interfaces.py	2011-01-28 01:13:23 +0000
@@ -0,0 +1,13 @@
+
+from oship.openehr.rm.demographic.interfaces import IPerson
+
+from zope.interface import invariant
+from zope import schema
+
+class IPatient(IPerson):
+
+    @invariant
+    def the_archetype_node_must_be_correct(obj):
+        assert obj.archetype_node_id == 'at0000'
+
+

=== added directory 'src/labrequest/src/labrequest/locales'
=== added directory 'src/labrequest/src/labrequest/static'
=== added file 'src/labrequest/src/labrequest/static/README.txt'
--- src/labrequest/src/labrequest/static/README.txt	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/static/README.txt	2011-01-28 01:13:23 +0000
@@ -0,0 +1,2 @@
+Put static files here, like javascript and css.  They will be
+available as static/<filename> in views.

=== added directory 'src/labrequest/src/labrequest/static/css'
=== added file 'src/labrequest/src/labrequest/static/css/lrmain.css'
--- src/labrequest/src/labrequest/static/css/lrmain.css	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/static/css/lrmain.css	2011-01-28 01:13:23 +0000
@@ -0,0 +1,4 @@
+#header { background-color: #F5F5F5; font-size:50%;color:#006400;height:5%;width:100%;padding:2px}
+#patients { background-color:#F5F5F5; color:#006400; height:80%; width:20%;padding:4px}
+#infoarea { background-color:#DFDFDF;float: right;height:80%; width:79%;padding:2px}
+#footer { background-color: #F5F5F5; font-size:30%;color:#006400; height:5%;width:100%;padding:2px}

=== added directory 'src/labrequest/src/labrequest/tests'
=== added file 'src/labrequest/src/labrequest/tests/__init__.py'
=== added file 'src/labrequest/src/labrequest/tests/oshipunittest.py'
--- src/labrequest/src/labrequest/tests/oshipunittest.py	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/tests/oshipunittest.py	2011-01-28 01:13:23 +0000
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+
+
+import unittest
+
+class TestCaseException(unittest.TestCase):
+    def assertNotRaises(self, exceptions, function, *args, **kw):
+        if not isinstance(exceptions, tuple):
+            exceptions = (exceptions, )
+        try:
+            function(*args, **kw)
+        except exceptions, error:
+            self.fail("Raised exception %s " % error)
+        return True
+
+def expectedFail(func):
+    def wrapper(self, *args, **kw):
+        old_fail = self.fail
+        self._failed = False
+        def fail(message=""):
+            self._failed = True
+        self.fail = fail
+        
+        result = func(self, *args, **kw)
+        
+        self.fail = old_fail
+        if not self._failed:
+            self.fail("Test did not fail")
+        del self._failed
+        return result
+    return wrapper
+
+if __name__ == "__main__":
+    #Not needed in Python 2.7
+
+        
+    class SelfTest(TestCaseException):
+        def test_not_raises(self):
+            def bla(): pass
+            self.assertNotRaises(ZeroDivisionError, bla)
+        @expectedFail
+        def test_raises(self):
+            def bla(): 1 / 0
+            self.assertNotRaises(ZeroDivisionError, bla)
+            
+    unittest.main()
+    
\ No newline at end of file

=== added file 'src/labrequest/src/labrequest/tests/test_patient.py'
--- src/labrequest/src/labrequest/tests/test_patient.py	1970-01-01 00:00:00 +0000
+++ src/labrequest/src/labrequest/tests/test_patient.py	2011-01-28 01:13:23 +0000
@@ -0,0 +1,129 @@
+# -*- coding: utf-8 -*-
+import unittest
+import oshipunittest
+import json
+"""
+Test-layer: python
+"""
+
+from labrequest.app import Patient, BirthDateElement, ItemTreeBirthDate,\
+                           PatientIdentity, PatientDetails, PatientDetailsElement
+from oship.openehr.rm.datatypes.quantity.datetime import DvDate
+from oship.openehr.rm.datatypes.text import DvText
+from labrequest.app import build_object
+
+class PatientTestCase(oshipunittest.TestCaseException):
+   
+   
+    def create_person(self):
+        date_obj  = DvDate(value='2011-01-12',
+                           magnitude = None,
+                           accuracy = None,
+                           normalRange = None,
+                           otherReferenceRanges = None,
+                           normalStatus = None )
+        element_obj = BirthDateElement(name='birth date',
+                                       value=date_obj)
+        item_tree  = ItemTreeBirthDate(name = '',
+                                       items = [element_obj])
+        element = PatientDetailsElement(name="detailselement01", value = DvText("Fulano"))
+        details = PatientDetails(name="details01", items=[element])
+        identity = PatientIdentity(details=details)
+        
+        return Patient(name='patient01', details=item_tree, identities=[identity])
+        
+    def test_serialize_reverse_patient_details(self):
+        element = PatientDetailsElement(name="detailselement01", value = DvText("Fulano"))
+        details = PatientDetails(name="details01", items=[element])
+        json_data = details.marshall()
+        built = build_object(json_data)
+        self.assertEquals(built.items[0].value.value, "Fulano")
+        
+    def test_creating_a_patient_instance(self):
+        date_obj  = DvDate(value='2011-01-12',
+                           magnitude = None,
+                           accuracy = None,
+                           normalRange = None,
+                           otherReferenceRanges = None,
+                           normalStatus = None )
+        element_obj = BirthDateElement(name='birth date',
+                                       value=date_obj)
+        item_tree  = ItemTreeBirthDate(name = '',
+                                       items = [element_obj])
+        element = PatientDetailsElement(name="detailselement01", value = DvText("Fulano"))
+        details = PatientDetails(name="details01", items=[element])
+        identity = PatientIdentity(details=details)
+        def create_patient_obj():
+            patient_obj = Patient(name='patient01', details=item_tree, identities=[identity])
+        self.assertNotRaises(AssertionError, create_patient_obj)
+        
+    
+    def test_creating_patient_identity(self):
+        element = PatientDetailsElement(name="detailselement01", value = DvText("Fulano"))
+        details = PatientDetails(name="details01", items=[element])
+        identity = PatientIdentity(details=details)
+        self.assertEquals(identity.archetypeNodeId, "at0002")
+    
+    def test_creating_patient_identity_fail(self):
+        self.assertRaises((AssertionError, TypeError, AttributeError), PatientIdentity, details=object())
+    
+    def test_creating_patient_details(self):
+        element = PatientDetailsElement(name="detailselement01", value = DvText("Fulano"))
+        details = PatientDetails(name="details01", items=[element])
+        
+    def test_creating_patient_details_fail(self):
+        element = PatientDetailsElement(name="detailselement01", value = DvText("Fulano"))
+        self.assertRaises((AssertionError, TypeError, AttributeError), PatientDetails, name="details01", items=["bla"])
+    
+    def test_creating_patient_details_element(self):
+        element = PatientDetailsElement(name="detailselement01", value = DvText("Fulano"))
+        self.assertEquals(element.archetypeNodeId, "at0030")
+        
+    def test_creating_patient_details_element_fail(self):
+        self.assertRaises((AssertionError, TypeError),PatientDetailsElement,
+                           name="detailelement01", value = "Fulano")
+
+    def test_if_doesnt_accept_a_different_object(self):
+        def generate_a_wrong_patient_object():
+            patient_obj = Patient(name='patient01', details = object())
+        self.assertRaises(TypeError, generate_a_wrong_patient_object)
+
+
+    def test_creating_a_Birthdate_element(self):
+        date_obj  = DvDate(value='2011-01-12',  
+                           magnitude = None,
+                           accuracy = None,
+                           normalRange = None,
+                           otherReferenceRanges = None,
+                           normalStatus = None )
+        def generate_a_date_element():
+            obj = BirthDateElement(name=' ',
+                            value=date_obj)
+                          
+        self.assertNotRaises(TypeError, generate_a_date_element)
+
+    def test_creating_a_wrong_birthdate_element(self):
+        def generate_a_wrong_element():
+            obj = BirthDateElement(name=' ',
+                            value=object())
+        self.assertRaises(AssertionError,generate_a_wrong_element)
+
+
+
+    def test_creating_a_wrong_item_tree_birth_date(self):
+        def generate_a_wrong_item_tree(items):
+            item_tree  = ItemTreeBirthDate(name = '',
+                                       items = items)
+        self.assertRaises(AssertionError,generate_a_wrong_item_tree,[object(),object()])
+        date_obj  = DvDate(value='2011-01-12',  
+                           magnitude = None,
+                           accuracy = None,
+                           normalRange = None,
+                           otherReferenceRanges = None,
+                           normalStatus = None )
+        element_obj = BirthDateElement(name='birth date',
+                                       value=date_obj)
+        self.assertRaises(AssertionError,generate_a_wrong_item_tree,[element_obj,object()])
+        self.assertRaises(AssertionError,generate_a_wrong_item_tree,[object(),element_obj])
+if __name__ == '__main__':
+    unittest.main()

=== modified file 'src/oship.openehr.rm/src/oship/openehr/rm/common/archetyped/__init__.py'
--- src/oship.openehr.rm/src/oship/openehr/rm/common/archetyped/__init__.py	2010-11-15 02:52:48 +0000
+++ src/oship.openehr.rm/src/oship/openehr/rm/common/archetyped/__init__.py	2011-01-28 01:13:23 +0000
@@ -7,7 +7,7 @@
 from interfaces import *
 
 
-class Pathable(grok.Model):
+class Pathable(grok.Container):
     """
     Abstract parent of all classes whose instances are reachable by paths, and
     which know how to locate child object by paths. The parent feature may be

=== modified file 'src/oship.openehr.rm/src/oship/openehr/rm/datatypes/quantity/datetime/__init__.py'
--- src/oship.openehr.rm/src/oship/openehr/rm/datatypes/quantity/datetime/__init__.py	2010-10-10 00:28:33 +0000
+++ src/oship.openehr.rm/src/oship/openehr/rm/datatypes/quantity/datetime/__init__.py	2011-01-28 01:13:23 +0000
@@ -245,11 +245,11 @@
         return False
 
     def __neg__(self):
-         new_obj = copy.copy(self)
-         if new_obj.sign == '+':
-             new_obj.sign = '-'
-         else: new_obj.sign = '+'
-         return new_obj
+        new_obj = copy.copy(self)
+        if new_obj.sign == '+':
+            new_obj.sign = '-'
+        else: new_obj.sign = '+'
+        return new_obj
 
     def __str__(self):
         return self.value