diff --git a/Food Counter/requirements.txt b/Food Counter/requirements.txt new file mode 100644 index 0000000..40dadff --- /dev/null +++ b/Food Counter/requirements.txt @@ -0,0 +1,5 @@ +flask +connexion +flask_cors +psycopg2 +connexion[swagger-ui] \ No newline at end of file diff --git a/Food Counter/src/__init__.py b/Food Counter/src/__init__.py new file mode 100644 index 0000000..1053101 --- /dev/null +++ b/Food Counter/src/__init__.py @@ -0,0 +1,10 @@ +import connexion +from flask_cors import CORS +from src.config.enviroment import HOST, PORT + + +def init_api(): + app = connexion.App(__name__, specification_dir="./swagger/") + app.add_api('swagger.yaml', arguments={"host_with_port": f"{HOST}:{PORT}"}) + CORS(app.app) + return app diff --git a/Food Counter/src/config/__init__.py b/Food Counter/src/config/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Food Counter/src/config/database.py b/Food Counter/src/config/database.py new file mode 100644 index 0000000..9e258c1 --- /dev/null +++ b/Food Counter/src/config/database.py @@ -0,0 +1,32 @@ +import psycopg2 + +from src.config.enviroment import DBHOST, DB_NAME, DB_USER, DB_PASS + + +class Conexao(object): + db = None + + def __init__(self): + self.db = psycopg2.connect(host=DBHOST, database=DB_NAME, user=DB_USER, password=DB_PASS) + + def manipular(self, sql): + try: + cur = self.db.cursor() + cur.execute(sql) + cur.close() + self.db.commit() + + except: + return False + + return True + + def consultar(self, sql): + data = None + try: + cur = self.db.cursor() + cur.execute(sql) + data = cur.fetchall() + except: + return None + return data \ No newline at end of file diff --git a/Food Counter/src/config/enviroment.py b/Food Counter/src/config/enviroment.py new file mode 100644 index 0000000..527bede --- /dev/null +++ b/Food Counter/src/config/enviroment.py @@ -0,0 +1,8 @@ +import os + +DBHOST = os.getenv("DB_HOST") +DB_NAME = os.getenv("DB_NAME") +DB_USER = os.getenv("DB_USER") +DB_PASS = os.getenv("DB_PASS") +HOST = os.getenv("IP_ADDRESS") or "localhost" +PORT = os.getenv("SERVER_PORT") or 8080 \ No newline at end of file diff --git a/Food Counter/src/controllers/__init__.py b/Food Counter/src/controllers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Food Counter/src/controllers/api_controller.py b/Food Counter/src/controllers/api_controller.py new file mode 100644 index 0000000..183a0d7 --- /dev/null +++ b/Food Counter/src/controllers/api_controller.py @@ -0,0 +1,2 @@ +def get_alive(): + return 'pong', 200 \ No newline at end of file diff --git a/Food Counter/src/controllers/food_list_controller.py b/Food Counter/src/controllers/food_list_controller.py new file mode 100644 index 0000000..65d6da4 --- /dev/null +++ b/Food Counter/src/controllers/food_list_controller.py @@ -0,0 +1,20 @@ +from src.services.food_list_service import get_food_list, add_to_food_list, delete_item_to_food_list, get_list_by_date_to_food_list + + +def get_list(): + return get_food_list() + + +def send_to_food_list(**kwargs): + item = kwargs.get('body') + return add_to_food_list(item) + + +def delete_item(id): + id = int(id) + return delete_item_to_food_list(id) + + +def get_list_by_date(**kwargs): + date = kwargs['date'] + return get_list_by_date_to_food_list(date) \ No newline at end of file diff --git a/Food Counter/src/main.py b/Food Counter/src/main.py new file mode 100644 index 0000000..53ecb2c --- /dev/null +++ b/Food Counter/src/main.py @@ -0,0 +1,13 @@ +import os +from src import init_api + +HOST = os.getenv("IP_ADDRESS") or "127.0.0.1" + + +def main(): + app = init_api() + app.run(host=HOST, port=8080) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/Food Counter/src/services/__init__.py b/Food Counter/src/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Food Counter/src/services/food_list_service.py b/Food Counter/src/services/food_list_service.py new file mode 100644 index 0000000..680cf1f --- /dev/null +++ b/Food Counter/src/services/food_list_service.py @@ -0,0 +1,55 @@ +from src.config.database import Conexao + +db = Conexao() + + +def get_food_list(): + datas = [] + query = "SELECT * FROM public.food_list where status is not false order by created_at desc" + lista = db.consultar(query) + for item in lista: + data = { + "id": item[0], + "name": item[1], + "type": item[2], + "amount": item[3], + "created_at": item[5] + } + datas.append(data) + + return datas + + +def add_to_food_list(item): + if item['food_type'] not in ['Proteina', 'Carboidrato', 'Gordura']: + return "Tipo alimento invalido." + else: + query = f"INSERT INTO public.food_list (nome, tipo, quantidade, created_at, updated_at) VALUES('{item['food_name']}', '{item['food_type']}', {item['food_amount']}, now(), now());" + data = db.manipular(query) + return data + + +def delete_item_to_food_list(id): + query = f"UPDATE public.food_list SET status=false, updated_at='now()' WHERE id={id};" + + if db.manipular(query): + return f"ID: {id} removido com sucesso!" + else: + return f"Erro ao remover ID: {id}!" + + +def get_list_by_date_to_food_list(date): + datas = [] + query = f"select * from food_list where created_at <= '{date}'" + list = db.consultar(query) + for item in list: + data = { + "id": item[0], + "name": item[1], + "type": item[2], + "amount": item[3], + "created_at": item[5] + } + datas.append(data) + + return datas \ No newline at end of file diff --git a/Food Counter/src/swagger/swagger.yaml b/Food Counter/src/swagger/swagger.yaml new file mode 100644 index 0000000..3d59ccd --- /dev/null +++ b/Food Counter/src/swagger/swagger.yaml @@ -0,0 +1,136 @@ +--- +swagger: "2.0" +info: + description: "Food Count" + version: "1.0.0" + title: "Finetune Challenge - Food Count" + contact: + email: "cristianoxavier_@outlook.com" + license: + name: "Apache 2.0" + url: "http://www.apache.org/licenses/LICENSE-2.0.html" +host: "{{host_with_port}}" +basePath: "/v1" +schemes: + - "https" + - "http" +paths: + #endpoints + /ping: + get: + tags: + - "Keepalive" + summary: "Api keepalive" + description: "Apikeepalive" + responses: + 200: + description: "pong response" + operationId: "get_alive" + x-swagger-router-controller: "src.controllers.api_controller" + + /food: + get: + tags: + - "Food List" + summary: "Retorna a lista de alimentos cadastrados" + description: "Retorna a lista de alimentos cadastrados" + responses: + 200: + description: "Retorna a lista de alimentos cadastrados" + operationId: "get_list" + x-swagger-router-controller: "src.controllers.food_list_controller" + + post: + tags: + - "Food List" + summary: "Adicionar um item a lista" + description: "Adicionar um item a lista" + parameters: + - name: "body" + in: "body" + required: true + schema: + $ref: "#/definitions/FoodInput" + responses: + 200: + description: 200 operation + schema: + $ref: "#/definitions/ArrayOfFoodOutput" + operationId: "send_to_food_list" + x-swagger-router-controller: "src.controllers.food_list_controller" + + + /food/{id}: + delete: + tags: + - "Food List" + summary: "Inativa um item da lista" + description: "Inativa um item da lista" + parameters: + - name: "id" + in: "path" + required: true + description: "O registro sera inativado" + type: "integer" + responses: + 200: + description: "Registro deletado com sucesso" + 500: + description: "Erro no servidor" + operationId: "delete_item" + x-swagger-router-controller: "src.controllers.food_list_controller" + + /food/{date}: + get: + tags: + - "Food List" + summary: "Retorna a lista de alimentos filtrados pela data" + description: "Retorna a lista de alimentos filtrados pela data" + parameters: + - name: "date" + in: "path" + required: true + description: "Retorna a lista de alimentos filtrados pela data" + type: "string" + responses: + 200: + description: "Registro deletado com sucesso" + 500: + description: "Erro no servidor" + operationId: "get_list_by_date" + x-swagger-router-controller: "src.controllers.food_list_controller" + + +definitions: + FoodInput: + type: "object" + properties: + food_name: + type: string + example: bananas + food_type: + type: string + example: proteina + food_amount: + type: integer + example: 2 + FoodOutput: + type: "object" + properties: + food_id: + type: integer + example: 10 + food_name: + type: string + example: bananas + food_type: + type: string + example: proteina + food_amount: + type: integer + example: 2 + + ArrayOfFoodOutput: + type: "array" + items: + $ref: "#/definitions/FoodInput" \ No newline at end of file diff --git a/Food Counter/src/wsgi.py b/Food Counter/src/wsgi.py new file mode 100644 index 0000000..72b1bd2 --- /dev/null +++ b/Food Counter/src/wsgi.py @@ -0,0 +1,3 @@ +from src import init_api + +application = init_api() \ No newline at end of file diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29