Package Gnumed :: Package business :: Module gmDemographicRecord
[frames] | no frames]

Source Code for Module Gnumed.business.gmDemographicRecord

   1  # -*- coding: utf-8 -*- 
   2  """GNUmed demographics object. 
   3   
   4  This is a patient object intended to let a useful client-side 
   5  API crystallize from actual use in true XP fashion. 
   6   
   7  license: GPL v2 or later 
   8  """ 
   9  #============================================================ 
  10  __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>, I.Haywood <ihaywood@gnu.org>" 
  11   
  12  # stdlib 
  13  import sys 
  14  import os 
  15  import os.path 
  16  import logging 
  17  import urllib.parse 
  18   
  19   
  20  # GNUmed 
  21  if __name__ == '__main__': 
  22          sys.path.insert(0, '../../') 
  23  from Gnumed.pycommon import gmDispatcher 
  24  from Gnumed.pycommon import gmBusinessDBObject 
  25  from Gnumed.pycommon import gmPG2 
  26  from Gnumed.pycommon import gmTools 
  27   
  28   
  29  _log = logging.getLogger('gm.business') 
  30   
  31  #============================================================ 
  32  # occupation handling 
  33  #------------------------------------------------------------ 
34 -def get_occupations(pk_identity=None):
35 cmd = """ 36 SELECT * 37 FROM dem.v_person_jobs 38 WHERE pk_identity = %(pk)s 39 ORDER BY l10n_occupation 40 """ 41 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': {'pk': pk_identity}}]) 42 return rows
43 #============================================================ 44 # text+image tags 45 #------------------------------------------------------------ 46 _SQL_get_tag_image = "SELECT * FROM ref.v_tag_images_no_data WHERE %s" 47
48 -class cTagImage(gmBusinessDBObject.cBusinessDBObject):
49 50 _cmd_fetch_payload = _SQL_get_tag_image % "pk_tag_image = %s" 51 _cmds_store_payload = [ 52 """ 53 UPDATE ref.tag_image SET 54 description = gm.nullify_empty_string(%(description)s), 55 filename = gm.nullify_empty_string(%(filename)s) 56 WHERE 57 pk = %(pk_tag_image)s 58 AND 59 xmin = %(xmin_tag_image)s 60 RETURNING 61 pk as pk_tag_image, 62 xmin as xmin_tag_image 63 """ 64 ] 65 _updatable_fields = ['description', 'filename'] 66 #--------------------------------------------------------
67 - def export_image2file(self, aChunkSize=0, filename=None):
68 69 if self._payload[self._idx['size']] == 0: 70 return None 71 72 if filename is None: 73 suffix = None 74 # preserve original filename extension if available 75 if self._payload[self._idx['filename']] is not None: 76 name, suffix = os.path.splitext(self._payload[self._idx['filename']]) 77 suffix = suffix.strip() 78 if suffix == '': 79 suffix = None 80 # get unique filename 81 filename = gmTools.get_unique_filename ( 82 prefix = 'gm-tag_image-', 83 suffix = suffix 84 ) 85 86 success = gmPG2.bytea2file ( 87 data_query = { 88 'cmd': 'SELECT substring(image from %(start)s for %(size)s) FROM ref.tag_image WHERE pk = %(pk)s', 89 'args': {'pk': self.pk_obj} 90 }, 91 filename = filename, 92 chunk_size = aChunkSize, 93 data_size = self._payload[self._idx['size']] 94 ) 95 96 if success: 97 return filename 98 99 return None
100 #--------------------------------------------------------
101 - def update_image_from_file(self, filename=None):
102 # sanity check 103 if not (os.access(filename, os.R_OK) and os.path.isfile(filename)): 104 _log.error('[%s] is not a readable file' % filename) 105 return False 106 107 gmPG2.file2bytea ( 108 query = "UPDATE ref.tag_image SET image = %(data)s::bytea WHERE pk = %(pk)s", 109 filename = filename, 110 args = {'pk': self.pk_obj} 111 ) 112 113 # must update XMIN now ... 114 self.refetch_payload() 115 return True
116 #------------------------------------------------------------
117 -def get_tag_images(order_by=None, return_pks=False):
118 if order_by is None: 119 order_by = 'true' 120 else: 121 order_by = 'true ORDER BY %s' % order_by 122 cmd = _SQL_get_tag_image % order_by 123 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = True) 124 if return_pks: 125 return [ r['pk_tag_image'] for r in rows ] 126 return [ cTagImage(row = {'data': r, 'idx': idx, 'pk_field': 'pk_tag_image'}) for r in rows ]
127 128 #------------------------------------------------------------
129 -def create_tag_image(description=None, link_obj=None):
130 131 args = {'desc': description, 'img': ''} 132 cmd = """ 133 INSERT INTO ref.tag_image ( 134 description, 135 image 136 ) VALUES ( 137 %(desc)s, 138 %(img)s::bytea 139 ) 140 RETURNING pk 141 """ 142 rows, idx = gmPG2.run_rw_queries ( 143 link_obj = link_obj, 144 queries = [{'cmd': cmd, 'args': args}], 145 end_tx = True, 146 return_data = True, 147 get_col_idx = False 148 ) 149 150 return cTagImage(aPK_obj = rows[0]['pk'])
151 #------------------------------------------------------------
152 -def delete_tag_image(tag_image=None):
153 args = {'pk': tag_image} 154 cmd = """ 155 DELETE FROM ref.tag_image 156 WHERE 157 pk = %(pk)s 158 AND 159 NOT EXISTS ( 160 SELECT 1 161 FROM dem.identity_tag 162 WHERE fk_tag = %(pk)s 163 LIMIT 1 164 ) 165 RETURNING 1 166 """ 167 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}], return_data = True) 168 if len(rows) == 0: 169 return False 170 return True
171 172 #============================================================ 173 _SQL_get_person_tags = """SELECT * FROM dem.v_identity_tags WHERE %s""" 174
175 -class cPersonTag(gmBusinessDBObject.cBusinessDBObject):
176 177 _cmd_fetch_payload = _SQL_get_person_tags % "pk_identity_tag = %s" 178 _cmds_store_payload = [ 179 """ 180 UPDATE dem.identity_tag SET 181 fk_tag = %(pk_tag_image)s, 182 comment = gm.nullify_empty_string(%(comment)s) 183 WHERE 184 pk = %(pk_identity_tag)s 185 AND 186 xmin = %(xmin_identity_tag)s 187 RETURNING 188 pk as pk_identity_tag, 189 xmin as xmin_identity_tag 190 """ 191 ] 192 _updatable_fields = ['fk_tag', 'comment'] 193 #--------------------------------------------------------
194 - def export_image2file(self, aChunkSize=0, filename=None):
195 196 if self._payload[self._idx['image_size']] == 0: 197 return None 198 199 if filename is None: 200 suffix = None 201 # preserve original filename extension if available 202 if self._payload[self._idx['filename']] is not None: 203 name, suffix = os.path.splitext(self._payload[self._idx['filename']]) 204 suffix = suffix.strip() 205 if suffix == '': 206 suffix = None 207 # get unique filename 208 filename = gmTools.get_unique_filename ( 209 prefix = 'gm-person_tag-', 210 suffix = suffix 211 ) 212 213 exported = gmPG2.bytea2file ( 214 data_query = { 215 'cmd': 'SELECT substring(image from %(start)s for %(size)s) FROM ref.tag_image WHERE pk = %(pk)s', 216 'args': {'pk': self._payload[self._idx['pk_tag_image']]} 217 }, 218 filename = filename, 219 chunk_size = aChunkSize, 220 data_size = self._payload[self._idx['image_size']] 221 ) 222 if exported: 223 return filename 224 225 return None
226 227 #============================================================ 228 # country/region related 229 #============================================================
230 -def get_countries():
231 cmd = """ 232 SELECT 233 _(name) AS l10n_country, name, code, deprecated 234 FROM dem.country 235 ORDER BY l10n_country""" 236 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}]) 237 return rows
238 239 #------------------------------------------------------------
240 -def get_country_for_region(region=None):
241 cmd = """ 242 SELECT code_country, l10n_country FROM dem.v_region WHERE lower(l10n_region) = lower(%(region)s) 243 union 244 SELECT code_country, l10n_country FROM dem.v_region WHERE lower(region) = lower(%(region)s) 245 """ 246 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': {'region': region}}]) 247 return rows
248 249 #------------------------------------------------------------
250 -def map_country2code(country=None):
251 cmd = """ 252 SELECT code FROM dem.country WHERE lower(_(name)) = lower(%(country)s) 253 UNION 254 SELECT code FROM dem.country WHERE lower(name) = lower(%(country)s) 255 """ 256 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': {'country': country}}], get_col_idx = False) 257 if len(rows) == 0: 258 return None 259 return rows[0][0]
260 261 #------------------------------------------------------------
262 -def map_urb_zip_region2country(urb=None, zip=None, region=None):
263 264 args = {'urb': urb, 'zip': zip, 'region': region} 265 cmd = """( 266 -- find by using all known details 267 SELECT 268 1 AS rank, 269 country, 270 l10n_country, 271 code_country 272 FROM dem.v_urb WHERE 273 postcode_urb = %(zip)s 274 AND 275 lower(urb) = lower(%(urb)s) 276 AND 277 ( 278 (lower(region) = lower(coalesce(%(region)s, 'state/territory/province/region not available'))) 279 OR 280 (lower(l10n_region) = lower(coalesce(%(region)s, _('state/territory/province/region not available')))) 281 ) 282 283 ) UNION ( 284 285 -- find by using zip/urb 286 SELECT 287 2 AS rank, 288 country, 289 l10n_country, 290 code_country 291 FROM dem.v_urb WHERE 292 postcode_urb = %(zip)s 293 AND 294 lower(urb) = lower(%(urb)s) 295 296 ) UNION ( 297 298 -- find by using zip/region 299 SELECT 300 2 AS rank, 301 country, 302 l10n_country, 303 code_country 304 FROM dem.v_urb WHERE 305 postcode_urb = %(zip)s 306 AND 307 ( 308 (lower(region) = lower(%(region)s)) 309 OR 310 (lower(l10n_region) = lower(%(region)s)) 311 ) 312 313 ) UNION ( 314 315 -- find by using urb/region 316 SELECT 317 2 AS rank, 318 country, 319 l10n_country, 320 code_country 321 FROM dem.v_urb WHERE 322 lower(urb) = lower(%(urb)s) 323 AND 324 ((lower(region) = lower(%(region)s)) 325 OR 326 (lower(l10n_region) = lower(%(region)s))) 327 328 ) UNION ( 329 330 -- find by region 331 SELECT 332 2 AS rank, 333 country, 334 l10n_country, 335 code_country 336 FROM dem.v_region WHERE 337 lower(region) = lower(%(region)s) 338 OR 339 lower(l10n_region) = lower(%(region)s) 340 341 ) ORDER BY rank""" 342 343 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False) 344 if len(rows) == 0: 345 _log.debug('zip [%s] / urb [%s] / region [%s] => ??', zip, urb, region) 346 return None 347 if len(rows) > 2: 348 _log.debug('zip [%s] / urb [%s] / region [%s] => [%s]', zip, urb, region, rows) 349 return None 350 country = rows[0] 351 _log.debug('zip [%s] / urb [%s] / region [%s] => [%s]', zip, urb, region, country) 352 return country
353 354 #------------------------------------------------------------
355 -def map_urb_zip_country2region(urb=None, zip=None, country=None, country_code=None):
356 357 args = {'urb': urb, 'zip': zip, 'country': country, 'country_code': country_code} 358 cmd = """( 359 -- find by using all known details 360 SELECT 361 1 AS rank, 362 region, 363 l10n_region, 364 code_region 365 FROM dem.v_urb WHERE 366 postcode_urb = %(zip)s 367 AND 368 lower(urb) = lower(%(urb)s) 369 AND 370 ( 371 (lower(country) = lower(%(country)s)) 372 OR 373 (lower(l10n_country) = lower(%(country)s)) 374 OR 375 (code_country = %(country_code)s) 376 ) 377 378 ) UNION ( 379 380 -- find by zip / urb 381 SELECT 382 2 AS rank, 383 region, 384 l10n_region, 385 code_region 386 FROM dem.v_urb WHERE 387 postcode_urb = %(zip)s 388 AND 389 lower(urb) = lower(%(urb)s) 390 391 ) UNION ( 392 393 -- find by zip / country 394 SELECT 395 2 AS rank, 396 region, 397 l10n_region, 398 code_region 399 FROM dem.v_urb WHERE 400 postcode_urb = %(zip)s 401 AND 402 ( 403 (lower(country) = lower(%(country)s)) 404 OR 405 (lower(l10n_country) = lower(%(country)s)) 406 OR 407 (code_country = %(country_code)s) 408 ) 409 410 ) UNION ( 411 412 -- find by urb / country 413 SELECT 414 2 AS rank, 415 region, 416 l10n_region, 417 code_region 418 FROM dem.v_urb WHERE 419 lower(urb) = lower(%(urb)s) 420 AND 421 ( 422 (lower(country) = lower(%(country)s)) 423 OR 424 (lower(l10n_country) = lower(%(country)s)) 425 OR 426 (code_country = %(country_code)s) 427 ) 428 429 ) ORDER BY rank""" 430 431 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False) 432 433 if len(rows) == 0: 434 cmd = """ 435 -- find by country (some countries will only have one region) 436 SELECT 437 1 AS rank, -- dummy to conform with function result structure at Python level 438 region, 439 l10n_region, 440 code_region 441 FROM dem.v_region WHERE 442 (lower(country) = lower(%(country)s)) 443 OR 444 (lower(l10n_country) = lower(%(country)s)) 445 OR 446 (code_country = %(country_code)s) 447 """ 448 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False) 449 if len(rows) == 1: 450 region = rows[0] 451 _log.debug('zip [%s] / urb [%s] / country [%s] (%s) => [%s]', zip, urb, country, country_code, region) 452 return region 453 _log.debug('zip [%s] / urb [%s] / country [%s] (%s) => [??]', zip, urb, country, country_code) 454 return None 455 456 if len(rows) > 2: 457 _log.debug('zip [%s] / urb [%s] / country [%s] (%s) => [%s]', zip, urb, country, country_code, rows) 458 return None 459 460 region = rows[0] 461 _log.debug('zip [%s] / urb [%s] / country [%s] (%s) => [%s]', zip, urb, country, country_code, region) 462 return region
463 464 #------------------------------------------------------------
465 -def map_region2code(region=None, country_code=None):
466 if country_code is None: 467 cmd = """ 468 SELECT code FROM dem.region WHERE lower(_(name)) = lower(%(region)s) 469 UNION 470 SELECT code FROM dem.region WHERE lower(name) = lower(%(region)s) 471 """ 472 else: 473 cmd = """ 474 SELECT code FROM dem.region WHERE lower(_(name)) = lower(%(region)s) AND lower(country) = lower(%(country_code)s) 475 UNION 476 SELECT code FROM dem.region WHERE lower(name) = %(region)s AND lower(country) = lower(%(country_code)s) 477 """ 478 args = { 479 'country_code': country_code, 480 'region': region 481 } 482 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False) 483 if len(rows) == 0: 484 return None 485 return rows[0][0]
486 487 #------------------------------------------------------------
488 -def delete_region(region=None, delete_urbs=False):
489 490 args = {'region': region} 491 492 queries = [] 493 if delete_urbs: 494 queries.append ({ 495 'cmd': """ 496 delete from dem.urb du 497 where 498 du.fk_region = %(region)s 499 and 500 not exists (select 1 from dem.street ds where ds.id_urb = du.id)""", 501 'args': args 502 }) 503 504 queries.append ({ 505 'cmd': """ 506 DELETE FROM dem.region d_r 507 WHERE 508 d_r.pk = %(region)s 509 AND 510 NOT EXISTS (SELECT 1 FROM dem.urb du WHERE du.fk_region = d_r.pk)""", 511 'args': args 512 }) 513 514 gmPG2.run_rw_queries(queries = queries) 515 516 return True
517 518 #------------------------------------------------------------
519 -def create_region(name=None, code=None, country=None):
520 521 args = {'code': code, 'country': country, 'name': name} 522 523 cmd = """SELECT EXISTS (SELECT 1 FROM dem.region WHERE name = %(name)s)""" 524 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False) 525 526 if rows[0][0]: 527 return 528 529 cmd = """ 530 INSERT INTO dem.region ( 531 code, country, name 532 ) VALUES ( 533 %(code)s, %(country)s, %(name)s 534 )""" 535 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
536 #------------------------------------------------------------
537 -def get_regions():
538 cmd = """ 539 select 540 l10n_region, l10n_country, region, code_region, code_country, pk_region, country_deprecated 541 from dem.v_region 542 order by l10n_country, l10n_region""" 543 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}]) 544 return rows
545 546 #============================================================ 547 # address related classes 548 #------------------------------------------------------------
549 -class cAddress(gmBusinessDBObject.cBusinessDBObject):
550 """A class representing an address as an entity in itself. 551 552 We consider addresses to be self-complete "labels" for locations. 553 It does not depend on any people actually living there. Thus 554 an address can get attached to as many people as we want to 555 signify that that is their place of residence/work/... 556 557 This class acts on the address as an entity. Therefore it can 558 modify the address fields. Think carefully about *modifying* 559 addresses attached to people, though. Most times when you think 560 person.modify_address() what you *really* want is as sequence of 561 person.unlink_address(old) and person.link_address(new). 562 563 Modifying an address may or may not be the proper thing to do as 564 it will transparently modify the address for *all* the people to 565 whom it is attached. In many cases you will want to create a *new* 566 address and link it to a person instead of the old address. 567 """ 568 _cmd_fetch_payload = "SELECT * FROM dem.v_address WHERE pk_address = %s" 569 _cmds_store_payload = [ 570 """UPDATE dem.address SET 571 aux_street = %(notes_street)s, 572 subunit = %(subunit)s, 573 addendum = %(notes_subunit)s, 574 lat_lon = %(lat_lon_street)s 575 WHERE 576 id = %(pk_address)s 577 AND 578 xmin = %(xmin_address)s 579 RETURNING 580 xmin AS xmin_address""" 581 ] 582 _updatable_fields = [ 583 'notes_street', 584 'subunit', 585 'notes_subunit', 586 'lat_lon_address' 587 ] 588 #--------------------------------------------------------
589 - def format(self, single_line=False, verbose=False, show_type=False):
590 if single_line: 591 return format_address_single_line(address = self, show_type = False, verbose = verbose) 592 return format_address(address = self, show_type = False)
593 594 #--------------------------------------------------------
595 - def _get_as_map_url(self):
596 url = 'http://nominatim.openstreetmap.org/search/%s/%s/%s/%s?limit=3' % ( 597 urllib.parse.quote(self['country'].encode('utf8')), 598 urllib.parse.quote(self['urb'].encode('utf8')), 599 urllib.parse.quote(self['street'].encode('utf8')), 600 urllib.parse.quote(self['number'].encode('utf8')) 601 ) 602 return url
603 604 as_map_url = property(_get_as_map_url, lambda x:x)
605 606 #------------------------------------------------------------
607 -def address_exists(country_code=None, region_code=None, urb=None, postcode=None, street=None, number=None, subunit=None):
608 609 cmd = """SELECT dem.address_exists(%(country_code)s, %(region_code)s, %(urb)s, %(postcode)s, %(street)s, %(number)s, %(subunit)s)""" 610 args = { 611 'country_code': country_code, 612 'region_code': region_code, 613 'urb': urb, 614 'postcode': postcode, 615 'street': street, 616 'number': number, 617 'subunit': subunit 618 } 619 620 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}]) 621 if rows[0][0] is None: 622 _log.debug('address does not exist') 623 for key, val in args.items(): 624 _log.debug('%s: %s', key, val) 625 return None 626 627 return rows[0][0]
628 629 #------------------------------------------------------------
630 -def create_address(country_code=None, region_code=None, urb=None, suburb=None, postcode=None, street=None, number=None, subunit=None):
631 632 if suburb is not None: 633 suburb = gmTools.none_if(suburb.strip(), '') 634 635 pk_address = address_exists ( 636 country_code = country_code, 637 region_code = region_code, 638 urb = urb, 639 # suburb = suburb, 640 postcode = postcode, 641 street = street, 642 number = number, 643 subunit = subunit 644 ) 645 if pk_address is not None: 646 return cAddress(aPK_obj = pk_address) 647 648 cmd = """ 649 SELECT dem.create_address ( 650 %(number)s, 651 %(street)s, 652 %(postcode)s, 653 %(urb)s, 654 %(region_code)s, 655 %(country_code)s, 656 %(subunit)s 657 )""" 658 args = { 659 'number': number, 660 'street': street, 661 'postcode': postcode, 662 'urb': urb, 663 'region_code': region_code, 664 'country_code': country_code, 665 'subunit': subunit 666 } 667 queries = [{'cmd': cmd, 'args': args}] 668 669 rows, idx = gmPG2.run_rw_queries(queries = queries, return_data = True) 670 adr = cAddress(aPK_obj = rows[0][0]) 671 672 if suburb is not None: 673 queries = [{ 674 # CAVE: suburb will be ignored if there already is one 675 'cmd': "UPDATE dem.street SET suburb = %(suburb)s WHERE id = %(pk_street)s AND suburb IS NULL", 676 'args': {'suburb': suburb, 'pk_street': adr['pk_street']} 677 }] 678 rows, idx = gmPG2.run_rw_queries(queries = queries) 679 680 return adr
681 #------------------------------------------------------------
682 -def delete_address(pk_address=None):
683 cmd = """ 684 DELETE FROM dem.address 685 WHERE 686 id = %(pk)s 687 AND 688 NOT EXISTS (( 689 SELECT 1 FROM dem.org_unit WHERE fk_address = %(pk)s LIMIT 1 690 ) UNION ( 691 SELECT 1 FROM dem.lnk_identity2comm WHERE fk_address = %(pk)s LIMIT 1 692 ) UNION ( 693 SELECT 1 FROM dem.lnk_person_org_address WHERE id_address = %(pk)s LIMIT 1 694 )) 695 """ 696 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': {'pk': pk_address}}]) 697 return True
698 699 #------------------------------------------------------------
700 -def format_address_single_line(address=None, verbose=False, show_type=False):
701 data = { 702 'pk_adr': address['pk_address'], 703 'street': address['street'], 704 'notes_street': gmTools.coalesce(address['notes_street'], '', ' (%s)'), 705 'number': address['number'], 706 'subunit': gmTools.coalesce(address['subunit'], '', '/%s'), 707 'notes_subunit': gmTools.coalesce(address['notes_subunit'], '', ' (%s)'), 708 'zip': address['postcode'], 709 'urb': address['urb'], 710 'suburb': gmTools.coalesce(address['suburb'], '', ' (%s)'), 711 'l10n_region': address['l10n_region'], 712 'code_region': address['code_region'], 713 'l10n_country': address['l10n_country'], 714 'code_country': address['code_country'] 715 } 716 if show_type: 717 data['type'] = address['l10n_address_type'] 718 719 if verbose: 720 if show_type: 721 template = _('%(type)s: %(street)s %(number)s%(subunit)s, %(zip)s %(urb)s %(suburb)s, %(code_region)s, %(code_country)s (%(l10n_region)s, %(l10n_country)s)') 722 else: 723 template = _('%(street)s %(number)s%(subunit)s, %(zip)s %(urb)s %(suburb)s, %(code_region)s, %(code_country)s (%(l10n_region)s, %(l10n_country)s)') 724 else: 725 if show_type: 726 template = _('%(type)s: %(street)s %(number)s%(subunit)s, %(zip)s %(urb)s, %(code_region)s, %(code_country)s (%(l10n_region)s, %(l10n_country)s)') 727 else: 728 template = _('%(street)s %(number)s%(subunit)s, %(zip)s %(urb)s, %(code_region)s, %(code_country)s (%(l10n_region)s, %(l10n_country)s)') 729 730 return template % data
731 732 #------------------------------------------------------------
733 -def format_address(address=None, show_type=False):
734 data = { 735 'pk_adr': address['pk_address'], 736 'street': address['street'], 737 'notes_street': gmTools.coalesce(address['notes_street'], '', ' (%s)'), 738 'number': address['number'], 739 'subunit': gmTools.coalesce(address['subunit'], '', '/%s'), 740 'notes_subunit': gmTools.coalesce(address['notes_subunit'], '', ' (%s)'), 741 'zip': address['postcode'], 742 'urb': address['urb'], 743 'suburb': gmTools.coalesce(address['suburb'], '', ' (%s)'), 744 'l10n_region': address['l10n_region'], 745 'code_region': address['code_region'], 746 'l10n_country': address['l10n_country'], 747 'code_country': address['code_country'] 748 } 749 if show_type: 750 data['type'] = address['l10n_address_type'] 751 template = _( 752 'Address (%(type)s) [#%(pk_adr)s]\n' 753 ' Street: %(street)s%(notes_street)s\n' 754 ' Number/Unit: %(number)s%(subunit)s%(notes_subunit)s\n' 755 ' Location: %(zip)s %(urb)s%(suburb)s\n' 756 ' Region: %(l10n_region)s, %(code_region)s\n' 757 ' Country: %(l10n_country)s, %(code_country)s' 758 ) 759 else: 760 template = _( 761 'Address [#%(pk_adr)s]\n' 762 ' Street: %(street)s%(notes_street)s\n' 763 ' Number/Unit: %(number)s%(subunit)s%(notes_subunit)s\n' 764 ' Location: %(zip)s %(urb)s%(suburb)s\n' 765 ' Region: %(l10n_region)s, %(code_region)s\n' 766 ' Country: %(l10n_country)s, %(code_country)s' 767 ) 768 txt = template % data 769 return txt.split('\n')
770 771 #------------------------------------------------------------
772 -def create_address_type(address_type=None):
773 args = {'typ': address_type} 774 cmd = 'INSERT INTO dem.address_type (name) SELECT %(typ)s WHERE NOT EXISTS (SELECT 1 FROM dem.address_type WHERE name = %(typ)s OR _(name) = %(typ)s)' 775 rows, idx = gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}]) 776 cmd = 'SELECT id FROM dem.address_type WHERE name = %(typ)s OR _(name) = %(typ)s' 777 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = False) 778 return rows[0][0]
779 780 #------------------------------------------------------------
781 -def get_address_types(identity=None):
782 cmd = 'select id as pk, name, _(name) as l10n_name from dem.address_type' 783 rows, idx = gmPG2.run_rw_queries(queries=[{'cmd': cmd}]) 784 return rows
785 786 #------------------------------------------------------------
787 -def get_addresses(order_by=None, return_pks=False):
788 789 if order_by is None: 790 order_by = '' 791 else: 792 order_by = 'ORDER BY %s' % order_by 793 794 cmd = "SELECT * FROM dem.v_address %s" % order_by 795 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = True) 796 if return_pks: 797 return [ r['pk_address'] for r in rows ] 798 return [ cAddress(row = {'data': r, 'idx': idx, 'pk_field': 'pk_address'}) for r in rows ]
799 800 #------------------------------------------------------------
801 -def get_address_from_patient_address_pk(pk_patient_address=None):
802 cmd = """ 803 SELECT * FROM dem.v_address WHERE 804 pk_address = ( 805 SELECT id_address 806 FROM dem.lnk_person_org_address 807 WHERE id = %(pk_pat_adr)s 808 ) 809 """ 810 args = {'pk_pat_adr': pk_patient_address} 811 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True) 812 if len(rows) == 0: 813 return None 814 815 return cAddress(row = {'data': rows[0], 'idx': idx, 'pk_field': 'pk_address'})
816 817 #===================================================================
818 -def get_patient_address(pk_patient_address=None, return_pks=False):
819 cmd = 'SELECT pk_address, pk_identity FROM dem.v_pat_addresses WHERE pk_lnk_person_org_address = %(pk)s' 820 args = {'pk': pk_patient_address} 821 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True) 822 if not rows: 823 return None 824 825 if return_pks: 826 return [ r['pk_address'] for r in rows ] 827 828 pk_data = { 829 'pk_adr': rows[0]['pk_address'], 830 'pk_pat': rows[0]['pk_identity'] 831 } 832 return cPatientAddress(aPK_obj = pk_data)
833 834 #-------------------------------------------------------------------
835 -def get_patient_address_by_type(pk_patient=None, adr_type=None):
836 cmd = 'SELECT pk_address, pk_identity FROM dem.v_pat_addresses WHERE pk_identity = %(pat)s AND (address_type = %(typ)s OR l10n_address_type = %(typ)s)' 837 args = {'pat': pk_patient, 'typ': adr_type} 838 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = True) 839 if len(rows) == 0: 840 return None 841 842 pk_data = { 843 'pk_adr': rows[0]['pk_address'], 844 'pk_pat': rows[0]['pk_identity'] 845 } 846 return cPatientAddress(aPK_obj = pk_data)
847 848 #-------------------------------------------------------------------
849 -class cPatientAddress(gmBusinessDBObject.cBusinessDBObject):
850 851 _cmd_fetch_payload = 'SELECT * FROM dem.v_pat_addresses WHERE pk_address = %(pk_adr)s AND pk_identity = %(pk_pat)s' 852 _cmds_store_payload = [ 853 """UPDATE dem.lnk_person_org_address SET 854 id_type = %(pk_address_type)s 855 WHERE 856 id = %(pk_lnk_person_org_address)s 857 AND 858 xmin = %(xmin_lnk_person_org_address)s 859 RETURNING 860 xmin AS xmin_lnk_person_org_address 861 """ 862 ] 863 _updatable_fields = ['pk_address_type'] 864 865 #---------------------------------------------------------------
866 - def get_identities(self, same_lastname=False):
867 pass
868 869 #--------------------------------------------------------
870 - def format(self, single_line=False, verbose=False, show_type=True):
871 if single_line: 872 return format_address_single_line(address = self, verbose = verbose, show_type = show_type) 873 txt = format_address(address = self, show_type = show_type) 874 return txt
875 876 #--------------------------------------------------------
877 - def _get_address(self):
878 return cAddress(aPK_obj = self._payload[self._idx['pk_address']])
879 880 address = property(_get_address, lambda x:x) 881 882 #--------------------------------------------------------
883 - def _get_as_map_url(self):
884 return self.address.as_map_url
885 886 as_map_url = property(_get_as_map_url, lambda x:x)
887 888 #=================================================================== 889 # communication channels API 890 #-------------------------------------------------------------------
891 -class cCommChannel(gmBusinessDBObject.cBusinessDBObject):
892 893 _cmd_fetch_payload = "SELECT * FROM dem.v_person_comms WHERE pk_lnk_identity2comm = %s" 894 _cmds_store_payload = [ 895 """UPDATE dem.lnk_identity2comm SET 896 --fk_address = %(pk_address)s, 897 fk_type = dem.create_comm_type(%(comm_type)s), 898 url = %(url)s, 899 is_confidential = %(is_confidential)s, 900 comment = gm.nullify_empty_string(%(comment)s) 901 WHERE 902 pk = %(pk_lnk_identity2comm)s 903 AND 904 xmin = %(xmin_lnk_identity2comm)s 905 RETURNING 906 xmin AS xmin_lnk_identity2comm 907 """ 908 ] 909 _updatable_fields = [ 910 'url', 911 'comm_type', 912 'is_confidential', 913 'comment' 914 ]
915 916 #-------------------------------------------------------------------
917 -class cOrgCommChannel(gmBusinessDBObject.cBusinessDBObject):
918 919 _cmd_fetch_payload = "SELECT * FROM dem.v_org_unit_comms WHERE pk_lnk_org_unit2comm = %s" 920 _cmds_store_payload = [ 921 """UPDATE dem.lnk_org_unit2comm SET 922 fk_type = dem.create_comm_type(%(comm_type)s), 923 url = %(url)s, 924 is_confidential = %(is_confidential)s, 925 comment = gm.nullify_empty_string(%(comment)s) 926 WHERE 927 pk = %(pk_lnk_org_unit2comm)s 928 AND 929 xmin = %(xmin_lnk_org_unit2comm)s 930 RETURNING 931 xmin AS xmin_lnk_org_unit2comm 932 """ 933 ] 934 _updatable_fields = [ 935 'url', 936 'comm_type', 937 'is_confidential', 938 'comment' 939 ]
940 941 #-------------------------------------------------------------------
942 -def create_comm_channel(comm_medium=None, url=None, is_confidential=False, pk_channel_type=None, pk_identity=None, pk_org_unit=None):
943 """Create a communications channel for a patient.""" 944 945 if url is None: 946 return None 947 948 args = { 949 'url': url, 950 'secret': is_confidential, 951 'pk_type': pk_channel_type, 952 'type': comm_medium 953 } 954 955 if pk_identity is not None: 956 args['pk_owner'] = pk_identity 957 tbl = 'dem.lnk_identity2comm' 958 col = 'fk_identity' 959 view = 'dem.v_person_comms' 960 view_pk = 'pk_lnk_identity2comm' 961 channel_class = cCommChannel 962 if pk_org_unit is not None: 963 args['pk_owner'] = pk_org_unit 964 tbl = 'dem.lnk_org_unit2comm' 965 col = 'fk_org_unit' 966 view = 'dem.v_org_unit_comms' 967 view_pk = 'pk_lnk_org_unit2comm' 968 channel_class = cOrgCommChannel 969 970 if pk_channel_type is None: 971 cmd = """INSERT INTO %s ( 972 %s, 973 url, 974 fk_type, 975 is_confidential 976 ) VALUES ( 977 %%(pk_owner)s, 978 %%(url)s, 979 dem.create_comm_type(%%(type)s), 980 %%(secret)s 981 )""" % (tbl, col) 982 else: 983 cmd = """INSERT INTO %s ( 984 %s, 985 url, 986 fk_type, 987 is_confidential 988 ) VALUES ( 989 %%(pk_owner)s, 990 %%(url)s, 991 %%(pk_type)s, 992 %%(secret)s 993 )""" % (tbl, col) 994 995 queries = [{'cmd': cmd, 'args': args}] 996 cmd = "SELECT * FROM %s WHERE %s = currval(pg_get_serial_sequence('%s', 'pk'))" % (view, view_pk, tbl) 997 queries.append({'cmd': cmd}) 998 999 rows, idx = gmPG2.run_rw_queries(queries = queries, return_data = True, get_col_idx = True) 1000 1001 if pk_identity is not None: 1002 return cCommChannel(row = {'pk_field': view_pk, 'data': rows[0], 'idx': idx}) 1003 1004 return channel_class(row = {'pk_field': view_pk, 'data': rows[0], 'idx': idx})
1005 #-------------------------------------------------------------------
1006 -def delete_comm_channel(pk=None, pk_patient=None, pk_org_unit=None):
1007 if pk_patient is not None: 1008 query = { 1009 'cmd': "DELETE FROM dem.lnk_identity2comm WHERE pk = %(pk)s AND fk_identity = %(pat)s", 1010 'args': {'pk': pk, 'pat': pk_patient} 1011 } 1012 if pk_org_unit is not None: 1013 query = { 1014 'cmd': "DELETE FROM dem.lnk_org_unit2comm WHERE pk = %(pk)s AND fk_org_unit = %(unit)s", 1015 'args': {'pk': pk, 'unit': pk_org_unit} 1016 } 1017 gmPG2.run_rw_queries(queries = [query])
1018 #-------------------------------------------------------------------
1019 -def get_comm_channel_types():
1020 cmd = "SELECT pk, _(description) AS l10n_description, description FROM dem.enum_comm_types" 1021 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd}], get_col_idx = False) 1022 return rows
1023 #-------------------------------------------------------------------
1024 -def delete_comm_channel_type(pk_channel_type=None):
1025 cmd = """ 1026 DELETE FROM dem.enum_comm_types 1027 WHERE 1028 pk = %(pk)s 1029 AND NOT EXISTS ( 1030 SELECT 1 FROM dem.lnk_identity2comm WHERE fk_type = %(pk)s 1031 ) 1032 AND NOT EXISTS ( 1033 SELECT 1 FROM dem.lnk_org_unit2comm WHERE fk_type = %(pk)s 1034 ) 1035 """ 1036 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': {'pk': pk_channel_type}}]) 1037 return True
1038 #=================================================================== 1039 #------------------------------------------------------------------- 1040 1041 #==============================================================================
1042 -def get_time_tuple (mx):
1043 """ 1044 wrap mx.DateTime brokenness 1045 Returns 9-tuple for use with pyhon time functions 1046 """ 1047 return [ int(x) for x in str(mx).split(' ')[0].split('-') ] + [0,0,0, 0,0,0]
1048 #----------------------------------------------------------------
1049 -def getAddressTypes():
1050 """Gets a dict matching address types to their ID""" 1051 row_list = gmPG.run_ro_query('personalia', "select name, id from dem.address_type") 1052 if row_list is None: 1053 return {} 1054 if len(row_list) == 0: 1055 return {} 1056 return dict (row_list)
1057 #----------------------------------------------------------------
1058 -def getMaritalStatusTypes():
1059 """Gets a dictionary matching marital status types to their internal ID""" 1060 row_list = gmPG.run_ro_query('personalia', "select name, pk from dem.marital_status") 1061 if row_list is None: 1062 return {} 1063 if len(row_list) == 0: 1064 return {} 1065 return dict(row_list)
1066 #------------------------------------------------------------------
1067 -def getRelationshipTypes():
1068 """Gets a dictionary of relationship types to internal id""" 1069 row_list = gmPG.run_ro_query('personalia', "select description, id from dem.relation_types") 1070 if row_list is None: 1071 return None 1072 if len (row_list) == 0: 1073 return None 1074 return dict(row_list)
1075 1076 #----------------------------------------------------------------
1077 -def getUrb (id_urb):
1078 cmd = """ 1079 select 1080 dem.region.name, 1081 dem.urb.postcode 1082 from 1083 dem.urb, 1084 dem.region 1085 where 1086 dem.urb.id = %s and 1087 dem.urb.fk_region = dem.region.pk""" 1088 row_list = gmPG.run_ro_query('personalia', cmd, None, id_urb) 1089 if not row_list: 1090 return None 1091 else: 1092 return (row_list[0][0], row_list[0][1])
1093
1094 -def getStreet (id_street):
1095 cmd = """ 1096 select 1097 dem.region.name, 1098 coalesce (dem.street.postcode, dem.urb.postcode), 1099 dem.urb.name 1100 from 1101 dem.urb, 1102 dem.region, 1103 dem.street 1104 where 1105 dem.street.id = %s and 1106 dem.street.id_urb = dem.urb.id and 1107 dem.urb.fk_region = dem.region.pk 1108 """ 1109 row_list = gmPG.run_ro_query('personalia', cmd, None, id_street) 1110 if not row_list: 1111 return None 1112 else: 1113 return (row_list[0][0], row_list[0][1], row_list[0][2])
1114
1115 -def getCountry (country_code):
1116 row_list = gmPG.run_ro_query('personalia', "select name from dem.country where code = %s", None, country_code) 1117 if not row_list: 1118 return None 1119 else: 1120 return row_list[0][0]
1121 #-------------------------------------------------------------------------------
1122 -def get_town_data (town):
1123 row_list = gmPG.run_ro_query ('personalia', """ 1124 select 1125 dem.urb.postcode, 1126 dem.region.code, 1127 dem.region.name, 1128 dem.country.code, 1129 dem.country.name 1130 from 1131 dem.urb, 1132 dem.region, 1133 dem.country 1134 where 1135 dem.urb.name = %s and 1136 dem.urb.fk_region = dem.region.pk and 1137 dem.region.country = dem.country.code""", None, town) 1138 if not row_list: 1139 return (None, None, None, None, None) 1140 else: 1141 return tuple (row_list[0])
1142 #============================================================ 1143 # callbacks 1144 #------------------------------------------------------------
1145 -def _post_patient_selection(**kwargs):
1146 print("received post_patient_selection notification") 1147 print(kwargs['kwds'])
1148 #============================================================ 1149 1150 #============================================================ 1151 # main 1152 #------------------------------------------------------------ 1153 if __name__ == "__main__": 1154 1155 if len(sys.argv) < 2: 1156 sys.exit() 1157 1158 if sys.argv[1] != 'test': 1159 sys.exit() 1160 1161 import random 1162 1163 from Gnumed.pycommon import gmConnectionPool 1164 #--------------------------------------------------------
1165 - def test_address_exists():
1166 1167 addresses = [ 1168 { 1169 'country_code': 'Germany', 1170 'region_code': 'Sachsen', 1171 'urb': 'Hannover', 1172 'postcode': '06672', 1173 'street': 'Rommelsberger Strasse', 1174 'number': '11' 1175 }, 1176 { 1177 'country_code': 'DE', 1178 'region_code': 'SN', 1179 'urb': 'Hannover', 1180 'postcode': '06671', 1181 'street': 'Tonnenstraße', 1182 'number': '65', 1183 'subunit': 'Parterre' 1184 }, 1185 { 1186 'country_code': 'DE', 1187 'region_code': 'SN', 1188 'urb': 'Hannover', 1189 'postcode': '06671', 1190 'street': 'Tonnenstraße', 1191 'number': '65', 1192 'subunit': '1. Stock' 1193 }, 1194 { 1195 'country_code': 'DE', 1196 'region_code': 'SN', 1197 'urb': 'Hannover', 1198 'postcode': '06671', 1199 'street': 'Tonnenstraße', 1200 'number': '65', 1201 'subunit': '1. Stock' 1202 }, 1203 { 1204 # 'country': 'DE', 1205 # 'region_code': 'HV', 1206 'urb': 'Hannover', 1207 'postcode': '06671', 1208 'street': 'Tonnenstraße', 1209 'number': '65', 1210 'subunit': '1. Stock' 1211 }, 1212 ] 1213 1214 for adr in addresses: 1215 print(adr) 1216 exists = address_exists(**adr) 1217 if exists is None: 1218 print("address does not exist") 1219 else: 1220 print("address exists, primary key:", exists)
1221 1222 #--------------------------------------------------------
1223 - def test_create_address():
1224 address = create_address ( 1225 country_code = 'DE', 1226 region_code = 'SN', 1227 urb ='Hannover', 1228 suburb ='Grabenthal', 1229 postcode ='06672', 1230 street = 'Rommelsberger Strasse', 1231 number = '11' 1232 # ,notes_subunit = '2.Stock oben' 1233 ) 1234 print("created existing address") 1235 print(address.format()) 1236 1237 su = str(random.random()) 1238 1239 address = create_address ( 1240 country_code = 'DE', 1241 region_code = 'SN', 1242 urb ='Hannover', 1243 suburb ='Grabenthal', 1244 postcode ='06672', 1245 street = 'Rommelsberger Strasse', 1246 number = '11', 1247 # notes_subunit = '2.Stock oben', 1248 subunit = su 1249 ) 1250 print("created new address with subunit", su) 1251 print(address) 1252 print(address.format()) 1253 print(address.as_map_url) 1254 print("deleted address:", delete_address(pk_address = address['pk_address']))
1255 #--------------------------------------------------------
1256 - def test_get_countries():
1257 for c in get_countries(): 1258 print(c)
1259 #--------------------------------------------------------
1260 - def test_get_country_for_region():
1261 region = input("Please enter a region: ") 1262 print("country for region [%s] is: %s" % (region, get_country_for_region(region = region)))
1263 #--------------------------------------------------------
1264 - def test_delete_tag():
1265 if delete_tag_image(tag_image = 9999): 1266 print("deleted tag 9999") 1267 else: 1268 print("did not delete tag 9999") 1269 if delete_tag_image(tag_image = 1): 1270 print("deleted tag 1") 1271 else: 1272 print("did not delete tag 1")
1273 #--------------------------------------------------------
1274 - def test_tag_images():
1275 tag = cTagImage(aPK_obj = 1) 1276 print(tag)
1277 #print get_tag_images() 1278 #--------------------------------------------------------
1279 - def test_get_billing_address():
1280 print(get_patient_address_by_type(pk_patient = 12, adr_type = 'billing'))
1281 #--------------------------------------------------------
1282 - def test_map_urb_zip_region2country():
1283 print(map_urb_zip_region2country(urb = 'Kassel', zip = '34119', region = 'Hessen')) 1284 print(map_urb_zip_region2country(urb = 'Kassel', zip = None, region = 'Hessen')) 1285 print(map_urb_zip_region2country(urb = None, zip = '34119', region = 'Hessen')) 1286 print(map_urb_zip_region2country(urb = 'Kassel', zip = '34119', region = None))
1287 #--------------------------------------------------------
1288 - def test_map_urb_zip_country2region():
1289 print(map_urb_zip_country2region(urb = 'Kassel', zip = '34119', country = 'Germany', country_code = 'DE')) 1290 print(map_urb_zip_country2region(urb = 'Kassel', zip = '34119', country = 'Germany', country_code = None)) 1291 print(map_urb_zip_country2region(urb = 'Kassel', zip = '34119', country = 'Deutschland', country_code = 'DE')) 1292 print(map_urb_zip_country2region(urb = 'Kassel', zip = '34119', country = 'Deutschland', country_code = None)) 1293 print(map_urb_zip_country2region(urb = 'Kassel', zip = '34119', country = None, country_code = 'DE')) 1294 print(map_urb_zip_country2region(urb = 'Kassel', zip = '34119', country = None, country_code = None))
1295 1296 # print map_urb_zip_country2region(urb = 'Kassel', zip = '34119', country = u'Deutschland', country_code = 'DE') 1297 # print map_urb_zip_country2region(urb = 'Kassel', zip = '34119', country = u'Deutschland', country_code = 'DE') 1298 # print map_urb_zip_country2region(urb = 'Kassel', zip = '34119', country = u'Deutschland', country_code = 'DE') 1299 # print map_urb_zip_country2region(urb = 'Kassel', zip = '34119', country = u'Deutschland', country_code = 'DE') 1300 1301 #-------------------------------------------------------- 1302 #gmPG2.get_connection() 1303 l, creds = gmPG2.request_login_params() 1304 gmConnectionPool.gmConnectionPool().credentials = creds 1305 1306 test_address_exists() 1307 #test_create_address() 1308 #test_get_countries() 1309 #test_get_country_for_region() 1310 #test_delete_tag() 1311 #test_tag_images() 1312 test_get_billing_address() 1313 #test_map_urb_zip_region2country() 1314 #test_map_urb_zip_country2region() 1315