[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

ramondelemos/tech-challenge

 
 

Repository files navigation

Tech Challenge

  • master: Build Status Coverage Status

  • dev: Build Status Coverage Status

Bem vindo(a)! Esse é a minha solução para o Tech Challenge Elixir!


O Sistema Financeiro precisa representar valores monetários. A ideia básica é ter uma estrutura de dados que permita realizar operações financeiras com dinheiro dentro de uma mesma moeda. Isso é pelo motivo de pontos flutuantes terem problemas de aritmética, logo encodificamos valores decimais/fracionais/reais como uma estrutura de dados com campos em inteiros, além de mapearmos operações aritméticas sobre tal estrutura. No fim, a implementação acaba sendo uma Estrutura de Dados Abstrata.

Essas operações financeiras precisam ser seguras e devem interromper a execução do programa em caso de erros críticos.

Sobre as operações financeiras que serão realizadas no sistema, é correto afirmar que os valores monetários devem suportar as seguintes operaçoes:

  • O sistema realizará split de transações financeiras, então deve ser possível realizar a operação de rateio de valores monetários entre diferentes indivíduos.

  • O sistema permite realizar câmbio então os valores monetários possuem uma operação para conversão de moeda.

  • O sistema precisa estar em compliance com as organizações internacionais, então é desejável estar em conformidade com a ISO 4217.

Requisitos Técnicos

  • O código deve estar na linguagem Elixir

Tech Challenge - Desafio Nº 2

API de Banking

O sistema deve oferecer a possibilidade de usuários realizarem transações financeiras como saque e transferencia entre contas.

Um usuário pode se cadastrar e ao completar o cadastro (com verificação de email) ele recebe R$ 1000,00.

Com isso ele pode transferir dinheiro para outras contas e pode sacar dinheiro. O saque do dinheiro simplesmente manda um email para o usuário informando sobre o saque e reduz o seu saldo.

Nenhuma conta pode ficar com saldo negativo.

É necessário autenticação para realizar qualquer operação.

Alguns relatórios devem ser gerados para o backoffice:

  • Total transacionado (R$) por dia, mês, ano e total.
  • Número de usuários que não transacionam há mais de 1 mês (por dia)

Requisitos Técnicos

  • O desafio deve ser feito na linguagem Elixir.
  • A API pode ser JSON ou GraphQL.
  • Docker é um diferencial.

Comandos básicos do projeto

mix deps.get Para obter as dependências.

mix deps.compile Para compilar as dependências.

mix docs Para gerar a documentação do projeto.

MIX_ENV=test mix build Para testar a aplicação.

mix ecto.setup Para configuar a base de dados.

mix phx.server Para rodar a aplicação.

Certifique-se de que as variáveis de ambiente abaixo estão corretamente configuradas:

  • DB_USERNAME=postgres
  • DB_PASSWORD=postgres
  • DB_DATABASE=financial_system_api
  • DB_HOSTNAME=db
  • DB_PORT=5432
  • SECRET_KEY=your-key
  • BAMBOO_API_KEY=your-key
  • BAMBOO_DOMAIN=your-domain
  • APP_HOSTNAME=localhost:4000
  • PORT=4000

Para facilitar o setup de teste está disponível meu ambiente de desenvolvimento elixir.

A Solução

Para atender ao que foi proposto foi criado um projeto umbrella contendo as aplicações FinancialSystem (Desafio Nº 1) e FinancialSystemApi, que é uma aplicação Phoenix responsável por servir uma API GraphQL para transações bancárias.

Para a cobertura dos testes foi utilizado o Coveralls.io.

A análise do código é feita com o Credo utilizando o parâmetro de execução --strict para reforçar o guia de estilo do credo.

Para o release da aplicação foram utilizados em conjunto os pacotes mix docker e Distillery. A aplicação é disponibilizada automaticamente em containers Docker no repositório público ramondelemos/tech-challenge.

Foram utilizados em conjunto o Travis CI, Webhooks do Docker Hub e o Rancher 1.6 para a orquestração das técnicas de Continuous Integration, Continuous Delivery e Continuous Deployment.

A aplicação está distribuída em dois servidores geograficamente separados e trabalhando de forma clusterizada.

  • Servidor Linode localizado em Fremont, USA
  • Servidor DigitalOcean localizado em London, UK

A adição de novos servidores ao cluster é feita de forma simples e rápida através da API do Rancher 1.6. As aplicações se conectam automaticamente umas as outras utilizando API de Metadata fornecida pelo Rancher 1.6 e um módulo worker FinancialSystemApi.Rancher que atualiza as conexões dos nós a cada 5 segundos. O crescimento/encolhimento horizontal pode ser feito de forma programática, mas não implementei para não estender em muito o escopo da solução.

O banco de dados da aplicação é o PostgreSQL 10 hospedado por Heroku Postgres.

O monitoramento da aplicação é feito com o DataDog, onde foram disponibilizados dois paineis públicos para acompanhamento da aplicação em tempo real.

API de Banking

A solução está disponível em http://ramondelemos.com/api. Para facilitar o uso, no endpoint http://ramondelemos.com/graphiql foi diponibilizada a interface gráfica GraphiQL fornecida pelo módulo absinthe.

O sistema permite o registro de novos usuários com confirmação por e-mail, autenticação, consulta de usuários e contas, transferência entre contas e saque. Com exceção do registro e autenticação, para todas as operações os usuários precisarão assinar suas requisições com o token jwt fornecido após a autenticação.

Registro de Usuários

O registro de novos usuários é feito utilizado a mutation register, onde serão informados os dados do usuário.

mutation UserRegister {
  register(name:"Ramon de Lemos",  username: "ramondelemos", email: "ramondelemos@gmail.com", password: "password") {
    email
    , name
    , username
    , id
  }
}

Logo após o registro o e-mail fornecido receberá um link para confirmação e ativação da conta. Depois de confirmado, o usuário receberá um e-mail de confirmação e uma conta com 1.000,00 BRL de saldo para operações.

Autenticação

A autenticação na aplicação é feita através da mutation login. Se a autenticação for bem sucedida o usuário receberá um token para ser utilizado em todas as demais operações.

mutation UserLogin {
  login(email: "ramondelemos@gmail.com", password: "password") {
    token
  }
}

Criação de Contas

O usuário pode abrir novas contas, para isso será necessário informar o código ISO 4217 da moéda que a conta armazenará. Esta operação é feita com a mutation createAccount.

mutation CreateAccount {
  createAccount(currency: "BRL") {
    id
    , amount
    , currency
    , transactions {
      id
      , dateTime
      , value
    }
  }
}

Contas novas são criadas com saldo 0.0.

Transferência entre contas

Os usuários podem fazer transferências entre contas, bastando informarem os códigos identificadores das contas de origem e destino e o valor da operação. O usuário não poderá transferir valores superiores ao saldo da conta de origem, para contas de moedas diferentes e de contas de terceiros. Para realizar trasferência utilize a mutation transfer.

mutation Transfer {
  transfer(from: "1", to: "2", value: 10.5){
    from {
      amount
      , currency
      , transactions {
        value
        , dateTime
      }
    }
  }
}

Saque de valores

Os usuários podem fazer saques de suas contas, bastando informar o código identificador da conta e o valor da operação. Os usuários que realizarem saques receberão uma notificação por e-mail informando o valor retirado e o salda atual da conta. O usuário não poderá sacar valores superiores ao saldo disponível. Para realizar saques utilize a mutation withdraw.

mutation Withdraw {
  withdraw(from: "1", value: 10.5){
    id
  	, amount
    , currency
    , transactions {
      value
      , dateTime
    }
  }
}

Relatórios de Backoffice.

Total transacionado por dia, mês, ano e total.

É possível realizar consulta em tempo real dos totais transacionados por moeda pela aplicação utilizando a mutation balanceReport. Os valores podem ser agrupados por dia: DAY, mês: MONTH, ano: YEAR ou total: TOTAL. Com exceção do agrupamento total: TOTAL, as consultas podem ser filtradas atravéz da variável date.

query Backoffice {
  balanceReport(by: DAY, date: "2018-07-09") {
    credit,
    debit,
    currency,
    date
  }
}

Número de usuários que não transacionam há mais de 1 mês (por dia).

Também é possível realizar consulta em tempo real do total de usuários que não transacionam há mais de 1 mês utilizando a mutation idleReport.

query Backoffice {
  idleReport {
    count
    , date
  }
}

Material de Referência Utilizado

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Elixir 94.7%
  • JavaScript 2.2%
  • PLpgSQL 1.9%
  • Other 1.2%