diff --git "a/00 - Fundamentos/Desafio de Projeto _ Sistema Banc\303\241rio.py" "b/00 - Fundamentos/Desafio de Projeto _ Sistema Banc\303\241rio.py" new file mode 100644 index 00000000..c616176c --- /dev/null +++ "b/00 - Fundamentos/Desafio de Projeto _ Sistema Banc\303\241rio.py" @@ -0,0 +1,166 @@ +''' +DESAFIO DE PROJETO - DIGITAL INNOVATION ONE - MaOtg +''' + +# Importando biblioteca que melhora o espaçamento visual no terminal +import textwrap + +def menu(): + menu = """\n + ================ MENU ================ + [d]\tDepositar + [s]\tSacar + [e]\tExtrato + [nc]\tNova Conta + [lc]\tListar Contas + [nu]\tNovo Usuário + [q]\tSair + => """ + return input(textwrap.dedent(menu)) + +def sacar(*, saldo, valor, extrato, limite, numero_saques, limite_saques): + excedeu_saldo = valor > saldo + excedeu_limite = valor > limite + excedeu_saques = numero_saques >= limite_saques + + if excedeu_saldo: + print("\n@@@ Operação falhou! Você não tem saldo suficiente. @@@") + + elif excedeu_limite: + print("\n@@@ Operação falhou! O valor do saque excede o limite de 500 reais. @@@") + + elif excedeu_saques: + print("\n@@@ Operação falhou! Número máximo de saques excedido. @@@") + + elif valor > 0: + saldo -= valor + extrato += f"\nSaque:\t\tR$ {valor:.2f}\n" + numero_saques += 1 + print("\n=== Saque realizado com sucesso! ===") + + else: + print("\n@@@ Operação falhou! O valor informado é inválido. @@@") + + return saldo, extrato + +def depositar(saldo, valor, extrato, /): + if valor > 0: + saldo += valor + extrato += f"\nDepósito:\tR$ {valor:.2f}\n" + print("\n=== Depósito realizado com sucesso! ===") + else: + print("\n@@@ Operação falhou! O valor informado é inválido. @@@") + + return saldo, extrato + +def ver_extrato(saldo, /, *, extrato): + print("\n================ EXTRATO ================") + print("Não foram realizadas movimentações." if not extrato else extrato) + print(f"\nSaldo: R$ {saldo:.2f}") + print("==========================================") + +def criar_usuario(usuarios): + cpf = input("\nInforme o CPF (somente números): ") + usuario = filtrar_usuario(cpf, usuarios) + + if usuario: + print("\n@@@ Já existe um usuário com esse CPF cadastrado! @@@") + return + + nome = input("Informe o seu nome completo: ") + data_nascimento = input("Informe a sua data de nascimento (dd-mm-aaaa): ") + endereco = input("Informe o endereço (logradouro, nro - bairro - cidade/sigla estado): ") + + usuarios.append({"nome": nome, "data_nascimento": data_nascimento, "cpf": cpf, "endereco": endereco}) + + print("\n=== Usuário criado com sucesso! ===") + +def filtrar_usuario(cpf, usuarios): + usuarios_filtrados = [usuario for usuario in usuarios if usuario["cpf"] == cpf] + return usuarios_filtrados[0] if usuarios_filtrados else None + +def criar_conta(agencia, numero_conta, usuarios): + cpf = input("Informe o CPF do usuário: ") + usuario = filtrar_usuario(cpf, usuarios) + + if usuario: + print("\n=== Conta criada com sucesso! ===") + return {"agencia": agencia, "numero_conta": numero_conta, "usuario": usuario} + + print("\n@@@ Usuário não encontrado, fluxo de criação de conta encerrado! @@@") + +def listar_contas(contas): + if contas: + for conta in contas: + linha = f""" + Agência:\t{conta["agencia"]} + C/C:\t\t{conta["numero_conta"]} + Titular:\t{conta["usuario"]["nome"]} + """ + print("=" * 100) + print(textwrap.dedent(linha)) + else: + print("\n@@@ Não há contas para listar. @@@") + + +# Função Principal +def main(): + LIMITE_SAQUES = 3 + AGENCIA = "0001" + saldo = 0 + limite = 500 + extrato = "" + numero_saques = 0 + usuarios = [] + contas = [] + + while True: + opcao = menu() + + # Opção de Depositar + if opcao == "d": + valor = float(input("\nInforme o valor do depósito: ")) + + saldo, extrato = depositar(saldo, valor, extrato) + + # Opção de Sacar + elif opcao == "s": + valor = float(input("\nInforme o valor do saque: ")) + + saldo, extrato = sacar( + saldo = saldo, + valor = valor, + extrato = extrato, + limite = limite, + numero_saques = numero_saques, + limite_saques = LIMITE_SAQUES + ) + + # Opção de Exibir extrato + elif opcao == "e": + ver_extrato(saldo, extrato = extrato) + + # Opção de Criar novo usuário + elif opcao == "nu": + criar_usuario(usuarios) + + # Opção de Criar nova conta + elif opcao == "nc": + numero_conta = len(contas) + 1 + conta = criar_conta(AGENCIA, numero_conta, usuarios) + + if conta: + contas.append(conta) + + # Opção de Listar as contas existentes + elif opcao == "lc": + listar_contas(contas) + + elif opcao == "q": + break + + else: + print("@@@ Operação inválida, por favor selecione novamente a operação desejada (observe as letras). @@@") + +# Chamando a função principal +main() \ No newline at end of file diff --git "a/02 - Programa\303\247\303\243o Orientada a Objetos/10 - desafio/Desafio de Projeto _ Upgrade Sistema Banc\303\241rio.py" "b/02 - Programa\303\247\303\243o Orientada a Objetos/10 - desafio/Desafio de Projeto _ Upgrade Sistema Banc\303\241rio.py" new file mode 100644 index 00000000..5896529e --- /dev/null +++ "b/02 - Programa\303\247\303\243o Orientada a Objetos/10 - desafio/Desafio de Projeto _ Upgrade Sistema Banc\303\241rio.py" @@ -0,0 +1,347 @@ +''' +DESAFIO DE PROJETO - DIGITAL INNOVATION ONE - MaOtg +''' + +import textwrap +from abc import ABC, abstractmethod +from datetime import datetime + + +class Cliente: + def __init__(self, endereco: str): + self.endereco = endereco + self.contas = [] + + def realizar_transacao(self, conta, transacao): + transacao.registrar(conta) + + def adicionar_conta(self, conta): + self.contas.append(conta) + + +class PessoaFisica(Cliente): + def __init__(self, nome: str, data_nascimento: str, cpf: str, endereco: str): + super().__init__(endereco) + self.nome = nome + self.data_nascimento = data_nascimento + self.cpf = cpf + + +class Conta: + def __init__(self, numero: int, cliente): + self._saldo = 0 + self._numero = numero + self._agencia = "0001" + self._cliente = cliente + self._historico = Historico() + + @classmethod + def nova_conta(cls, cliente, numero: int): + return cls(numero, cliente) + + @property + def saldo(self): + return self._saldo + + @property + def numero(self): + return self._numero + + @property + def agencia(self): + return self._agencia + + @property + def cliente(self): + return self._cliente + + @property + def historico(self): + return self._historico + + def sacar(self, valor): + saldo = self.saldo + excedeu_saldo = valor > saldo + + if excedeu_saldo: + print("\n@@@ Operação falhou! Você não tem saldo suficiente. @@@") + + elif valor > 0: + self._saldo -= valor + print("\n=== Saque realizado com sucesso! ===") + return True + + else: + print("\n@@@ Operação falhou! O valor informado é inválido. @@@") + + return False + + def depositar(self, valor: int): + if valor > 0: + self._saldo += valor + print("\n=== Depósito realizado com sucesso! ===") + else: + print("\n@@@ Operação falhou! O valor informado é inválido. @@@") + return False + + return True + + +class ContaCorrente(Conta): + def __init__(self, numero, cliente, limite=990, limite_saques=3): + super().__init__(numero, cliente) + self._limite = limite + self._limite_saques = limite_saques + + def sacar(self, valor): + numero_saques = len( + [transacao for transacao in self.historico.transacoes if transacao["tipo"] == Saque.__name__] + ) + + excedeu_limite = valor > self._limite + excedeu_saques = numero_saques >= self._limite_saques + + if excedeu_limite: + print("\n@@@ Operação falhou! O valor do saque excede o limite. @@@") + + elif excedeu_saques: + print("\n@@@ Operação falhou! Número máximo de saques excedido. @@@") + + else: + return super().sacar(valor) + + return False + + def __str__(self): + return f"""\ + Agência:\t{self.agencia} + C/C:\t\t{self.numero} + Titular:\t{self.cliente.nome} + """ + + +class Historico: + def __init__(self): + self._transacoes = [] + + @property + def transacoes(self): + return self._transacoes + + def adicionar_transacao(self, transacao): + self._transacoes.append( + { + "tipo": transacao.__class__.__name__, + "valor": transacao.valor, + "data": datetime.now().strftime("%d-%m-%Y %H:%M:%S"), + } + ) + + +class Transacao(ABC): + @property + @abstractmethod + def valor(self): + pass + + @abstractmethod + def registrar(self, conta): + pass + + +class Saque(Transacao): + def __init__(self, valor): + self._valor = valor + + @property + def valor(self): + return self._valor + + def registrar(self, conta): + sucesso_transacao = conta.sacar(self.valor) + + if sucesso_transacao: + conta.historico.adicionar_transacao(self) + + +class Deposito(Transacao): + def __init__(self, valor): + self._valor = valor + + @property + def valor(self): + return self._valor + + def registrar(self, conta): + sucesso_transacao = conta.depositar(self.valor) + + if sucesso_transacao: + conta.historico.adicionar_transacao(self) + + +def menu(): + menu = """\n + ================ MENU ================ + [d]\tDepositar + [s]\tSacar + [e]\tExtrato + [nc]\tNova conta + [lc]\tListar contas + [nu]\tNovo usuário + [q]\tSair + => """ + return input(textwrap.dedent(menu)) + + +def filtrar_cliente(cpf, clientes): + clientes_filtrados = [cliente for cliente in clientes if cliente.cpf == cpf] + return clientes_filtrados[0] if clientes_filtrados else None + + +def recuperar_conta_cliente(cliente): + if not cliente.contas: + print("\n@@@ Cliente não possui conta! @@@") + return + + # FIXME: não permite cliente escolher a conta + return cliente.contas[0] + + +def depositar(clientes): + cpf = input("Informe o CPF do cliente: ") + cliente = filtrar_cliente(cpf, clientes) + + if not cliente: + print("\n@@@ Cliente não encontrado! @@@") + return + + valor = float(input("Informe o valor do depósito: ")) + transacao = Deposito(valor) + + conta = recuperar_conta_cliente(cliente) + if not conta: + return + + cliente.realizar_transacao(conta, transacao) + + +def sacar(clientes): + cpf = input("Informe o CPF do cliente: ") + cliente = filtrar_cliente(cpf, clientes) + + if not cliente: + print("\n@@@ Cliente não encontrado! @@@") + return + + valor = float(input("Informe o valor do saque: ")) + transacao = Saque(valor) + + conta = recuperar_conta_cliente(cliente) + if not conta: + return + + cliente.realizar_transacao(conta, transacao) + + +def exibir_extrato(clientes): + cpf = input("Informe o CPF do cliente: ") + cliente = filtrar_cliente(cpf, clientes) + + if not cliente: + print("\n@@@ Cliente não encontrado! @@@") + return + + conta = recuperar_conta_cliente(cliente) + if not conta: + return + + print("\n================ EXTRATO ================") + transacoes = conta.historico.transacoes + + extrato = "" + if not transacoes: + extrato = "Não foram realizadas movimentações." + else: + for transacao in transacoes: + extrato += f"\n{transacao['tipo']}:\n\tR$ {transacao['valor']:.2f}" + + print(extrato) + print(f"\nSaldo:\n\tR$ {conta.saldo:.2f}") + print("==========================================") + + +def criar_cliente(clientes): + cpf = input("Informe o CPF (somente número): ") + cliente = filtrar_cliente(cpf, clientes) + + if cliente: + print("\n@@@ Já existe cliente com esse CPF! @@@") + return + + nome = input("Informe o nome completo: ") + data_nascimento = input("Informe a data de nascimento (dd-mm-aaaa): ") + endereco = input("Informe o endereço (logradouro, nro - bairro - cidade/sigla estado): ") + + cliente = PessoaFisica(nome=nome, data_nascimento=data_nascimento, cpf=cpf, endereco=endereco) + + clientes.append(cliente) + + print("\n=== Cliente criado com sucesso! ===") + + +def criar_conta(numero_conta, clientes, contas): + cpf = input("Informe o CPF do cliente: ") + cliente = filtrar_cliente(cpf, clientes) + + if not cliente: + print("\n@@@ Cliente não encontrado, fluxo de criação de conta encerrado! @@@") + return + + conta = ContaCorrente.nova_conta(cliente=cliente, numero=numero_conta) + contas.append(conta) + cliente.contas.append(conta) + + print("\n=== Conta criada com sucesso! ===") + + +def listar_contas(contas): + for conta in contas: + print("=" * 100) + print(textwrap.dedent(str(conta))) + + +def main(): + clientes = [] + contas = [] + + while True: + opcao = menu() + + if opcao == "d": + depositar(clientes) + + elif opcao == "s": + sacar(clientes) + + elif opcao == "e": + exibir_extrato(clientes) + + elif opcao == "nu": + criar_cliente(clientes) + + elif opcao == "nc": + numero_conta = len(contas) + 1 + criar_conta(numero_conta, clientes, contas) + + elif opcao == "lc": + listar_contas(contas) + + elif opcao == "q": + print("=) Obrigado por utilizar nossos serviços, estamos a disposição! (=") + break + + else: + print("\n@@@ Operação inválida, por favor selecione novamente a operação desejada. @@@") + + +main() \ No newline at end of file