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