Componentes: Larissa M. A. da Conceição, Leonardo R. Schlögl e Matheus Fuga.
Objetivos: Desenvolver um software voltado para otimizar o gerenciamento do estoque de óleo lubrificante em uma empresa do setor automotivo. O sistema foi idealizado para facilitar o controle de entrada e saída de produtos, monitorar níveis de estoque em tempo real, emitir alertas de reposição e gerar relatórios que auxiliem na tomada de decisões.
Metodologia de desenvolvimento: Fizemos reuniões para fazer o código juntos, utilizamos o Visual Studio Code para fazer toda a programação do nosso código.
import json
import os
from typing import Optional, List
class Produto:
def __init__(
self,
id: str,
nome: str,
categoria: str = "",
quantidade: float = 0.0,
unidade: str = "un",
preco_compra: float = 0.0,
preco_venda: float = 0.0,
estoque_minimo: int = 0,
):
self._id = str(id)
self._nome = nome
self._categoria = categoria
self._quantidade = float(quantidade)
self._unidade = unidade
self._preco_compra = float(preco_compra)
self._preco_venda = float(preco_venda)
self._estoque_minimo = int(estoque_minimo)
@property
def id(self):
return self._id
@property
def nome(self):
return self._nome
@nome.setter
def nome(self, value):
self._nome = value
@property
def quantidade(self):
return self._quantidade
def ajustar_quantidade(self, delta: float):
self._quantidade += float(delta)
def is_baixo_estoque(self) -> bool:
return self._quantidade <= self._estoque_minimo
def to_dict(self) -> dict:
return {
"type": "Produto",
"id": self._id,
"nome": self._nome,
"categoria": self._categoria,
"quantidade": self._quantidade,
"unidade": self._unidade,
"preco_compra": self._preco_compra,
"preco_venda": self._preco_venda,
"estoque_minimo": self._estoque_minimo,
}
@classmethod
def from_dict(cls, d: dict):
return cls(
id=d["id"],
nome=d.get("nome", ""),
categoria=d.get("categoria", ""),
quantidade=d.get("quantidade", 0),
unidade=d.get("unidade", "un"),
preco_compra=d.get("preco_compra", 0.0),
preco_venda=d.get("preco_venda", 0.0),
estoque_minimo=d.get("estoque_minimo", 0),
)
def __str__(self):
return f"{self._id} | {self._nome} | {self._quantidade:.2f} {self._unidade} | Min:{self._estoque_minimo}"
class ProdutoOleo(Produto):
def __init__(
self,
id: str,
nome: str,
viscosidade: str = "",
tipo_motor: str = "",
**kwargs,
):
super().__init__(id, nome, **kwargs)
self._viscosidade = viscosidade
self._tipo_motor = tipo_motor
def to_dict(self) -> dict:
d = super().to_dict()
d["type"] = "ProdutoOleo"
d["viscosidade"] = self._viscosidade
d["tipo_motor"] = self._tipo_motor
return d
@classmethod
def from_dict(cls, d: dict):
kwargs = {
"categoria": d.get("categoria", ""),
"quantidade": d.get("quantidade", 0),
"unidade": d.get("unidade", "un"),
"preco_compra": d.get("preco_compra", 0.0),
"preco_venda": d.get("preco_venda", 0.0),
"estoque_minimo": d.get("estoque_minimo", 0),
}
return cls(
id=d["id"],
nome=d.get("nome", ""),
viscosidade=d.get("viscosidade", ""),
tipo_motor=d.get("tipo_motor", ""),
**kwargs
)
def __str__(self):
base = super().__str__()
return f"{base} | {self._viscosidade} | Motor:{self._tipo_motor}"
# ----------------------------
# Gerenciador de Estoque
# ----------------------------
DATA_DIR = "data"
DATA_FILE = os.path.join(DATA_DIR, "estoque.json")
class Estoque:
def __init__(self):
self._produtos: dict[str, Produto] = {}
def adicionar_produto(self, produto: Produto):
if produto.id in self._produtos:
raise ValueError("ID já existente.")
self._produtos[produto.id] = produto
def remover_produto(self, id: str):
if id not in self._produtos:
raise KeyError("ID não encontrado.")
del self._produtos[id]
def alterar_produto(self, id: str, **campos):
p = self._produtos.get(id)
if not p:
raise KeyError("ID não encontrado.")
if "nome" in campos:
p.nome = campos["nome"]
if "categoria" in campos:
p._categoria = campos["categoria"]
if "preco_compra" in campos:
p._preco_compra = float(campos["preco_compra"])
if "preco_venda" in campos:
p._preco_venda = float(campos["preco_venda"])
if "estoque_minimo" in campos:
p._estoque_minimo = int(campos["estoque_minimo"])
if "unidade" in campos:
p._unidade = campos["unidade"]
if isinstance(p, ProdutoOleo):
if "viscosidade" in campos:
p._viscosidade = campos["viscosidade"]
if "tipo_motor" in campos:
p._tipo_motor = campos["tipo_motor"]
def listar_produtos(self) -> List[Produto]:
return list(self._produtos.values())
def buscar_por_id(self, id: str) -> Optional[Produto]:
return self._produtos.get(id)
def buscar_por_nome(self, nome_substr: str) -> List[Produto]:
s = nome_substr.lower()
return [p for p in self._produtos.values() if s in p.nome.lower()]
def ajustar_estoque(self, id: str, delta: float, tipo: str):
p = self._produtos.get(id)
if not p:
raise KeyError("ID não encontrado.")
if tipo == "entrada":
p.ajustar_quantidade(abs(delta))
elif tipo == "saida":
if delta > p.quantidade:
raise ValueError("Quantidade insuficiente.")
p.ajustar_quantidade(-abs(delta))
def itens_baixo_estoque(self) -> List[Produto]:
return [p for p in self._produtos.values() if p.is_baixo_estoque()]
def salvar_json(self, path: str = DATA_FILE):
os.makedirs(os.path.dirname(path), exist_ok=True)
data = {"produtos": [p.to_dict() for p in self._produtos.values()]}
with open(path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
def carregar_json(self, path: str = DATA_FILE):
if not os.path.exists(path):
return
with open(path, "r", encoding="utf-8") as f:
data = json.load(f)
self._produtos = {}
for d in data.get("produtos", []):
if d.get("type") == "ProdutoOleo":
prod = ProdutoOleo.from_dict(d)
else:
prod = Produto.from_dict(d)
self._produtos[prod.id] = prod
class Aplicacao:
def __init__(self):
self.estoque = Estoque()
def ler_input(self, prompt: str, obrigatorio: bool = True, cast=None, default=None):
while True:
try:
s = input(prompt).strip()
except (KeyboardInterrupt, EOFError):
print()
return default
if s == "" and default is not None:
return default
if s == "" and obrigatorio:
print("Valor obrigatório. Tente novamente.")
continue
if cast:
try:
return cast(s)
except Exception:
print("Valor inválido. Tente novamente.")
continue
return s
def cadastrar_produto(self):
print("\n--- Cadastrar Produto ---")
id_ = self.ler_input("ID (único): ")
if self.estoque.buscar_por_id(id_):
print("ID já cadastrado!")
return
nome = self.ler_input("Nome: ")
categoria = self.ler_input("Categoria (opcional): ", obrigatorio=False, default="")
quantidade = self.ler_input("Quantidade inicial: ", cast=float, default=0.0)
unidade = self.ler_input("Unidade (ex: L, un): ", obrigatorio=False, default="un")
preco_compra = self.ler_input("Preço compra: ", cast=float, default=0.0)
preco_venda = self.ler_input("Preço venda: ", cast=float, default=0.0)
estoque_minimo = self.ler_input("Estoque mínimo: ", cast=int, default=0)
print("Tipo de produto:")
print("1 - Produto Geral")
print("2 - Produto Óleo")
tipo = self.ler_input("Escolha: ", default="1")
if tipo == "2":
viscosidade = self.ler_input("Viscosidade (ex: 5W40): ", default="")
tipo_motor = self.ler_input("Tipo motor (gasolina/diesel/flex): ", default="")
p = ProdutoOleo(
id=id_,
nome=nome,
viscosidade=viscosidade,
tipo_motor=tipo_motor,
categoria=categoria,
quantidade=quantidade,
unidade=unidade,
preco_compra=preco_compra,
preco_venda=preco_venda,
estoque_minimo=estoque_minimo,
)
else:
p = Produto(
id=id_,
nome=nome,
categoria=categoria,
quantidade=quantidade,
unidade=unidade,
preco_compra=preco_compra,
preco_venda=preco_venda,
estoque_minimo=estoque_minimo,
)
try:
self.estoque.adicionar_produto(p)
print("Produto cadastrado com sucesso!")
except Exception as e:
print("Erro ao cadastrar produto:", e)
def listar_produtos(self):
print("\n--- Lista de Produtos ---")
produtos = self.estoque.listar_produtos()
if not produtos:
print("Nenhum produto cadastrado.")
return
print(f"{'ID':<10} {'Nome':<28} {'Qtd':>8} {'Un':>4} {'Min':>5} {'Extra':<20}")
print("-" * 95)
for p in produtos:
extra = ""
if isinstance(p, ProdutoOleo):
extra = f"{p._viscosidade}/{p._tipo_motor}"
print(f"{p.id:<10} {p.nome:<28} {p.quantidade:>8.2f} "
f"{p._unidade:>4} {p._estoque_minimo:>5} {extra:<20}")
def buscar_por_id(self):
print("\n--- Buscar por ID ---")
id_ = self.ler_input("ID: ")
p = self.estoque.buscar_por_id(id_)
if not p:
print("Produto não encontrado.")
return
print("Encontrado:")
print(p)
def buscar_por_nome(self):
print("\n--- Buscar por Nome ---")
nome = self.ler_input("Parte do nome: ")
encontrados = self.estoque.buscar_por_nome(nome)
if not encontrados:
print("Nenhum produto encontrado.")
return
for p in encontrados:
print(p)
def alterar_produto(self):
print("\n--- Alterar Produto ---")
id_ = self.ler_input("ID: ")
p = self.estoque.buscar_por_id(id_)
if not p:
print("Produto não encontrado.")
return
novo_nome = self.ler_input(f"Nome [{p.nome}]: ", obrigatorio=False, default=p.nome)
nova_categoria = self.ler_input(
f"Categoria [{getattr(p,'_categoria','')}]: ", obrigatorio=False, default=getattr(p,'_categoria','')
)
novo_preco_compra = self.ler_input(
f"Preço compra [{getattr(p,'_preco_compra',0.0)}]: ", obrigatorio=False,
cast=float, default=getattr(p,'_preco_compra',0.0)
)
novo_preco_venda = self.ler_input(
f"Preço venda [{getattr(p,'_preco_venda',0.0)}]: ", obrigatorio=False,
cast=float, default=getattr(p,'_preco_venda',0.0)
)
novo_estoque_min = self.ler_input(
f"Estoque mínimo [{getattr(p,'_estoque_minimo',0)}]: ",
obrigatorio=False, cast=int, default=getattr(p,'_estoque_minimo',0)
)
nova_unidade = self.ler_input(
f"Unidade [{getattr(p,'_unidade','un')}]: ", obrigatorio=False, default=getattr(p,'_unidade','un')
)
campos = {
"nome": novo_nome,
"categoria": nova_categoria,
"preco_compra": novo_preco_compra,
"preco_venda": novo_preco_venda,
"estoque_minimo": novo_estoque_min,
"unidade": nova_unidade,
}
if isinstance(p, ProdutoOleo):
nova_visc = self.ler_input(
f"Viscosidade [{getattr(p,'_viscosidade','')}]: ",
obrigatorio=False, default=getattr(p,'_viscosidade','')
)
novo_tipo_motor = self.ler_input(
f"Tipo motor [{getattr(p,'_tipo_motor','')}]: ",
obrigatorio=False, default=getattr(p,'_tipo_motor','')
)
campos["viscosidade"] = nova_visc
campos["tipo_motor"] = novo_tipo_motor
try:
self.estoque.alterar_produto(id_, **campos)
print("Produto alterado com sucesso!")
except Exception as e:
print("Erro ao alterar produto:", e)
def excluir_produto(self):
print("\n--- Excluir Produto ---")
id_ = self.ler_input("ID: ")
try:
self.estoque.remover_produto(id_)
print("Produto removido.")
except KeyError:
print("ID não encontrado.")
def registrar_entrada(self):
print("\n--- Entrada de Estoque ---")
id_ = self.ler_input("ID: ")
p = self.estoque.buscar_por_id(id_)
if not p:
print("Produto não encontrado.")
return
qty = self.ler_input("Quantidade a adicionar: ", cast=float)
try:
self.estoque.ajustar_estoque(id_, qty, "entrada")
print("Entrada registrada!")
except Exception as e:
print("Erro ao registrar entrada:", e)
def registrar_saida(self):
print("\n--- Saída de Estoque ---")
id_ = self.ler_input("ID: ")
p = self.estoque.buscar_por_id(id_)
if not p:
print("Produto não encontrado.")
return
qty = self.ler_input("Quantidade a remover: ", cast=float)
if qty > p.quantidade:
print("Quantidade insuficiente.")
return
try:
self.estoque.ajustar_estoque(id_, qty, "saida")
print("Saída registrada!")
except Exception as e:
print("Erro ao registrar saída:", e)
def itens_baixo_estoque(self):
print("\n--- Itens com Baixo Estoque ---")
items = self.estoque.itens_baixo_estoque()
if not items:
print("Nenhum item abaixo do mínimo.")
return
for p in items:
print(p)
# ----------------------------
# Loop principal (Menu)
# ----------------------------
def run(self):
# Carrega dados na inicialização
if os.path.exists(DATA_FILE):
try:
self.estoque.carregar_json(DATA_FILE)
print(f"Dados carregados de {DATA_FILE}.")
except Exception as e:
print("Falha ao carregar dados:", e)
else:
# cria dados iniciais
exemplo = [
ProdutoOleo("OIL001", "Óleo 5W40 Sintético",
viscosidade="5W40", tipo_motor="flex",
quantidade=20, unidade="L",
preco_compra=80.0, preco_venda=120.0,
estoque_minimo=5),
Produto("FILT01", "Filtro de Óleo Padrão",
quantidade=30, unidade="un",
preco_compra=10.0, preco_venda=18.0,
estoque_minimo=5),
Produto("ADIT01", "Aditivo Limpeza",
quantidade=10, unidade="L",
preco_compra=25.0, preco_venda=40.0,
estoque_minimo=2),
]
for p in exemplo:
try:
self.estoque.adicionar_produto(p)
except:
pass
self.estoque.salvar_json(DATA_FILE)
print(f"Arquivo de dados criado em {DATA_FILE}.")
# Loop do menu
while True:
print("\n=== GERENCIADOR DE ESTOQUE - TROCA DE ÓLEO ===")
print("1) Cadastrar produto")
print("2) Listar todos os produtos")
print("3) Buscar produto por ID")
print("4) Buscar por nome")
print("5) Alterar produto")
print("6) Excluir produto")
print("7) Registrar entrada")
print("8) Registrar saída")
print("9) Itens com baixo estoque")
print("10) Salvar dados")
print("0) Sair")
escolha = self.ler_input("Escolha uma opção: ")
if escolha == "1":
self.cadastrar_produto()
elif escolha == "2":
self.listar_produtos()
elif escolha == "3":
self.buscar_por_id()
elif escolha == "4":
self.buscar_por_nome()
elif escolha == "5":
self.alterar_produto()
elif escolha == "6":
self.excluir_produto()
elif escolha == "7":
self.registrar_entrada()
elif escolha == "8":
self.registrar_saida()
elif escolha == "9":
self.itens_baixo_estoque()
elif escolha == "10":
self.estoque.salvar_json(DATA_FILE)
print("Dados salvos!")
elif escolha == "0":
self.estoque.salvar_json(DATA_FILE)
print("Saindo...")
break
else:
print("Opção inválida. Tente novamente.")
# ----------------------------
# Ponto de entrada
# ----------------------------
if __name__ == "__main__":
app = Aplicacao()
app.run()