Coverage for presidio_analyzer / predefined_recognizers / country_specific / germany / de_tax_id_recognizer.py: 96%
27 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-03-29 09:03 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-03-29 09:03 +0000
1from typing import List, Optional
3from presidio_analyzer import Pattern, PatternRecognizer
6class DeTaxIdRecognizer(PatternRecognizer):
7 """
8 Recognizes German Steueridentifikationsnummer (Steuer-IdNr.).
10 The Steueridentifikationsnummer is a unique 11-digit personal tax identification
11 number issued by the Bundeszentralamt für Steuern to every person registered in
12 Germany. It does not change over a person's lifetime.
14 Legal basis: §§ 139a–139e Abgabenordnung (AO), in force since 2007.
15 Data protection: DSGVO Art. 4 Nr. 1 (personenbezogene Daten), BDSG.
17 Format:
18 - 11 digits
19 - First digit: 1–9 (never 0)
20 - Digit 11: check digit (ISO 7064 Mod 11, 10 variant)
22 Examples (fictitious): 86095742719, 12345678903
24 :param patterns: List of patterns to be used by this recognizer
25 :param context: List of context words to increase confidence in detection
26 :param supported_language: Language this recognizer supports
27 :param supported_entity: The entity this recognizer can detect
28 """
30 PATTERNS = [
31 Pattern(
32 "Steueridentifikationsnummer (High)",
33 r"\b[1-9]\d{10}\b",
34 0.5,
35 ),
36 ]
38 CONTEXT = [
39 "steueridentifikationsnummer",
40 "steuer-id",
41 "steuerid",
42 "steuerliche identifikationsnummer",
43 "steuerliche identifikation",
44 "persönliche identifikationsnummer",
45 "steuer identifikation",
46 "idnr",
47 "steuer-idnr",
48 "steuernummer",
49 "bzst",
50 ]
52 def __init__(
53 self,
54 patterns: Optional[List[Pattern]] = None,
55 context: Optional[List[str]] = None,
56 supported_language: str = "de",
57 supported_entity: str = "DE_TAX_ID",
58 name: Optional[str] = None,
59 ):
60 patterns = patterns if patterns else self.PATTERNS
61 context = context if context else self.CONTEXT
62 super().__init__(
63 supported_entity=supported_entity,
64 patterns=patterns,
65 context=context,
66 supported_language=supported_language,
67 name=name,
68 )
70 def validate_result(self, pattern_text: str) -> Optional[bool]:
71 """
72 Validate the Steueridentifikationsnummer using the official checksum algorithm.
74 Algorithm: ISO 7064 Mod 11, 10 variant as specified by the
75 Bundeszentralamt für Steuern.
77 :param pattern_text: the text to validate (11 digits)
78 :return: True if valid, False if invalid
79 """
80 if len(pattern_text) != 11 or not pattern_text.isdigit():
81 return False
82 if pattern_text[0] == "0":
83 return False
85 digits = [int(d) for d in pattern_text]
87 # Check that the first 10 digits do not consist of the same digit repeated
88 if len(set(digits[:10])) == 1:
89 return False
91 # ISO 7064 Mod 11, 10 checksum
92 product = 10
93 for i in range(10):
94 total = (digits[i] + product) % 10
95 if total == 0:
96 total = 10
97 product = (total * 2) % 11
99 check = 11 - product
100 if check == 10:
101 check = 0
103 return check == digits[10]