diff --git a/app/order_processor.py b/app/order_processor.py new file mode 100644 index 0000000..e10354b --- /dev/null +++ b/app/order_processor.py @@ -0,0 +1,33 @@ +from datetime import datetime + +import app.database as database +import app.stock_exchange as stock_exchange +from app.types import Order + + +class FailedToProcessOrderError(Exception): + pass + + +def process_order(db_connection, order_request, place_order=stock_exchange.place_order): + order = Order( + id="-1", + created_at=datetime.now(), + side=order_request.side, + type=order_request.type_, + instrument=order_request.instrument, + limit_price=order_request.limit_price, + quantity=order_request.quantity, + ) + + order = database.insert_order(db_connection, order) + try: + place_order(order) + database.mark_order_as(db_connection, order.id_, "placed") + except stock_exchange.OrderPlacementError: + database.mark_order_as(db_connection, order.id_, "failed") + raise FailedToProcessOrderError(order) + finally: + db_connection.commit() + + return order diff --git a/tests/order_processor_test.py b/tests/order_processor_test.py new file mode 100644 index 0000000..97926b0 --- /dev/null +++ b/tests/order_processor_test.py @@ -0,0 +1,62 @@ +import app.stock_exchange as stock_exchange +from app.api import CreateOrderModel +from app.order_processor import FailedToProcessOrderError, process_order +from app.types import OrderSide, OrderType + + +def successful_place_order(_order): + pass + + +def test_placing_an_order(db_connection): + order_request = CreateOrderModel( + type=OrderType.LIMIT, + side=OrderSide.BUY, + instrument="123456789123", + limit_price="12.00", + quantity=1, + ) + + order_count_before = db_connection.execute( + "SELECT COUNT(*) from orders" + ).fetchone()[0] + order = process_order( + db_connection, order_request, place_order=successful_place_order + ) + order_count_after = db_connection.execute( + "SELECT COUNT(*) from orders where status = 'placed'" + ).fetchone()[0] + + assert order_count_after - order_count_before == 1 + assert order.id_ is not None + + +def failing_place_order(_order): + raise stock_exchange.OrderPlacementError() + + +def test_placing_an_order_that_fails(db_connection): + order_request = CreateOrderModel( + type=OrderType.LIMIT, + side=OrderSide.BUY, + instrument="123456789123", + limit_price="12.00", + quantity=1, + ) + + order_count_before = db_connection.execute( + "SELECT COUNT(*) from orders" + ).fetchone()[0] + order = None + try: + order = process_order( + db_connection, order_request, place_order=failing_place_order + ) + except Exception as e: + assert type(e) is FailedToProcessOrderError + + order_count_after = db_connection.execute( + "SELECT COUNT(*) from orders where status = 'failed'" + ).fetchone()[0] + + assert order_count_after - order_count_before == 1