@@ -64,111 +64,3 @@ export function truncate(value: string | undefined, maxLength: number, suffix =
6464
6565 return `${ value . slice ( 0 , maxLength ) } ${ suffix } ` ;
6666}
67-
68- /**
69- * Checks if the provided string is a valid swiss IBAN number
70- * @param ibanNumber The provided IBAN number to check
71- * Must be in one of the following formats:
72- * - "CHXX XXXX XXXX XXXX XXXX X" with whitespaces
73- * - "CHXXXXXXXXXXXXXXXXXXX" without whitespaces
74- * @returns The result of the IBAN number check
75- */
76- export function isValidSwissIbanNumber ( ibanNumber : string ) : boolean {
77- // 1. Reject null, undefined or whitespace-only strings
78- if ( isNullOrWhitespace ( ibanNumber ) ) {
79- return false ;
80- }
81-
82- // 2. Define allowed strict formats
83- // - with spaces: "CHXX XXXX XXXX XXXX XXXX X"
84- const compactIbanNumberWithWhiteSpaces = new RegExp ( / ^ C H \d { 2 } (?: \d { 4 } ) { 4 } \d { 1 } $ / ) ;
85- // - without spaces: "CHXXXXXXXXXXXXXXXXXXX"
86- const compactIbanNumberWithoutWhiteSpaces = new RegExp ( / ^ C H \d { 19 } $ / ) ;
87-
88- // 3. Check if input matches one of the allowed formats
89- if ( ! compactIbanNumberWithWhiteSpaces . test ( ibanNumber ) && ! compactIbanNumberWithoutWhiteSpaces . test ( ibanNumber ) ) {
90- return false ;
91- }
92-
93- // 4. Remove all spaces to get a compact IBAN string
94- const compactIbanNumber = ibanNumber . replaceAll ( " " , "" ) ;
95-
96- // 5. Rearrange IBAN for checksum calculation
97- // - move first 4 characters (CH + 2 check digits) to the end
98- const rearrangedIban = compactIbanNumber . slice ( 4 ) + compactIbanNumber . slice ( 0 , 4 ) ;
99-
100- // 6. Replace letters with numbers (A=10, B=11, ..., Z=35)
101- const numericStr = rearrangedIban . replaceAll ( / [ A - Z ] / g, ( ch ) => ( ch . codePointAt ( 0 ) ! - 55 ) . toString ( ) ) ;
102-
103- // 7. Perform modulo 97 calculation to validate IBAN
104- let restOfCalculation = 0 ;
105- for ( const digit of numericStr ) {
106- restOfCalculation = ( restOfCalculation * 10 + Number ( digit ) ) % 97 ;
107- }
108-
109- // 8. IBAN is valid only if the remainder equals 1
110- return restOfCalculation === 1 ;
111- }
112-
113- /**
114- * Validation of social insurance number with checking the checksum
115- * Validation according to https://www.sozialversicherungsnummer.ch/aufbau-neu.htm
116- * @param socialInsuranceNumber The social insurance number to check
117- * Must be in one of the following formats:
118- * - "756.XXXX.XXXX.XX" with dots as separators
119- * - "756XXXXXXXXXX" with digits only
120- * @returns The result if the social insurance number is valid or not
121- */
122- export function isValidSwissSocialSecurityNumber ( socialInsuranceNumber : string ) : boolean {
123- // 1. Check if input is empty or only whitespace
124- if ( isNullOrWhitespace ( socialInsuranceNumber ) ) {
125- return false ;
126- }
127-
128- /**
129- * 2. Check if input matches accepted formats:
130- * - With dots: 756.XXXX.XXXX.XX
131- * - Without dots: 756XXXXXXXXXX
132- */
133- const socialInsuranceNumberWithDots = new RegExp ( / ^ 7 5 6 \. \d { 4 } \. \d { 4 } \. \d { 2 } $ / ) ;
134- const socialInsuranceNumberWithoutDots = new RegExp ( / ^ 7 5 6 \d { 10 } $ / ) ;
135-
136- if ( ! socialInsuranceNumberWithDots . test ( socialInsuranceNumber ) && ! socialInsuranceNumberWithoutDots . test ( socialInsuranceNumber ) ) {
137- return false ;
138- }
139-
140- // 3. Remove all dots → get a string of 13 digits
141- const compactNumber = socialInsuranceNumber . replaceAll ( "." , "" ) ;
142-
143- /**
144- * 4. Separate digits for checksum calculation
145- * - first 12 digits: used to calculate checksum
146- * - last digit: actual check digit
147- */
148- const digits = compactNumber . slice ( 0 , - 1 ) ;
149- const reversedDigits = [ ...digits ] . reverse ( ) . join ( "" ) ;
150- const reversedDigitsArray = [ ...reversedDigits ] ;
151-
152- /*
153- * 5. Calculate weighted sum for checksum
154- * - Even positions (after reversing) ×3
155- * - Odd positions ×1
156- */
157- let sum = 0 ;
158- for ( const [ i , element ] of reversedDigitsArray . entries ( ) ) {
159- sum += i % 2 === 0 ? Number ( element ) * 3 : Number ( element ) * 1 ;
160- }
161-
162- /*
163- * 6. Calculate expected check digit
164- * - Check digit = value to reach next multiple of 10
165- */
166- const checksum = ( 10 - ( sum % 10 ) ) % 10 ;
167- const checknumber = Number . parseInt ( compactNumber . slice ( - 1 ) ) ;
168-
169- /*
170- * 7. Compare calculated check digit with actual last digit
171- * - If equal → valid AHV number
172- */
173- return checksum === checknumber ;
174- }
0 commit comments