Repository: brazilian-utils/brutils-python (python)

Issue:
Gerar número de PIS válido e aleatório
**Seu pedido de recurso está relacionado a um problema? Por favor, descreva.**
Gerar um número de PIS válido e aleatório.

**Descreva a solução que você gostaria**
- Chamar um novo utilitário que retorna um número de PIS válido e aleatório.
- Sem formatação

**Descreva alternativas que você considerou**
- Criar um novo utilitário generate_pis:
```python
def generate_pis():
...
```
Exemplo de uso:
```
from brutils import generate_pis

>>> generate_pis()
"12042644708"
>>> generate_pis()
"12021423567"
```

**Contexto adicional**
- https://pt.wikipedia.org/wiki/PIS/PASEP
- https://www.macoratti.net/alg_pis.htm


Pull request description:
feat: add `generate_pis`
## Descrição
<!--- Descreva de forma sucinta e clara qual é o propósito deste Pull Request. Explique o que ele faz ou resolve.-->
Adiciona suporte à geração de números PIS/PASEP válidos e aleatórios.

## Mudanças Propostas
<!--- Liste as principais alterações ou melhorias que estão sendo propostas neste Pull Request.

- Exemplo 1: Descrição da primeira alteração.
- Exemplo 2: Descrição da segunda alteração.
- ...-->
Implementação da função geradora de números PIS/PASEP aleatórios.

## Checklist de Revisão
<!--- Marque as caixas que se aplicam. Você pode deixar caixas desmarcadas se elas não se aplicarem.-->

- [x] Eu li o [Contributing.md](https://github.com/brazilian-utils/brutils-python/blob/main/CONTRIBUTING.md)
- [x] Os testes foram adicionados ou atualizados para refletir as mudanças (se aplicável).
- [x] Foi adicionada uma entrada no changelog / Meu PR não necessita de uma nova entrada no changelog.
- [x] A [documentação](https://github.com/brazilian-utils/brutils-python/blob/main/README.md) em português foi atualizada ou criada, se necessário.
- [x] Se feita a documentação, a atualização do [arquivo em inglês](https://github.com/brazilian-utils/brutils-python/blob/main/README_EN.md). <!---Permitido uso de Google Tradutor/ChatGPT. -->
- [x] Eu documentei as minhas mudanças no código, adicionando docstrings e comentários. [Instruções](https://github.com/brazilian-utils/brutils-python/blob/main/CONTRIBUTING.md#8-fa%C3%A7a-as-suas-altera%C3%A7%C3%B5es)
- [x] O código segue as diretrizes de estilo e padrões de codificação do projeto.
- [x] Todos os testes passam. [Instruções](https://github.com/brazilian-utils/brutils-python/blob/main/CONTRIBUTING.md#testes)
- [x] O Pull Request foi testado localmente. [Instruções](https://github.com/brazilian-utils/brutils-python/blob/main/CONTRIBUTING.md#7-execute-o-brutils-localmente)
- [x] Não há conflitos de mesclagem.


## Comentários Adicionais (opcional)
<!--- Adicione qualquer informação adicional ou contexto que você acha importante para os revisores entenderem suas mudanças.-->
- PR deve ser mesclado depois que o PR #216 for mesclado, pois contém dependências das funções base.

## Issue Relacionada
<!---Todos os PRs devem ter uma issue relacionada. Dessa forma, podemos garantir que ninguém perca tempo trabalhando em algo que não precisa ser feito. -->


Closes #204 


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ca57531..08d7efd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ### Added
 
+- Utilitário `generate_pis` [#218](https://github.com/brazilian-utils/brutils-python/pull/218)
 - Utilitário `is_valid_pis` [#216](https://github.com/brazilian-utils/brutils-python/pull/216)
 - Utilitário `is_valid_email` [#213](https://github.com/brazilian-utils/brutils-python/pull/213)
 - Utilitário `iis_valid_license_plate_old_format` [#174](https://github.com/brazilian-utils/brutils-python/pull/174)
diff --git a/README.md b/README.md
index c84c2ac..886d9c1 100644
--- a/README.md
+++ b/README.md
@@ -71,6 +71,7 @@ False
   - [is_valid_license_plate_mercosul](#is_valid_license_plate_mercosul)
 - [PIS](#pis)
   - [is_valid_pis](#is_valid_pis)
+  - [generate_pis](#generate_pis)
 
 ## CPF
 
@@ -325,15 +326,19 @@ True
 Verifica se o número PIS/PASEP é valido. Apenas números, formatados como string. Não verifica se o PIS/PASEP existe.
 Mais detalhes sobre a validação estão disponíveis em https://www.macoratti.net/alg_pis.htm.
 
-```python
-from brutils import is_valid_pis
+### generate_pis
 
->>> is_valid_pis("12038619494")
-True
->>> is_valid_pis("11111111111")
-False
->>> is_valid_pis("123456")
-False
+Gera um PIS/PASEP válido aleatório.
+
+```python
+from brutils import generate_pis
+
+>>> generate_pis()
+'12038619494'
+>>> generate_pis()
+'57817700092'
+>>> generate_pis()
+'49850211630'
 ```
 
 # Novos Utilitários e Reportar Bugs
diff --git a/README_EN.md b/README_EN.md
index 4adf5b0..c60d2d2 100644
--- a/README_EN.md
+++ b/README_EN.md
@@ -70,7 +70,7 @@ False
   - [is_valid_license_plate_mercosul](#is_valid_license_plate_mercosul)
 - [PIS](#pis)
   - [is_valid_pis](#is_valid_pis)
-
+  - [generate_pis](#generate_pis)
 
 ## CPF
 
@@ -311,6 +311,21 @@ False
 False
 ```
 
+### generate_pis
+
+Generates a valid random PIS/PASEP number.
+
+```python
+from brutils import generate_pis
+
+>>> generate_pis()
+'12038619494'
+>>> generate_pis()
+'57817700092'
+>>> generate_pis()
+'49850211630'
+```
+
 # Feature Request and Bug Report
 
 If you want to suggest new features or report bugs, simply create
diff --git a/brutils/__init__.py b/brutils/__init__.py
index 8bc0b0d..1400999 100644
--- a/brutils/__init__.py
+++ b/brutils/__init__.py
@@ -32,4 +32,5 @@ from brutils.license_plate import is_valid_license_plate_old_format
 
 from brutils.pis import (
     is_valid as is_valid_pis,
+    generate as generate_pis,
 )
diff --git a/brutils/pis.py b/brutils/pis.py
index ddb213b..f5957ac 100644
--- a/brutils/pis.py
+++ b/brutils/pis.py
@@ -1,3 +1,6 @@
+from random import randint
+
+
 WEIGHTS = [3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
 
 
@@ -40,6 +43,21 @@ def is_valid(pis: str) -> bool:
     return isinstance(pis, str) and validate(pis)
 
 
+def generate() -> str:
+    """
+    Generates a random valid Brazilian PIS number.
+
+    Args:
+        None
+
+    Returns:
+        value[str]: PIS number as a string.
+    """
+    base = str(randint(0, 9999999999)).zfill(10)
+
+    return base + str(_checksum(base))
+
+
 def _checksum(base_pis: str) -> int:
     """
     Calculates the checksum digit of the given `base_pis` string.


Test patch:
diff --git a/tests/test_pis.py b/tests/test_pis.py
index bd81287..ac6bf5d 100644
--- a/tests/test_pis.py
+++ b/tests/test_pis.py
@@ -9,7 +9,7 @@ range = range if version_info.major >= 3 else xrange
 path.insert(
     1, abspath(join(dirname(abspath(getsourcefile(lambda: 0))), pardir))
 )
-from brutils.pis import validate, is_valid, _checksum
+from brutils.pis import validate, is_valid, generate, _checksum
 from unittest import TestCase, main
 
 
@@ -53,6 +53,10 @@ class TestPIS(TestCase):
         self.assertEqual(_checksum("1203861949"), 4)
         self.assertEqual(_checksum("1208321082"), 6)
 
+    def test_generate(self):
+        for _ in range(10_000):
+            self.assertIs(validate(generate()), True)
+
 
 if __name__ == "__main__":
     main()