trilha-python-dio icon indicating copy to clipboard operation
trilha-python-dio copied to clipboard

Otimizando o Sistema Bancário com Funções Python

Open 94submarina opened this issue 6 months ago • 0 comments

import textwrap from abc import ABC, abstractclassmethod, abstractproperty from datetime import datetime

class ContasIterador: def init(self, contas): self.contas = contas self._index = 0

def __iter__(self):
    return self

def __next__(self):
    try:
        conta = self.contas[self._index]
        return f"""\
        Agência:\t{conta.agencia}
        Número:\t\t{conta.numero}
        Titular:\t{conta.cliente.nome}
        Saldo:\t\tR$ {conta.saldo:.2f}
    """
    except IndexError:
        raise StopIteration
    finally:
        self._index += 1

class Cliente: def init(self, endereco): self.endereco = endereco self.contas = [] self.indice_conta = 0

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, data_nascimento, cpf, endereco): super().init(endereco) self.nome = nome self.data_nascimento = data_nascimento self.cpf = cpf

class Conta: def init(self, numero, cliente): self._saldo = 0 self._numero = numero self._agencia = "0001" self._cliente = cliente self._historico = Historico()

@classmethod
def nova_conta(cls, cliente, numero):
    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):
    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=500, limite_saques=3): super().init(numero, cliente) self._limite = limite self._limite_saques = limite_saques

@classmethod
def nova_conta(cls, cliente, numero, limite, limite_saques):
    return cls(numero, cliente, limite, 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"),
        }
    )

def gerar_relatorio(self, tipo_transacao=None):
    for transacao in self._transacoes:
        if tipo_transacao is None or transacao["tipo"].lower() == tipo_transacao.lower():
            yield transacao

def transacoes_do_dia(self):
    pass

class Transacao(ABC): @property @abstractproperty def valor(self): pass

@abstractclassmethod
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 log_transacao(func): def envelope(*args, **kwargs): resultado = func(*args, **kwargs) print(f"{datetime.now()}: {func.name.upper()}") return resultado

return envelope

def menu(): menu = """\n ****************** MENU ****************** [nu]\tNovo usuário [nc]\tNova conta [d]\tDepositar [s]\tSacar [e]\tExtrato [lc]\tListar contas [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*** Esse Cliente não possui conta! ***") return return cliente.contas[0]

@log_transacao 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)

@log_transacao def sacar(clientes): cpf = input("Informe o seu CPF: ") cliente = filtrar_cliente(cpf, clientes)

if not cliente:
    print("\n*** Cliente nao encontrado! ***")
    return

valor = float(input("Informe o valor que deseja sacar: "))
transacao = Saque(valor)

conta = recuperar_conta_cliente(cliente)
if not conta:
    return

cliente.realizar_transacao(conta, transacao)

@log_transacao def exibir_extrato(clientes): cpf = input("Informe o seu CPF: ") 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 ******************")
extrato = ""
tem_transacao = False
for transacao in conta.historico.gerar_relatorio():
    tem_transacao = True
    extrato += f"\n{transacao['tipo']}:\n\tR$ {transacao['valor']:.2f}"

if not tem_transacao:
    extrato = "Não foram realizadas transações"

print(extrato)
print(f"\nSaldo:\n\tR$ {conta.saldo:.2f}")
print("***********************************")

@log_transacao def criar_cliente(clientes): cpf = input("Informe o seu CPF (somente número): ") cliente = filtrar_cliente(cpf, clientes)

if cliente:
    print("\n****** Já existe cliente com esse CPF! ******")
    return

nome = input("Informe o seu nome completo: ")
data_nascimento = input("Informe a sua data de nascimento (dd-mm-aaaa): ")
endereco = input("Informe o seu 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*** Novo Cliente criado com sucesso! ***")

@log_transacao def criar_conta(numero_conta, clientes, contas): cpf = input("Informe o seu CPF : ") cliente = filtrar_cliente(cpf, clientes)

if not cliente:
    print("\n*** Cliente não encontrado, criação de conta encerrado! ***")
    return

conta = ContaCorrente.nova_conta(cliente=cliente, numero=numero_conta, limite=2000, limite_saques=20)
contas.append(conta)
cliente.contas.append(conta)

print("\n*** Parabens, conta criada com sucesso! ***")

def listar_contas(contas): for conta in ContasIterador(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":
        break

    else:
        print("\n*** Opção inválida, por favor selecione novamente a operação desejada. ***")

main()

RESULTADO IMPRESSO

****************** MENU ****************** [nu] Novo usuário [nc] Nova conta [d] Depositar [s] Sacar [e] Extrato [lc] Listar contas [q] Sair => nu Informe o seu CPF (somente número): 301994 Informe o seu nome completo: Marina Freitas Informe a sua data de nascimento (dd-mm-aaaa): 30041994 Informe o seu endereço (logradouro, nro - bairro - cidade/sigla estado): Rua 12, 200 - Jd Finotti - Uberlandia MG

*** Novo Cliente criado com sucesso! *** 2024-08-23 00:18:41.365696: CRIAR_CLIENTE

****************** MENU ****************** [nu] Novo usuário [nc] Nova conta [d] Depositar [s] Sacar [e] Extrato [lc] Listar contas [q] Sair => nc Informe o seu CPF : 301994

*** Parabens, conta criada com sucesso! *** 2024-08-23 00:18:47.864918: CRIAR_CONTA

****************** MENU ****************** [nu] Novo usuário [nc] Nova conta [d] Depositar [s] Sacar [e] Extrato [lc] Listar contas [q] Sair => d Informe o CPF do cliente: 301994 Informe o valor do depósito: 5000

*** Depósito realizado com sucesso! *** 2024-08-23 00:18:56.745940: DEPOSITAR

****************** MENU ****************** [nu] Novo usuário [nc] Nova conta [d] Depositar [s] Sacar [e] Extrato [lc] Listar contas [q] Sair => s Informe o seu CPF: 301994 Informe o valor que deseja sacar: 1000

***** Saque realizado com sucesso! **** 2024-08-23 00:19:06.483734: SACAR

****************** MENU ****************** [nu] Novo usuário [nc] Nova conta [d] Depositar [s] Sacar [e] Extrato [lc] Listar contas [q] Sair => e Informe o seu CPF: 301994

***************** EXTRATO ******************

Deposito: R$ 5000.00 Saque: R$ 1000.00

Saldo: R$ 4000.00


2024-08-23 00:19:13.637899: EXIBIR_EXTRATO

****************** MENU ****************** [nu] Novo usuário [nc] Nova conta [d] Depositar [s] Sacar [e] Extrato [lc] Listar contas [q] Sair =>

94submarina avatar Aug 22 '24 23:08 94submarina