From b29cc47f4d51dc614750e8f63fbc007d9dc22f97 Mon Sep 17 00:00:00 2001 From: "Khadija M. Al-Khashab" Date: Wed, 3 Nov 2021 03:32:43 +0300 Subject: [PATCH 1/2] add multiple endpoints --- commerce/controllers.py | 173 ++++++++++++++++++++++++++++++++++------ commerce/models.py | 4 + commerce/schemas.py | 42 +++++++++- 3 files changed, 193 insertions(+), 26 deletions(-) diff --git a/commerce/controllers.py b/commerce/controllers.py index 389aff6..9748511 100644 --- a/commerce/controllers.py +++ b/commerce/controllers.py @@ -8,8 +8,8 @@ from ninja import Router from pydantic import UUID4 -from commerce.models import Product, Category, City, Vendor, Item, Order, OrderStatus -from commerce.schemas import MessageOut, ProductOut, CitiesOut, CitySchema, VendorOut, ItemOut, ItemSchema, ItemCreate +from commerce.models import Product, Category, City, Vendor, Item, Order, OrderStatus, Order, Address +from commerce.schemas import MessageOut, ProductOut, CitiesOut, CitySchema, VendorOut, ItemOut, ItemSchema, ItemCreate, AddressOut, CheckoutSchema, CheckoutSchemaOut, AddressUpdate, AddressCreate, OrderOut products_controller = Router(tags=['products']) address_controller = Router(tags=['addresses']) @@ -111,9 +111,17 @@ def list_products( """ -@address_controller.get('') +@address_controller.get('', response={ + 200: List[AddressOut], + 404: MessageOut +}) def list_addresses(request): - pass + addresses_qs = Address.objects.all() + + if addresses_qs: + return addresses_qs + + return 404, {'detail': 'No addresses found'} # @products_controller.get('categories', response=List[CategoryOut]) @@ -191,11 +199,11 @@ def view_cart(request): }) def add_update_cart(request, item_in: ItemCreate): try: - item = Item.objects.get(product_id=item_in.product_id, user=User.objects.first()) - item.item_qty += 1 + item = Item.objects.get(product_id=item_in.product_id, user=User.objects.first(), ordered=False) + item.item_qty += item_in.item_qty item.save() except Item.DoesNotExist: - Item.objects.create(**item_in.dict(), user=User.objects.first()) + Item.objects.create(**item_in.dict(), user=User.objects.first(), ordered=False) return 200, {'detail': 'Added to cart successfully'} @@ -228,27 +236,144 @@ def generate_ref_code(): return ''.join(random.sample(string.ascii_letters + string.digits, 6)) -@order_controller.post('create-order', response=MessageOut) +# @order_controller.post('create-order', response=MessageOut) +# def create_order(request): +# ''' +# * add items and mark (ordered) field as True +# * add ref_number +# * add NEW status +# * calculate the total +# ''' + +# order_qs = Order.objects.create( +# user=User.objects.first(), +# status=OrderStatus.objects.get(is_default=True), +# ref_code=generate_ref_code(), +# ordered=False, +# ) + +# user_items = Item.objects.filter(user=User.objects.first()).filter(ordered=False) + +# order_qs.items.add(*user_items) +# order_qs.total = order_qs.order_total +# user_items.update(ordered=True) +# order_qs.save() + +# return {'detail': 'order created successfully'} + +# endpoint for increasing an item quantity within an order +@order_controller.post('item/{id}/increase-quantity', response={ + 200: MessageOut, + 404: MessageOut +}) +def increase_item_quantity(request, id: UUID4): + item = get_object_or_404(Item, id=id, user=User.objects.first()) + item.item_qty += 1 + item.save() + + return 200, {'detail': 'Item quantity increased successfully!'} + +# create-order endpoint +@order_controller.post('create-order', response={ + 200: MessageOut, + 404: MessageOut +}) def create_order(request): - ''' - * add items and mark (ordered) field as True - * add ref_number - * add NEW status - * calculate the total - ''' - - order_qs = Order.objects.create( - user=User.objects.first(), + user_items = Item.objects.filter(user=User.objects.first(), ordered=False) + active_order = Order.objects.filter(user=User.objects.first(), ordered=False, status__is_default = True) + + if user_items: + if active_order: + for item in user_items: + item_product = item.product_id + if item_product in active_order.values('product_id'): + order_item = active_order.items.filter(product_id=item_product) + order_item.qty += item.qty + order_item.save() + else: + active_order.items.create(item) + else: + active_order = Order.objects.create(user=User.objects.first(), status=OrderStatus.objects.get(is_default=True), ref_code=generate_ref_code(), - ordered=False, - ) + ordered=False + ) + active_order.items.add(*user_items) + + active_order.items.update(ordered=True) + active_order.total = active_order.order_total + active_order.save() + return 200, {'detail': 'An order was created successfully'} + + return 404, {'detail': 'No items in cart to be ordered'} + +######## addresses CRUD endpoints +#get an address +@address_controller.get('addresses/{id}', response={ + 200: AddressOut, + 404: MessageOut +}) +def retrieve_address(request, id: UUID4): + return get_object_or_404(Address, id=id) - user_items = Item.objects.filter(user=User.objects.first()).filter(ordered=False) +#create an addresss +@address_controller.post('addresses', response={ + 201: AddressOut, + 400: MessageOut +}) +def create_address(request, address_in: AddressCreate): + address = Address(**address_in.dict(), user=User.objects.first()) + address.save() + return 201, address + +#update an address +@address_controller.put('addresses/{id}', response={ + 200: AddressOut, + 400: MessageOut +}) +def update_address(request, id: UUID4, address_in: AddressUpdate): + address = get_object_or_404(Address, id=id) + for attr, val in address_in.dict().items(): + setattr(address, attr, val) - order_qs.items.add(*user_items) - order_qs.total = order_qs.order_total - user_items.update(ordered=True) + address.save() + return 200, address + +#delete an addresss +@address_controller.delete('addresses/{id}', response={ + 204: MessageOut +}) +def delete_address(request, id: UUID4): + address = get_object_or_404(Address, id=id) + address.delete() + return 204, {'detail': ''} + +#implement checkout endpoint +@order_controller.post('checkout', response={ + 201: list[CheckoutSchemaOut], + 404: MessageOut +}) +def checkout(request, checkout_in: CheckoutSchema): + order_qs = Order.objects.filter(user=User.objects.first(), status__is_default=True) + if order_qs: + for attr, val in checkout_in.dict().items(): + setattr(order_qs, attr, val) order_qs.save() + order_qs.update(ordered=True) + order_qs.update(status=OrderStatus.objects.get(title="COMPLETED")) + else: + return 404, {"detail" : "No order to checkout"} + + return 201, order_qs + +@order_controller.get('', response={ + 200: list[OrderOut], + 404: MessageOut +}) +def view_orders(request): + orders = Order.objects.filter(user=User.objects.first()) + + if orders: + return orders - return {'detail': 'order created successfully'} + return 404, {'detail': 'No orders to show!'} diff --git a/commerce/models.py b/commerce/models.py index edbedee..331dd68 100644 --- a/commerce/models.py +++ b/commerce/models.py @@ -68,6 +68,10 @@ def order_total(self): return sum( i.product.discounted_price * i.item_qty for i in self.items.all() ) + + @property + def children(self): + return self.children class Item(Entity): diff --git a/commerce/schemas.py b/commerce/schemas.py index 0944297..cc5afc6 100644 --- a/commerce/schemas.py +++ b/commerce/schemas.py @@ -1,10 +1,10 @@ -from typing import List +from typing import List, Optional from ninja import ModelSchema, Schema from ninja.orm import create_schema from pydantic import UUID4 -from commerce.models import Product, Merchant +from commerce.models import Product, Merchant, Address, Order class MessageOut(Schema): @@ -92,3 +92,41 @@ class ItemOut(UUIDSchema, ItemSchema): pass +class OrderOut(ModelSchema): + class Config: + model = Order + model_fields = ['total', 'ordered'] + +class OrderStatusOut(UUIDSchema): + status: str + +class AddressUpdate(Schema): + # user_id: UUID4 + work_address: Optional[bool] + address2: Optional[str] + address1: Optional[str] + city_id: Optional[UUID4] + phone: Optional[str] + +class AddressCreate(Schema): + # user_id: UUID4 + address1: str + city_id: UUID4 + phone: str + + +class AddressOut(ModelSchema): + city: CitySchema + class Config: + model = Address + model_fields = ['id','phone', 'address1', 'address2', 'work_address'] + +class CheckoutSchema(Schema): + note: Optional[str] + address_id: Optional[UUID4] + +class CheckoutSchemaOut(CheckoutSchema): + note: str + address: AddressOut + ordered: bool + total: int From 396d085c69131512e5d1b2d7db6cf8050f76889b Mon Sep 17 00:00:00 2001 From: "Khadija M. Al-Khashab" Date: Fri, 5 Nov 2021 01:53:30 +0300 Subject: [PATCH 2/2] couple of fixes --- commerce/controllers.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/commerce/controllers.py b/commerce/controllers.py index 9748511..6f5728e 100644 --- a/commerce/controllers.py +++ b/commerce/controllers.py @@ -203,7 +203,7 @@ def add_update_cart(request, item_in: ItemCreate): item.item_qty += item_in.item_qty item.save() except Item.DoesNotExist: - Item.objects.create(**item_in.dict(), user=User.objects.first(), ordered=False) + Item.objects.create(**item_in.dict(), user=User.objects.first()) return 200, {'detail': 'Added to cart successfully'} @@ -280,18 +280,18 @@ def increase_item_quantity(request, id: UUID4): }) def create_order(request): user_items = Item.objects.filter(user=User.objects.first(), ordered=False) - active_order = Order.objects.filter(user=User.objects.first(), ordered=False, status__is_default = True) + active_order = Order.objects.get(user=User.objects.first(), ordered=False, status__is_default = True) if user_items: if active_order: for item in user_items: item_product = item.product_id - if item_product in active_order.values('product_id'): + if item_product in active_order.items.values('product_id'): order_item = active_order.items.filter(product_id=item_product) order_item.qty += item.qty order_item.save() else: - active_order.items.create(item) + active_order.items.add(item) else: active_order = Order.objects.create(user=User.objects.first(), status=OrderStatus.objects.get(is_default=True), @@ -303,7 +303,7 @@ def create_order(request): active_order.items.update(ordered=True) active_order.total = active_order.order_total active_order.save() - return 200, {'detail': 'An order was created successfully'} + return 200, {'detail': 'An order was issued successfully'} return 404, {'detail': 'No items in cart to be ordered'} @@ -354,17 +354,18 @@ def delete_address(request, id: UUID4): 404: MessageOut }) def checkout(request, checkout_in: CheckoutSchema): - order_qs = Order.objects.filter(user=User.objects.first(), status__is_default=True) - if order_qs: + try: + order = Order.objects.get(user=User.objects.first(), status__is_default=True) for attr, val in checkout_in.dict().items(): - setattr(order_qs, attr, val) - order_qs.save() - order_qs.update(ordered=True) - order_qs.update(status=OrderStatus.objects.get(title="COMPLETED")) - else: + setattr(order, attr, val) + order.ordered= True + order.status= OrderStatus.objects.get(title="COMPLETED") + order.save() + + except Order.DoesNotExist: return 404, {"detail" : "No order to checkout"} - return 201, order_qs + return 201, order @order_controller.get('', response={ 200: list[OrderOut],