Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

commerce #31

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 164 additions & 22 deletions commerce/controllers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import random
import string
from typing import List

from django.contrib.auth.models import User
Expand All @@ -6,8 +8,8 @@
from ninja import Router
from pydantic import UUID4

from commerce.models import Product, Category, City, Vendor, Item
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'])
Expand Down Expand Up @@ -58,7 +60,6 @@ def list_products(
# 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:
Expand All @@ -67,51 +68,45 @@ def list_products(
#
# 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('')
@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])
Expand Down Expand Up @@ -189,11 +184,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'}

Expand All @@ -220,3 +215,150 @@ def delete_item(request, id: UUID4):
item.delete()

return 204, {'detail': 'Item deleted!'}


def generate_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(),
# 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'}


# create-order

def generate_ref_code():
return ''.join(random.sample(string.ascii_letters+string.digits, 6))

@order_controller.post('create-order', response={
200: MessageOut,
404: MessageOut
})
def create_order(request):
order_qs = Order(
user=User.objects.first,
status=OrderStatus.objects.get(is_defult=True),
ref_code=generate_ref_code(),
ordered=False,
)

user_items = Item.objects.filter(user=User.objects.first()),
user_items.update(ordered=True)
order_qs.items.add(*user_items)
order_qs.total = order_qs.order_total
order_qs.save()

return {'details': 'order created successfully'}





#checkout-endpoint
@order_controller.post('checkout', response={200: MessageOut, 400: MessageOut})
def checkout(request, address_in: AddressOut, city : str , note : str):
address_qs = Address(**address_in.dict(), user = User.objects.first(), city = UUID4)

address_qs.save()

try:
order = Order.objects.get(user=User.objects.first(), ordered=False)

except Order.DoesNotExist:
return 400 ,{'detail': 'Not Found Any Order'}

if note :
order.note = note
order.ordered = True
order.address = address_qs
order.status = OrderStatus
order.save()

return 200, {'detail': 'Checkout Created successfully'}




# addresses

@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=User.objects.first())




@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



@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 x, y in address_in.dict().items():
setattr(address, x, y)

address.save()
return 200, address




@address_controller.delete('addresses/{id}', response={
204: MessageOut
})
def delete_address(request, id: UUID4):
address = get_object_or_404(Address, id=id ,user = User.objects.first())
address.delete()
return 204, {'detail': ''}





# increas-item
@order_controller.post('item/{id}/increase-item', response={
200: MessageOut,
404: MessageOut
})
def increase_item(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!'}
44 changes: 42 additions & 2 deletions commerce/schemas.py
Original file line number Diff line number Diff line change
@@ -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):
Expand Down Expand Up @@ -90,3 +90,43 @@ class ItemCreate(Schema):

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