Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
daltroedu committed Sep 26, 2020
0 parents commit b14b649
Show file tree
Hide file tree
Showing 42 changed files with 1,878 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FLASK_APP=app:create_app

POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_MULTIPLE_DATABASES=acmevita,testing
TZ=America/Sao_Paulo

DATABASE_URI=postgresql://postgres:postgres@acmevita-db:5432/acmevita
DATABASE_TESTING=postgresql://postgres:postgres@acmevita-db:5432/testing
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.venv/
migrations/
.__pycache__/
.coverage

.idea/
.vscode/
21 changes: 21 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
FROM python:3.8.5-alpine

WORKDIR /usr/src/project
COPY . /usr/src/project

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

RUN apk add --update tzdata
ENV TZ=America/Sao_Paulo

RUN apk add gcc musl-dev postgresql-dev python3-dev bash

RUN pip install --upgrade pip
RUN pip install -r requirements.txt

EXPOSE 5000

RUN chmod +x ./scripts/docker-entrypoint.sh

ENTRYPOINT ["./scripts/docker-entrypoint.sh"]
46 changes: 46 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
.PHONY: help build

help:
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)

.DEFAULT_GOAL := help


build:
docker-compose build

run:
docker-compose up -d

run-stdout:
docker-compose up

stop:
docker-compose stop

down:
docker-compose down

logs-web:
docker-compose logs -f acmevita-web

logs-db:
docker-compose logs -f acmevita-db

db-init:
docker-compose exec acmevita-web flask db init

db-migrate:
docker-compose exec acmevita-web flask db migrate

db-upgrade:
docker-compose exec acmevita-web flask db upgrade

run-tests:
docker-compose exec acmevita-web coverage run -m unittest discover app/tests

coverage-tests:
docker-compose exec acmevita-web coverage report -m

coverage-html-tests:
docker-compose exec acmevita-web coverage html
118 changes: 118 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# ACMEVita

API REST desenvolvida com Python 3, Flask e Postgres.

## Estrutura

Projeto baseado no padrão *factory*, arquitetura com *blueprints* e práticas do *Twelve Factor*.

Principais arquivos:

* ```/app/__init__.py```: instancia as configurações e blueprints;

* ```/app/config.py```: configurações da aplicação, determinada por tipo de ambiente;

* ```/app/blueprints/```: endpoints das regras negócios e outros;

* ```/app/extensions/```: instancia e configura extensões de terceiros;

* ```/app/tests/```: testes do projeto;

**Visão geral:**

```
.
├── app
│   ├── blueprints
│   │   ├── business
│   │   │   ├── __init__.py
│   │   │   └── v1
│   │   │   ├── departament
│   │   │   │   ├── __init__.py
│   │   │   │   ├── models.py
│   │   │   │   ├── resources.py
│   │   │   │   ├── schemas.py
│   │   │   │   └── swagger.py
│   │   │   ├── dependent
│   │   │   │   ├── __init__.py
│   │   │   │   ├── models.py
│   │   │   │   ├── resources.py
│   │   │   │   └── schemas.py
│   │   │   ├── employee
│   │   │   │   ├── __init__.py
│   │   │   │   ├── models.py
│   │   │   │   ├── resources.py
│   │   │   │   ├── schemas.py
│   │   │   │   └── swagger.py
│   │   │   └── __init__.py
│   │   ├── common
│   │   │   ├── __init__.py
│   │   │   └── pagination.py
│   │   └── __init__.py
│   ├── extensions
│   │   ├── __init__.py
│   │   ├── cors
│   │   │   └── __init__.py
│   │   ├── database
│   │   │   └── __init__.py
│   │   ├── migrate
│   │   │   └── __init__.py
│   │   └── schema
│   │   └── __init__.py
│   ├── tests
│   │   ├── __init__.py
│   │   ├── test_departament.py
│   │   ├── test_dependent.py
│   │   └── test_employee.py
│   ├── __init__.py
│   ├── config.py
│   └── wsgi.py
├── contrib/
├── docs/
├── scripts/
├── .env
├── docker-compose.yml
├── Dockerfile
├── Makefile
├── README.md
└── requirements.txt
```

A aplicação deve ser executada nos ambientes de *development* ou *production*, via Docker. Para executar sem o Docker, instale o Python 3, as dependências do `requirements.txt`, o Postgres e crie os databases/credenciais de acordo com o `.env`.

## Configurações

Requisitos:

* Git - https://git-scm.com/downloads

* Docker - https://docs.docker.com/engine/install/

* Docker Compose - https://docs.docker.com/compose/install/

Após instalar os requisitos:

1. Clone o repositório: `git clone https://github.com/daltroedu/acmevita.git`
2. Acesse o diretório: `cd acmevita/`
3. Exporte o ambiente de *develompent*: `export FLASK_ENV=development`
4. *Build* os containers: `make build`
* A primeira build pode demorar
* A aplicação escuta na porta 5000 e o banco de dados na 5432
5. Execute os containers: `make run`
* Para executar com logs/stdout: `make run-stdout`
* Encerrar: `make stop`
* Esses e outros comandos/atalhos estão disponíveis no arquivo `Makefile`
6. Crie as migrações: `make db-init`
7. Execute: `make db-migrate`
8. Exporte para o Postgres: `make db-upgrade`
9. Executando os testes: `make run-tests`

## Endpoints

Os endpoints estão divididos por contexto: *departaments*, *employees* e *dependents*, sendo *employees* um recurso pai de *dependents*.

Caso utilize o Postman, no diretório `contrib/` tem as collections para exportação.

A documentação da API (Swagger) pode ser acessada em: `http://localhost:5000/v1`

![swagger](docs/imgs/swagger.png)
30 changes: 30 additions & 0 deletions app/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from flask import Flask
from app.config import env_app
from app.extensions.database import db
from app.extensions.migrate import migrate
from app.extensions.schema import ma
from app.extensions.cors import cors


def create_app():
app = Flask(__name__)
app.config.from_object(env_app[app.config['ENV']])
app.url_map.strict_slashes = False

configure_extensions(app)
register_blueprints(app)

return app


def configure_extensions(app):
db.init_app(app)
migrate.init_app(app, db)
ma.init_app(app)
cors.init_app(app)


def register_blueprints(app):
from app.blueprints.business.v1 import bp as bp_v1

app.register_blueprint(bp_v1)
Empty file added app/blueprints/__init__.py
Empty file.
Empty file.
13 changes: 13 additions & 0 deletions app/blueprints/business/v1/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from flask import Blueprint
from flask_restx import Api

bp = Blueprint('bp_v1', __name__, url_prefix='/v1')
api = Api(bp, title='ACMEVita API', version='1.0', description='')

from .departament.resources import api as departament
from .dependent.resources import api as dependent
from .employee.resources import api as employee

api.add_namespace(departament)
api.add_namespace(dependent)
api.add_namespace(employee)
Empty file.
20 changes: 20 additions & 0 deletions app/blueprints/business/v1/departament/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import uuid
from sqlalchemy.dialects.postgresql import UUID
from app.extensions.database import db
from app.blueprints.business.v1.employee.models import Employee


class Departament(db.Model):
__tablename__ = 'departament'

id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
created_at = db.Column(db.DateTime, nullable=False, default=db.func.now())
updated_at = db.Column(db.DateTime, nullable=False, default=db.func.now(), onupdate=db.func.now())
name = db.Column(db.String(64), nullable=False, unique=True, index=True)
employee = db.relationship(Employee, backref='departament', lazy='dynamic')

def __init__(self, data):
self.name = data['name']

def __repr__(self):
return f'<Departament {self.id}>'
Loading

0 comments on commit b14b649

Please sign in to comment.