UNPKG

@italia-tools/faker

Version:

Italian-specific fake data generator based on Faker.js

82 lines (79 loc) 3.84 kB
import { Gender } from '../types/types.mjs'; // biome-ignore lint/complexity/noStaticOnlyClass: <explanation> class FiscalCodeGenerator { static generate(person) { const surname = FiscalCodeGenerator.processSurname(person.lastName); const name = FiscalCodeGenerator.processName(person.firstName); const dateCode = FiscalCodeGenerator.processDate(person.birthDate, person.gender); const belfioreCode = person.birthPlace.type === 'italian' ? person.birthPlace.city.belfioreCode : person.birthPlace.country.code; const baseCode = surname + name + dateCode + belfioreCode; const controlChar = FiscalCodeGenerator.calculateControlChar(baseCode); return baseCode + controlChar; } static processSurname(surname) { const consonants = surname.toUpperCase().replace(/[^BCDFGHJKLMNPQRSTVWXYZ]/g, ''); const vowels = surname.toUpperCase().replace(/[^AEIOU]/g, ''); const combined = consonants + vowels + 'XXX'; return combined.slice(0, 3); } static processName(name) { const consonants = name.toUpperCase().replace(/[^BCDFGHJKLMNPQRSTVWXYZ]/g, ''); if (consonants.length > 3) { return consonants[0] + consonants[2] + consonants[3]; } const vowels = name.toUpperCase().replace(/[^AEIOU]/g, ''); const combined = consonants + vowels + 'XXX'; return combined.slice(0, 3); } static processDate(date, gender) { const year = date.getFullYear().toString().slice(-2); const month = FiscalCodeGenerator.MONTH_CODES[date.getMonth()]; let day = date.getDate().toString().padStart(2, '0'); if (gender === Gender.Female) { day = (parseInt(day) + 40).toString(); } return year + month + day; } static calculateControlChar(code) { if (code.length !== 15) { throw new Error('Base code must be exactly 15 characters long'); } let sum = 0; // Process characters in odd positions (1-based index) for (let i = 0; i < code.length; i += 2) { const char = code[i]; const value = FiscalCodeGenerator.ODD_CHARS[char]; if (value === undefined) { throw new Error(`Invalid character in odd position: ${char}`); } sum += value; } // Process characters in even positions (1-based index) for (let i = 1; i < code.length; i += 2) { const char = code[i]; const value = FiscalCodeGenerator.EVEN_CHARS[char]; if (value === undefined) { throw new Error(`Invalid character in even position: ${char}`); } sum += value; } // Calculate remainder and get corresponding letter const remainder = sum % 26; return FiscalCodeGenerator.REMAINDER_CHARS.charAt(remainder); } } FiscalCodeGenerator.MONTH_CODES = ['A', 'B', 'C', 'D', 'E', 'H', 'L', 'M', 'P', 'R', 'S', 'T']; FiscalCodeGenerator.ODD_CHARS = { '0': 1, '1': 0, '2': 5, '3': 7, '4': 9, '5': 13, '6': 15, '7': 17, '8': 19, '9': 21, 'A': 1, 'B': 0, 'C': 5, 'D': 7, 'E': 9, 'F': 13, 'G': 15, 'H': 17, 'I': 19, 'J': 21, 'K': 2, 'L': 4, 'M': 18, 'N': 20, 'O': 11, 'P': 3, 'Q': 6, 'R': 8, 'S': 12, 'T': 14, 'U': 16, 'V': 10, 'W': 22, 'X': 25, 'Y': 24, 'Z': 23 }; FiscalCodeGenerator.EVEN_CHARS = { '0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, 'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7, 'I': 8, 'J': 9, 'K': 10, 'L': 11, 'M': 12, 'N': 13, 'O': 14, 'P': 15, 'Q': 16, 'R': 17, 'S': 18, 'T': 19, 'U': 20, 'V': 21, 'W': 22, 'X': 23, 'Y': 24, 'Z': 25 }; FiscalCodeGenerator.REMAINDER_CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; export { FiscalCodeGenerator };