Repository: joke2k/faker

Issue:
Support United States ITIN and EIN tax identification numbers
While United States SSNs are used by naturalized aliens and citizens, but businesses are identified by EINs and IRS issues ITINs to foreign nationals and others who have federal tax reporting or filing requirements and do not qualify for SSNs. 

Each type of tax identification number follows specific rules. 

Discussion:

Patch:
diff --git a/faker/providers/ssn/en_US/__init__.py b/faker/providers/ssn/en_US/__init__.py
index 4357535c..a6930f4a 100644
--- a/faker/providers/ssn/en_US/__init__.py
+++ b/faker/providers/ssn/en_US/__init__.py
@@ -1,19 +1,169 @@
 # coding=utf-8
 from __future__ import unicode_literals
+
+import random
 from .. import Provider as BaseProvider
 
 
 class Provider(BaseProvider):
+    SSN_TYPE = 'SSN'
+    ITIN_TYPE = 'ITIN'
+    EIN_TYPE = 'EIN'
+
+    def itin(self):
+        """Generate a random United States Individual Taxpayer Identification Number (ITIN).
+
+        An United States Individual Taxpayer Identification Number
+        (ITIN) is a tax processing number issued by the Internal
+        Revenue Service. It is a nine-digit number that always begins
+        with the number 9 and has a range of 70-88 in the fourth and
+        fifth digit. Effective April 12, 2011, the range was extended
+        to include 900-70-0000 through 999-88-9999, 900-90-0000
+        through 999-92-9999 and 900-94-0000 through 999-99-9999.
+        https://www.irs.gov/individuals/international-taxpayers/general-itin-information
+        """
+
+        area = self.random_int(min=900, max=999)
+        serial = self.random_int(min=0, max=9999)
+
+        # The group number must be between 70 and 99 inclusively but not 89 or 93
+        group = random.choice([x for x in range(70,100) if x not in [89, 93]])
+
+        itin = "{0:03d}-{1:02d}-{2:04d}".format(area, group, serial)
+        return itin
+
+    def ein(self):
+        """Generate a random United States Employer Identification Number (EIN).
+        
+         An United States An Employer Identification Number (EIN) is
+         also known as a Federal Tax Identification Number, and is
+         used to identify a business entity. EINs follow a format of a
+         two-digit prefix followed by a hyphen and a seven-digit sequence:
+         ##-######
+
+         https://www.irs.gov/businesses/small-businesses-self-employed/employer-id-numbers
+        """
+
+        # Only certain EIN Prefix values are assigned:
+        #
+        # https://www.irs.gov/businesses/small-businesses-self-employed/how-eins-are-assigned-and-valid-ein-prefixes
+
+        ein_prefix_choices = [
+            '01',
+            '02',
+            '03',
+            '04',
+            '05',
+            '06',
+            '10',
+            '11',
+            '12',
+            '13',
+            '14',
+            '15',
+            '16',
+            '20',
+            '21',
+            '22',
+            '23',
+            '24',
+            '25',
+            '26',
+            '27',
+            '30',
+            '31',
+            '32',
+            '33',
+            '34',
+            '35',
+            '36',
+            '37',
+            '38',
+            '39',
+            '40',
+            '41',
+            '42',
+            '43',
+            '44',
+            '45',
+            '46',
+            '47',
+            '48',
+            '50',
+            '51',
+            '52',
+            '53',
+            '54',
+            '55',
+            '56',
+            '57',
+            '58',
+            '59',
+            '60',
+            '61',
+            '62',
+            '63',
+            '64',
+            '65',
+            '66',
+            '67',
+            '68',
+            '71',
+            '72',
+            '73',
+            '74',
+            '75',
+            '76',
+            '77',
+            '80',
+            '81',
+            '82',
+            '83',
+            '84',
+            '85',
+            '86',
+            '87',
+            '88',
+            '90',
+            '91',
+            '92',
+            '93',
+            '94',
+            '95',
+            '98',
+            '99']
+
+        ein_prefix = random.choice(ein_prefix_choices)
+        sequence = self.random_int(min=0, max=9999999)
+
+        ein = "{0:s}-{1:07d}".format(ein_prefix, sequence)
+        return ein
+
+    def ssn(self, taxpayer_identification_number_type=SSN_TYPE):
+        """ Generate a random United States Taxpayer Identification Number of the specified type.
+
+        If no type is specified, a US SSN is returned.
+        """
+
+        if taxpayer_identification_number_type == self.ITIN_TYPE:
+            return self.itin()
+        elif taxpayer_identification_number_type == self.EIN_TYPE:
+            return self.ein()
+        elif taxpayer_identification_number_type == self.SSN_TYPE:
+
+            # Certain numbers are invalid for United States Social Security
+            # Numbers. The area (first 3 digits) cannot be 666 or 900-999.
+            # The group number (middle digits) cannot be 00. The serial
+            # (last 4 digits) cannot be 0000.
+        
+            area = self.random_int(min=1, max=899)
+            if area == 666:
+                area += 1
+            group = self.random_int(1, 99)
+            serial = self.random_int(1, 9999)
 
-    def ssn(self):
-        # Certain numbers are invalid for U.S. SSNs. The area (first 3 digits)
-        # cannot be 666 or 900-999. The group number (middle digits) cannot be
-        # 00. The serial (last 4 digits) cannot be 0000
-        area = self.random_int(min=1, max=899)
-        if area == 666:
-            area += 1
-        group = self.random_int(1, 99)
-        serial = self.random_int(1, 9999)
-
-        ssn = "{0:03d}-{1:02d}-{2:04d}".format(area, group, serial)
-        return ssn
+            ssn = "{0:03d}-{1:02d}-{2:04d}".format(area, group, serial)
+            return ssn
+    
+        else:
+            raise ValueError("taxpayer_identification_number_type must be one of 'SSN', 'EIN', or 'ITIN'.")


Test patch:
diff --git a/tests/providers/test_ssn.py b/tests/providers/test_ssn.py
index ea58fcf8..06234fd5 100644
--- a/tests/providers/test_ssn.py
+++ b/tests/providers/test_ssn.py
@@ -15,6 +15,7 @@ from faker.providers.ssn.pt_BR import checksum as pt_checksum
 from faker.providers.ssn.pl_PL import checksum as pl_checksum, calculate_month as pl_calculate_mouth
 from faker.providers.ssn.no_NO import checksum as no_checksum, Provider as no_Provider
 
+
 class TestEnCA(unittest.TestCase):
     def setUp(self):
         self.factory = Faker('en_CA')
@@ -26,11 +27,207 @@ class TestEnCA(unittest.TestCase):
 
             # Ensure that generated SINs are 11 characters long
             # including spaces, consist of spaces and digits only, and
-            # satisfy the validation algorithm. 
+            # satisfy the validation algorithm.
             assert len(sin) == 11
-            assert sin.replace(' ','').isdigit()
+            assert sin.replace(' ', '').isdigit()
             assert ca_checksum(sin) == int(sin[-1])
 
+
+class TestEnUS(unittest.TestCase):
+    def setUp(self):
+        self.factory = Faker('en_US')
+        self.factory.seed(0)
+
+    def test_ssn(self):
+        for _ in range(100):
+            ssn = self.factory.ssn(taxpayer_identification_number_type='SSN')
+
+            # Ensure that generated SINs are 11 characters long
+            # including dashes, consist of dashes and digits only, and
+            # satisfy these requirements:
+            #
+            # An United States Social Security Number
+            # (SSN) is a tax processing number issued by the Internal
+            # Revenue Service with the format "AAA-GG-SSSS".  The
+            # number is divided into three parts: the first three
+            # digits, known as the area number because they were
+            # formerly assigned by geographical region; the middle two
+            # digits, known as the group number; and the final four
+            # digits, known as the serial number. SSNs with the
+            # following characteristics are not allocated:
+            #
+            # 1) Numbers with all zeros in any digit group
+            # (000-##-####, ###-00-####, ###-##-0000).
+            #
+            # 2) Numbers with 666 or 900-999 in the first digit group.
+            #
+            # https://en.wikipedia.org/wiki/Social_Security_number
+
+            assert len(ssn) == 11
+            assert ssn.replace('-', '').isdigit()
+
+            [area, group, serial] = ssn.split('-')
+
+            assert 1 <= int(area) <= 899 and int(area) != 666
+            assert 1 <= int(group) <= 99
+            assert 1 <= int(serial) <= 9999
+            assert area != '666'
+
+    def test_prohibited_ssn_value(self):
+        # 666 is a prohibited value. The magic number selected as a seed
+        # is one that would (if not specifically checked for) return an
+        # SSN with an area of '666'.
+
+        self.factory.seed(19031)
+        ssn = self.factory.ssn()
+        [area, group, serial] = ssn.split('-')
+        assert area != '666'
+
+    def test_itin(self):
+        for _ in range(100):
+            itin = self.factory.ssn(taxpayer_identification_number_type='ITIN')
+
+            # Ensure that generated SINs are 11 characters long
+            # including dashes, consist of dashes and digits only, and
+            # satisfy these requirements:
+            #
+            # An United States Individual Taxpayer Identification Number
+            # (ITIN) is a tax processing number issued by the Internal
+            # Revenue Service. It is a nine-digit number that always begins
+            # with the number 9 and has a range of 70-88 in the fourth and
+            # fifth digit. Effective April 12, 2011, the range was extended
+            # to include 900-70-0000 through 999-88-9999, 900-90-0000
+            # through 999-92-9999 and 900-94-0000 through 999-99-9999.
+            # https://www.irs.gov/individuals/international-taxpayers/general-itin-information
+
+            assert len(itin) == 11
+            assert itin.replace('-', '').isdigit()
+
+            [area, group, serial] = itin.split('-')
+
+            assert 900 <= int(area) <= 999
+            assert 70 <= int(group) <= 88 or 90 <= int(group) <= 92 or 94 <= int(group) <= 99
+            assert 0 <= int(serial) <= 9999
+
+    def test_ein(self):
+        ein_prefix_choices = [
+            '01',
+            '02',
+            '03',
+            '04',
+            '05',
+            '06',
+            '10',
+            '11',
+            '12',
+            '13',
+            '14',
+            '15',
+            '16',
+            '20',
+            '21',
+            '22',
+            '23',
+            '24',
+            '25',
+            '26',
+            '27',
+            '30',
+            '31',
+            '32',
+            '33',
+            '34',
+            '35',
+            '36',
+            '37',
+            '38',
+            '39',
+            '40',
+            '41',
+            '42',
+            '43',
+            '44',
+            '45',
+            '46',
+            '47',
+            '48',
+            '50',
+            '51',
+            '52',
+            '53',
+            '54',
+            '55',
+            '56',
+            '57',
+            '58',
+            '59',
+            '60',
+            '61',
+            '62',
+            '63',
+            '64',
+            '65',
+            '66',
+            '67',
+            '68',
+            '71',
+            '72',
+            '73',
+            '74',
+            '75',
+            '76',
+            '77',
+            '80',
+            '81',
+            '82',
+            '83',
+            '84',
+            '85',
+            '86',
+            '87',
+            '88',
+            '90',
+            '91',
+            '92',
+            '93',
+            '94',
+            '95',
+            '98',
+            '99']
+
+        for _ in range(100):
+            ein = self.factory.ssn(taxpayer_identification_number_type='EIN')
+
+            # An United States An Employer Identification Number (EIN) is
+            # also known as a Federal Tax Identification Number, and is
+            # used to identify a business entity. EINs follow a format of a
+            # two-digit prefix followed by a hyphen and a seven-digit sequence.
+            # https://www.irs.gov/businesses/small-businesses-self-employed/employer-id-numbers
+            #
+            # Ensure that generated EINs are 10 characters long
+            # including a dash, consist of dashes and digits only, and
+            # satisfy these requirements:
+            #
+            # There are only certain EIN Prefix values assigned:
+            # https://www.irs.gov/businesses/small-businesses-self-employed/how-eins-are-assigned-and-valid-ein-prefixes
+
+            assert len(ein) == 10
+            assert ein.replace('-', '').isdigit()
+
+            [prefix, sequence] = ein.split('-')
+
+            assert prefix in ein_prefix_choices
+            assert 0 <= int(sequence) <= 9999999
+
+    def test_bad_tin_type(self):
+        with self.assertRaises(ValueError):
+            self.factory.ssn(taxpayer_identification_number_type='badValue')
+
+    def test_wrong_tin_type_case(self):
+        with self.assertRaises(ValueError):
+            self.factory.ssn(taxpayer_identification_number_type='ssn')
+
+
 class TestEtEE(unittest.TestCase):
     """ Tests SSN in the et_EE locale """