diff --git a/be/api/v1/endpoints/cart/checkout/post.py b/be/api/v1/endpoints/cart/checkout/post.py index 8638bea..155cc27 100644 --- a/be/api/v1/endpoints/cart/checkout/post.py +++ b/be/api/v1/endpoints/cart/checkout/post.py @@ -25,7 +25,7 @@ class PaymentModel(BaseModel): class PostCheckoutResponseModel(BaseModel): - orderId: str + id: str email: str items: list[OrderItem] price: PriceModel @@ -59,27 +59,29 @@ async def post_checkout(req: CheckoutRequestBodyModel): receipt_email=req.email, description=f"SCSE Merch Purchase:\n{description}" ) - orderDateTime = datetime.now().__str__() + + id = uuid.uuid4().__str__() + dateTime = datetime.now().__str__() customerEmail = req.email transactionID = payment_intent.id paymentPlatform = "stripe" - orderItems = items_products + items = items_products status = OrderStatus.PENDING_PAYMENT order = Order( - orderID = orderID, - orderDateTime = orderDateTime, + id = id, + dateTime = dateTime, customerEmail = customerEmail, transactionID = transactionID, paymentGateway = paymentPlatform, - orderItems = orderItems, + items = items, status = status ) dal_create_order(order) return { - "orderId": orderID, + "id": id, "items": items_products, "price": price, "payment": { diff --git a/be/api/v1/endpoints/product_categories/__init__.py b/be/api/v1/endpoints/product_categories/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/be/api/v1/endpoints/product_categories/conftest.py b/be/api/v1/endpoints/product_categories/conftest.py deleted file mode 100644 index 8e20218..0000000 --- a/be/api/v1/endpoints/product_categories/conftest.py +++ /dev/null @@ -1,14 +0,0 @@ -import pytest -from be.api.v1.endpoints.product_categories.test_utils import ( - create_mock_db_with_items, - delete_mock_table, -) - - -@pytest.fixture(scope="package") -def provision_mock_db(): - print("Provisioning mock db") - create_mock_db_with_items() - yield - print("deleting mock db") - delete_mock_table() diff --git a/be/api/v1/endpoints/product_categories/delete.py b/be/api/v1/endpoints/product_categories/delete.py deleted file mode 100644 index 4fe35d0..0000000 --- a/be/api/v1/endpoints/product_categories/delete.py +++ /dev/null @@ -1,23 +0,0 @@ -import os -from fastapi import APIRouter, HTTPException -from be.api.v1.templates.non_auth_route import create_non_auth_router -from utils.aws.dynamodb import delete_item_from_db - -router = APIRouter(prefix="/product-categories") - - -@router.delete("/{product_category_name}") -# Delete an item in the product-categories table -async def delete_product_category(product_category_name: str): - table_name = os.environ["PRODUCT_CATEGORIES_TABLE_NAME"] - key = {"name": {"S": product_category_name}} - response = delete_item_from_db(table_name, key) - # if not response.get('Attributes'): - # raise HTTPException(status_code=404, detail="Product category does not exist") - return { - "status": "Product category successfully deleted", - "category": product_category_name, - } - - -handler = create_non_auth_router(router) diff --git a/be/api/v1/endpoints/product_categories/delete_test.py b/be/api/v1/endpoints/product_categories/delete_test.py deleted file mode 100644 index 201c099..0000000 --- a/be/api/v1/endpoints/product_categories/delete_test.py +++ /dev/null @@ -1,37 +0,0 @@ -from moto import mock_dynamodb -import pytest -from fastapi import HTTPException -from pytest import raises - -from utils.test_app import createTestClient -from be.api.v1.endpoints.product_categories.delete import router -from be.api.v1.endpoints.product_categories.test_utils import get_mock_db_item - -client = createTestClient(router) - - -@pytest.mark.usefixtures("provision_mock_db") -@pytest.mark.skip(reason="test setup fails at create_mock_db()") -def test_delete_product_category_200(): - response = client.delete("/product-categories/category_to_be_deleted") - item = get_mock_db_item("category_to_be_deleted") - assert response.status_code == 200 - assert response.json() == { - "status": "Product category successfully deleted", - "category": "category_to_be_deleted", - } - assert item is None - - -@pytest.mark.skip( - reason="deletion doesn't return if the item doesnt exist yet - to be added!" -) -@pytest.mark.usefixtures("provision_mock_db") -@pytest.mark.skip(reason="test setup fails at create_mock_db()") -def test_delete_product_category_404(): - with raises(HTTPException) as err: - client.delete("/product-categories/category_that_doesnt_exist") - item = get_mock_db_item("category_that_doesnt_exist") - assert err.value.status_code == 404 - assert err.value.detail == "Product category does not exist" - assert item is None diff --git a/be/api/v1/endpoints/product_categories/get.py b/be/api/v1/endpoints/product_categories/get.py deleted file mode 100644 index be7bacb..0000000 --- a/be/api/v1/endpoints/product_categories/get.py +++ /dev/null @@ -1,24 +0,0 @@ -from be.api.v1.templates.non_auth_route import create_non_auth_router -from utils.aws.dynamodb import read_item_from_db -from fastapi import APIRouter, HTTPException -import os - -router = APIRouter(prefix="/product-categories") - - -@router.get("/{product_category_name}") -# Get specific product category -async def get_product_category(product_category_name: str): - try: - key = {"name": {"S": product_category_name}} - table_name = os.environ["PRODUCT_CATEGORIES_TABLE_NAME"] - response = read_item_from_db(table_name, key) - if not response: - raise HTTPException(status_code=404, detail="Product category not found") - except Exception as e: - raise HTTPException(status_code=500, detail=e) - - return {"product_category": {"name": response["name"]["S"]}} - - -handler = create_non_auth_router(router) diff --git a/be/api/v1/endpoints/product_categories/get_test.py b/be/api/v1/endpoints/product_categories/get_test.py deleted file mode 100644 index 4b8650d..0000000 --- a/be/api/v1/endpoints/product_categories/get_test.py +++ /dev/null @@ -1,14 +0,0 @@ -import pytest -from utils.test_app import createTestClient -from be.api.v1.endpoints.product_categories.get import router -from be.api.v1.endpoints.product_categories.test_utils import get_mock_db_item - -client = createTestClient(router) - - -@pytest.mark.usefixtures("provision_mock_db") -@pytest.mark.skip(reason="test setup fails at create_mock_db()") -def test_get_product_categories_200(): - response = client.get("/product-categories/category_to_be_got") - assert response.status_code == 200 - assert response.json() == {"product_category": {"name": "category_to_be_got"}} diff --git a/be/api/v1/endpoints/product_categories/post.py b/be/api/v1/endpoints/product_categories/post.py deleted file mode 100644 index 80c261b..0000000 --- a/be/api/v1/endpoints/product_categories/post.py +++ /dev/null @@ -1,27 +0,0 @@ -from pydantic import BaseModel -from be.api.v1.templates.non_auth_route import create_non_auth_router -from utils.aws.dynamodb import write_item_to_db -from fastapi import APIRouter, HTTPException -import os - -router = APIRouter(prefix="/product-categories") - -table_name = os.environ["PRODUCT_CATEGORIES_TABLE_NAME"] - - -class ProductCategory(BaseModel): - name: str - - -@router.post("") -# Create an item in the product-categories table -def create_product_category(product_category: ProductCategory): - item = {"name": {"S": product_category.name}} - write_item_to_db(table_name, item) - return { - "status": "Product category successfully created", - "category": product_category.name, - } - - -handler = create_non_auth_router(router) diff --git a/be/api/v1/endpoints/product_categories/post_test.py b/be/api/v1/endpoints/product_categories/post_test.py deleted file mode 100644 index f1177d4..0000000 --- a/be/api/v1/endpoints/product_categories/post_test.py +++ /dev/null @@ -1,21 +0,0 @@ -from moto import mock_dynamodb -import pytest -from utils.test_app import createTestClient -from be.api.v1.endpoints.product_categories.post import router -from be.api.v1.endpoints.product_categories.test_utils import get_mock_db_item - -client = createTestClient(router) - -# @pytest.mark.usefixtures("provision_mock_db") -@mock_dynamodb -@pytest.mark.skip(reason="test setup fails at create_mock_db()") -def test_post_product_categories(): - req_body = {"name": "test-category"} - response = client.post("/product-categories", json=req_body) - item = get_mock_db_item("test-category") - print(item) - assert response.status_code == 200 - assert response.json() == { - "status": "Product category successfully created", - "category": "test-category", - } diff --git a/be/api/v1/endpoints/product_categories/test_utils.py b/be/api/v1/endpoints/product_categories/test_utils.py deleted file mode 100644 index 7508220..0000000 --- a/be/api/v1/endpoints/product_categories/test_utils.py +++ /dev/null @@ -1,45 +0,0 @@ -import os -from utils.aws.dynamodb import ( - create_db, - delete_table_from_db, - write_item_to_db, - read_item_from_db, - dynamodb, -) - - -def create_mock_db(): - try: - create_db( - table_name=os.environ["PRODUCT_CATEGORIES_TABLE_NAME"], - attribute_definitions=[{"AttributeName": "name", "AttributeType": "S"}], - key_schema=[{"AttributeName": "name", "KeyType": "HASH"}], - provisioned_throughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5}, - ) - except dynamodb.exceptions.ResourceInUseException: - return - - -def populate_db_with_items(): - items = ["category_to_be_deleted", "category_to_be_got"] - for item in items: - write_item_to_db( - table_name=os.environ["PRODUCT_CATEGORIES_TABLE_NAME"], - item={"name": {"S": item}}, - ) - - -def get_mock_db_item(item): - return read_item_from_db( - table_name=os.environ["PRODUCT_CATEGORIES_TABLE_NAME"], - key={"name": {"S": item}}, - ) - - -def create_mock_db_with_items(): - create_mock_db() - populate_db_with_items() - - -def delete_mock_table(): - delete_table_from_db(table_name=os.environ["PRODUCT_CATEGORIES_TABLE_NAME"]) diff --git a/be/api/v1/endpoints/users/__init__.py b/be/api/v1/endpoints/users/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/be/api/v1/endpoints/users/get.py b/be/api/v1/endpoints/users/get.py deleted file mode 100644 index 4e6f7da..0000000 --- a/be/api/v1/endpoints/users/get.py +++ /dev/null @@ -1,23 +0,0 @@ -from fastapi import APIRouter -from be.api.v1.templates.non_auth_route import create_non_auth_router - - -router = APIRouter(prefix="/users") - - -@router.get("") -async def root(): - return { - "users": [ - {"id": 1, "name": "Andrew"}, - {"id": 2, "name": "Benjamin"}, - ] - } - - -@router.get("/{user_id}") -async def get_user_id(user_id): - return {"id": user_id, "name": "Benjamin", "regTime": "1643716201"} - - -handler = create_non_auth_router(router) diff --git a/be/api/v1/endpoints/users/get_test.py b/be/api/v1/endpoints/users/get_test.py deleted file mode 100644 index f96a585..0000000 --- a/be/api/v1/endpoints/users/get_test.py +++ /dev/null @@ -1,18 +0,0 @@ -from utils.test_app import createTestClient -from be.api.v1.endpoints.users.get import router - -client = createTestClient(router) - - -def test_get_users(): - response = client.get("/users") - assert response.status_code == 200 - assert response.json() == { - "users": [{"id": 1, "name": "Andrew"}, {"id": 2, "name": "Benjamin"}] - } - - -def test_get_user(): - response = client.get("/users/2") - assert response.status_code == 200 - assert response.json() == {"id": "2", "name": "Benjamin", "regTime": "1643716201"} diff --git a/be/api/v1/models/cart.py b/be/api/v1/models/cart.py index 4b59419..518aba1 100644 --- a/be/api/v1/models/cart.py +++ b/be/api/v1/models/cart.py @@ -6,13 +6,13 @@ class CartItem(BaseModel): size: Optional[str] quantity: int colorway: str - + class Cart(BaseModel): items: list[CartItem] promoCode: Optional[str] class PriceModel(BaseModel): currency: str - subtotal: float - discount: float - grandTotal: float + subtotal: int + discount: int + grandTotal: int diff --git a/be/api/v1/models/orders.py b/be/api/v1/models/orders.py index ef6fcf9..96312cd 100644 --- a/be/api/v1/models/orders.py +++ b/be/api/v1/models/orders.py @@ -19,10 +19,10 @@ class OrderItem(BaseModel): size: Optional[str] class Order(BaseModel): - orderID: str - orderDateTime: datetime + id: str + dateTime: datetime customerEmail: str transactionID: str paymentGateway: str - orderItems: list[OrderItem] + items: list[OrderItem] status: OrderStatus diff --git a/be/api/v1/models/product_category.py b/be/api/v1/models/product_category.py deleted file mode 100644 index a1ac437..0000000 --- a/be/api/v1/models/product_category.py +++ /dev/null @@ -1,5 +0,0 @@ -from pydantic import BaseModel - - -class ProductCategory(BaseModel): - name: str \ No newline at end of file diff --git a/be/docs.py b/be/docs.py index a6985d9..d17dc36 100644 --- a/be/docs.py +++ b/be/docs.py @@ -5,25 +5,14 @@ from fastapi.openapi.utils import get_openapi from dotenv import load_dotenv -load_dotenv(join(dirname(__file__), '..', '.env.test')) -base_api_server_url: str = os.getenv('BASE_API_SERVER_URL') - +from be.api.v1.endpoints.cart.checkout.post import router as v1_checkout_post +from be.api.v1.endpoints.cart.quotation.post import router as v1_cart_quotation_post +from be.api.v1.endpoints.orders.get import router as v1_orders_get +from be.api.v1.endpoints.payments.intent.post import router as v1_payments_intent_post from be.api.v1.endpoints.products.get import router as v1_products_get - -from be.api.v1.endpoints.product_categories.get import ( - router as v1_product_categories_get, -) -from be.api.v1.endpoints.product_categories.post import ( - router as v1_product_categories_post, -) -from be.api.v1.endpoints.product_categories.delete import ( - router as v1_product_categories_delete, -) - -from be.api.v1.endpoints.payments.intent.post import router as v1_payments_intent_post -from be.api.v1.endpoints.cart.quotation.post import router as v1_cart_quotation_post -from be.api.v1.endpoints.cart.checkout.post import router as v1_checkout_post +load_dotenv(join(dirname(__file__), '..', '.env.test')) +base_api_server_url: str = os.getenv('BASE_API_SERVER_URL') tags_metadata = [ { @@ -43,10 +32,7 @@ ) app.include_router(v1_products_get) - -app.include_router(v1_product_categories_get) -app.include_router(v1_product_categories_post) -app.include_router(v1_product_categories_delete) +app.include_router(v1_orders_get) app.include_router(v1_payments_intent_post) app.include_router(v1_cart_quotation_post) diff --git a/serverless.yml b/serverless.yml index ddc5d9f..11d28f5 100644 --- a/serverless.yml +++ b/serverless.yml @@ -25,7 +25,6 @@ provider: Resource: "*" environment: SERVERLESS_STAGE: ${opt:stage, "dev"} - PRODUCT_CATEGORIES_TABLE_NAME: ${self:custom.tableNames.productCategoriesTableName} PRODUCTS_TABLE_NAME: ${self:custom.tableNames.productsTableName} ORDERS_TABLE_NAME: ${self:custom.tableNames.ordersTableName} FRONTEND_HOST: ${env:FRONTEND_HOST, ssm:/FRONTEND_HOST_${self:provider.stage}} @@ -49,9 +48,8 @@ custom: useChildProcesses: true httpPort: 4000 tableNames: - productCategoriesTableName: 'be-${self:provider.stage}-product_categories' - productsTableName: 'be-${self:provider.stage}-products' - ordersTableName: 'be-${self:provider.stage}-orders' + productsTableName: 'merch-${self:provider.stage}-products' + ordersTableName: 'merch-${self:provider.stage}-orders' dynamodb: stages: - dev @@ -190,20 +188,6 @@ functions: resources: Resources: - productCategoriesTable: - Type: 'AWS::DynamoDB::Table' - Properties: - TableName: ${self:provider.environment.PRODUCT_CATEGORIES_TABLE_NAME} - AttributeDefinitions: - - AttributeName: name - AttributeType: S - KeySchema: - - AttributeName: name - KeyType: HASH - ProvisionedThroughput: - ReadCapacityUnits: 1 - WriteCapacityUnits: 1 - productsTable: Type: 'AWS::DynamoDB::Table' Properties: @@ -223,10 +207,10 @@ resources: Properties: TableName: ${self:provider.environment.ORDERS_TABLE_NAME} AttributeDefinitions: - - AttributeName: orderID + - AttributeName: id AttributeType: S KeySchema: - - AttributeName: orderID + - AttributeName: id KeyType: HASH ProvisionedThroughput: ReadCapacityUnits: 2 diff --git a/utils/dal/order.py b/utils/dal/order.py index 9ddc94b..361d3d7 100644 --- a/utils/dal/order.py +++ b/utils/dal/order.py @@ -6,7 +6,7 @@ table_name = os.environ.get("ORDERS_TABLE_NAME", "test_orders_table") def dal_create_order(order: Order): - orderItems = [{ + items = [{ "id": orderItem.id, "name": orderItem.name, "price": orderItem.price, @@ -15,30 +15,30 @@ def dal_create_order(order: Order): "quantity": orderItem.quantity, "colorway": orderItem.colorway, "size": orderItem.size, - } for orderItem in order.orderItems] + } for orderItem in order.items] order_dict = { - "orderID": order.orderID, - "orderDateTime": order.orderDateTime.__str__(), + "id": order.id, + "dateTime": order.dateTime.__str__(), "customerEmail": order.customerEmail, "transactionID": order.transactionID, "paymentGateway": order.paymentGateway, "status": order.status.value, - "orderItems": orderItems, + "items": items, } write_item_to_db(table_name, order_dict) def dal_read_order(order_id: str) -> Order: - key = {"orderID": order_id} + key = {"id": order_id} res = read_item_from_db(table_name, key) if res is None: raise Exception("Order not found in db") - orderItems = [ + items = [ OrderItem( id=item["id"], name=item["name"], @@ -48,15 +48,15 @@ def dal_read_order(order_id: str) -> Order: quantity=item["quantity"], colorway=item["colorway"], size=item["size"], - ) for item in res["orderItems"] + ) for item in res["items"] ] return Order( - orderID=res["orderID"], - orderDateTime=datetime.fromisoformat(res["orderDateTime"]), + id=res["id"], + dateTime=datetime.fromisoformat(res["dateTime"]), customerEmail=res["customerEmail"], transactionID=res["transactionID"], paymentGateway=res["paymentGateway"], status=OrderStatus(res["status"]), - orderItems=orderItems, + items=items, )