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
155 changes: 155 additions & 0 deletions Guia2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# Guia 2 — Sistema de Folha de Pagamento (RH)

## Contexto

Você faz parte da equipe responsável por manter um módulo de **Folha de Pagamento** dentro de um sistema de **Recursos Humanos (RH)**.

Esse módulo calcula informações básicas de funcionários de diferentes cargos, como:

- nome
- matricula
- salario_base

Atualmente o sistema possui uma hierarquia de classes para representar funcionários, mas carece implementar as subclasses de acordo com o diagrama UML abaixo:

--------------------------------
| Funcionario |
--------------------------------
| - nome |
| - matricula |
| - salario_base |
--------------------------------
| + dados_basicos() |
| + gerar_contracheque() |
| + calcular_salario_liquido() |
| # calcular_bonus() |
| # calcular_descontos() |
| # calcular_adicionais() |
--------------------------------
-----------------------------------------
| | |
| | |
----------------- ----------------- -----------------
| Desenvolvedor | | Gerente | | Estagiari o |
----------------- ----------------- -----------------
| linguagem | | setor | | curso |
| senioridade | | qtd_equipe | | carga_horaria |
----------------- ----------------- -----------------

Seu papel é implementar as subclasses passando nos testes propostos.

---

## 1. Desenvolvedor

### Atributos adicionais

- `linguagem`
- `senioridade`

### Regras

#### `calcular_bonus()`

O bônus depende da senioridade:

| Senioridade | Bônus |
|-------------|----------------------|
| junior | 5% do salário base |
| pleno | 10% do salário base |
| senior | 15% do salário base |

---

#### `calcular_descontos()`

Desconto fixo de **8% do salário base**.

---

#### `calcular_adicionais()`

Adicional definido pela linguagem principal:

| Linguagem | Adicional |
|----------------|-----------|
| Python | +500 |
| Java | +400 |
| JavaScript | +350 |
| Qualquer outra | +200 |

---

## 2. Gerente

### Atributos adicionais

- `setor`
- `qtd_equipe`

### Regras

#### `calcular_bonus()`

O bônus depende da quantidade de pessoas na equipe:

| Tamanho da equipe | Bônus |
|-------------------|---------------------|
| até 5 | 10% do salário base |
| de 6 até 10 | 15% do salário base |
| acima de 10 | 20% do salário base |

---

#### `calcular_descontos()`

Desconto fixo de **12% do salário base**.

---

#### `calcular_adicionais()`

Adicional por responsabilidade:

| Quantidade da equipe | Adicional |
|----------------------|-----------|
| equipe > 10 | +2000 |
| equipe > 5 | +1000 |
| caso contrário | +500 |

---

## 3. Estagiario

### Atributos adicionais

- `curso`
- `carga_horaria`

### Regras

#### `calcular_bonus()`

Bônus fixo de **3% do salário base**.

---

#### `calcular_descontos()`

Desconto fixo de **2% do salário base**.

---

#### `calcular_adicionais()`

Auxílio baseado na carga horária:

| Carga horária | Adicional |
|---------------|-----------|
| até 20h | +150 |
| até 30h | +250 |
| acima de 30h | +350 |

---
995b5983a8b684cba7bbc7f802c760906f0d690c1e90bf440631cfe486082eb3
3 changes: 3 additions & 0 deletions Guia2/pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[pytest]
pythonpath = src
testpaths = tests
Empty file added Guia2/requirements.txt
Empty file.
2 changes: 2 additions & 0 deletions Guia2/run_tests.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pytest -v
pause
1 change: 1 addition & 0 deletions Guia2/src/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from folha_pagamento import Estagiario, Gerente, Desenvolvedor, Funcionario
Binary file added Guia2/src/__pycache__/__init__.cpython-312.pyc
Binary file not shown.
4 changes: 4 additions & 0 deletions Guia2/src/folha_pagamento/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from .funcionario import Funcionario
from .estagiario import Estagiario
from .desenvolvedor import Desenvolvedor
from .gerente import Gerente
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
6 changes: 6 additions & 0 deletions Guia2/src/folha_pagamento/desenvolvedor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from folha_pagamento.funcionario import Funcionario

# Desenvolva a classe Desenvolvedor aqui.

class Desenvolvedor:
pass
6 changes: 6 additions & 0 deletions Guia2/src/folha_pagamento/estagiario.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from folha_pagamento.funcionario import Funcionario

# Desenvolva a classe Estagiario aqui.

class Estagiario:
pass
77 changes: 77 additions & 0 deletions Guia2/src/folha_pagamento/funcionario.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from abc import ABC, abstractmethod

class Funcionario(ABC):
def __init__(self, nome: str, matricula: str, salario_base: float):
if not nome:
raise ValueError("Nome inválido.")

if not matricula:
raise ValueError("Matrícula inválida.")

if salario_base < 0:
raise ValueError("Salário não pode ser negativo.")

self._nome = nome
self._matricula = matricula
self._salario_base = salario_base

# ---------------------------
# Propriedades comuns
# ---------------------------
@property
def nome(self) -> str:
return self._nome

@property
def matricula(self) -> str:
return self._matricula

@property
def salario_base(self) -> float:
return self._salario_base

# ---------------------------
# Métodos concretos
# ---------------------------
def dados_basicos(self) -> dict:
return {
"nome": self.nome,
"matricula": self.matricula,
"salario_base": self.salario_base,
"cargo": self.__class__.__name__
}

def calcular_salario_liquido(self) -> float:
return (
self.salario_base
+ self.calcular_bonus()
+ self.calcular_adicionais()
- self.calcular_descontos()
)

def gerar_contracheque(self) -> dict:
return {
"nome": self.nome,
"matricula": self.matricula,
"cargo": self.__class__.__name__,
"salario_base": self.salario_base,
"bonus": self.calcular_bonus(),
"adicionais": self.calcular_adicionais(),
"descontos": self.calcular_descontos(),
"salario_liquido": self.calcular_salario_liquido()
}

# ---------------------------
# Contrato abstrato
# ---------------------------
@abstractmethod
def calcular_bonus(self) -> float:
pass

@abstractmethod
def calcular_descontos(self) -> float:
pass

@abstractmethod
def calcular_adicionais(self) -> float:
pass
6 changes: 6 additions & 0 deletions Guia2/src/folha_pagamento/gerente.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from folha_pagamento.funcionario import Funcionario

# Desenvolva a classe Gerente aqui.

class Gerente:
pass
Empty file added Guia2/tests/__init__.py
Empty file.
Binary file added Guia2/tests/__pycache__/__init__.cpython-312.pyc
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
32 changes: 32 additions & 0 deletions Guia2/tests/integrity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from pathlib import Path
import hashlib


def gerar_hash_pasta(pasta=".", extensao=".py"):
arquivos = sorted(
[
arquivo
for arquivo in Path(pasta).rglob(f"*{extensao}")
if arquivo.name != "integrity.py"
]
)

print(arquivos)

hash_global = hashlib.sha256()

for arquivo in arquivos:
# inclui nome/caminho do arquivo no hash
hash_global.update(str(arquivo.relative_to(pasta)).encode())

# inclui conteúdo
with open(arquivo, "rb") as f:
while bloco := f.read(4096):
hash_global.update(bloco)

return hash_global.hexdigest()


if __name__ == "__main__":
resultado = gerar_hash_pasta()
print(resultado)
44 changes: 44 additions & 0 deletions Guia2/tests/test_desenvolvedor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import pytest
from src import Desenvolvedor


@pytest.fixture
def desenvolvedor():
# Instância base com salário 5000, linguagem Python, senioridade pleno
return Desenvolvedor("Ana", "123", 5000.0, "Python", "pleno")

# ---- Testes para calcular_bonus() ----
@pytest.mark.parametrize("senioridade,percentual", [
("junior", 0.05),
("pleno", 0.10),
("senior", 0.15),
])
def test_bonus_por_senioridade(desenvolvedor, senioridade, percentual):
desenvolvedor.senioridade = senioridade
esperado = percentual * desenvolvedor.salario_base
assert desenvolvedor.calcular_bonus() == esperado

# ---- Teste para calcular_descontos() ----
def test_desconto_fixo(desenvolvedor):
# 8% do salário base
assert desenvolvedor.calcular_descontos() == 0.08 * desenvolvedor.salario_base

# ---- Testes para calcular_adicionais() ----
@pytest.mark.parametrize("linguagem,adicional_esperado", [
("Python", 500),
("Java", 400),
("JavaScript", 350),
("C++", 200),
("Ruby", 200),
])
def test_adicional_por_linguagem(desenvolvedor, linguagem, adicional_esperado):
desenvolvedor.linguagem = linguagem
assert desenvolvedor.calcular_adicionais() == adicional_esperado

# ---- Teste integrado de salário líquido ----
def test_salario_liquido_pleno_python(desenvolvedor):
desenvolvedor.senioridade = "pleno"
desenvolvedor.linguagem = "Python"
# salario_base (5000) + bonus(10%) + adicional(500) - desconto(8%)
esperado = 5000 + 500 + 500 - 400 # 5600
assert desenvolvedor.calcular_salario_liquido() == esperado
38 changes: 38 additions & 0 deletions Guia2/tests/test_estagiario.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import pytest
from src import Estagiario


@pytest.fixture
def estagiario():
# Salário base 1500, carga horária 30h
return Estagiario("Carlos", "456", 1500.0, "Engenharia", 30)

# ---- Teste do bônus fixo ----
def test_bonus_fixo(estagiario):
# 3% do salário base
assert estagiario.calcular_bonus() == 0.03 * estagiario.salario_base

# ---- Teste do desconto fixo ----
def test_desconto_fixo(estagiario):
# 2% do salário base
assert estagiario.calcular_descontos() == 0.02 * estagiario.salario_base

# ---- Testes de adicionais por carga horária ----
@pytest.mark.parametrize("carga_horaria,adicional_esperado", [
(20, 150),
(15, 150), # até 20h inclusive
(25, 250),
(30, 250), # até 30h inclusive
(35, 350),
(40, 350),
])
def test_adicional_por_carga_horaria(estagiario, carga_horaria, adicional_esperado):
estagiario.carga_horaria = carga_horaria
assert estagiario.calcular_adicionais() == adicional_esperado

# ---- Teste de salário líquido para carga de 30h ----
def test_salario_liquido_30h(estagiario):
estagiario.carga_horaria = 30
# 1500 + 45 (bônus) + 250 (adicional) - 30 (desconto) = 1765
esperado = 1500 + 45 + 250 - 30
assert estagiario.calcular_salario_liquido() == esperado
Loading