Componentes: André C. Rodrigues, Elian E. L. Ferreira, Kalebe D. Elisio Scheidt e Murilo E. Da Rosa.
Objetivos: Desenvolver um sistema para gerenciar o estoque de uma empresa, controlando entradas e saídas e a localização dos itens.
Metodologia de desenvolvimento: Elaboração do propósito inicial, levando em consideração o desenvolvimento das ferramentas críticas. Seguindo, divisão de papéis para individualizar o processo de desenvolvimento. Depois, fase de demonstração inicial e feedbacks. Por fim, reelaboração contínua do código com enfoque na eficiência da usabilidade e qualidade da estrutura do programa.
# @title Código final
import pickle
import signal
# ===================== FUNÇÕES UTILITÁRIAS =====================
def criar_manejador_de_sinal(callback):
return lambda sinal, quadro: callback()
def solicitar_valor(mensagem, conversor=lambda x: x, validar=lambda _: True, mensagem_erro="Valor inválido. Tente novamente."):
while True:
try:
valor = conversor(input(mensagem))
if validar(valor):
return valor
except Exception:
pass
print(mensagem_erro)
"""
solicitar_valor(mensagem, conversor, validar, messagem_error):
while True
try
resultado = conversor(input(mensagem))
if validar(resultado):
return resultado
except
pass
print(messagem_error)
solicitar_valor("Me de um numero", lambda numero: int(numero), lambda numero: numero >= 0 and x <= 10)
solicitar_valor("Me diga um texto")
"""
def solicitar_opcao(limite):
while True:
try:
opcao = int(input("Escolha uma opção: ")) - 1
if 0 <= opcao < limite:
return opcao
except Exception:
pass
print("Opção inválida. Tente novamente.")
# ===================== CLASSES DE MENU =====================
class OpcaoDeMenu:
def __init__(self, titulo, acao):
self.titulo = titulo
self.acao = acao
class Menu:
def __init__(self, titulo):
self.titulo = titulo
self.opcoes = [OpcaoDeMenu("Sair", lambda: None)]
def registrar_opcao(self, titulo, acao):
self.opcoes.append(OpcaoDeMenu(titulo, acao))
def exibir(self):
while True:
print(f"\n[{self.titulo}]")
for indice, opcao in enumerate(self.opcoes):
print(f"\t[{indice + 1}] {opcao.titulo}")
opcao_escolhida = solicitar_opcao(len(self.opcoes))
if opcao_escolhida == 0:
break
self.opcoes[opcao_escolhida].acao()
# ===================== MODELOS DE ESTOQUE =====================
class ItemDeEstoque:
def __init__(self, nome="", quantidade=0):
if not nome or quantidade <= 0:
self.solicitar_dados()
else:
self.nome = nome
self.quantidade = quantidade
def __str__(self):
return f"[Quantidade: {self.quantidade}] [Nome: {self.nome}]"
def solicitar_dados(self):
self.nome = solicitar_valor("\tNome do produto: ", str, lambda v: v.strip() != "")
self.quantidade = solicitar_valor("\tQuantidade: ", int, lambda v: v >= 0)
class PosicaoDoEstoque:
def __init__(self, linha=-1, coluna=-1):
if linha > 0 and coluna > 0:
self.linha = linha - 1
self.coluna = coluna - 1
else:
self.linha, self.coluna = self.solicitar_posicao()
def solicitar_posicao(self):
linha = solicitar_valor("Linha: ", int, lambda v: v > 0) - 1
coluna = solicitar_valor("Coluna: ", int, lambda v: v > 0) - 1
return linha, coluna
def __str__(self):
return f"({self.linha + 1}, {self.coluna + 1})"
class LinhaDeArmazenamento:
def __init__(self, tamanho):
self.colunas = [None] * tamanho
def obter(self, indice):
return self.colunas[indice] if 0 <= indice < len(self.colunas) else None
def inserir_em(self, item, indice):
if not (0 <= indice < len(self.colunas)):
return None
antigo = self.colunas[indice]
self.colunas[indice] = item
return antigo
class Armazenamento:
def __init__(self, largura, altura):
self.linhas = [LinhaDeArmazenamento(largura) for _ in range(altura)]
def existe(self, posicao):
return 0 <= posicao.linha < len(self.linhas) and 0 <= posicao.coluna < len(self.linhas[posicao.linha].colunas)
def obter(self, posicao):
return self.linhas[posicao.linha].obter(posicao.coluna) if self.existe(posicao) else None
def esta_vazio(self, posicao):
return self.obter(posicao) is None
def inserir(self, item, posicao):
if not self.existe(posicao):
return False
self.linhas[posicao.linha].inserir_em(item, posicao.coluna)
return True
def remover(self, posicao):
if not self.existe(posicao):
return False
self.linhas[posicao.linha].inserir_em(None, posicao.coluna)
return True
def listar_todos(self):
for i, linha in enumerate(self.linhas):
for j, item in enumerate(linha.colunas):
if item:
print(f"({i + 1}, {j + 1}) {item}")
def listar_por_nome(self, nome):
for i, linha in enumerate(self.linhas):
for j, item in enumerate(linha.colunas):
if item and nome.lower() in item.nome.lower():
print(f"({i + 1}, {j + 1}) {item}")
# ===================== GERENCIADOR DE ESTOQUE =====================
class GerenciadorDeEstoque(Menu):
def __init__(self, armazenamento=None):
super().__init__("Gerenciador de Estoque")
if (armazenamento == None):
print("[AVISO] Nenhum registro de estoque encontrado. Iniciando arquiteto de estoque.")
armazenamento = self._criar_novo_armazenamento()
self.armazenamento = armazenamento
self._configurar_sinal_de_salvamento()
self._registrar_opcoes()
def _adicionar_item(self):
item = ItemDeEstoque()
posicao = PosicaoDoEstoque()
if not self.armazenamento.existe(posicao):
return print("Posição inválida.")
if not self.armazenamento.esta_vazio(posicao) and not self._confirmar("Sobrescrever item existente? (s/n): "):
return print("Operação cancelada.")
self.armazenamento.inserir(item, posicao)
print(f"{item.nome} adicionado em {posicao}.")
def _remover_item(self):
posicao = self._solicitar_posicao_valida("Remover item de:")
item = self.armazenamento.obter(posicao)
self.armazenamento.remover(posicao)
print(f"{item.nome} removido com sucesso.")
def _mover_item(self):
posicao_origem = self._solicitar_posicao_valida("Posição de origem:")
item = self.armazenamento.obter(posicao_origem)
while True:
posicao_destino = PosicaoDoEstoque()
if not self.armazenamento.existe(posicao_destino):
print("Posição de destino inválida. Tente novamente.")
continue
if not self.armazenamento.esta_vazio(posicao_destino):
item = self.armazenamento.obter(posicao_destino)
print(f"A posição atual está preenchida com o item {item.name}")
if not self._confirmar("Sobrescrever item do destino? (s/n): "):
print("Operação cancelada.")
return
break
self.armazenamento.remover(posicao_origem)
self.armazenamento.inserir(item, posicao_destino)
print(f"Item movido de {posicao_origem} para {posicao_destino} com sucesso.")
def _substituir_item(self):
posicao = self._solicitar_posicao_valida("Escolha o item para substituir:")
if not self._confirmar("Confirmar substituição? (s/n): "):
return print("Operação cancelada.")
self.armazenamento.inserir(ItemDeEstoque(), posicao)
print("Item substituído com sucesso.")
def _atualizar_item(self):
posicao = self._solicitar_posicao_valida("Atualizar item em:")
item = self.armazenamento.obter(posicao)
if not item:
return
print(f"[1] Nome ({item.nome})\n[2] Quantidade ({item.quantidade})")
opcao = solicitar_opcao(2)
if opcao == 0:
item.nome = solicitar_valor("Novo nome: ", str, lambda x: x.strip() != "")
else:
item.quantidade = solicitar_valor("Nova quantidade: ", int, lambda x: x >= 0)
print("Item atualizado com sucesso.")
def _menu_visualizacao(self):
print("[1] Todos\n[2] Por nome\n[3] Por posição")
opcao = solicitar_opcao(3)
if opcao == 0:
self.armazenamento.listar_todos()
elif opcao == 1:
self.armazenamento.listar_por_nome(input("Nome: "))
else:
print(self.armazenamento.obter(PosicaoDoEstoque()))
def _salvar(self):
with open("estoque.pkl", "wb") as arquivo:
pickle.dump(self.armazenamento, arquivo)
print("Estoque salvo com sucesso.")
def _criar_novo_armazenamento(self):
print("[Arquiteto de Estoque]")
largura = solicitar_valor("\tPor favor, insira a largura do estoque: ", int, lambda x: x > 0)
altura = solicitar_valor("\tPor favor, insira a altura do estoque: ", int, lambda x: x > 0)
return Armazenamento(largura, altura)
def _configurar_sinal_de_salvamento(self):
try:
signal.signal(signal.SIGINT, criar_manejador_de_sinal(self._salvar))
except:
print("[Aviso] Devido a um erro interno, as mudanças nesta sessão só serão salvas manualmente.")
def _registrar_opcoes(self):
opcoes = [
("Visualizar Itens", self._menu_visualizacao),
("Adicionar Item", self._adicionar_item),
("Remover Item", self._remover_item),
("Mover Item", self._mover_item),
("Substituir Item", self._substituir_item),
("Atualizar Item", self._atualizar_item),
("Salvar Estoque", self._salvar),
]
for titulo, acao in opcoes:
self.registrar_opcao(titulo, acao)
def _confirmar(self, mensagem):
return input(mensagem).strip().lower().startswith("s")
def _solicitar_posicao_valida(self, mensagem, exigir_item=True):
print(mensagem)
while True:
posicao = PosicaoDoEstoque()
if not self.armazenamento.existe(posicao):
print("Posição inválida.")
elif exigir_item and self.armazenamento.esta_vazio(posicao):
print("Posição vazia.")
else:
return posicao
# ===================== EXECUÇÃO =====================
def carregar_armazenamento():
try:
with open("estoque.pkl", "rb") as arquivo:
return pickle.load(arquivo)
except Exception:
return None
if __name__ == "__main__":
GerenciadorDeEstoque(carregar_armazenamento()).exibir()