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