1 """GNUmed demographics object.
2
3 This is a patient object intended to let a useful client-side
4 API crystallize from actual use in true XP fashion.
5
6 license: GPL v2 or later
7 """
8
9 __version__ = "$Revision: 1.106 $"
10 __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>, I.Haywood <ihaywood@gnu.org>"
11
12
13 import sys
14 import os
15 import os.path
16 import logging
17
18
19
20 if __name__ == '__main__':
21 sys.path.insert(0, '../../')
22 from Gnumed.pycommon import gmDispatcher
23 from Gnumed.pycommon import gmBusinessDBObject
24 from Gnumed.pycommon import gmPG2
25 from Gnumed.pycommon import gmTools
26
27
28 _log = logging.getLogger('gm.business')
29 _log.info(__version__)
30
31
32
33
34 _SQL_get_tag_image = u"SELECT * FROM ref.v_tag_images_no_data WHERE %s"
35
36 -class cTagImage(gmBusinessDBObject.cBusinessDBObject):
37
38 _cmd_fetch_payload = _SQL_get_tag_image % u"pk_tag_image = %s"
39 _cmds_store_payload = [
40 u"""
41 UPDATE ref.tag_image SET
42 description = gm.nullify_empty_string(%(description)s),
43 filename = gm.nullify_empty_string(%(filename)s)
44 WHERE
45 pk = %(pk_tag_image)s
46 AND
47 xmin = %(xmin_tag_image)s
48 RETURNING
49 pk as pk_tag_image,
50 xmin as xmin_tag_image
51 """
52 ]
53 _updatable_fields = [u'description', u'filename']
54
56
57 if self._payload[self._idx['size']] == 0:
58 return None
59
60 if filename is None:
61 suffix = None
62
63 if self._payload[self._idx['filename']] is not None:
64 name, suffix = os.path.splitext(self._payload[self._idx['filename']])
65 suffix = suffix.strip()
66 if suffix == u'':
67 suffix = None
68
69 filename = gmTools.get_unique_filename (
70 prefix = 'gm-tag_image-',
71 suffix = suffix
72 )
73
74 success = gmPG2.bytea2file (
75 data_query = {
76 'cmd': u'SELECT substring(image from %(start)s for %(size)s) FROM ref.tag_image WHERE pk = %(pk)s',
77 'args': {'pk': self.pk_obj}
78 },
79 filename = filename,
80 chunk_size = aChunkSize,
81 data_size = self._payload[self._idx['size']]
82 )
83
84 if success:
85 return filename
86
87 return None
88
104
106 if order_by is None:
107 order_by = u'true'
108 else:
109 order_by = 'true ORDER BY %s' % order_by
110
111 cmd = _SQL_get_tag_image % order_by
112 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = True)
113 return [ cTagImage(row = {'data': r, 'idx': idx, 'pk_field': 'pk_tag_image'}) for r in rows ]
114
116
117 args = {u'desc': description, u'img': u''}
118 cmd = u"""
119 INSERT INTO ref.tag_image (
120 description,
121 image
122 ) VALUES (
123 %(desc)s,
124 %(img)s::bytea
125 )
126 RETURNING pk
127 """
128 rows, idx = gmPG2.run_rw_queries (
129 link_obj = link_obj,
130 queries = [{'cmd': cmd, 'args': args}],
131 end_tx = True,
132 return_data = True,
133 get_col_idx = False
134 )
135
136 return cTagImage(aPK_obj = rows[0]['pk'])
137
139 args = {'pk': tag_image}
140 cmd = u"""
141 DELETE FROM ref.tag_image
142 WHERE
143 pk = %(pk)s
144 AND
145 NOT EXISTS (
146 SELECT 1
147 FROM dem.identity_tag
148 WHERE fk_tag = %(pk)s
149 LIMIT 1
150 )
151 RETURNING 1
152 """
153 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True)
154 if len(rows) == 0:
155 return False
156 return True
157
158
159 _SQL_get_identity_tags = u"""SELECT * FROM dem.v_identity_tags WHERE %s"""
160
162
163 _cmd_fetch_payload = _SQL_get_identity_tags % u"pk_identity_tag = %s"
164 _cmds_store_payload = [
165 u"""
166 UPDATE dem.identity_tag SET
167 fk_tag = %(pk_tag_image)s,
168 comment = gm.nullify_empty_string(%(comment)s)
169 WHERE
170 pk = %(pk_identity_tag)s
171 AND
172 xmin = %(xmin_identity_tag)s
173 RETURNING
174 pk as pk_identity_tag,
175 xmin as xmin_identity_tag
176 """
177 ]
178 _updatable_fields = [u'fk_tag', u'comment']
179
181
182 if self._payload[self._idx['image_size']] == 0:
183 return None
184
185 if filename is None:
186 suffix = None
187
188 if self._payload[self._idx['filename']] is not None:
189 name, suffix = os.path.splitext(self._payload[self._idx['filename']])
190 suffix = suffix.strip()
191 if suffix == u'':
192 suffix = None
193
194 filename = gmTools.get_unique_filename (
195 prefix = 'gm-identity_tag-',
196 suffix = suffix
197 )
198
199 exported = gmPG2.bytea2file (
200 data_query = {
201 'cmd': u'SELECT substring(image from %(start)s for %(size)s) FROM ref.tag_image WHERE pk = %(pk)s',
202 'args': {'pk': self._payload[self._idx['pk_tag_image']]}
203 },
204 filename = filename,
205 chunk_size = aChunkSize,
206 data_size = self._payload[self._idx['image_size']]
207 )
208 if exported:
209 return filename
210
211 return None
212
213
215 cmd = u"""
216 select
217 _(name) as l10n_country, name, code, deprecated
218 from dem.country
219 order by l10n_country"""
220 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}])
221 return rows
222
224 cmd = u"""
225 SELECT code_country, l10n_country FROM dem.v_state WHERE l10n_state = %(region)s
226 union
227 SELECT code_country, l10n_country FROM dem.v_state WHERE state = %(region)s
228 """
229 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': {'region': region}}])
230 return rows
231
233
234 args = {'prov': province}
235
236 queries = []
237 if delete_urbs:
238 queries.append ({
239 'cmd': u"""
240 delete from dem.urb du
241 where
242 du.id_state = %(prov)s
243 and
244 not exists (select 1 from dem.street ds where ds.id_urb = du.id)""",
245 'args': args
246 })
247
248 queries.append ({
249 'cmd': u"""
250 delete from dem.state ds
251 where
252 ds.id = %(prov)s
253 and
254 not exists (select 1 from dem.urb du where du.id_state = ds.id)""",
255 'args': args
256 })
257
258 gmPG2.run_rw_queries(queries = queries)
259
260 return True
261
263
264 args = {'code': code, 'country': country, 'name': name}
265
266 cmd = u"""SELECT EXISTS (SELECT 1 FROM dem.state WHERE name = %(name)s)"""
267 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
268
269 if rows[0][0]:
270 return
271
272 cmd = u"""
273 INSERT INTO dem.state (
274 code, country, name
275 ) VALUES (
276 %(code)s, %(country)s, %(name)s
277 )"""
278 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
279
281 cmd = u"""
282 select
283 l10n_state, l10n_country, state, code_state, code_country, pk_state, country_deprecated
284 from dem.v_state
285 order by l10n_country, l10n_state"""
286 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}])
287 return rows
288
289
290
291 -class cAddress(gmBusinessDBObject.cBusinessDBObject):
292 """A class representing an address as an entity in itself.
293
294 We consider addresses to be self-complete "labels" for locations.
295 It does not depend on any people potentially living there. Thus
296 an address can get attached to as many people as we want to
297 signify that that is their place of residence/work/...
298
299 This class acts on the address as an entity. Therefore it can
300 modify the address fields. Think carefully about *modifying*
301 addresses attached to people, though. Most times when you think
302 person.modify_address() what you *really* want is as sequence of
303 person.unlink_address(old) and person.link_address(new).
304
305 Modifying an address may or may not be the proper thing to do as
306 it will transparently modify the address for *all* the people to
307 whom it is attached. In many cases you will want to create a *new*
308 address and link it to a person instead of the old address.
309 """
310 _cmd_fetch_payload = u"select * from dem.v_address where pk_address=%s"
311 _cmds_store_payload = [
312 u"""UPDATE dem.address SET
313 aux_street = %(notes_street)s,
314 subunit = %(subunit)s,
315 addendum = %(notes_subunit)s,
316 lat_lon = %(lat_lon_street)s
317 WHERE id = %(pk_address)s AND xmin = %(xmin_address)s""",
318 u"select xmin as xmin_address from dem.address where id=%(pk_address)s"
319 ]
320 _updatable_fields = ['notes_street', 'subunit', 'notes_subunit', 'lat_lon_address']
321
322 -def address_exists(country=None, state=None, urb=None, suburb=None, postcode=None, street=None, number=None, subunit=None, notes_street=None, notes_subunit=None):
323
324 where_parts = [u"""
325 code_country = %(country)s and
326 code_state = %(state)s and
327 urb = %(urb)s and
328 postcode = %(postcode)s and
329 street = %(street)s and
330 number = %(number)s"""
331 ]
332
333 if suburb is None:
334 where_parts.append(u"suburb is %(suburb)s")
335 else:
336 where_parts.append(u"suburb = %(suburb)s")
337
338 if notes_street is None:
339 where_parts.append(u"notes_street is %(notes_street)s")
340 else:
341 where_parts.append(u"notes_street = %(notes_street)s")
342
343 if subunit is None:
344 where_parts.append(u"subunit is %(subunit)s")
345 else:
346 where_parts.append(u"subunit = %(subunit)s")
347
348 if notes_subunit is None:
349 where_parts.append(u"notes_subunit is %(notes_subunit)s")
350 else:
351 where_parts.append(u"notes_subunit = %(notes_subunit)s")
352
353 cmd = u"select pk_address from dem.v_address where %s" % u" and ".join(where_parts)
354 data = {
355 'country': country,
356 'state': state,
357 'urb': urb,
358 'suburb': suburb,
359 'postcode': postcode,
360 'street': street,
361 'notes_street': notes_street,
362 'number': number,
363 'subunit': subunit,
364 'notes_subunit': notes_subunit
365 }
366
367 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': data}])
368
369 if len(rows) == 0:
370 return None
371 return rows[0][0]
372
373 -def create_address(country=None, state=None, urb=None, suburb=None, postcode=None, street=None, number=None, subunit=None):
374
375 if suburb is not None:
376 suburb = gmTools.none_if(suburb.strip(), u'')
377
378 pk_address = address_exists (
379 country = country,
380 state = state,
381 urb = urb,
382 suburb = suburb,
383 postcode = postcode,
384 street = street,
385 number = number,
386 subunit = subunit
387 )
388 if pk_address is not None:
389 return cAddress(aPK_obj=pk_address)
390
391 cmd = u"""
392 select dem.create_address (
393 %(number)s,
394 %(street)s,
395 %(postcode)s,
396 %(urb)s,
397 %(state)s,
398 %(country)s,
399 %(subunit)s
400 )"""
401 args = {
402 'number': number,
403 'street': street,
404 'postcode': postcode,
405 'urb': urb,
406 'state': state,
407 'country': country,
408 'subunit': subunit
409 }
410 queries = [{'cmd': cmd, 'args': args}]
411
412 rows, idx = gmPG2.run_rw_queries(queries = queries, return_data = True)
413 adr = cAddress(aPK_obj=rows[0][0])
414
415 if suburb is not None:
416 queries = [{
417
418 'cmd': u"update dem.street set suburb = %(suburb)s where id=%(pk_street)s and suburb is Null",
419 'args': {'suburb': suburb, 'pk_street': adr['pk_street']}
420 }]
421 rows, idx = gmPG2.run_rw_queries(queries = queries)
422
423 return adr
424
426 cmd = u"delete from dem.address where id=%s"
427 rows, idx = gmPG2.run_rw_queries(queries=[{'cmd': cmd, 'args': [address['pk_address']]}])
428 return True
429
431 cmd = u'select id as pk, name, _(name) as l10n_name from dem.address_type'
432 rows, idx = gmPG2.run_rw_queries(queries=[{'cmd': cmd}])
433 return rows
434
436
437 if order_by is None:
438 order_by = u''
439 else:
440 order_by = u'ORDER BY %s' % order_by
441
442 cmd = u"SELECT * FROM dem.v_address %s" % order_by
443 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = True)
444 return [ cAddress(row = {'data': r, 'idx': idx, 'pk_field': u'pk_address'}) for r in rows ]
445
446
448
449 _cmd_fetch_payload = u"SELECT * FROM dem.v_pat_addresses WHERE pk_address = %s"
450 _cmds_store_payload = [
451 u"""UPDATE dem.lnk_person_org_address SET
452 id_type = %(pk_address_type)s
453 WHERE
454 id = %(pk_lnk_person_org_address)s
455 AND
456 xmin = %(xmin_lnk_person_org_address)s
457 RETURNING
458 xmin AS xmin_lnk_person_org_address
459 """
460
461 ]
462 _updatable_fields = ['pk_address_type']
463
466
467
468
470
471 _cmd_fetch_payload = u"SELECT * FROM dem.v_person_comms WHERE pk_lnk_identity2comm = %s"
472 _cmds_store_payload = [
473 u"""UPDATE dem.lnk_identity2comm SET
474 fk_address = %(pk_address)s,
475 fk_type = dem.create_comm_type(%(comm_type)s),
476 url = %(url)s,
477 is_confidential = %(is_confidential)s
478 WHERE
479 pk = %(pk_lnk_identity2comm)s
480 AND
481 xmin = %(xmin_lnk_identity2comm)s
482 RETURNING
483 xmin AS xmin_lnk_identity2comm
484 """
485 ]
486 _updatable_fields = [
487 'pk_address',
488 'url',
489 'comm_type',
490 'is_confidential'
491 ]
492
493 -def create_comm_channel(comm_medium=None, url=None, is_confidential=False, pk_channel_type=None, pk_identity=None):
494 """Create a communications channel for a patient."""
495
496 if url is None:
497 return None
498
499 args = {'pat': pk_identity, 'url': url, 'secret': is_confidential}
500
501 if pk_channel_type is None:
502 args['type'] = comm_medium
503 cmd = u"""insert into dem.lnk_identity2comm (
504 fk_identity,
505 url,
506 fk_type,
507 is_confidential
508 ) values (
509 %(pat)s,
510 %(url)s,
511 dem.create_comm_type(%(type)s),
512 %(secret)s
513 )"""
514 else:
515 args['type'] = pk_channel_type
516 cmd = u"""insert into dem.lnk_identity2comm (
517 fk_identity,
518 url,
519 fk_type,
520 is_confidential
521 ) values (
522 %(pat)s,
523 %(url)s,
524 %(type)s,
525 %(secret)s
526 )"""
527
528 rows, idx = gmPG2.run_rw_queries (
529 queries = [
530 {'cmd': cmd, 'args': args},
531 {'cmd': u"select * from dem.v_person_comms where pk_lnk_identity2comm = currval(pg_get_serial_sequence('dem.lnk_identity2comm', 'pk'))"}
532 ],
533 return_data = True,
534 get_col_idx = True
535 )
536
537 return cCommChannel(row = {'pk_field': 'pk_lnk_identity2comm', 'data': rows[0], 'idx': idx})
538
540 cmd = u"DELETE FROM dem.lnk_identity2comm WHERE pk = %(pk)s AND fk_identity = %(pat)s"
541 args = {'pk': pk, 'pat': pk_patient}
542 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
543
545 cmd = u"SELECT pk, _(description) AS l10n_description, description FROM dem.enum_comm_types"
546 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = False)
547 return rows
548
550 cmd = u"""
551 DELETE FROM dem.enum_comm_types
552 WHERE
553 pk = %(pk)s
554 AND NOT EXISTS (
555 SELECT 1 FROM dem.lnk_identity2comm WHERE fk_type = %(pk)s
556 )
557 AND NOT EXISTS (
558 SELECT 1 FROM dem.lnk_org_unit2comm WHERE fk_type = %(pk)s
559 )
560 """
561 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': {'pk': pk_channel_type}}])
562 return True
563
564
565
566 -class cOrg (gmBusinessDBObject.cBusinessDBObject):
567 """
568 Organisations
569
570 This is also the common ancestor of cIdentity, self._table is used to
571 hide the difference.
572 The aim is to be able to sanely write code which doesn't care whether
573 its talking to an organisation or an individual"""
574 _table = "org"
575
576 _cmd_fetch_payload = "select *, xmin from dem.org where id=%s"
577 _cmds_lock_rows_for_update = ["select 1 from dem.org where id=%(id)s and xmin=%(xmin)s"]
578 _cmds_store_payload = [
579 """update dem.org set
580 description=%(description)s,
581 id_category=(select id from dem.org_category where description=%(occupation)s)
582 where id=%(id)s""",
583 "select xmin from dem.org where id=%(id)s"
584 ]
585 _updatable_fields = ["description", "occupation"]
586 _service = 'personalia'
587
590
592 if not self.__cache.has_key ('addresses'):
593 self['addresses']
594 if not self.__cache.has_key ('comms'):
595 self['comms']
596 return self.__cache
597
599 """
600 Returns a list of (address dict, cIdentity) tuples
601 """
602 cmd = """select
603 vba.id,
604 vba.number,
605 vba.addendum,
606 vba.street,
607 vba.urb,
608 vba.postcode,
609 at.name,
610 lpoa.id_type,
611 vbp.pk_identity,
612 title,
613 firstnames,
614 lastnames,
615 dob,
616 cob,
617 gender,
618 pupic,
619 pk_marital_status,
620 marital_status,
621 karyotype,
622 xmin_identity,
623 preferred
624 from
625 dem.v_basic_address vba,
626 dem.lnk_person_org_address lpoa,
627 dem.address_type at,
628 dem.v_basic_person vbp
629 where
630 lpoa.id_address = vba.id
631 and lpoa.id_type = at.id
632 and lpoa.id_identity = vbp.pk_identity
633 and lpoa.id_org = %%s
634 """
635
636 rows, idx = gmPG.run_ro_query('personalia', cmd, 1, self.getId ())
637 if rows is None:
638 return []
639 elif len(rows) == 0:
640 return []
641 else:
642 return [({'pk':i[0], 'number':i[1], 'addendum':i[2], 'street':i[3], 'city':i[4], 'postcode':i[5], 'type':i[6], 'id_type':i[7]}, cIdentity (row = {'data':i[8:], 'id':idx[8:], 'pk_field':'id'})) for i in rows]
643
645 """
646 Binds a person to this organisation at this address.
647 person is a cIdentity object
648 address is a dict of {'number', 'street', 'addendum', 'city', 'postcode', 'type'}
649 type is one of the IDs returned by getAddressTypes
650 """
651 cmd = "insert into dem.lnk_person_org_address (id_type, id_address, id_org, id_identity) values (%(type)s, dem.create_address (%(number)s, %(addendum)s, %(street)s, %(city)s, %(postcode)s), %(org_id)s, %(pk_identity)s)"
652 address['pk_identity'] = person['pk_identity']
653 address['org_id'] = self.getId()
654 if not id_addr:
655 return (False, None)
656 return gmPG.run_commit2 ('personalia', [(cmd, [address])])
657
661
663 """
664 Hide the difference between org.id and v_basic_person.pk_identity
665 """
666 return self['id']
667
669 """
670 wrap mx.DateTime brokenness
671 Returns 9-tuple for use with pyhon time functions
672 """
673 return [ int(x) for x in str(mx).split(' ')[0].split('-') ] + [0,0,0, 0,0,0]
674
676 """Gets a dict matching address types to their ID"""
677 row_list = gmPG.run_ro_query('personalia', "select name, id from dem.address_type")
678 if row_list is None:
679 return {}
680 if len(row_list) == 0:
681 return {}
682 return dict (row_list)
683
685 """Gets a dictionary matching marital status types to their internal ID"""
686 row_list = gmPG.run_ro_query('personalia', "select name, pk from dem.marital_status")
687 if row_list is None:
688 return {}
689 if len(row_list) == 0:
690 return {}
691 return dict(row_list)
692
694 """Gets a dictionary of relationship types to internal id"""
695 row_list = gmPG.run_ro_query('personalia', "select description, id from dem.relation_types")
696 if row_list is None:
697 return None
698 if len (row_list) == 0:
699 return None
700 return dict(row_list)
701
702
704 cmd = """
705 select
706 dem.state.name,
707 dem.urb.postcode
708 from
709 dem.urb,
710 dem.state
711 where
712 dem.urb.id = %s and
713 dem.urb.id_state = dem.state.id"""
714 row_list = gmPG.run_ro_query('personalia', cmd, None, id_urb)
715 if not row_list:
716 return None
717 else:
718 return (row_list[0][0], row_list[0][1])
719
721 cmd = """
722 select
723 dem.state.name,
724 coalesce (dem.street.postcode, dem.urb.postcode),
725 dem.urb.name
726 from
727 dem.urb,
728 dem.state,
729 dem.street
730 where
731 dem.street.id = %s and
732 dem.street.id_urb = dem.urb.id and
733 dem.urb.id_state = dem.state.id
734 """
735 row_list = gmPG.run_ro_query('personalia', cmd, None, id_street)
736 if not row_list:
737 return None
738 else:
739 return (row_list[0][0], row_list[0][1], row_list[0][2])
740
742 row_list = gmPG.run_ro_query('personalia', "select name from dem.country where code = %s", None, country_code)
743 if not row_list:
744 return None
745 else:
746 return row_list[0][0]
747
749 row_list = gmPG.run_ro_query ('personalia', """
750 select
751 dem.urb.postcode,
752 dem.state.code,
753 dem.state.name,
754 dem.country.code,
755 dem.country.name
756 from
757 dem.urb,
758 dem.state,
759 dem.country
760 where
761 dem.urb.name = %s and
762 dem.urb.id_state = dem.state.id and
763 dem.state.country = dem.country.code""", None, town)
764 if not row_list:
765 return (None, None, None, None, None)
766 else:
767 return tuple (row_list[0])
768
769
770
772 print "received post_patient_selection notification"
773 print kwargs['kwds']
774
775
776
777
778
779 if __name__ == "__main__":
780
781 if len(sys.argv) < 2:
782 sys.exit()
783
784 if sys.argv[1] != 'test':
785 sys.exit()
786
787 import random
788
790 exists = address_exists (
791 country ='Germany',
792 state ='Sachsen',
793 urb ='Leipzig',
794 suburb ='Sellerhausen',
795 postcode ='04318',
796 street = u'Cunnersdorfer Strasse',
797 number = '11',
798 notes_subunit = '4.Stock rechts'
799 )
800 if exists is None:
801 print "address does not exist"
802 else:
803 print "address exists, primary key:", exists
804
806 address = create_address (
807 country ='DE',
808 state ='SN',
809 urb ='Leipzig',
810 suburb ='Sellerhausen',
811 postcode ='04318',
812 street = u'Cunnersdorfer Strasse',
813 number = '11'
814
815 )
816 print "created existing address"
817 print address
818
819 su = str(random.random())
820
821 address = create_address (
822 country ='DE',
823 state = 'SN',
824 urb ='Leipzig',
825 suburb ='Sellerhausen',
826 postcode ='04318',
827 street = u'Cunnersdorfer Strasse',
828 number = '11',
829
830 subunit = su
831 )
832 print "created new address with subunit", su
833 print address
834 print "deleted address:", delete_address(address)
835
839
841 region = raw_input("Please enter a region: ")
842 print "country for region [%s] is: %s" % (region, get_country_for_region(region = region))
843
845 if delete_tag_image(tag_image = 9999):
846 print "deleted tag 9999"
847 else:
848 print "did not delete tag 9999"
849 if delete_tag_image(tag_image = 1):
850 print "deleted tag 1"
851 else:
852 print "did not delete tag 1"
853
858
859
860
861
862
863
864
865
866
867 test_tag_images()
868
869 sys.exit()
870
871 gmDispatcher.connect(_post_patient_selection, 'post_patient_selection')
872 while 1:
873 pID = raw_input('a patient: ')
874 if pID == '':
875 break
876 try:
877 print pID
878 myPatient = gmPerson.cIdentity (aPK_obj = pID)
879 except:
880 _log.exception('Unable to set up patient with ID [%s]' % pID)
881 print "patient", pID, "can not be set up"
882 continue
883 print "ID ", myPatient.ID
884 print "name ", myPatient['description']
885 print "name ", myPatient['description_gender']
886 print "title ", myPatient['title']
887 print "dob ", myPatient['dob']
888 print "med age ", myPatient['medical_age']
889 for adr in myPatient.get_addresses():
890 print "address ", adr
891 print "--------------------------------------"
892
893