diff --git a/app.py b/app.py index 7202014..4e2eb1b 100644 --- a/app.py +++ b/app.py @@ -1,70 +1,11 @@ -import os -import psycopg2 -import time as time_2 -from pydantic import BaseModel -from dotenv import load_dotenv -from fastapi import FastAPI, APIRouter - -load_dotenv() - -conn_param = "host=%s port=%s dbname=%s user=%s password=%s" % ( - os.getenv("DB_URL"), - os.getenv("DB_PORT"), - os.getenv("DB_DATABASE"), - os.getenv("DB_USERNAME"), - os.getenv("DB_PASSWORD") -) +from routes.balance import router +from fastapi import FastAPI, Response app = FastAPI() -router = APIRouter() -class Balance(BaseModel): - name: str - date: int - price: int - -@router.get("/") -def index(): +@app.get("/") +def index(resp: Response): + resp.headers.setdefault("Content-Type", "text") return "Hello, World!" -@router.post("/balance") -def insert(balance: Balance): - started = time_2.time() - conn = psycopg2.connect(conn_param) - cur = conn.cursor() - cur.execute( - "insert into balset(name, date, price) values (%s, %s, %s);", - (balance.name, balance.date, balance.price) - ) - - conn.commit() - - cur.close() - conn.close() - - return {"ok": 1, "respond_time": f"{time_2.time() - started}ms", "name": balance.name} - -@router.get("/balance/{id}") -def query(id): - conn = psycopg2.connect(conn_param) - cur = conn.cursor() - cur.execute( - "select * from balset where id = %s", - id - ) - - data = cur.fetchone() - cur.close() - conn.close() - - return {"ok": 1, "data": {"id": data[0], "name": data[1], "date": data[2], "price": data[3]}} - -@router.patch("/balance/{id}") -def update(): - return {"ok": 1, "id": "test"} - -@router.delete("/balance/{id}") -def delete(): - return {"ok": 1, "id": "test"} - app.include_router(router=router) diff --git a/generate.py b/generate.py new file mode 100644 index 0000000..846c8a3 --- /dev/null +++ b/generate.py @@ -0,0 +1,25 @@ +import psycopg2 +from util.config import conn_param + +def __main__(): + conn = psycopg2.connect(conn_param) + cur = conn.cursor() + + cur.execute( + """ + create table balset( + id serial primary key, + name varchar(50), + date bigint, + price bigint, + memo varchar(300) + ); + """ + ) + + conn.commit() + + cur.close() + conn.close() + +__main__() diff --git a/routes/balance.py b/routes/balance.py new file mode 100644 index 0000000..945f595 --- /dev/null +++ b/routes/balance.py @@ -0,0 +1,92 @@ +from datetime import datetime +from fastapi import APIRouter, Response +from service.balance_service import Balance, BalanceService, UpdateForm + +router = APIRouter() + +@router.post("/balance", status_code=201) +def insert(balance: Balance): + started = datetime.now().microsecond / 1000 + service = BalanceService() + name = service.create(balance=balance) + + return { + "ok": 1, + "name": name, + "respond_time": "{}ms".format(round((datetime.now().microsecond / 1000) - started)) + } + +@router.get("/balance/{id}") +def query(id, resp: Response): + started = datetime.now().microsecond / 1000 + service = BalanceService() + + try: + data = service.read(int(id)) + except: + resp.status_code = 204 + return {"ok": 0, "errno": "id '{}' result is not found".format(id)} + + return { + "ok": 1, + "id": int(id), + "data": data, + "respond_time": "{}ms".format(round((datetime.now().microsecond / 1000) - started)) + } + +@router.patch("/balance/{action}/{id}") +def update(action, id, balance: UpdateForm, resp: Response): + service = BalanceService() + if action != "name" and action != "date" and action != "price" and action != "memo": + print(action) + print(id) + resp.status_code = 400 + return {"ok": 0, "errno": "action must be to name, date, price or memo"} + + if action == "name" and balance.name == "": + resp.status_code = 400 + return {"ok": 0, "action": action, "errno": "name value cannot be empty"} + + if action == "date" and balance.date <= 0: + resp.status_code = 400 + return {"ok": 0, "action": action, "errno": "date value cannot be 0 or minus"} + + if action == "price" and balance.price <= 0: + resp.status_code = 400 + return {"ok": 0, "action": action, "errno": "price value cannot be 0 or minus"} + + if action == "memo" and len(balance.memo) > 300: + resp.status_code = 400 + return { + "ok": 0, + "action": action, + "errno": "memo value size is too long: (maximum size: 300 bytes, your size: {} bytes)".format(len(balance.memo)) + } + + service.update( + int(id), + action, { + "name": balance.name, + "date": balance.date, + "price": balance.price, + "memo": balance.memo + } + ) + + return { + "ok": 1, + "id": int(id), + "action": action + } + +@router.delete("/balance/{id}") +def delete(id): + started = datetime.now().microsecond / 1000 + service = BalanceService() + service.delete(int(id)) + + return { + "ok": 1, + "id": int(id), + "respond_time": "{}ms".format((round(datetime.now().microsecond / 1000) - started)) + } diff --git a/service/balance_service.py b/service/balance_service.py new file mode 100644 index 0000000..6fb3f6f --- /dev/null +++ b/service/balance_service.py @@ -0,0 +1,71 @@ +import psycopg2 +from pydantic import BaseModel +from util.config import conn_param + +class Balance(BaseModel): + name: str + date: int + price: int + memo: str = "" + +class UpdateForm(BaseModel): + name: str = "" + date: int = 0 + price: int = 0 + memo: str = "" + +class BalanceService: + def __init__(self): + self._conn = psycopg2.connect(conn_param) + + def create(self, balance: Balance) -> str: + cur = self._conn.cursor() + cur.execute( + "insert into balset(name, date, price, memo) values (%s, %s, %s, %s);", + (balance.name, balance.date, balance.price, balance.memo) + ) + + self._conn.commit() + + cur.close() + self._conn.close() + + return balance.name + + def read(self, id: int): + cur = self._conn.cursor() + cur.execute("select * from balset where id = %s;", (id)) + + data = cur.fetchone() + + if data == None: + raise RuntimeError("data not found") + + cur.close() + self._conn.close() + + return { + "id": data[0], + "name": data[1], + "date": data[2], + "price": data[3], + "memo": data[4] + } + + def update(self, id: int, act: str, balance: UpdateForm): + cur = self._conn.cursor() + cur.execute(f"update balset set {act} = %s where id = %s;", (balance[act], id)) + + self._conn.commit() + + cur.close() + self._conn.close() + + def delete(self, id: int): + cur = self._conn.cursor() + cur.execute("delete from balset where id = %s;", (id)) + + self._conn.commit() + + cur.close() + self._conn.close() diff --git a/util/config.py b/util/config.py new file mode 100644 index 0000000..c00e94f --- /dev/null +++ b/util/config.py @@ -0,0 +1,12 @@ +import os +from dotenv import load_dotenv + +load_dotenv() + +conn_param = "host=%s port=%s dbname=%s user=%s password=%s" % ( + os.getenv("DB_URL"), + os.getenv("DB_PORT"), + os.getenv("DB_DATABASE"), + os.getenv("DB_USERNAME"), + os.getenv("DB_PASSWORD") +)