BRomano / desafio-dev

Desafio desenvolvimento

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

interview

Descrição da Solução

De acordo com o desafio proposto, para cada item descrevi os principais pontos que acho importante, descrevendo a solução adotada, bem como o que acredito ser um ponto de atenção.

  1. Ter uma tela (via um formulário) para fazer o upload do arquivo(pontos extras se não usar um popular CSS Framework )
  • Na parte Web evitei utilizar qualquer css framework (como Bootstrap), porém se pudesse utilizar um framework css eu utilizaria tailwind.
  • Como não se falou na utilização de um JS framework, escolhi vue.js pela familiaridade que tenho, e escrevi o CSS na mão a maneira antiga.
  • Desta forma criei todo o desafio dentro de uma mesma tela, evitando complexidades do projeto, até pela natureza de "desafio".
  • Para o upload do CNAB.txt criei uma funcionalidade de upload do arquivo e um endpoint no backend.
    • Pequenas validações, e maneiras de autilizar o UX, como não foi frisado absolutamente nada sobre a parte frontend, foquei os esforços no backend.
  1. Interpretar ("parsear") o arquivo recebido, normalizar os dados, e salvar corretamente a informação em um banco de dados relacional, se atente as documentações que estão logo abaixo.
  • O endpoint de upload de arquivo, recebe o arquivo lê linha a linha, extrai os dados, transforma os dados e então insere na base de dados.
  • Linhas corrompidas ou com problemas de validação o importador ignora, não retornando erro na importação.
  • Para armazenar os dados, criei uma tabela de transação e uma tabela de loja.
  • A loja é inserida com um primary key, e cada transação tem uma loja como foreign key.
    • A chave da loja para inserir é somente o nome dela, como é feriado e acabei não tirando essa dúvida, interpretei desta maneira.
  • No tratamento das string, todas fiz o decode byte para utf-8 normalizando as acentuações, e fazendo trim dos espaços.
  • No campo valor, converti para float, dividi por 100 para ter os centavos, e caso o tipo da transação fosse saída, multipliquei por -1 para auxiliar em pontos mais a frente.
  • No tratamento do campo data, juntei data e hora em um mesmo campo, localizei e gravei com timezone no timezone do Brasil -3, então converti para UTC para facilitar.
    • Gravei no formato UTC pois acredito que o frontend na exibição dos dados tem a "obrigação" de converter a data para o timezone que o browser esta configurado.
    • Ressalto esta parte da conversão da data no código abaixo.
def _convert_to_date(date_str: str, date_format: str='%Y%m%d%H%M%S') -> datetime:
    """
    Function will convert a str date with date_format
     
    :param date_str: the date str
    :param date_format: date format on @date_str. default value is '%Y%m%d%H%M%S'
    
    :return: the datetime object 
    """
    date_format = datetime.strptime(date_str, date_format)
    loc_sp = sao_paulo.localize(date_format)
    return loc_sp.astimezone(utc)
  1. Exibir uma lista das operações importadas por lojas, e nesta lista deve conter um totalizador do saldo em conta
  • Na mesma tela de upload de arquivos, o frontend ao carregar a página carrega uma tela de sumário das lojas e o respectivo saldo.

  • Para isso o frontend chama o endpoint.

    • Este endpoint irá agregar todas as lojas e fazer um SUM do valor, por este motivo que guardei o valor com sinal.
    • Este endpoint, também evita carregar uma quantidade enorme de dados, sem a real necessidade do uso, por este motivo que decidi implementar desta forma.
  • No frontend quando clicado em cima da loja, ele carrega a lista de transações daquela respectiva loja.

    • Para isso o frontend chama o endpoint passando a store_id como parâmetro.
  • Como ficou em aberto o item 3, se era pra mostrar um listão de todas as transações importadas, ou se agregar. Bem como criar um saldo. Então decidi criar dois endpoints um para cada, e fazer esta navegação simplificada no frontend.

  1. Ser escrita na sua linguagem de programação de preferência
  • Escrito em Python, utilizando o framework Flask e no frontend usando vue.js.
  • A moça do RH assim solicitou, e é a Stack que utilizo e tenho maior familiaridade hoje.
  1. Ser simples de configurar e rodar, funcionando em ambiente compatível com Unix (Linux ou Mac OS X). Ela deve utilizar apenas linguagens e bibliotecas livres ou gratuitas.
  • Para simplificar o run, configurei tudo dentro de dockers, e um docker compose, e também estou disponibilizando no endereço
  • Foram criados 2 dockers.
    • Docker da aplicação backend, que cria todo um ambiente em python e roda atras de um gunicorn (Para aplicações de produção)
    • Criado um Docker de frontend, que possui um nginx como reverse proxy, e faz o build de um vue.js
    • E dentro do docker-compose, ele junta o banco de dados, e as duas imagens e configura tudo e roda.

Para rodar o projeto basta utilizar

docker-compose up

Como o mysql demora para estar ready, o serviço de migration fica fazendo pooling ate conseguir criar o banco de dados, então necessário esperar um pouco para utilizar a aplicação. Até que o mysql crie as estruturas internas.

  1. Git com commits atomicos e bem descritos
  • Todo o desafio esta em um repositório público e devidamente documentado.
  • Porém a atomicidade dos commits foi por fases de funcionalidades. Evitei fazer 1 commit para cada modificação por achar péssima abordagem.
  1. PostgreSQL, MySQL ou SQL Server
  • Utilizando Mysql e configurado dentro de docker-compose
  1. Docker compose (Pontos extras se utilizar)

Cada pasta interna tem o dockerfile respectivo do serviço, sendo separado em:

  1. interview é o backend, configurado em Dockerfile para rodar um python
  2. Front é a pasta que esta toda a parte do projeto frontend e nessa configuração irá compilar todo o projeto frontend e configurar um nginx para servir como reverse proxy. Sendo que tudo que vier na URL /api será redirecionado para o backend, senão serve a aplicação vue.js.
  3. Em docker-compose.yml temos as configurações:
    1. Serviço database, migratiion, backend e frontend.
    2. Feita toda configuração para o projeto rodar em ambiente de Produção, com nginx, gunicorn, build da aplicação front, e build da aplicação backend.
  1. Incluir informação descrevendo como consumir o endpoint da API
  • Toda documentação dos endpoints foi configurado utilizando openAPI 3.0, entendo que esta é uma ótima solução para disponibilizar configurações, e é um padrão muito bem aceito.
  • Para acessar a documentação dos 3 endpoints configurados acessar.
  • Inclusive a documentação auxilia para consumir e testar os endpoints, bem como o frontend também os consome.

Aplicação Não precisa fazer...

  1. Lidar com autenticação ou autorização (pontos extras se ela fizer, mais pontos extras se a autenticação for feita via OAuth).

Decidi não fazer a autenticação, apesar de ter criado uma rota para uma possivel autenticação, bem como uma tabela de usuario, decidi por não continuar, por causa do tempo, do feriado, e de outros testes que estou aplicando também.

  1. Ser escrita usando algum framework específico (mas não há nada errado em usá-los também, use o que achar melhor).

Utilizei Python, Flask.

  • Configurado de acordo com a especificação para large applications como package.
  • Isso pode ser visto no Dockerfile, quando instala o python package usando pipenv. Desta forma a aplicação dispensa mais uma variável de ambiente para ser configurada "FLASK_APP"
COPY setup.py $HOME
RUN pipenv install .
  • E o gunicorn pode chamar a aplicação através de package:function(configuration)
  • Desta forma o pacote pode ser usado como qualquer outro pacote de python, com from... import..., isso traz uma oportunidade para arquitetar uma aplicação em grande escala.
  • Também auxilia na configuração de pipelines CI/CD.
  1. Documentação da api.(Será um diferencial e pontos extras se fizer)

Toda explicação da documentação da API esta descrita no item 11 deste documento, bem como em acessível pelo link acessar

About

Desafio desenvolvimento


Languages

Language:Python 58.6%Language:Vue 25.8%Language:TypeScript 5.6%Language:Dockerfile 3.6%Language:JavaScript 2.8%Language:HTML 1.8%Language:Mako 1.4%Language:Shell 0.2%