Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions docs/pt-br/utilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,37 @@ generateCpf('SP'); // o 9º dígito é 8, o código da região fiscal de SP
generateCpf('MG'); // o 9º dígito é 6, o código da região fiscal de MG
```

### getCpfInfo

Lê os campos que um CPF codifica, como um `CpfInfo`: a `base` de 8 dígitos, o dígito `fiscalRegion` (o 9º dígito, a Região Fiscal da Receita Federal em que o CPF foi inscrito, `"1"` a `"9"` e `"0"` para a 10ª), os `states` dessa região (`StateCode[]`, ordenados pelo nome do estado) e os 2 `checkDigits`. Aceita a mesma entrada com ou sem máscara que o `isValidCpf` e retorna `null` para tudo que não for um CPF válido. A região é a do endereço informado na primeira inscrição: ela não diz onde o titular nasceu, onde mora hoje nem onde pediu o número, e uma região com mais de um estado não diz qual deles foi.

| `fiscalRegion` | `states` |
| --- | --- |
| `"1"` | DF, GO, MT, MS, TO |
| `"2"` | AC, AP, AM, PA, RO, RR |
| `"3"` | CE, MA, PI |
| `"4"` | AL, PB, PE, RN |
| `"5"` | BA, SE |
| `"6"` | MG |
| `"7"` | ES, RJ |
| `"8"` | SP |
| `"9"` | PR, SC |
| `"0"` | RS |

```javascript
import { getCpfInfo } from '@brazilian-utils/brazilian-utils';

getCpfInfo('123.456.789-09');
// {
// base: '12345678',
// fiscalRegion: '9',
// states: ['PR', 'SC'],
// checkDigits: '09',
// }

getCpfInfo('12345678900'); // null (dígitos verificadores inválidos)
```

Fonte: [Receita Federal, "Cadastros: CPF e CNPJ"](https://www.gov.br/receitafederal/pt-br/assuntos/educacao-fiscal/educacao_fiscal/folhetos-orientativos/cadastros-dig.pdf).

## CNPJ
Expand Down
31 changes: 31 additions & 0 deletions docs/utilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,37 @@ generateCpf('SP'); // the 9th digit is 8, the SP região fiscal code
generateCpf('MG'); // the 9th digit is 6, the MG região fiscal code
```

### getCpfInfo

Read the fields a CPF encodes, as a `CpfInfo`: the 8 digit `base`, the `fiscalRegion` digit (the 9th digit, the Região Fiscal of the Receita Federal the CPF was registered in, `"1"` to `"9"` and `"0"` for the 10ª), the `states` of that region (`StateCode[]`, sorted by state name) and the 2 `checkDigits`. Accepts the same masked or unmasked input as `isValidCpf` and returns `null` for anything that is not a valid CPF. The region is the one of the address given at the first registration: it says nothing about where the holder was born, lives today or asked for the number, and a region with more than one state does not tell which of them it was.

| `fiscalRegion` | `states` |
| --- | --- |
| `"1"` | DF, GO, MT, MS, TO |
| `"2"` | AC, AP, AM, PA, RO, RR |
| `"3"` | CE, MA, PI |
| `"4"` | AL, PB, PE, RN |
| `"5"` | BA, SE |
| `"6"` | MG |
| `"7"` | ES, RJ |
| `"8"` | SP |
| `"9"` | PR, SC |
| `"0"` | RS |

```javascript
import { getCpfInfo } from '@brazilian-utils/brazilian-utils';

getCpfInfo('123.456.789-09');
// {
// base: '12345678',
// fiscalRegion: '9',
// states: ['PR', 'SC'],
// checkDigits: '09',
// }

getCpfInfo('12345678900'); // null (invalid check digits)
```

Source: [Receita Federal, "Cadastros: CPF e CNPJ"](https://www.gov.br/receitafederal/pt-br/assuntos/educacao-fiscal/educacao_fiscal/folhetos-orientativos/cadastros-dig.pdf).

## CNPJ
Expand Down
1 change: 1 addition & 0 deletions jsr.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"./get-cfop": "./src/get-cfop/get-cfop.ts",
"./get-cities": "./src/get-cities/get-cities.ts",
"./get-cnae": "./src/get-cnae/get-cnae.ts",
"./get-cpf-info": "./src/get-cpf-info/get-cpf-info.ts",
"./get-format-license-plate": "./src/get-format-license-plate/get-format-license-plate.ts",
"./get-holidays": "./src/get-holidays/get-holidays.ts",
"./get-iban-info": "./src/get-iban-info/get-iban-info.ts",
Expand Down
11 changes: 11 additions & 0 deletions reports/api/brazilian-utils.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,14 @@ export type ConvertNumberToWordsOptions = {
gender?: NumberToWordsGender;
};

// @public
export type CpfInfo = {
base: string;
fiscalRegion: string;
states: StateCode[];
checkDigits: string;
};

// @public
export const differenceInBusinessDays: (laterDate: Date, earlierDate: Date, options?: BusinessDayOptions) => number | null;

Expand Down Expand Up @@ -488,6 +496,9 @@ export const getCities: (state?: StateCode) => string[];
// @public
export const getCnae: (value: string | number) => Cnae | null;

// @public
export const getCpfInfo: (value: string) => CpfInfo | null;

// @public
export const getFormatLicensePlate: (value: string) => LicensePlateFormat | null;

Expand Down
43 changes: 43 additions & 0 deletions src/_internals/constants/cpf.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,45 @@
import { type StateCode } from "./states";

/** Digits of a CPF. */
export const CPF_LENGTH = 11;

/** Digits of a CPF ahead of the região fiscal digit. */
export const CPF_BASE_LENGTH = 8;

/**
* The região fiscal digit (the 9th digit of a CPF) of each state, as listed by the Receita
* Federal in the folheto "Cadastros: CPF e CNPJ": 1 for DF, GO, MT, MS and TO; 2 for PA, AM, AC,
* AP, RO and RR; 3 for CE, MA and PI; 4 for PE, RN, PB and AL; 5 for BA and SE; 6 for MG; 7 for
* RJ and ES; 8 for SP; 9 for PR and SC; 0 for RS.
*
* @see Official: https://www.gov.br/receitafederal/pt-br/assuntos/educacao-fiscal/educacao_fiscal/folhetos-orientativos/cadastros-dig.pdf
*/
export const CPF_FISCAL_REGION_BY_STATE: Record<StateCode, string> = {
AC: "2",
AL: "4",
AP: "2",
AM: "2",
BA: "5",
CE: "3",
DF: "1",
ES: "7",
GO: "1",
MA: "3",
MT: "1",
MS: "1",
MG: "6",
PR: "9",
PB: "4",
PA: "2",
PE: "4",
PI: "3",
RN: "4",
RS: "0",
RJ: "7",
RO: "2",
RR: "2",
SC: "9",
SE: "5",
SP: "8",
TO: "1",
};
33 changes: 0 additions & 33 deletions src/generate-cpf/constants.ts

This file was deleted.

13 changes: 6 additions & 7 deletions src/generate-cpf/generate-cpf.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import * as fc from "fast-check";

import { CPF_LENGTH } from "../_internals/constants/cpf";
import { CPF_FISCAL_REGION_BY_STATE, CPF_LENGTH } from "../_internals/constants/cpf";
import { DATA, type StateCode } from "../_internals/constants/states";
import { PROTOTYPE_KEYS } from "../_internals/test/arbitraries";
import { describe, expect, expectTypeOf, test } from "../_internals/test/runtime";
import { isValidCpf } from "../is-valid-cpf/is-valid-cpf";
import { STATE_CODES } from "./constants";
import { generateCpf } from "./generate-cpf";

describe("generateCpf", () => {
Expand Down Expand Up @@ -50,15 +49,15 @@ describe("generateCpf", () => {
}
});

test("should embed the literal STATE_CODES digit at the 9th position, not a random one", () => {
test("should embed the literal CPF_FISCAL_REGION_BY_STATE digit at the 9th position, not a random one", () => {
for (let i = 0; i < 20; i++) {
expect(generateCpf("SP")[8]).toBe(STATE_CODES.SP);
expect(generateCpf("SP")[8]).toBe(CPF_FISCAL_REGION_BY_STATE.SP);
}
});

test("should embed the 1st região fiscal digit for the states the Receita Federal groups there", () => {
expect(STATE_CODES.MS).toBe("1");
expect(STATE_CODES.MT).toBe("1");
expect(CPF_FISCAL_REGION_BY_STATE.MS).toBe("1");
expect(CPF_FISCAL_REGION_BY_STATE.MT).toBe("1");
expect(generateCpf("MS")[8]).toBe("1");
expect(generateCpf("MT")[8]).toBe("1");
});
Expand Down Expand Up @@ -102,7 +101,7 @@ describe("generateCpf", () => {
const cpf = generateCpf(state);

expect(cpf).toHaveLength(CPF_LENGTH);
expect(cpf[8]).toBe(STATE_CODES[state]);
expect(cpf[8]).toBe(CPF_FISCAL_REGION_BY_STATE[state]);
expect(isValidCpf(cpf)).toBe(true);
}),
);
Expand Down
11 changes: 7 additions & 4 deletions src/generate-cpf/generate-cpf.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { calculateCpfCheckDigit } from "../_internals/calculate-cpf-check-digit/calculate-cpf-check-digit";
import { CPF_BASE_LENGTH, CPF_FISCAL_REGION_BY_STATE } from "../_internals/constants/cpf";
import { type StateCode } from "../_internals/constants/states";
import { generateRandomNumber } from "../_internals/generate-random-number/generate-random-number";
import { isRepeatedDigits } from "../_internals/is-repeated-digits/is-repeated-digits";
import { BASE_LENGTH, STATE_CODES } from "./constants";

export type { StateCode } from "../_internals/constants/states";

Expand All @@ -16,7 +16,10 @@ export type { StateCode } from "../_internals/constants/states";
* @returns {string} The região fiscal digit of that state, or a random digit.
*/
const getStateCode = (state?: StateCode): string => {
if (typeof state === "string" && Object.hasOwn(STATE_CODES, state)) return STATE_CODES[state];
if (typeof state === "string" && Object.hasOwn(CPF_FISCAL_REGION_BY_STATE, state)) {
return CPF_FISCAL_REGION_BY_STATE[state];
}

return generateRandomNumber(1);
};

Expand Down Expand Up @@ -52,10 +55,10 @@ const getStateCode = (state?: StateCode): string => {
* @see Based on: https://github.com/brazilian-utils/python/blob/main/brutils/cpf.py
*/
export const generateCpf = (state?: StateCode): string => {
let base = generateRandomNumber(BASE_LENGTH) + getStateCode(state);
let base = generateRandomNumber(CPF_BASE_LENGTH) + getStateCode(state);

while (isRepeatedDigits(base)) {
base = generateRandomNumber(BASE_LENGTH) + getStateCode(state);
base = generateRandomNumber(CPF_BASE_LENGTH) + getStateCode(state);
}

const firstCheckDigit = String(calculateCpfCheckDigit(base));
Expand Down
Loading
Loading