From 1377e7624c6336dca9ae0f4368273bc34e3f4996 Mon Sep 17 00:00:00 2001 From: Maha Date: Sat, 13 Nov 2021 13:53:01 +0300 Subject: [PATCH] 04-commerce task --- commerce/controllers.py | 179 ++++++++++++++++++++++++---------------- commerce/models.py | 4 +- commerce/schemas.py | 42 +++++++++- 3 files changed, 153 insertions(+), 72 deletions(-) diff --git a/commerce/controllers.py b/commerce/controllers.py index 389aff6..a4caf99 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 Address, Product, Category, City, Vendor, Item, Order, OrderStatus +from commerce.schemas import OrderOut, AddressCreate, OrderSchema, CheckOut, AddressOut, AddressSchema, MessageOut, ProductOut, CitiesOut, CitySchema, VendorOut, ItemOut, ItemSchema, ItemCreate products_controller = Router(tags=['products']) address_controller = Router(tags=['addresses']) @@ -55,71 +55,43 @@ def list_products( return products_qs -""" -# product = Product.objects.all().select_related('merchant', 'category', 'vendor', 'label') - # print(product) - # - # order = Product.objects.all().select_related('address', 'user').prefetch_related('items') - # try: - # one_product = Product.objects.get(id='8d3dd0f1-2910-457c-89e3-1b0ed6aa720a') - # except Product.DoesNotExist: - # return {"detail": "Not found"} - # print(one_product) - # - # shortcut_function = get_object_or_404(Product, id='8d3dd0f1-2910-457c-89e3-1b0ed6aa720a') - # print(shortcut_function) - - # print(type(product)) - # print(product.merchant.name) - # print(type(product.merchant)) - # print(type(product.category)) - - -Product <- Merchant, Label, Category, Vendor - -Retrieve 1000 Products form DB - -products = Product.objects.all()[:1000] (select * from product limit 1000) - -for p in products: - print(p) - -for every product, we retrieve (Merchant, Label, Category, Vendor) records - -Merchant.objects.get(id=p.merchant_id) (select * from merchant where id = 'p.merchant_id') -Label.objects.get(id=p.label_id) (select * from merchant where id = 'p.label_id') -Category.objects.get(id=p.category_id) (select * from merchant where id = 'p.category_id') -Vendor.objects.get(id=p.vendor_id) (select * from merchant where id = 'p.vendor_id') - -4*1000+1 - -Solution: Eager loading - -products = (select * from product limit 1000) - -mids = [p1.merchant_id, p2.merchant_id, ...] -[p1.label_id, p2.label_id, ...] -. -. -. - -select * from merchant where id in (mids) * 4 for (label, category and vendor) - -4+1 +@address_controller.get('', response={ + 200: List[AddressOut], + 404: MessageOut +}) +def list_addresses(request): + address = Address.objects.all() + if address: + return address -""" + return 404, {'datail': 'no addresses'} -@address_controller.get('') -def list_addresses(request): - pass +@address_controller.get('address/{id}', response={ + 200: AddressOut, + 404: MessageOut +}) +def retrieve_address(request, id: UUID4): + return get_object_or_404(Address, id=id) +@address_controller.post('create', response={ + 200: AddressSchema, + 400: MessageOut +}) +def create_address(request, address_in: AddressCreate): + address = Address(**address_in.dict(), user=User.objects.first()) + address.save() + return address -# @products_controller.get('categories', response=List[CategoryOut]) -# def list_categories(request): -# return Category.objects.all() +@address_controller.delete('address/{id}', response={ + 204: MessageOut +}) +def delete_address(request, id: UUID4): + address = get_object_or_404(Address, id=id) + address.delete() + return 204, {'detail': 'deleted'} @address_controller.get('cities', response={ 200: List[CitiesOut], @@ -214,6 +186,18 @@ def reduce_item_quantity(request, id: UUID4): return 200, {'detail': 'Item quantity reduced successfully!'} + +@order_controller.post('item/{id}/increase-quantity', response={ + 200: 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 reduced successfully!'} + + @order_controller.delete('item/{id}', response={ 204: MessageOut }) @@ -224,23 +208,31 @@ def delete_item(request, id: UUID4): return 204, {'detail': 'Item deleted!'} -def generate_ref_code(): + +@order_controller.get('', response={ + 200: List[OrderSchema], + 404: MessageOut +}) +def get_orders(request): + orders = Order.objects.all() + + if orders: + return orders + + return 404, {'detail': 'No cities found'} + + +def create_ref_code(): return ''.join(random.sample(string.ascii_letters + string.digits, 6)) + @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(), + ref_code=create_ref_code(), ordered=False, ) @@ -252,3 +244,52 @@ def create_order(request): order_qs.save() return {'detail': 'order created successfully'} + + + + + +# checkout + + + + +@order_controller.post('ordered_item/{id}/reduce-quantity', response={ + 200: MessageOut, +}) +def reduce_ordered_item_quantity(request, id: UUID4): + item = get_object_or_404(Item, id=id, user=User.objects.first()) + if item.item_qty <= 1: + item.delete() + return 200, {'detail': 'Item deleted!'} + item.item_qty -= 1 + item.save() + + return 200, {'detail': 'Item quantity reduced successfully!'} + + + +@order_controller.post('ordered_item/{id}/increase-quantity', response={ + 200: MessageOut, +}) +def increase_ordered_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!'} + + +@order_controller.post('checkout', response={ + 200: MessageOut, +}) +def checkout(request, item_in: CheckOut): + order=get_object_or_404(Order, user=User.objects.first(), ordered=False) + + order.note = item_in.note + order.address = Address.objects.get(id=item_in.address_id) + order.ordered = True + order.status = OrderStatus.objects.get(title='COMPLETED') + + order.save() + return 200, {'detail': 'checkout complated successfully'} diff --git a/commerce/models.py b/commerce/models.py index edbedee..39ce3f4 100644 --- a/commerce/models.py +++ b/commerce/models.py @@ -82,7 +82,7 @@ class Item(Entity): ordered = models.BooleanField('ordered', default=False) def __str__(self): - return self.product.name + return f'' class OrderStatus(Entity): @@ -214,4 +214,4 @@ class Address(Entity): phone = models.CharField('phone', max_length=255) def __str__(self): - return f'{self.user.first_name} - {self.address1} - {self.address2} - {self.phone}' + return f'{self.user.first_name} - {self.address1} - {self.address2} - {self.phone}' \ No newline at end of file diff --git a/commerce/schemas.py b/commerce/schemas.py index 0944297..90be651 100644 --- a/commerce/schemas.py +++ b/commerce/schemas.py @@ -1,5 +1,5 @@ from typing import List - +from uuid import UUID, uuid4 from ninja import ModelSchema, Schema from ninja.orm import create_schema from pydantic import UUID4 @@ -91,4 +91,44 @@ class ItemCreate(Schema): class ItemOut(UUIDSchema, ItemSchema): pass +class AddressSchema(Schema): + work_address: bool + address1: str + address2: str + phone: str + city: CitiesOut + + +class AddressCreate(Schema): + work_address: bool + address1: str + address2: str + phone: str + city_id: UUID4 + + +class AddressOut(AddressSchema, UUIDSchema): + pass + + +class OrderOut(Schema): + note: str = None + ref_code: str + ordered: bool + address: AddressSchema = None + items: List[ItemOut] + + +class OrderSchema(OrderOut, UUIDSchema): + pass + + +class OrderChange(Schema): + item_id: UUID4 + prodect_id: UUID4 + + +class CheckOut(Schema): + note: str + address_id: UUID4