- Introdução
- Requisitos Funcionais
- Requisitos Não Funcionais
- Propósta Técnica
- Detalhamento da Solução
- Configurando Ambientes
- Executando Aplicação
Aqui está sendo proposto um cenário hipotético onde duas empresas de venda e locação de imóveis se uniram, porem ambas continuaram com as suas marcas e portais distintos, porem e um novo backe-end deve ser construído para fornecer qual imóvel deve aparecer em cada um dos portais. A primeira empresa é Imóveis .COM e Pronto pra Morar.
A API deve retornar a lista de imóveis habilitados para cada portal (Imóveis .COM e Pronto pra Morar).
- Caso os atributos "lat" e "lon" sejam iguais a zero o imóvel não deve ser exibido em nenhum dos portais.
- O valor mínimo deve ser R$ 3.500,00.
- O valor mínimo deve ser R$ 600.000,00.
- O metro quadrado "usableAreas" deve ser maior do que 0.
- O preço do metro quadrado deve ser maior que R$ 3.500,00.
- Caso o imóvel esteja dentro do "bounding box" abaixo, o valor mínimo passa a ser R$ 540.000,00.
- minlon: -46.693419.
- minlat -23.568704.
- maxlon: -46.641146.
- maxlat: -23.546686.
- O valor máximo deve ser R$ 4.000,00.
- Caso o imóvel esteja dentro do bounding box do Potal Imóveis .COM o valor máximo do aluguel passa a ser R$ 6.000,00.
- O valor de condomínio "monthlyCondoFee" deve ser numérico e menor que 30% do valor do aluguel.
- O valor máximo deve ser R$ 700.000,00.
- Faça essa API pensando que ela pode ser consumida por vários tipos de clientes e com diferentes propósitos.
- Os dados devem ser trabalhados em memória não sendo permitido usar qualquer tipo de banco de dados.
- Usar o source abaixo:
- O metadados de resposta deve conter os campos abaixo:
{
pageNumber: int32,
pageSize: int32,
totalCount: int32,
listings: [
...
]
}
- Clean Architecture.
- Paradigma Orientado a Objetos.
- Dependency Injection.
- SOLID
- Design Patterns GoF
- Liguagem de programação NodeJS com TypeScript.
- Controle de acesso por meio de Token JWT.
- GraphQL para dar autonomia ao consumidor de quais dados deseja receber.
- Apollo Server e Express para construção da camada de APIs.
- Jest para testes e relatório de cobertura.
Visando atender de uma melhor forma os aspectos de "organização, manutenibilidade, rastreabilidade, testabilidade, performance e portabilidade" toda estrutura da aplicações foi baseada em Clean Architecture, abaixo diagrama conceitual dessa proposta:
├── src # Código Fonte
|── crossCutting.layer # Bibliotecas e recursos que são usados por todas as camadas da aplicação
└── _tests # Testes unitários isolados usando MOCKs para integrações
|── domain.layer # Entidades do domínio do negócio
└── _tests # Testes unitários isolados usando MOCKs para integrações
|── application.layer # Contém a implementação dos casos de uso e fornece os sockets aos adaptadores
└── _tests # Testes unitários isolados usando MOCKs para integrações
|── adapters.layer # Implementação dos sockets demandados pela camada de application
└── _tests # Testes unitários isolados usando MOCKs para integrações
|── presentations.layer # Controllers para fazer abstração ao framework de APIs
└── _tests # Testes unitários integrados
├── main.layer # Configurações de IoC, framework de APIs e startup da aplicação
└── settings.layer # Configurações para os ambientes (local, test, develop, production)
Abaixo tabela que mostra a qual camada da arquitetura que cada pasta pertence:
Pasta | Camada |
---|---|
crossCutting.layer | Transversal |
domain.layer | Enterprise Business Rule |
application.layer | Application Business Rule |
adapters.layer | Interface Adapters |
presentations.layer | Interface Adapters |
main.layer | Frameworks & Drivers |
settings.layer | Transversal |
Abaixo tabela com os atributos do metadados e qual o dados que é apresentado em cada um:
Atributo | Descrição |
---|---|
pageNumber | Número da página atual |
pageSize | Quantidade de registros por página |
totalPages | Total de páginas existentes |
totalCount | Quantidade total de registros |
listings | Lista dos imoveis da pagina atual |
Para que a aplicação seja executada corretamente deve ser instalado os recursos abaixo:
- NodeJS
- NPM
- Docker
$ git clone https://github.com/macgyver1985/api-backend-to-rental-estate.git
$ cd api-backend-to-rental-estate
$ npm install
Este comando irá converter o código de typescript para javascript e salvar na pasta dist.
$ npm run build
$ npm start
Será executada no endereço http://localhost:3333/graphql
Basta abrir a pasta "api-backend-to-rental-estate" pelo Visual Studio Code e executar o comando abaixo no terminal:
$ npm run dev
Será executada no endereço http://localhost:3333/graphql
Em seguida é só colocar o break point nos pontos que deseja debugar, veja exemplo abaixo:
Este comando irá executar os teste e disponibulizar o relatório de cobertura na pasta coverage.
$ npm test
A aplicação está preparada para ser executada em container.
Caso o npm run publish já tenha sido executado, execute os comandos abaixo:
$ docker stop -t 0 macgyver_application
$ docker rm macgyver_application
$ docker rmi macgyver1985/imoveis
Para publicar no container execute o comando abaixo:
$ npm run publish
Será executada no endereço http://localhost:3333/graphql
Caso queria subir a imagem da aplicação manualmente execute os comandos abaixo:
$ npm run build
$ docker build -f Dockerfile -t macgyver1985/imoveis .
$ docker run -d -e NODE_ENV=production -p 3333:3333 macgyver1985/imoveis
Será executada no endereço http://localhost:3333/graphql
As opções descritas abaixo servem para instânicas da aplicação em ambiente local ou container.
Foram configurados dois usuários, onde uma está atralado ao Portal Imóveis .COM e o outro ao Pronto pra Morar. Para ter acesso aos imóveis disponíveis a cada portal basta gerar o token JWT com os respectivos usuários.
- Username: prontopramoraruser
- Password: prontopramorarpwd
- Username: imoveiscomuser
- Password: imoveiscompwd
Excelente forma de efetuar requisições à API pois já fornece toda a documentação dos "SCHEMAS" e ajuda muito na construção das chamadas do tipo "Mutation ou Query".
- Acesso a url http://localhost:3333/graphql
- Execute a mutation GetAuthorization
mutation{
GetAuthorization (
command: {
userName: "imoveiscomuser"
password: "imoveiscompwd"
}
) {
authorization,
expiresIn
}
}
- Acesso a url http://localhost:3333/graphql
- Execute a query obtainRealEstate informando quais campos deseja receber
query {
obtainRealEstate(
command:{
pageNumber: 1,
pageSize: 10
}) {
pageNumber
pageSize
totalPages
totalCount
listings {
id
usableAreas
bathrooms
bedrooms
createdAt
updatedAt
listingType
listingStatus
parkingSpaces
owner
images
address {
city
neighborhood
geoLocation{
precision
location{
lon
lat
}
}
}
pricingInfos {
businessType
price
period
yearlyIptu
monthlyCondoFee
rentalTotalPrice
}
}
}
}
- Configura o token em HTTP HEADERS incluindo o parâmetro "authorization"
{
"authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGFpbXMiOiJ7XCJ1c2VyTmFtZVwiOlwidml2YXJlYWx1c2VyXCIsXCJ1c2VySWRcIjpcIjI3OTQ5OGM5LTFmYTctNDY5Zi1iNmQ2LWIyYjYwMDY1NDI1NlwifSIsImNyZWF0ZWREYXRlIjoiMjAyMS0wNS0xOFQwNTowNDo0NS42ODRaIiwiZXhwaXJlc0RhdGUiOiIyMDIxLTA1LTE4VDA2OjA0OjQ1LjY4NFoiLCJleHBpcmVzSW4iOjM2MDAwMDAsImlkZW50aXR5IjoiMTQyY2UxZGQtNjRkYS00MGFiLTk0NTgtMGMzZjg4YTVmYTZhIiwiaWF0IjoxNjIxMzE0Mjg1LCJleHAiOjE2MjEzMTc4ODV9.-G_ShzMbwYN5kZgJWoDdc92kIxXuvmJ2ajf93D479QU"
}