diff --git "a/05 - Manipula\303\247\303\243o de arquivos/1_operacao_leitura.py" "b/05 - Manipula\303\247\303\243o de arquivos/1_operacao_leitura.py" new file mode 100644 index 00000000..354ea98e --- /dev/null +++ "b/05 - Manipula\303\247\303\243o de arquivos/1_operacao_leitura.py" @@ -0,0 +1,28 @@ +# Lembre-se de alterar o caminho do arquivo, para o caminho completo da sua máquina! + +arquivo = open( + "/home/guilherme/Projetos/dio/codigo-fonte/trilha-python-dio/05 - Manipulação de arquivos/lorem.txt", "r" +) +print(arquivo.read()) +arquivo.close() + +arquivo = open( + "/home/guilherme/Projetos/dio/codigo-fonte/trilha-python-dio/05 - Manipulação de arquivos/lorem.txt", "r" +) +print(arquivo.readline()) +arquivo.close() + +arquivo = open( + "/home/guilherme/Projetos/dio/codigo-fonte/trilha-python-dio/05 - Manipulação de arquivos/lorem.txt", "r" +) +print(arquivo.readlines()) +arquivo.close() + +arquivo = open( + "/home/guilherme/Projetos/dio/codigo-fonte/trilha-python-dio/05 - Manipulação de arquivos/lorem.txt", "r" +) +# tip +while len(linha := arquivo.readline()): + print(linha) + +arquivo.close() diff --git "a/05 - Manipula\303\247\303\243o de arquivos/2_operacao_escrita.py" "b/05 - Manipula\303\247\303\243o de arquivos/2_operacao_escrita.py" new file mode 100644 index 00000000..3543afbe --- /dev/null +++ "b/05 - Manipula\303\247\303\243o de arquivos/2_operacao_escrita.py" @@ -0,0 +1,6 @@ +arquivo = open( + "/home/guilherme/Projetos/dio/codigo-fonte/trilha-python-dio/05 - Manipulação de arquivos/teste.txt", "w" +) +arquivo.write("Escrevendo dados em um novo arquivo.") +arquivo.writelines(["\n", "escrevendo", "\n", "um", "\n", "novo", "\n", "texto"]) +arquivo.close() diff --git "a/05 - Manipula\303\247\303\243o de arquivos/3_os_shutil.py" "b/05 - Manipula\303\247\303\243o de arquivos/3_os_shutil.py" new file mode 100644 index 00000000..aaa6280f --- /dev/null +++ "b/05 - Manipula\303\247\303\243o de arquivos/3_os_shutil.py" @@ -0,0 +1,16 @@ +import os +import shutil +from pathlib import Path + +ROOT_PATH = Path(__file__).parent + +os.mkdir(ROOT_PATH / "novo-diretorio") + +arquivo = open(ROOT_PATH / "novo.txt", "w") +arquivo.close() + +os.rename(ROOT_PATH / "novo.txt", ROOT_PATH / "alterado.txt") + +os.remove(ROOT_PATH / "alterado.txt") + +shutil.move(ROOT_PATH / "novo.txt", ROOT_PATH / "novo-diretorio" / "novo.txt") diff --git "a/05 - Manipula\303\247\303\243o de arquivos/4_tratamento_erro.py" "b/05 - Manipula\303\247\303\243o de arquivos/4_tratamento_erro.py" new file mode 100644 index 00000000..fb099fb8 --- /dev/null +++ "b/05 - Manipula\303\247\303\243o de arquivos/4_tratamento_erro.py" @@ -0,0 +1,22 @@ +from pathlib import Path + +ROOT_PATH = Path(__file__).parent + + +try: + arquivo = open(ROOT_PATH / "novo-diretorio" / "novo.txt", "r") +except FileNotFoundError as exc: + print("Arquivo não encontrado!") + print(exc) +except IsADirectoryError as exc: + print(f"Não foi possível abrir o arquivo: {exc}") +except IOError as exc: + print(f"Erro ao abrir o arquivo: {exc}") +except Exception as exc: + print(f"Algum problema ocorreu ao tentar abrir o arquivo: {exc}") + + +# try: +# arquivo = open(ROOT_PATH / "novo-diretorio") +# except IsADirectoryError as exc: +# print(f"Não foi possível abrir o arquivo: {exc}") diff --git "a/05 - Manipula\303\247\303\243o de arquivos/5_boas_praticas.py" "b/05 - Manipula\303\247\303\243o de arquivos/5_boas_praticas.py" new file mode 100644 index 00000000..eda7a616 --- /dev/null +++ "b/05 - Manipula\303\247\303\243o de arquivos/5_boas_praticas.py" @@ -0,0 +1,24 @@ +from pathlib import Path + +ROOT_PATH = Path(__file__).parent + +try: + with open(ROOT_PATH / "1lorem.txt", "r") as arquivo: + print(arquivo.read()) +except IOError as exc: + print(f"Erro ao abrir o arquivo {exc}") + + +# try: +# with open(ROOT_PATH / "arquivo-utf-8.txt", "w", encoding="utf-8") as arquivo: +# arquivo.write("Aprendendo a manipular arquivos utilizando Python.") +# except IOError as exc: +# print(f"Erro ao abrir o arquivo {exc}") + +try: + with open(ROOT_PATH / "arquivo-utf-8.txt", "r", encoding="utf-8") as arquivo: + print(arquivo.read()) +except IOError as exc: + print(f"Erro ao abrir o arquivo {exc}") +except UnicodeDecodeError as exc: + print(exc) diff --git "a/05 - Manipula\303\247\303\243o de arquivos/6_csv.py" "b/05 - Manipula\303\247\303\243o de arquivos/6_csv.py" new file mode 100644 index 00000000..04f53603 --- /dev/null +++ "b/05 - Manipula\303\247\303\243o de arquivos/6_csv.py" @@ -0,0 +1,39 @@ +import csv +from pathlib import Path + +ROOT_PATH = Path(__file__).parent + +COLUNA_ID = 0 +COLUNA_NOME = 1 + + +try: + with open(ROOT_PATH / "usuarios.csv", "w", newline="", encoding="utf-8") as arquivo: + escritor = csv.writer(arquivo) + escritor.writerow(["id", "nome"]) + escritor.writerow(["1", "Maria"]) + escritor.writerow(["2", "João"]) +except IOError as exc: + print(f"Erro ao criar o arquivo. {exc}") + + +try: + with open(ROOT_PATH / "usuarios.csv", "r", newline="", encoding="utf-8") as arquivo: + leitor = csv.reader(arquivo) + for idx, row in enumerate(leitor): + if idx == 0: + continue + print(f"ID: {row[COLUNA_ID]}") + print(f"Nome: {row[COLUNA_NOME]}") +except IOError as exc: + print(f"Erro ao criar o arquivo. {exc}") + + +try: + with open(ROOT_PATH / "usuarios.csv", newline="") as csvfile: + reader = csv.DictReader(csvfile) + for row in reader: + print(f"ID: {row['id']}") + print(f"Nome: {row['nome']}") +except IOError as exc: + print(f"Erro ao criar o arquivo. {exc}") diff --git "a/05 - Manipula\303\247\303\243o de arquivos/arquivo-utf-8.txt" "b/05 - Manipula\303\247\303\243o de arquivos/arquivo-utf-8.txt" new file mode 100644 index 00000000..de149a6b --- /dev/null +++ "b/05 - Manipula\303\247\303\243o de arquivos/arquivo-utf-8.txt" @@ -0,0 +1 @@ +Aprendendo a manipular arquivos utilizando Python.ÿÿÿ \ No newline at end of file diff --git "a/05 - Manipula\303\247\303\243o de arquivos/desafio/desafio_v1.py" "b/05 - Manipula\303\247\303\243o de arquivos/desafio/desafio_v1.py" new file mode 100644 index 00000000..657703d2 --- /dev/null +++ "b/05 - Manipula\303\247\303\243o de arquivos/desafio/desafio_v1.py" @@ -0,0 +1,411 @@ +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): + if len(conta.historico.transacoes_do_dia()) >= 2: + print("\n@@@ Você excedeu o número de transações permitidas para hoje! @@@") + return + + 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 + + def __repr__(self) -> str: + return f"<{self.__class__.__name__}: ('{self.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 __repr__(self): + return f"<{self.__class__.__name__}: ('{self.agencia}', '{self.numero}', '{self.cliente.nome}')>" + + 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.utcnow().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): + data_atual = datetime.utcnow().date() + transacoes = [] + for transacao in self._transacoes: + data_transacao = datetime.strptime(transacao["data"], "%d-%m-%Y %H:%M:%S").date() + if data_atual == data_transacao: + transacoes.append(transacao) + return transacoes + + +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) + data_hora = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + # TODO: alterar a implementação para salvar em arquivo. + # f"[{data_hora}] Função '{func.__name__}' executada com argumentos {args} e {kwargs}. Retornou {result}\n" + print(f"{data_hora}: {func.__name__.upper()}") + return resultado + + return envelope + + +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] + + +@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 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) + + +@log_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 ================") + extrato = "" + tem_transacao = False + for transacao in conta.historico.gerar_relatorio(): + tem_transacao = True + extrato += f"\n{transacao['data']}\n{transacao['tipo']}:\n\tR$ {transacao['valor']:.2f}" + + if not tem_transacao: + extrato = "Não foram realizadas movimentações" + + print(extrato) + print(f"\nSaldo:\n\tR$ {conta.saldo:.2f}") + print("==========================================") + + +@log_transacao +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! ===") + + +@log_transacao +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, limite=500, limite_saques=50) + contas.append(conta) + cliente.contas.append(conta) + + print("\n=== 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@@@ Operação inválida, por favor selecione novamente a operação desejada. @@@") + + +main() diff --git "a/05 - Manipula\303\247\303\243o de arquivos/desafio/desafio_v2.py" "b/05 - Manipula\303\247\303\243o de arquivos/desafio/desafio_v2.py" new file mode 100644 index 00000000..9740b0c5 --- /dev/null +++ "b/05 - Manipula\303\247\303\243o de arquivos/desafio/desafio_v2.py" @@ -0,0 +1,416 @@ +import textwrap +from abc import ABC, abstractclassmethod, abstractproperty +from datetime import datetime +from pathlib import Path + +ROOT_PATH = Path(__file__).parent + + +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): + if len(conta.historico.transacoes_do_dia()) >= 2: + print("\n@@@ Você excedeu o número de transações permitidas para hoje! @@@") + return + + 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 + + def __repr__(self) -> str: + return f"<{self.__class__.__name__}: ('{self.nome}', '{self.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 __repr__(self): + return f"<{self.__class__.__name__}: ('{self.agencia}', '{self.numero}', '{self.cliente.nome}')>" + + 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.utcnow().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): + data_atual = datetime.utcnow().date() + transacoes = [] + for transacao in self._transacoes: + data_transacao = datetime.strptime(transacao["data"], "%d-%m-%Y %H:%M:%S").date() + if data_atual == data_transacao: + transacoes.append(transacao) + return transacoes + + +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) + data_hora = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") + with open(ROOT_PATH / "log.txt", "a") as arquivo: + arquivo.write( + f"[{data_hora}] Função '{func.__name__}' executada com argumentos {args} e {kwargs}. " + f"Retornou {resultado}\n" + ) + return resultado + + return envelope + + +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] + + +@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 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) + + +@log_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 ================") + extrato = "" + tem_transacao = False + for transacao in conta.historico.gerar_relatorio(): + tem_transacao = True + extrato += f"\n{transacao['data']}\n{transacao['tipo']}:\n\tR$ {transacao['valor']:.2f}" + + if not tem_transacao: + extrato = "Não foram realizadas movimentações" + + print(extrato) + print(f"\nSaldo:\n\tR$ {conta.saldo:.2f}") + print("==========================================") + + +@log_transacao +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! ===") + + +@log_transacao +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, limite=500, limite_saques=50) + contas.append(conta) + cliente.contas.append(conta) + + print("\n=== 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@@@ Operação inválida, por favor selecione novamente a operação desejada. @@@") + + +main() diff --git "a/05 - Manipula\303\247\303\243o de arquivos/desafio/log.txt" "b/05 - Manipula\303\247\303\243o de arquivos/desafio/log.txt" new file mode 100644 index 00000000..19190e38 --- /dev/null +++ "b/05 - Manipula\303\247\303\243o de arquivos/desafio/log.txt" @@ -0,0 +1,6 @@ +[2023-10-04 19:56:53] Função 'criar_cliente' executada com argumentos ([],) e {}. Retornou None +[2023-10-04 19:57:40] Função 'criar_conta' executada com argumentos (1, [], []) e {}. Retornou None +[2023-10-04 19:57:46] Função 'depositar' executada com argumentos ([],) e {}. Retornou None +[2023-10-04 20:00:03] Função 'criar_conta' executada com argumentos (1, [], []) e {}. Retornou None +[2023-10-04 20:00:14] Função 'criar_cliente' executada com argumentos ([],) e {}. Retornou None +[2023-10-04 20:05:27] Função 'criar_cliente' executada com argumentos ([],) e {}. Retornou None diff --git "a/05 - Manipula\303\247\303\243o de arquivos/lorem.txt" "b/05 - Manipula\303\247\303\243o de arquivos/lorem.txt" new file mode 100644 index 00000000..940e1521 --- /dev/null +++ "b/05 - Manipula\303\247\303\243o de arquivos/lorem.txt" @@ -0,0 +1,2 @@ +What is Lorem Ipsum? +Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. \ No newline at end of file diff --git "a/05 - Manipula\303\247\303\243o de arquivos/novo-diretorio/novo.txt" "b/05 - Manipula\303\247\303\243o de arquivos/novo-diretorio/novo.txt" new file mode 100644 index 00000000..e69de29b diff --git "a/05 - Manipula\303\247\303\243o de arquivos/teste.txt" "b/05 - Manipula\303\247\303\243o de arquivos/teste.txt" new file mode 100644 index 00000000..60c2a132 --- /dev/null +++ "b/05 - Manipula\303\247\303\243o de arquivos/teste.txt" @@ -0,0 +1,5 @@ +Escrevendo dados em um novo arquivo. +escrevendo +um +novo +texto \ No newline at end of file diff --git "a/05 - Manipula\303\247\303\243o de arquivos/usuarios.csv" "b/05 - Manipula\303\247\303\243o de arquivos/usuarios.csv" new file mode 100644 index 00000000..906f94d1 --- /dev/null +++ "b/05 - Manipula\303\247\303\243o de arquivos/usuarios.csv" @@ -0,0 +1,3 @@ +id,nome +1,Maria +2,João