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

Source Code for Module Gnumed.business.gmKVK

  1  # -*- coding: utf-8 -*- 
  2  """GNUmed German KVK/eGK objects. 
  3   
  4  These objects handle German patient cards (KVK and eGK). 
  5   
  6  KVK: http://www.kbv.de/ita/register_G.html 
  7  eGK: http://www.gematik.de/upload/gematik_Qop_eGK_Spezifikation_Teil1_V1_1_0_Kommentare_4_1652.pdf 
  8  """ 
  9  #============================================================ 
 10  __author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>" 
 11  __license__ = "GPL v2 or later" 
 12   
 13  import sys 
 14  import os 
 15  import os.path 
 16  import fileinput 
 17  import io 
 18  import time 
 19  import glob 
 20  import datetime as pyDT 
 21  import re as regex 
 22  #import simplejson as json 
 23  import logging 
 24   
 25   
 26  # our modules 
 27  if __name__ == '__main__': 
 28          sys.path.insert(0, '../../') 
 29  from Gnumed.business import gmPerson 
 30  from Gnumed.pycommon import gmExceptions, gmDateTime, gmTools, gmPG2 
 31   
 32   
 33  _log = logging.getLogger('gm.kvk') 
 34   
 35  true_egk_fields = [ 
 36          'insurance_company', 
 37          'insurance_number', 
 38          'insuree_number', 
 39          'insuree_status', 
 40          'insuree_status_detail', 
 41          'insuree_status_comment', 
 42          'title', 
 43          'firstnames', 
 44          'lastnames', 
 45          'dob', 
 46          'street', 
 47          'zip', 
 48          'urb', 
 49          'valid_since', 
 50  ] 
 51   
 52   
 53  true_kvk_fields = [ 
 54          'insurance_company', 
 55          'insurance_number', 
 56          'insurance_number_vknr', 
 57          'insuree_number', 
 58          'insuree_status', 
 59          'insuree_status_detail', 
 60          'insuree_status_comment', 
 61          'title', 
 62          'firstnames', 
 63          'name_affix', 
 64          'lastnames', 
 65          'dob', 
 66          'street', 
 67          'urb_region_code', 
 68          'zip', 
 69          'urb', 
 70          'valid_until' 
 71  ] 
 72   
 73   
 74  map_kvkd_tags2dto = { 
 75          'Version': 'libchipcard_version', 
 76          'Datum': 'last_read_date', 
 77          'Zeit': 'last_read_time', 
 78          'Lesertyp': 'reader_type', 
 79          'Kartentyp': 'card_type', 
 80          'KK-Name': 'insurance_company', 
 81          'KK-Nummer': 'insurance_number', 
 82          'KVK-Nummer': 'insurance_number_vknr', 
 83          'VKNR': 'insurance_number_vknr', 
 84          'V-Nummer': 'insuree_number', 
 85          'V-Status': 'insuree_status', 
 86          'V-Statusergaenzung': 'insuree_status_detail', 
 87          'V-Status-Erlaeuterung': 'insuree_status_comment', 
 88          'Titel': 'title', 
 89          'Vorname': 'firstnames', 
 90          'Namenszusatz': 'name_affix', 
 91          'Familienname': 'lastnames', 
 92          'Geburtsdatum': 'dob', 
 93          'Strasse': 'street', 
 94          'Laendercode': 'urb_region_code', 
 95          'PLZ': 'zip', 
 96          'Ort': 'urb', 
 97          'gueltig-seit': 'valid_since', 
 98          'gueltig-bis': 'valid_until', 
 99          'Pruefsumme-gueltig': 'crc_valid', 
100          'Kommentar': 'comment' 
101  } 
102   
103   
104  map_CCRdr_gender2gm = { 
105          'M': 'm', 
106          'W': 'f', 
107          'U': None 
108  } 
109   
110   
111  map_CCRdr_region_code2country = { 
112          'D': 'DE' 
113  } 
114   
115   
116  EXTERNAL_ID_ISSUER_TEMPLATE = '%s (%s)' 
117  EXTERNAL_ID_TYPE_VK_INSUREE_NUMBER = 'Versichertennummer' 
118  EXTERNAL_ID_TYPE_VK_INSUREE_NUMBER_EGK = 'Versichertennummer (eGK)' 
119   
120  #============================================================ 
121 -class cDTO_CCRdr(gmPerson.cDTO_person):
122
123 - def __init__(self, filename=None, strict=True):
124 125 gmPerson.cDTO_person.__init__(self) 126 127 self.filename = filename 128 self.date_format = '%Y%m%d' 129 self.valid_since = None 130 self.valid_until = None 131 self.card_is_rejected = False 132 self.card_is_expired = False 133 134 self.__load_vk_file()
135 136 # if we need to interpret KBV requirements by the 137 # letter we have to delete the file right here 138 #self.delete_from_source() 139 140 #-------------------------------------------------------- 141 # external API 142 #--------------------------------------------------------
143 - def get_candidate_identities(self, can_create = False):
144 old_idents = gmPerson.cDTO_person.get_candidate_identities(self, can_create = can_create) 145 146 # look for candidates based on their Insuree Number 147 if not self.card_is_rejected: 148 cmd = """ 149 SELECT pk_identity FROM dem.v_external_ids4identity WHERE 150 value = %(val)s AND 151 name = %(name)s AND 152 issuer = %(kk)s 153 """ 154 args = { 155 'val': self.insuree_number, 156 'name': '%s (%s)' % ( 157 EXTERNAL_ID_TYPE_VK_INSUREE_NUMBER, 158 self.raw_data['Karte'] 159 ), 160 'kk': EXTERNAL_ID_ISSUER_TEMPLATE % (self.raw_data['KostentraegerName'], self.raw_data['Kostentraegerkennung']) 161 } 162 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}], get_col_idx = None) 163 164 # weed out duplicates 165 name_candidate_ids = [ o.ID for o in old_idents ] 166 for r in rows: 167 if r[0] not in name_candidate_ids: 168 old_idents.append(gmPerson.cPerson(aPK_obj = r[0])) 169 170 return old_idents
171 172 #--------------------------------------------------------
173 - def delete_from_source(self):
174 # try: 175 # os.remove(self.filename) 176 # self.filename = None 177 # except: 178 # _log.exception('cannot delete CCReader file [%s]' % self.filename, verbose = False) 179 pass # for now
180 181 #--------------------------------------------------------
182 - def import_extra_data(self, identity=None, *args, **kwargs):
183 if not self.card_is_rejected: 184 args = { 185 'pat': identity.ID, 186 'dob': self.preformatted_dob, 187 'valid_until': self.valid_until, 188 'data': self.raw_data 189 } 190 cmd = """ 191 INSERT INTO de_de.insurance_card ( 192 fk_identity, 193 formatted_dob, 194 valid_until, 195 raw_data 196 ) VALUES ( 197 %(pat)s, 198 %(dob)s, 199 %(valid_until)s, 200 %(data)s 201 )""" 202 gmPG2.run_rw_queries(queries = [{'cmd': cmd, 'args': args}])
203 204 #-------------------------------------------------------- 205 # internal helpers 206 #--------------------------------------------------------
207 - def __load_vk_file(self):
208 209 _log.debug('loading eGK/KVK/PKVK data from [%s]', self.filename) 210 vk_file = io.open(self.filename, mode = 'rt', encoding = 'utf8') 211 self.raw_data = json.load(vk_file) 212 vk_file.close() 213 214 if self.raw_data['Fehlerbericht']['FehlerNr'] != '0x9000': 215 _log.error('error [%s] reading VK: %s', self.raw_data['Fehlerbericht']['FehlerNr'], self.raw_data['Fehlerbericht']['Fehlermeldung']) 216 raise ValueError('error [%s] reading VK: %s' % (self.raw_data['Fehlerbericht']['FehlerNr'], self.raw_data['Fehlerbericht']['Fehlermeldung'])) 217 218 # rejection 219 if self.raw_data['Ablehnen'] == 'ja': 220 self.card_is_rejected = True 221 _log.info('eGK may contain insurance information but KBV says it must be rejected because it is of generation 0') 222 223 # validity 224 # - since 225 tmp = time.strptime(self.raw_data['VersicherungsschutzBeginn'], self.date_format) 226 self.valid_since = pyDT.date(tmp.tm_year, tmp.tm_mon, tmp.tm_mday) 227 # - until 228 tmp = time.strptime(self.raw_data['VersicherungsschutzEnde'], self.date_format) 229 self.valid_until = pyDT.date(tmp.tm_year, tmp.tm_mon, tmp.tm_mday) 230 if self.valid_until < pyDT.date.today(): 231 self.card_is_expired = True 232 233 # DTO source 234 src_attrs = [] 235 if self.card_is_expired: 236 src_attrs.append(_('expired')) 237 if self.card_is_rejected: 238 _log.info('eGK contains insurance information but KBV says it must be rejected because it is of generation 0') 239 src_attrs.append(_('rejected')) 240 src_attrs.append('CCReader') 241 self.source = '%s (%s)' % ( 242 self.raw_data['Karte'], 243 ', '.join(src_attrs) 244 ) 245 246 # name / gender 247 self.firstnames = self.raw_data['Vorname'] 248 self.lastnames = self.raw_data['Nachname'] 249 self.gender = map_CCRdr_gender2gm[self.raw_data['Geschlecht']] 250 251 # title 252 title_parts = [] 253 for part in ['Titel', 'Namenszusatz', 'Vorsatzwort']: 254 tmp = self.raw_data[part].strip() 255 if tmp == '': 256 continue 257 title_parts.append(tmp) 258 if len(title_parts) > 0: 259 self.title = ' '.join(title_parts) 260 261 # dob 262 dob_str = self.raw_data['Geburtsdatum'] 263 year_str = dob_str[:4] 264 month_str = dob_str[4:6] 265 day_str = dob_str[6:8] 266 self.preformatted_dob = '%s.%s.%s' % (day_str, month_str, year_str) # pre-format for printing including "0"-parts 267 if year_str == '0000': 268 self.dob = None # redundant but explicit is good 269 else: 270 if day_str == '00': 271 self.dob_is_estimated = True 272 day_str = '01' 273 if month_str == '00': 274 self.dob_is_estimated = True 275 month_str = '01' 276 dob_str = year_str + month_str + day_str 277 tmp = time.strptime(dob_str, self.date_format) 278 self.dob = pyDT.datetime(tmp.tm_year, tmp.tm_mon, tmp.tm_mday, 11, 11, 11, 111, tzinfo = gmDateTime.gmCurrentLocalTimezone) 279 280 # addresses 281 # - street 282 try: 283 adr = self.raw_data['StrassenAdresse'] 284 try: 285 self.remember_address ( 286 adr_type = 'eGK (Wohnadresse)', 287 number = adr['Hausnummer'], 288 subunit = adr['Anschriftenzusatz'], 289 street = adr['Strasse'], 290 urb = adr['Ort'], 291 region_code = '', 292 zip = adr['Postleitzahl'], 293 country_code = map_CCRdr_region_code2country[adr['Wohnsitzlaendercode']] 294 ) 295 except ValueError: 296 _log.exception('invalid street address on card') 297 except KeyError: 298 _log.error('unknown country code [%s] on card in street address', adr['Wohnsitzlaendercode']) 299 except KeyError: 300 _log.warning('no street address on card') 301 # PO Box 302 try: 303 adr = self.raw_data['PostfachAdresse'] 304 try: 305 self.remember_address ( 306 adr_type = 'eGK (Postfach)', 307 number = adr['Postfach'], 308 #subunit = adr['Anschriftenzusatz'], 309 street = _('PO Box'), 310 urb = adr['PostfachOrt'], 311 region_code = '', 312 zip = adr['PostfachPLZ'], 313 country_code = map_CCRdr_region_code2country[adr['PostfachWohnsitzlaendercode']] 314 ) 315 except ValueError: 316 _log.exception('invalid PO Box address on card') 317 except KeyError: 318 _log.error('unknown country code [%s] on card in PO Box address', adr['Wohnsitzlaendercode']) 319 except KeyError: 320 _log.warning('no PO Box address on card') 321 322 if not (self.card_is_expired or self.card_is_rejected): 323 self.insuree_number = None 324 try: 325 self.insuree_number = self.raw_data['Versicherten_ID'] 326 except KeyError: 327 pass 328 try: 329 self.insuree_number = self.raw_data['Versicherten_ID_KVK'] 330 except KeyError: 331 pass 332 try: 333 self.insuree_number = self.raw_data['Versicherten_ID_PKV'] 334 except KeyError: 335 pass 336 if self.insuree_number is not None: 337 try: 338 self.remember_external_id ( 339 name = '%s (%s)' % ( 340 EXTERNAL_ID_TYPE_VK_INSUREE_NUMBER, 341 self.raw_data['Karte'] 342 ), 343 value = self.insuree_number, 344 issuer = EXTERNAL_ID_ISSUER_TEMPLATE % (self.raw_data['KostentraegerName'], self.raw_data['Kostentraegerkennung']), 345 comment = 'Nummer (eGK) des Versicherten bei der Krankenkasse, gültig: %s - %s' % ( 346 gmDateTime.pydt_strftime(self.valid_since, '%Y %b %d'), 347 gmDateTime.pydt_strftime(self.valid_until, '%Y %b %d') 348 ) 349 ) 350 except KeyError: 351 _log.exception('no insurance information on eGK')
352 353 #============================================================
354 -class cDTO_eGK(gmPerson.cDTO_person):
355 356 kvkd_card_id_string = 'Elektronische Gesundheitskarte' 357
358 - def __init__(self, filename=None, strict=True):
359 self.card_type = 'eGK' 360 self.dob_format = '%d%m%Y' 361 self.valid_since_format = '%d%m%Y' 362 self.last_read_time_format = '%H:%M:%S' 363 self.last_read_date_format = '%d.%m.%Y' 364 self.filename = filename 365 366 self.__parse_egk_file(strict = strict)
367 368 # if we need to interpret KBV requirements by the 369 # letter we have to delete the file right here 370 #self.delete_from_source() 371 #-------------------------------------------------------- 372 # external API 373 #--------------------------------------------------------
374 - def get_candidate_identities(self, can_create = False):
375 old_idents = gmPerson.cDTO_person.get_candidate_identities(self, can_create = can_create) 376 377 cmd = """ 378 select pk_identity from dem.v_external_ids4identity where 379 value = %(val)s and 380 name = %(name)s and 381 issuer = %(kk)s 382 """ 383 args = { 384 'val': self.insuree_number, 385 'name': EXTERNAL_ID_TYPE_VK_INSUREE_NUMBER, 386 'kk': EXTERNAL_ID_ISSUER_TEMPLATE % (self.insurance_company, self.insurance_number) 387 } 388 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}]) 389 390 # weed out duplicates 391 new_idents = [] 392 for r in rows: 393 for oid in old_idents: 394 if r[0] == oid.ID: 395 break 396 new_idents.append(gmPerson.cPerson(aPK_obj = r['pk_identity'])) 397 398 old_idents.extend(new_idents) 399 400 return old_idents
401 #--------------------------------------------------------
402 - def import_extra_data(self, identity=None, *args, **kwargs):
403 # FIXME: rather use remember_external_id() 404 405 # Versicherungsnummer 406 identity.add_external_id ( 407 type_name = EXTERNAL_ID_TYPE_VK_INSUREE_NUMBER_EGK, 408 value = self.insuree_number, 409 issuer = EXTERNAL_ID_ISSUER_TEMPLATE % (self.insurance_company, self.insurance_number), 410 comment = 'Nummer (eGK) des Versicherten bei der Krankenkasse' 411 ) 412 # address 413 street = self.street 414 number = regex.findall(' \d+.*', street) 415 if len(number) == 0: 416 number = None 417 else: 418 street = street.replace(number[0], '') 419 number = number[0].strip() 420 identity.link_address ( 421 number = number, 422 street = street, 423 postcode = self.zip, 424 urb = self.urb, 425 region_code = '', # actually: map urb2region ? 426 country_code = 'DE' # actually: map urb+region2country_code 427 )
428 # FIXME: eGK itself 429 #--------------------------------------------------------
430 - def delete_from_source(self):
431 try: 432 os.remove(self.filename) 433 self.filename = None 434 except: 435 _log.exception('cannot delete kvkd file [%s]' % self.filename, verbose = False)
436 #-------------------------------------------------------- 437 # internal helpers 438 #--------------------------------------------------------
439 - def __parse_egk_file(self, strict=True):
440 441 _log.debug('parsing eGK data in [%s]', self.filename) 442 443 egk_file = io.open(self.filename, mode = 'rt', encoding = 'utf8') 444 445 card_type_seen = False 446 for line in egk_file: 447 line = line.replace('\n', '').replace('\r', '') 448 tag, content = line.split(':', 1) 449 content = content.strip() 450 451 if tag == 'Kartentyp': 452 card_type_seen = True 453 if content != cDTO_eGK.kvkd_card_id_string: 454 _log.error('parsing wrong card type') 455 _log.error('found : %s', content) 456 _log.error('expected: %s', cDTO_KVK.kvkd_card_id_string) 457 if strict: 458 raise ValueError('wrong card type: %s, expected %s', content, cDTO_KVK.kvkd_card_id_string) 459 else: 460 _log.debug('trying to parse anyway') 461 462 if tag == 'Geburtsdatum': 463 tmp = time.strptime(content, self.dob_format) 464 content = pyDT.datetime(tmp.tm_year, tmp.tm_mon, tmp.tm_mday, tzinfo = gmDateTime.gmCurrentLocalTimezone) 465 466 try: 467 setattr(self, map_kvkd_tags2dto[tag], content) 468 except KeyError: 469 _log.exception('unknown KVKd eGK file key [%s]' % tag) 470 471 # valid_since -> valid_since_timestamp 472 ts = time.strptime ( 473 '%s20%s' % (self.valid_since[:4], self.valid_since[4:]), 474 self.valid_since_format 475 ) 476 477 # last_read_date and last_read_time -> last_read_timestamp 478 ts = time.strptime ( 479 '%s %s' % (self.last_read_date, self.last_read_time), 480 '%s %s' % (self.last_read_date_format, self.last_read_time_format) 481 ) 482 self.last_read_timestamp = pyDT.datetime(ts.tm_year, ts.tm_mon, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec, tzinfo = gmDateTime.gmCurrentLocalTimezone) 483 484 # guess gender from firstname 485 self.gender = gmTools.coalesce(gmPerson.map_firstnames2gender(firstnames=self.firstnames), 'f') 486 487 if not card_type_seen: 488 _log.warning('no line with card type found, unable to verify')
489 490 #============================================================
491 -class cDTO_KVK(gmPerson.cDTO_person):
492 493 kvkd_card_id_string = 'Krankenversichertenkarte' 494
495 - def __init__(self, filename=None, strict=True):
496 self.card_type = 'KVK' 497 self.dob_format = '%d%m%Y' 498 self.valid_until_format = '%d%m%Y' 499 self.last_read_time_format = '%H:%M:%S' 500 self.last_read_date_format = '%d.%m.%Y' 501 self.filename = filename 502 503 self.__parse_kvk_file(strict = strict)
504 505 # if we need to interpret KBV requirements by the 506 # letter we have to delete the file right here 507 #self.delete_from_source() 508 #-------------------------------------------------------- 509 # external API 510 #--------------------------------------------------------
511 - def get_candidate_identities(self, can_create = False):
512 old_idents = gmPerson.cDTO_person.get_candidate_identities(self, can_create = can_create) 513 514 cmd = """ 515 select pk_identity from dem.v_external_ids4identity where 516 value = %(val)s and 517 name = %(name)s and 518 issuer = %(kk)s 519 """ 520 args = { 521 'val': self.insuree_number, 522 'name': EXTERNAL_ID_TYPE_VK_INSUREE_NUMBER, 523 'kk': EXTERNAL_ID_ISSUER_TEMPLATE % (self.insurance_company, self.insurance_number) 524 } 525 rows, idx = gmPG2.run_ro_queries(queries = [{'cmd': cmd, 'args': args}]) 526 527 # weed out duplicates 528 new_idents = [] 529 for r in rows: 530 for oid in old_idents: 531 if r[0] == oid.ID: 532 break 533 new_idents.append(gmPerson.cPerson(aPK_obj = r['pk_identity'])) 534 535 old_idents.extend(new_idents) 536 537 return old_idents
538 #--------------------------------------------------------
539 - def import_extra_data(self, identity=None, *args, **kwargs):
540 # Versicherungsnummer 541 identity.add_external_id ( 542 type_name = EXTERNAL_ID_TYPE_VK_INSUREE_NUMBER, 543 value = self.insuree_number, 544 issuer = EXTERNAL_ID_ISSUER_TEMPLATE % (self.insurance_company, self.insurance_number), 545 comment = 'Nummer des Versicherten bei der Krankenkasse' 546 ) 547 # address 548 street = self.street 549 number = regex.findall(' \d+.*', street) 550 if len(number) == 0: 551 number = None 552 else: 553 street = street.replace(number[0], '') 554 number = number[0].strip() 555 identity.link_address ( 556 number = number, 557 street = street, 558 postcode = self.zip, 559 urb = self.urb, 560 region_code = '', 561 country_code = 'DE' # actually: map urb_region_code 562 )
563 # FIXME: kvk itself 564 #--------------------------------------------------------
565 - def delete_from_source(self):
566 try: 567 os.remove(self.filename) 568 self.filename = None 569 except: 570 _log.exception('cannot delete kvkd file [%s]' % self.filename, verbose = False)
571 #-------------------------------------------------------- 572 # internal helpers 573 #--------------------------------------------------------
574 - def __parse_kvk_file(self, strict=True):
575 576 _log.debug('parsing KVK data in [%s]', self.filename) 577 578 kvk_file = io.open(self.filename, mode = 'rt', encoding = 'utf8') 579 580 card_type_seen = False 581 for line in kvk_file: 582 line = line.replace('\n', '').replace('\r', '') 583 tag, content = line.split(':', 1) 584 content = content.strip() 585 586 if tag == 'Kartentyp': 587 card_type_seen = True 588 if content != cDTO_KVK.kvkd_card_id_string: 589 _log.error('parsing wrong card type') 590 _log.error('found : %s', content) 591 _log.error('expected: %s', cDTO_KVK.kvkd_card_id_string) 592 if strict: 593 raise ValueError('wrong card type: %s, expected %s', content, cDTO_KVK.kvkd_card_id_string) 594 else: 595 _log.debug('trying to parse anyway') 596 597 if tag == 'Geburtsdatum': 598 tmp = time.strptime(content, self.dob_format) 599 content = pyDT.datetime(tmp.tm_year, tmp.tm_mon, tmp.tm_mday, tzinfo = gmDateTime.gmCurrentLocalTimezone) 600 601 try: 602 setattr(self, map_kvkd_tags2dto[tag], content) 603 except KeyError: 604 _log.exception('unknown KVKd kvk file key [%s]' % tag) 605 606 # valid_until -> valid_until_timestamp 607 ts = time.strptime ( 608 '28%s20%s' % (self.valid_until[:2], self.valid_until[2:]), 609 self.valid_until_format 610 ) 611 612 # last_read_date and last_read_time -> last_read_timestamp 613 ts = time.strptime ( 614 '%s %s' % (self.last_read_date, self.last_read_time), 615 '%s %s' % (self.last_read_date_format, self.last_read_time_format) 616 ) 617 self.last_read_timestamp = pyDT.datetime(ts.tm_year, ts.tm_mon, ts.tm_mday, ts.tm_hour, ts.tm_min, ts.tm_sec, tzinfo = gmDateTime.gmCurrentLocalTimezone) 618 619 # guess gender from firstname 620 self.gender = gmTools.coalesce(gmPerson.map_firstnames2gender(firstnames=self.firstnames), 'f') 621 622 if not card_type_seen: 623 _log.warning('no line with card type found, unable to verify')
624 #============================================================
625 -def detect_card_type(card_file=None):
626 627 data_file = io.open(card_file, mode = 'rt', encoding = 'utf8') 628 629 for line in kvk_file: 630 line = line.replace('\n', '').replace('\r', '') 631 tag, content = line.split(':', 1) 632 content = content.strip() 633 634 if tag == 'Kartentyp': 635 pass
636 #============================================================
637 -def get_available_kvks_as_dtos(spool_dir = None):
638 639 kvk_files = glob.glob(os.path.join(spool_dir, 'KVK-*.dat')) 640 dtos = [] 641 for kvk_file in kvk_files: 642 try: 643 dto = cDTO_KVK(filename = kvk_file) 644 except: 645 _log.exception('probably not a KVKd KVK file: [%s]' % kvk_file) 646 continue 647 dtos.append(dto) 648 649 return dtos
650 #------------------------------------------------------------
651 -def get_available_egks_as_dtos(spool_dir = None):
652 653 egk_files = glob.glob(os.path.join(spool_dir, 'eGK-*.dat')) 654 dtos = [] 655 for egk_file in egk_files: 656 try: 657 dto = cDTO_eGK(filename = egk_file) 658 except: 659 _log.exception('probably not a KVKd eGK file: [%s]' % egk_file) 660 continue 661 dtos.append(dto) 662 663 return dtos
664 #------------------------------------------------------------
665 -def get_available_CCRdr_files_as_dtos(spool_dir = None):
666 667 ccrdr_files = glob.glob(os.path.join(spool_dir, 'CCReader-*.dat')) 668 dtos = [] 669 for ccrdr_file in ccrdr_files: 670 try: 671 dto = cDTO_CCRdr(filename = ccrdr_file) 672 except: 673 _log.exception('probably not a CCReader file: [%s]' % ccrdr_file) 674 continue 675 dtos.append(dto) 676 677 return dtos
678 #------------------------------------------------------------
679 -def get_available_cards_as_dtos(spool_dir = None):
680 dtos = [] 681 # dtos.extend(get_available_CCRdr_files_as_dtos(spool_dir = spool_dir)) 682 dtos.extend(get_available_kvks_as_dtos(spool_dir = spool_dir)) 683 dtos.extend(get_available_egks_as_dtos(spool_dir = spool_dir)) 684 685 return dtos
686 687 #============================================================ 688 # main 689 #------------------------------------------------------------ 690 if __name__ == "__main__": 691 692 from Gnumed.pycommon import gmI18N 693 694 gmI18N.activate_locale() 695 gmDateTime.init() 696
697 - def test_vks():
698 dtos = get_available_CCRdr_files_as_dtos(spool_dir = sys.argv[2]) 699 for dto in dtos: 700 print(dto)
701
702 - def test_egk_dto():
703 # test cKVKd_file object 704 kvkd_file = sys.argv[2] 705 print("reading eGK data from KVKd file", kvkd_file) 706 dto = cDTO_eGK(filename = kvkd_file, strict = False) 707 print(dto) 708 for attr in true_egk_fields: 709 print(getattr(dto, attr))
710
711 - def test_kvk_dto():
712 # test cKVKd_file object 713 kvkd_file = sys.argv[2] 714 print("reading KVK data from KVKd file", kvkd_file) 715 dto = cDTO_KVK(filename = kvkd_file, strict = False) 716 print(dto) 717 for attr in true_kvk_fields: 718 print(getattr(dto, attr))
719
720 - def test_get_available_kvks_as_dto():
721 dtos = get_available_kvks_as_dtos(spool_dir = sys.argv[2]) 722 for dto in dtos: 723 print(dto)
724 725 if (len(sys.argv)) > 1 and (sys.argv[1] == 'test'): 726 if len(sys.argv) < 3: 727 print("give name of KVKd file as first argument") 728 sys.exit(-1) 729 test_vks() 730 #test_egk_dto() 731 #test_kvk_dto() 732 #test_get_available_kvks_as_dto() 733 734 #============================================================ 735 # docs 736 #------------------------------------------------------------ 737 # name | mandat | type | length | format 738 # -------------------------------------------- 739 # Name Kasse | x | str | 2-28 740 # Nr. Kasse | x | int | 7 741 # VKNR | | int | 5 # MUST be derived from Stammdaten-file, not from KVK 742 # Nr. Pat | x | int | 6-12 743 # Status Pat | x | str | 1 or 4 744 # Statuserg. | | str | 1-3 745 # Titel Pat | | str | 3-15 746 # Vorname | | str | 2-28 747 # Adelspraed.| | str | 1-15 748 # Nachname | x | str | 2-28 749 # geboren | x | int | 8 | DDMMYYYY 750 # Straße | | str | 1-28 751 # Ländercode | | str | 1-3 752 # PLZ | x | int | 4-7 753 # Ort | x | str | 2-23 754 # gültig bis | | int | 4 | MMYY 755