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