Implement /orders endpoint
This commit is contained in:
parent
a5d3c4d22a
commit
a718c60561
56
app/api.py
56
app/api.py
@ -1,13 +1,15 @@
|
|||||||
from typing import Optional
|
import os
|
||||||
|
import sqlite3
|
||||||
|
from typing import Annotated, Optional
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import Depends, FastAPI
|
||||||
|
from fastapi.responses import JSONResponse
|
||||||
from pydantic import BaseModel, Field, condecimal, conint, constr, root_validator
|
from pydantic import BaseModel, Field, condecimal, conint, constr, root_validator
|
||||||
|
|
||||||
|
import app.database as database
|
||||||
|
from app.order_processor import FailedToProcessOrderError, process_order
|
||||||
from app.types import Order, OrderSide, OrderType
|
from app.types import Order, OrderSide, OrderType
|
||||||
|
|
||||||
from datetime import datetime
|
|
||||||
from app.stock_exchange import place_order
|
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
@ -35,21 +37,33 @@ class CreateOrderResponseModel(Order):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@app.post(
|
async def get_db():
|
||||||
"/orders",
|
# Replace with proper db connection pooling implementation
|
||||||
status_code=201,
|
db = database.connect(os.getenv("DB_CONNECTION"))
|
||||||
response_model=CreateOrderResponseModel,
|
database.apply_database_schema(db)
|
||||||
response_model_by_alias=True,
|
try:
|
||||||
)
|
yield db
|
||||||
async def create_order(model: CreateOrderModel):
|
finally:
|
||||||
place_order(model)
|
db.close()
|
||||||
return CreateOrderResponseModel(
|
|
||||||
id=1,
|
|
||||||
created_at=datetime.now(),
|
|
||||||
type=model.type_,
|
|
||||||
side=model.side,
|
|
||||||
instrument=model.instrument,
|
|
||||||
limit_price=model.limit_price,
|
|
||||||
quantity=model.quantity
|
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/orders", status_code=201)
|
||||||
|
async def create_order(
|
||||||
|
model: CreateOrderModel, db: Annotated[sqlite3.Connection, Depends(get_db)]
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
order = process_order(db, model)
|
||||||
|
return CreateOrderResponseModel(
|
||||||
|
id=order.id_,
|
||||||
|
created_at=order.created_at,
|
||||||
|
type=order.type_,
|
||||||
|
side=order.side,
|
||||||
|
instrument=order.instrument,
|
||||||
|
limit_price=order.limit_price,
|
||||||
|
quantity=order.quantity,
|
||||||
|
)
|
||||||
|
except FailedToProcessOrderError:
|
||||||
|
return JSONResponse(
|
||||||
|
content={"message": "Internal server error while placing the order"},
|
||||||
|
status_code=500,
|
||||||
)
|
)
|
||||||
|
@ -1,11 +1,27 @@
|
|||||||
import pytest
|
def test_placing_an_order(client):
|
||||||
|
response = client.post(
|
||||||
def test_rudimentary_request(client):
|
"/orders",
|
||||||
response = client.post("/orders", json={
|
json={
|
||||||
"type": "limit",
|
"type": "limit",
|
||||||
"instrument": "US0378331005",
|
"instrument": "US0378331005",
|
||||||
"limit_price": 100.00,
|
"limit_price": 100.00,
|
||||||
"quantity": 10,
|
"quantity": 10,
|
||||||
"side": "buy"
|
"side": "buy",
|
||||||
})
|
},
|
||||||
assert response.status_code == 201
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 201 or response.status_code == 500
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_order_with_invalid_request(client):
|
||||||
|
response = client.post(
|
||||||
|
"/orders",
|
||||||
|
json={
|
||||||
|
"type": "unknown_type",
|
||||||
|
"instrument": "US0378331005",
|
||||||
|
"limit_price": 100.00,
|
||||||
|
"quantity": 10,
|
||||||
|
"side": "buy",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert response.status_code == 422
|
||||||
|
@ -18,6 +18,7 @@ from app.api import app
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def client() -> TestClient:
|
def client() -> TestClient:
|
||||||
|
os.environ["DB_CONNECTION"] = ":memory:"
|
||||||
return TestClient(app)
|
return TestClient(app)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user