| Trees | Indices | Help |
|
|---|
|
|
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
7 """
8 #============================================================
9 # $Source: /cvsroot/gnumed/gnumed/gnumed/client/business/gmDemographicRecord.py,v $
10 # $Id: gmDemographicRecord.py,v 1.106 2010/01/31 18:12:53 ncq Exp $
11 __version__ = "$Revision: 1.106 $"
12 __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>, I.Haywood <ihaywood@gnu.org>"
13
14 # stdlib
15 import sys, os.path, time, string, logging
16
17
18 # 3rd party
19 import mx.DateTime as mxDT
20
21
22 # GNUmed
23 if __name__ == '__main__':
24 sys.path.insert(0, '../../')
25 from Gnumed.pycommon import gmDispatcher, gmBusinessDBObject, gmPG2, gmTools
26 from Gnumed.business import gmMedDoc
27
28
29 _log = logging.getLogger('gm.business')
30 _log.info(__version__)
31
32 #============================================================
34 cmd = u"""
35 select
36 _(name) as l10n_country, name, code, deprecated
37 from dem.country
38 order by l10n_country"""
39 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}])
40 return rows
41 #============================================================
43 cmd = u"""
44 SELECT code_country, l10n_country FROM dem.v_state WHERE l10n_state = %(region)s
45 union
46 SELECT code_country, l10n_country FROM dem.v_state WHERE state = %(region)s
47 """
48 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': {'region': region}}])
49 return rows
50 #============================================================
52
53 args = {'prov': province}
54
55 queries = []
56 if delete_urbs:
57 queries.append ({
58 'cmd': u"""
59 delete from dem.urb du
60 where
61 du.id_state = %(prov)s
62 and
63 not exists (select 1 from dem.street ds where ds.id_urb = du.id)""",
64 'args': args
65 })
66
67 queries.append ({
68 'cmd': u"""
69 delete from dem.state ds
70 where
71 ds.id = %(prov)s
72 and
73 not exists (select 1 from dem.urb du where du.id_state = ds.id)""",
74 'args': args
75 })
76
77 gmPG2.run_rw_queries(queries = queries)
78
79 return True
80 #------------------------------------------------------------
82
83 args = {'code': code, 'country': country, 'name': name}
84
85 cmd = u"""SELECT EXISTS (SELECT 1 FROM dem.state WHERE name = %(name)s)"""
86 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False)
87
88 if rows[0][0]:
89 return
90
91 cmd = u"""
92 INSERT INTO dem.state (
93 code, country, name
94 ) VALUES (
95 %(code)s, %(country)s, %(name)s
96 )"""
97 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
98 #------------------------------------------------------------
100 cmd = u"""
101 select
102 l10n_state, l10n_country, state, code_state, code_country, pk_state, country_deprecated
103 from dem.v_state
104 order by l10n_country, l10n_state"""
105 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}])
106 return rows
107 #============================================================
108 # address related classes
109 #------------------------------------------------------------
111 """A class representing an address as an entity in itself.
112
113 We consider addresses to be self-complete "labels" for locations.
114 It does not depend on any people potentially living there. Thus
115 an address can get attached to as many people as we want to
116 signify that that is their place of residence/work/...
117
118 This class acts on the address as an entity. Therefore it can
119 modify the address fields. Think carefully about *modifying*
120 addresses attached to people, though. Most times when you think
121 person.modify_address() what you *really* want is as sequence of
122 person.unlink_address(old) and person.link_address(new).
123
124 Modifying an address may or may not be the proper thing to do as
125 it will transparently modify the address for *all* the people to
126 whom it is attached. In many cases you will want to create a *new*
127 address and link it to a person instead of the old address.
128 """
129 _cmd_fetch_payload = u"select * from dem.v_address where pk_address=%s"
130 _cmds_store_payload = [
131 u"""update dem.address set
132 aux_street = %(notes_street)s,
133 subunit = %(subunit)s,
134 addendum = %(notes_subunit)s,
135 lat_lon = %(lat_lon_street)s
136 where id=%(pk_address)s and xmin=%(xmin_address)s""",
137 u"select xmin as xmin_address from dem.address where id=%(pk_address)s"
138 ]
139 _updatable_fields = ['notes_street', 'subunit', 'notes_subunit', 'lat_lon_address']
140 #------------------------------------------------------------
141 -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):
142
143 where_parts = [u"""
144 code_country = %(country)s and
145 code_state = %(state)s and
146 urb = %(urb)s and
147 postcode = %(postcode)s and
148 street = %(street)s and
149 number = %(number)s"""
150 ]
151
152 if suburb is None:
153 where_parts.append(u"suburb is %(suburb)s")
154 else:
155 where_parts.append(u"suburb = %(suburb)s")
156
157 if notes_street is None:
158 where_parts.append(u"notes_street is %(notes_street)s")
159 else:
160 where_parts.append(u"notes_street = %(notes_street)s")
161
162 if subunit is None:
163 where_parts.append(u"subunit is %(subunit)s")
164 else:
165 where_parts.append(u"subunit = %(subunit)s")
166
167 if notes_subunit is None:
168 where_parts.append(u"notes_subunit is %(notes_subunit)s")
169 else:
170 where_parts.append(u"notes_subunit = %(notes_subunit)s")
171
172 cmd = u"select pk_address from dem.v_address where %s" % u" and ".join(where_parts)
173 data = {
174 'country': country,
175 'state': state,
176 'urb': urb,
177 'suburb': suburb,
178 'postcode': postcode,
179 'street': street,
180 'notes_street': notes_street,
181 'number': number,
182 'subunit': subunit,
183 'notes_subunit': notes_subunit
184 }
185
186 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': data}])
187
188 if len(rows) == 0:
189 return None
190 return rows[0][0]
191 #------------------------------------------------------------
192 -def create_address(country=None, state=None, urb=None, suburb=None, postcode=None, street=None, number=None, subunit=None):
193
194 if suburb is not None:
195 suburb = gmTools.none_if(suburb.strip(), u'')
196
197 pk_address = address_exists (
198 country = country,
199 state = state,
200 urb = urb,
201 suburb = suburb,
202 postcode = postcode,
203 street = street,
204 number = number,
205 subunit = subunit
206 )
207 if pk_address is not None:
208 return cAddress(aPK_obj=pk_address)
209
210 cmd = u"""
211 select dem.create_address (
212 %(number)s,
213 %(street)s,
214 %(postcode)s,
215 %(urb)s,
216 %(state)s,
217 %(country)s,
218 %(subunit)s
219 )"""
220 args = {
221 'number': number,
222 'street': street,
223 'postcode': postcode,
224 'urb': urb,
225 'state': state,
226 'country': country,
227 'subunit': subunit
228 }
229 queries = [{'cmd': cmd, 'args': args}]
230
231 rows, idx = gmPG2.run_rw_queries(queries = queries, return_data = True)
232 adr = cAddress(aPK_obj=rows[0][0])
233
234 if suburb is not None:
235 queries = [{
236 # CAVE: suburb will be ignored if there already is one
237 'cmd': u"update dem.street set suburb = %(suburb)s where id=%(pk_street)s and suburb is Null",
238 'args': {'suburb': suburb, 'pk_street': adr['pk_street']}
239 }]
240 rows, idx = gmPG2.run_rw_queries(queries = queries)
241
242 return adr
243 #------------------------------------------------------------
245 cmd = u"delete from dem.address where id=%s"
246 rows, idx = gmPG2.run_rw_queries(queries=[{'cmd': cmd, 'args': [address['pk_address']]}])
247 return True
248 #------------------------------------------------------------
250 cmd = u'select id as pk, name, _(name) as l10n_name from dem.address_type'
251 rows, idx = gmPG2.run_rw_queries(queries=[{'cmd': cmd}])
252 return rows
253 #===================================================================
255
256 _cmd_fetch_payload = u"select * from dem.v_pat_addresses where pk_address=%s"
257 _cmds_store_payload = [
258 u"""update dem.lnk_person_org_address set id_type=%(pk_address_type)s
259 where id=%(pk_lnk_person_org_address)s and xmin=%(xmin_lnk_person_org_address)s""",
260 u"""select xmin from dem.lnk_person_org_address where id=%(pk_lnk_person_org_address)s"""
261 ]
262 _updatable_fields = ['pk_address_type']
263 #---------------------------------------------------------------
266 #===================================================================
267 # communication channels API
268 #-------------------------------------------------------------------
270
271 _cmd_fetch_payload = u"select * from dem.v_person_comms where pk_lnk_identity2comm = %s"
272 _cmds_store_payload = [
273 u"""update dem.lnk_identity2comm set
274 fk_address = %(pk_address)s,
275 fk_type = dem.create_comm_type(%(comm_type)s),
276 url = %(url)s,
277 is_confidential = %(is_confidential)s
278 where pk = %(pk_lnk_identity2comm)s and xmin = %(xmin_lnk_identity2comm)s
279 """,
280 u"select xmin as xmin_lnk_identity2comm from dem.lnk_identity2comm where pk = %(pk_lnk_identity2comm)s"
281 ]
282 _updatable_fields = ['pk_address', 'url', 'comm_type', 'is_confidential']
283 #-------------------------------------------------------------------
284 -def create_comm_channel(comm_medium=None, url=None, is_confidential=False, pk_channel_type=None, pk_identity=None):
285 """Create a communications channel for a patient."""
286
287 if url is None:
288 return None
289
290 # FIXME: create comm type if necessary
291 args = {'pat': pk_identity, 'url': url, 'secret': is_confidential}
292
293 if pk_channel_type is None:
294 args['type'] = comm_medium
295 cmd = u"""insert into dem.lnk_identity2comm (
296 fk_identity,
297 url,
298 fk_type,
299 is_confidential
300 ) values (
301 %(pat)s,
302 %(url)s,
303 dem.create_comm_type(%(type)s),
304 %(secret)s
305 )"""
306 else:
307 args['type'] = pk_channel_type
308 cmd = u"""insert into dem.lnk_identity2comm (
309 fk_identity,
310 url,
311 fk_type,
312 is_confidential
313 ) values (
314 %(pat)s,
315 %(url)s,
316 %(type)s,
317 %(secret)s
318 )"""
319
320 rows, idx = gmPG2.run_rw_queries (
321 queries = [
322 {'cmd': cmd, 'args': args},
323 {'cmd': u"select * from dem.v_person_comms where pk_lnk_identity2comm = currval(pg_get_serial_sequence('dem.lnk_identity2comm', 'pk'))"}
324 ],
325 return_data = True,
326 get_col_idx = True
327 )
328
329 return cCommChannel(row = {'pk_field': 'pk_lnk_identity2comm', 'data': rows[0], 'idx': idx})
330 #-------------------------------------------------------------------
332 cmd = u"delete from dem.lnk_identity2comm where pk = %(pk)s and fk_identity = %(pat)s"
333 args = {'pk': pk, 'pat': pk_patient}
334 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
335 #-------------------------------------------------------------------
336 __comm_channel_types = None
337
339 global __comm_channel_types
340 if __comm_channel_types is None:
341 cmd = u"select pk, _(description) from dem.enum_comm_types"
342 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}])
343 __comm_channel_types = rows
344 return __comm_channel_types
345 #-------------------------------------------------------------------
346
347 #===================================================================
349 """
350 Organisations
351
352 This is also the common ancestor of cIdentity, self._table is used to
353 hide the difference.
354 The aim is to be able to sanely write code which doesn't care whether
355 its talking to an organisation or an individual"""
356 _table = "org"
357
358 _cmd_fetch_payload = "select *, xmin from dem.org where id=%s"
359 _cmds_lock_rows_for_update = ["select 1 from dem.org where id=%(id)s and xmin=%(xmin)s"]
360 _cmds_store_payload = [
361 """update dem.org set
362 description=%(description)s,
363 id_category=(select id from dem.org_category where description=%(occupation)s)
364 where id=%(id)s""",
365 "select xmin from dem.org where id=%(id)s"
366 ]
367 _updatable_fields = ["description", "occupation"]
368 _service = 'personalia'
369 #------------------------------------------------------------------
372 #------------------------------------------------------------------
374 if not self.__cache.has_key ('addresses'):
375 self['addresses']
376 if not self.__cache.has_key ('comms'):
377 self['comms']
378 return self.__cache
379 #--------------------------------------------------------------------
381 """
382 Returns a list of (address dict, cIdentity) tuples
383 """
384 cmd = """select
385 vba.id,
386 vba.number,
387 vba.addendum,
388 vba.street,
389 vba.urb,
390 vba.postcode,
391 at.name,
392 lpoa.id_type,
393 vbp.pk_identity,
394 title,
395 firstnames,
396 lastnames,
397 dob,
398 cob,
399 gender,
400 pupic,
401 pk_marital_status,
402 marital_status,
403 karyotype,
404 xmin_identity,
405 preferred
406 from
407 dem.v_basic_address vba,
408 dem.lnk_person_org_address lpoa,
409 dem.address_type at,
410 dem.v_basic_person vbp
411 where
412 lpoa.id_address = vba.id
413 and lpoa.id_type = at.id
414 and lpoa.id_identity = vbp.pk_identity
415 and lpoa.id_org = %%s
416 """
417
418 rows, idx = gmPG.run_ro_query('personalia', cmd, 1, self.getId ())
419 if rows is None:
420 return []
421 elif len(rows) == 0:
422 return []
423 else:
424 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]
425 #------------------------------------------------------------
427 """
428 Binds a person to this organisation at this address.
429 person is a cIdentity object
430 address is a dict of {'number', 'street', 'addendum', 'city', 'postcode', 'type'}
431 type is one of the IDs returned by getAddressTypes
432 """
433 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)"
434 address['pk_identity'] = person['pk_identity']
435 address['org_id'] = self.getId()
436 if not id_addr:
437 return (False, None)
438 return gmPG.run_commit2 ('personalia', [(cmd, [address])])
439 #------------------------------------------------------------
441 cmd = "delete from dem.lnk_person_org_address where id_org = %s and id_identity = %s"
442 return gmPG.run_commit2 ('personalia', [(cmd, [self.getId(), person.ID])])
443 #----------------------------------------------------------------------
449 #==============================================================================
451 """
452 wrap mx.DateTime brokenness
453 Returns 9-tuple for use with pyhon time functions
454 """
455 return [ int(x) for x in str(mx).split(' ')[0].split('-') ] + [0,0,0, 0,0,0]
456 #----------------------------------------------------------------
458 """Gets a dict matching address types to their ID"""
459 row_list = gmPG.run_ro_query('personalia', "select name, id from dem.address_type")
460 if row_list is None:
461 return {}
462 if len(row_list) == 0:
463 return {}
464 return dict (row_list)
465 #----------------------------------------------------------------
467 """Gets a dictionary matching marital status types to their internal ID"""
468 row_list = gmPG.run_ro_query('personalia', "select name, pk from dem.marital_status")
469 if row_list is None:
470 return {}
471 if len(row_list) == 0:
472 return {}
473 return dict(row_list)
474 #------------------------------------------------------------------
476 """Gets dictionary mapping ext ID names to internal code from the backend for the given context
477 """
478 # FIXME: error handling
479 rl = gmPG.run_ro_query('personalia', "select name, pk from dem.enum_ext_id_types where context = %s", None, context)
480 if rl is None:
481 return {}
482 return dict (rl)
483 #----------------------------------------------------------------
485 """Gets a dictionary of relationship types to internal id"""
486 row_list = gmPG.run_ro_query('personalia', "select description, id from dem.relation_types")
487 if row_list is None:
488 return None
489 if len (row_list) == 0:
490 return None
491 return dict(row_list)
492
493 #----------------------------------------------------------------
495 cmd = """
496 select
497 dem.state.name,
498 dem.urb.postcode
499 from
500 dem.urb,
501 dem.state
502 where
503 dem.urb.id = %s and
504 dem.urb.id_state = dem.state.id"""
505 row_list = gmPG.run_ro_query('personalia', cmd, None, id_urb)
506 if not row_list:
507 return None
508 else:
509 return (row_list[0][0], row_list[0][1])
510
512 cmd = """
513 select
514 dem.state.name,
515 coalesce (dem.street.postcode, dem.urb.postcode),
516 dem.urb.name
517 from
518 dem.urb,
519 dem.state,
520 dem.street
521 where
522 dem.street.id = %s and
523 dem.street.id_urb = dem.urb.id and
524 dem.urb.id_state = dem.state.id
525 """
526 row_list = gmPG.run_ro_query('personalia', cmd, None, id_street)
527 if not row_list:
528 return None
529 else:
530 return (row_list[0][0], row_list[0][1], row_list[0][2])
531
533 row_list = gmPG.run_ro_query('personalia', "select name from dem.country where code = %s", None, country_code)
534 if not row_list:
535 return None
536 else:
537 return row_list[0][0]
538 #-------------------------------------------------------------------------------
540 row_list = gmPG.run_ro_query ('personalia', """
541 select
542 dem.urb.postcode,
543 dem.state.code,
544 dem.state.name,
545 dem.country.code,
546 dem.country.name
547 from
548 dem.urb,
549 dem.state,
550 dem.country
551 where
552 dem.urb.name = %s and
553 dem.urb.id_state = dem.state.id and
554 dem.state.country = dem.country.code""", None, town)
555 if not row_list:
556 return (None, None, None, None, None)
557 else:
558 return tuple (row_list[0])
559 #============================================================
560 # callbacks
561 #------------------------------------------------------------
565 #============================================================
566
567 #============================================================
568 # main
569 #------------------------------------------------------------
570 if __name__ == "__main__":
571
572 if len(sys.argv) < 2:
573 sys.exit()
574
575 import random
576 #--------------------------------------------------------
578 exists = address_exists (
579 country ='Germany',
580 state ='Sachsen',
581 urb ='Leipzig',
582 suburb ='Sellerhausen',
583 postcode ='04318',
584 street = u'Cunnersdorfer Strasse',
585 number = '11',
586 notes_subunit = '4.Stock rechts'
587 )
588 if exists is None:
589 print "address does not exist"
590 else:
591 print "address exists, primary key:", exists
592 #--------------------------------------------------------
594 address = create_address (
595 country ='DE',
596 state ='SN',
597 urb ='Leipzig',
598 suburb ='Sellerhausen',
599 postcode ='04318',
600 street = u'Cunnersdorfer Strasse',
601 number = '11'
602 # ,notes_subunit = '4.Stock rechts'
603 )
604 print "created existing address"
605 print address
606
607 su = str(random.random())
608
609 address = create_address (
610 country ='DE',
611 state = 'SN',
612 urb ='Leipzig',
613 suburb ='Sellerhausen',
614 postcode ='04318',
615 street = u'Cunnersdorfer Strasse',
616 number = '11',
617 # notes_subunit = '4.Stock rechts',
618 subunit = su
619 )
620 print "created new address with subunit", su
621 print address
622 print "deleted address:", delete_address(address)
623 #--------------------------------------------------------
627 #--------------------------------------------------------
629 region = raw_input("Please enter a region: ")
630 print "country for region [%s] is: %s" % (region, get_country_for_region(region = region))
631 #--------------------------------------------------------
632 if sys.argv[1] != 'test':
633 sys.exit()
634
635 #gmPG2.get_connection()
636
637 #test_address_exists()
638 #test_create_address()
639 #test_get_countries()
640 test_get_country_for_region()
641
642 sys.exit()
643
644 gmDispatcher.connect(_post_patient_selection, 'post_patient_selection')
645 while 1:
646 pID = raw_input('a patient: ')
647 if pID == '':
648 break
649 try:
650 print pID
651 myPatient = gmPerson.cIdentity (aPK_obj = pID)
652 except:
653 _log.exception('Unable to set up patient with ID [%s]' % pID)
654 print "patient", pID, "can not be set up"
655 continue
656 print "ID ", myPatient.ID
657 print "name ", myPatient['description']
658 print "name ", myPatient['description_gender']
659 print "title ", myPatient['title']
660 print "dob ", myPatient['dob']
661 print "med age ", myPatient['medical_age']
662 for adr in myPatient.get_addresses():
663 print "address ", adr
664 print "--------------------------------------"
665 #============================================================
666 # $Log: gmDemographicRecord.py,v $
667 # Revision 1.106 2010/01/31 18:12:53 ncq
668 # - get-country-for-region
669 #
670 # Revision 1.105 2010/01/31 16:51:21 ncq
671 # - fix get-countries()
672 #
673 # Revision 1.104 2010/01/31 16:32:19 ncq
674 # - get-countries()
675 #
676 # Revision 1.103 2009/11/18 16:10:02 ncq
677 # - more provinces handling
678 #
679 # Revision 1.102 2009/11/17 19:40:40 ncq
680 # - delete-province()
681 #
682 # Revision 1.101 2009/09/29 13:13:41 ncq
683 # - get-address-types
684 #
685 # Revision 1.100 2009/04/24 12:04:25 ncq
686 # - if url is None do not add comm channel
687 #
688 # Revision 1.99 2009/04/21 16:53:42 ncq
689 # - cleanup
690 #
691 # Revision 1.98 2008/12/09 23:47:12 ncq
692 # - adjust to description_gender
693 #
694 # Revision 1.97 2008/08/15 15:55:53 ncq
695 # - get_provinces
696 #
697 # Revision 1.96 2008/02/26 16:24:49 ncq
698 # - remove pk_address from create_comm_channel
699 #
700 # Revision 1.95 2008/02/25 17:29:40 ncq
701 # - cleanup
702 #
703 # Revision 1.94 2008/01/07 19:32:15 ncq
704 # - cleanup, rearrange
705 # - create comm channel API
706 #
707 # Revision 1.93 2007/12/03 20:41:07 ncq
708 # - get_comm_channel_types()
709 #
710 # Revision 1.92 2007/12/02 20:56:37 ncq
711 # - adjust to table changes
712 #
713 # Revision 1.91 2007/11/17 16:10:53 ncq
714 # - improve create_address()
715 # - cleanup and fixes
716 #
717 # Revision 1.90 2007/11/12 22:52:01 ncq
718 # - create_address() now doesn't care about non-changing fields
719 #
720 # Revision 1.89 2007/11/07 22:59:31 ncq
721 # - don't allow editing number on address
722 #
723 # Revision 1.88 2007/03/23 15:01:36 ncq
724 # - no more person['id']
725 #
726 # Revision 1.87 2007/02/22 16:26:54 ncq
727 # - fix create_address()
728 #
729 # Revision 1.86 2006/11/26 15:44:03 ncq
730 # - do not use es-zet in test suite
731 #
732 # Revision 1.85 2006/11/19 10:58:52 ncq
733 # - fix imports
734 # - add cAddress
735 # - add cPatientAddress
736 # - remove dead match provider code
737 # - add address_exists(), create_address(), delete_address()
738 # - improve test suite
739 #
740 # Revision 1.84 2006/10/25 07:17:40 ncq
741 # - no more gmPG
742 # - no more cClinItem
743 #
744 # Revision 1.83 2006/10/24 13:15:48 ncq
745 # - comment out/remove a bunch of deprecated/unused match providers
746 #
747 # Revision 1.82 2006/07/19 20:25:00 ncq
748 # - gmPyCompat.py is history
749 #
750 # Revision 1.81 2006/06/14 10:22:46 ncq
751 # - create_* stored procs are in schema dem.* now
752 #
753 # Revision 1.80 2006/05/15 13:24:13 ncq
754 # - signal "activating_patient" -> "pre_patient_selection"
755 # - signal "patient_selected" -> "post_patient_selection"
756 #
757 # Revision 1.79 2006/01/07 13:13:46 ncq
758 # - more schema qualifications
759 #
760 # Revision 1.78 2006/01/07 11:23:24 ncq
761 # - must use """ for multi-line string
762 #
763 # Revision 1.77 2006/01/06 10:15:37 ncq
764 # - lots of small fixes adjusting to "dem" schema
765 #
766 # Revision 1.76 2005/10/09 08:11:48 ihaywood
767 # introducing get_town_data (), a convience method to get info that can be inferred from a town's name (in AU)
768 #
769 # Revision 1.75 2005/10/09 02:19:40 ihaywood
770 # the address widget now has the appropriate widget order and behaviour for australia
771 # when os.environ["LANG"] == 'en_AU' (is their a more graceful way of doing this?)
772 #
773 # Remember our postcodes work very differently.
774 #
775 # Revision 1.74 2005/06/07 10:15:47 ncq
776 # - setContext -> set_context
777 #
778 # Revision 1.73 2005/04/25 08:26:48 ncq
779 # - cleanup
780 #
781 # Revision 1.72 2005/04/14 19:14:51 cfmoro
782 # Gender dict was replaced by get_genders method
783 #
784 # Revision 1.71 2005/04/14 18:58:14 cfmoro
785 # Added create occupation method and minor gender map clean up, to replace later by get_gender_list
786 #
787 # Revision 1.70 2005/04/14 08:49:29 ncq
788 # - move cIdentity and dob2medical_age() to gmPerson.py
789 #
790 # Revision 1.69 2005/03/30 21:04:01 cfmoro
791 # id -> pk_identity
792 #
793 # Revision 1.68 2005/03/29 18:55:39 cfmoro
794 # Var name fix
795 #
796 # Revision 1.67 2005/03/20 16:47:26 ncq
797 # - cleanup
798 #
799 # Revision 1.66 2005/03/08 16:41:37 ncq
800 # - properly handle title
801 #
802 # Revision 1.65 2005/03/06 08:17:02 ihaywood
803 # forms: back to the old way, with support for LaTeX tables
804 #
805 # business objects now support generic linked tables, demographics
806 # uses them to the same functionality as before (loading, no saving)
807 # They may have no use outside of demographics, but saves much code already.
808 #
809 # Revision 1.64 2005/02/20 21:00:20 ihaywood
810 # getId () is back
811 #
812 # Revision 1.63 2005/02/20 09:46:08 ihaywood
813 # demographics module with load a patient with no exceptions
814 #
815 # Revision 1.61 2005/02/19 15:04:55 sjtan
816 #
817 # identity.id is now identity.pk_identity, so adapt
818 #
819 # Revision 1.60 2005/02/18 11:16:41 ihaywood
820 # new demographics UI code won't crash the whole client now ;-)
821 # still needs much work
822 # RichardSpace working
823 #
824 # Revision 1.59 2005/02/13 15:46:46 ncq
825 # - trying to keep up to date with schema changes but may conflict with Ian
826 #
827 # Revision 1.58 2005/02/12 14:00:21 ncq
828 # - identity.id -> pk
829 # - v_basic_person.i_id -> i_pk
830 # - likely missed some places here, though
831 #
832 # Revision 1.57 2005/02/03 20:17:18 ncq
833 # - get_demographic_record() -> get_identity()
834 #
835 # Revision 1.56 2005/02/01 10:16:07 ihaywood
836 # refactoring of gmDemographicRecord and follow-on changes as discussed.
837 #
838 # gmTopPanel moves to gmHorstSpace
839 # gmRichardSpace added -- example code at present, haven't even run it myself
840 # (waiting on some icon .pngs from Richard)
841 #
842 # Revision 1.55 2005/01/31 10:37:26 ncq
843 # - gmPatient.py -> gmPerson.py
844 #
845 # Revision 1.54 2004/08/18 09:05:07 ncq
846 # - just some cleanup, double-check _ is defined for epydoc
847 #
848 # Revision 1.53 2004/07/26 14:34:49 sjtan
849 #
850 # numbering correction from labels in gmDemograpics.
851 #
852 # Revision 1.52 2004/06/25 12:37:19 ncq
853 # - eventually fix the import gmI18N issue
854 #
855 # Revision 1.51 2004/06/21 16:02:08 ncq
856 # - cleanup, trying to make epydoc fix do the right thing
857 #
858 # Revision 1.50 2004/06/21 14:48:25 sjtan
859 #
860 # restored some methods that gmContacts depends on, after they were booted
861 # out from gmDemographicRecord with no home to go , works again ;
862 # removed cCatFinder('occupation') instantiating in main module scope
863 # which was a source of complaint , as it still will lazy load anyway.
864 #
865 # Revision 1.49 2004/06/20 15:38:00 ncq
866 # - remove import gettext/_ = gettext.gettext
867 # - import gmI18N handles that if __main__
868 # - else the importer of gmDemographicRecord has
869 # to handle setting _
870 # - this is the Right Way as per the docs !
871 #
872 # Revision 1.48 2004/06/20 06:49:21 ihaywood
873 # changes required due to Epydoc's OCD
874 #
875 # Revision 1.47 2004/06/17 11:36:12 ihaywood
876 # Changes to the forms layer.
877 # Now forms can have arbitrary Python expressions embedded in @..@ markup.
878 # A proper forms HOWTO will appear in the wiki soon
879 #
880 # Revision 1.46 2004/05/30 03:50:41 sjtan
881 #
882 # gmContacts can create/update org, one level of sub-org, org persons, sub-org persons.
883 # pre-alpha or alpha ? Needs cache tune-up .
884 #
885 # Revision 1.45 2004/05/29 12:03:47 sjtan
886 #
887 # OrgCategoryMP for gmContact's category field
888 #
889 # Revision 1.44 2004/05/28 15:05:10 sjtan
890 #
891 # utility functions only called with exactly 2 args in order to fulfill function intent, but do some checking for invalid args.
892 #
893 # Revision 1.43 2004/05/26 12:58:14 ncq
894 # - cleanup, error handling
895 #
896 # Revision 1.42 2004/05/25 16:18:13 sjtan
897 #
898 # move methods for postcode -> urb interaction to gmDemographics so gmContacts can use it.
899 #
900 # Revision 1.41 2004/05/25 16:00:34 sjtan
901 #
902 # move common urb/postcode collaboration to business class.
903 #
904 # Revision 1.40 2004/05/19 11:16:08 sjtan
905 #
906 # allow selecting the postcode for restricting the urb's picklist, and resetting
907 # the postcode for unrestricting the urb picklist.
908 #
909 # Revision 1.39 2004/04/15 09:46:56 ncq
910 # - cleanup, get_lab_data -> get_lab_results
911 #
912 # Revision 1.38 2004/04/11 10:15:56 ncq
913 # - load title in get_names() and use it superceding getFullName
914 #
915 # Revision 1.37 2004/04/10 01:48:31 ihaywood
916 # can generate referral letters, output to xdvi at present
917 #
918 # Revision 1.36 2004/04/07 18:43:47 ncq
919 # - more gender mappings
920 # - *comm_channel -> comm_chan
921 #
922 # Revision 1.35 2004/03/27 04:37:01 ihaywood
923 # lnk_person2address now lnk_person_org_address
924 # sundry bugfixes
925 #
926 # Revision 1.34 2004/03/25 11:01:45 ncq
927 # - getActiveName -> get_names(all=false)
928 # - export_demographics()
929 #
930 # Revision 1.33 2004/03/20 19:43:16 ncq
931 # - do import gmI18N, we need it
932 # - gm2long_gender_map -> map_gender_gm2long
933 # - gmDemo* -> cDemo*
934 #
935 # Revision 1.32 2004/03/20 17:53:15 ncq
936 # - cleanup
937 #
938 # Revision 1.31 2004/03/15 15:35:45 ncq
939 # - optimize getCommChannel() a bit
940 #
941 # Revision 1.30 2004/03/10 12:56:01 ihaywood
942 # fixed sudden loss of main.shadow
943 # more work on referrals,
944 #
945 # Revision 1.29 2004/03/10 00:09:51 ncq
946 # - cleanup imports
947 #
948 # Revision 1.28 2004/03/09 07:34:51 ihaywood
949 # reactivating plugins
950 #
951 # Revision 1.27 2004/03/04 10:41:21 ncq
952 # - comments, cleanup, adapt to minor schema changes
953 #
954 # Revision 1.26 2004/03/03 23:53:22 ihaywood
955 # GUI now supports external IDs,
956 # Demographics GUI now ALPHA (feature-complete w.r.t. version 1.0)
957 # but happy to consider cosmetic changes
958 #
959 # Revision 1.25 2004/03/03 05:24:01 ihaywood
960 # patient photograph support
961 #
962 # Revision 1.24 2004/03/02 10:21:09 ihaywood
963 # gmDemographics now supports comm channels, occupation,
964 # country of birth and martial status
965 #
966 # Revision 1.23 2004/02/26 17:19:59 ncq
967 # - setCommChannel: arg channel -> channel_type
968 # - setCommChannel: we need to read currval() within
969 # the same transaction as the insert to get consistent
970 # results
971 #
972 # Revision 1.22 2004/02/26 02:12:00 ihaywood
973 # comm channel methods
974 #
975 # Revision 1.21 2004/02/25 09:46:20 ncq
976 # - import from pycommon now, not python-common
977 #
978 # Revision 1.20 2004/02/18 15:26:39 ncq
979 # - fix dob2medical_age()
980 #
981 # Revision 1.19 2004/02/18 06:36:04 ihaywood
982 # bugfixes
983 #
984 # Revision 1.18 2004/02/17 10:30:14 ncq
985 # - enhance GetAddresses() to return all types if addr_type is None
986 #
987 # Revision 1.17 2004/02/17 04:04:34 ihaywood
988 # fixed patient creation refeential integrity error
989 #
990 # Revision 1.16 2004/02/14 00:37:10 ihaywood
991 # Bugfixes
992 # - weeks = days / 7
993 # - create_new_patient to maintain xlnk_identity in historica
994 #
995 # Revision 1.15 2003/12/01 01:01:41 ncq
996 # - get_medical_age -> dob2medical_age
997 #
998 # Revision 1.14 2003/11/30 01:06:21 ncq
999 # - add/remove_external_id()
1000 #
1001 # Revision 1.13 2003/11/23 23:32:01 ncq
1002 # - some cleanup
1003 # - setTitle now works on identity instead of names
1004 #
1005 # Revision 1.12 2003/11/23 14:02:40 sjtan
1006 #
1007 # by setting active=false first, then updating values, side effects from triggers can be avoided; see also
1008 # F_active_name trigger function in server sql script,which fires only if new.active = true .
1009 #
1010 # Revision 1.11 2003/11/22 14:44:17 ncq
1011 # - setTitle now only operates on active names and also doesn't set the name
1012 # to active which would trigger the trigger
1013 #
1014 # Revision 1.10 2003/11/22 14:40:59 ncq
1015 # - setActiveName -> addName
1016 #
1017 # Revision 1.9 2003/11/22 12:53:48 sjtan
1018 #
1019 # modified the setActiveName and setTitle so it works as intended in the face of insurmountable triggers ;)
1020 #
1021 # Revision 1.8 2003/11/20 07:45:45 ncq
1022 # - update names/identity, not v_basic_person in setTitle et al
1023 #
1024 # Revision 1.7 2003/11/20 02:10:50 sjtan
1025 #
1026 # remove 'self' parameter from functions moved into global module namespace.
1027 #
1028 # Revision 1.6 2003/11/20 01:52:03 ncq
1029 # - actually, make that **?** for good measure
1030 #
1031 # Revision 1.5 2003/11/20 01:50:52 ncq
1032 # - return '?' for missing names in getActiveName()
1033 #
1034 # Revision 1.4 2003/11/18 16:44:24 ncq
1035 # - getAddress -> getAddresses
1036 # - can't verify mxDateTime bug with missing time tuple
1037 # - remove getBirthYear, do getDOB() -> mxDateTime -> format
1038 # - get_relative_list -> get_relatives
1039 # - create_dummy_relative -> link_new_relative
1040 # - cleanup
1041 #
1042 # Revision 1.3 2003/11/17 10:56:34 sjtan
1043 #
1044 # synced and commiting.
1045 #
1046 # Revision 1.2 2003/11/04 10:35:22 ihaywood
1047 # match providers in gmDemographicRecord
1048 #
1049 # Revision 1.1 2003/11/03 23:59:55 ncq
1050 # - renamed to avoid namespace pollution with plugin widget
1051 #
1052 # Revision 1.6 2003/10/31 23:21:20 ncq
1053 # - remove old history
1054 #
1055 # Revision 1.5 2003/10/27 15:52:41 ncq
1056 # - if aFormat is None in getDOB() return datetime object, else return formatted string
1057 #
1058 # Revision 1.4 2003/10/26 17:35:04 ncq
1059 # - conceptual cleanup
1060 # - IMHO, patient searching and database stub creation is OUTSIDE
1061 # THE SCOPE OF gmPerson and gmDemographicRecord
1062 #
1063 # Revision 1.3 2003/10/26 16:35:03 ncq
1064 # - clean up as discussed with Ian, merge conflict resolution
1065 #
1066 # Revision 1.2 2003/10/26 11:27:10 ihaywood
1067 # gmPatient is now the "patient stub", all demographics stuff in gmDemographics.
1068 #
1069 # Ergregious breakages are fixed, but needs more work
1070 #
1071 # Revision 1.1 2003/10/25 08:48:06 ihaywood
1072 # Split from gmTmpPatient
1073 #
1074
1075
1076
1077 # old gmTmpPatient log
1078 # Revision 1.41 2003/10/19 10:42:57 ihaywood
1079 # extra functions
1080 #
1081 # Revision 1.40 2003/09/24 08:45:40 ihaywood
1082 # NewAddress now functional
1083 #
1084 # Revision 1.39 2003/09/23 19:38:03 ncq
1085 # - cleanup
1086 # - moved GetAddressesType out of patient class - it's a generic function
1087 #
1088
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Tue Feb 9 04:01:21 2010 | http://epydoc.sourceforge.net |