2023-05-22 19:27:59 +00:00
|
|
|
from abc import (
|
|
|
|
ABC,
|
|
|
|
abstractmethod
|
|
|
|
)
|
|
|
|
from typing import List
|
|
|
|
from dataclasses import dataclass
|
|
|
|
from django.http.request import HttpRequest
|
|
|
|
from django.conf import settings
|
|
|
|
|
|
|
|
from store.models import Product
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class CartItem:
|
|
|
|
product: Product
|
|
|
|
quantity: int
|
|
|
|
|
|
|
|
|
|
|
|
class BaseCart(ABC):
|
|
|
|
|
|
|
|
def validate_item_id(self, item_id):
|
|
|
|
return Product.objects.get(id=item_id)
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def add_item(self, item_id, quantity):
|
|
|
|
...
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def remove_item(self, item_id):
|
|
|
|
...
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def update_item_quantity(self, item_id, change):
|
|
|
|
...
|
|
|
|
|
|
|
|
@abstractmethod
|
|
|
|
def get_items(self):
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
|
|
class SessionCart(BaseCart):
|
|
|
|
|
|
|
|
def __init__(self, request: HttpRequest) -> None:
|
|
|
|
super().__init__()
|
|
|
|
self.session = request.session
|
|
|
|
if not self.session.get(settings.CART_SESSION_ID):
|
|
|
|
self.session[settings.CART_SESSION_ID] = {}
|
|
|
|
|
2023-05-22 20:11:42 +00:00
|
|
|
def add_item(self, item_id: int, quantity: int) -> None:
|
2023-05-22 19:27:59 +00:00
|
|
|
# TODO - add logging
|
|
|
|
self.validate_item_id(item_id)
|
2023-05-28 15:06:50 +00:00
|
|
|
quantity = int(quantity)
|
|
|
|
item_id = int(item_id)
|
2023-05-28 16:35:08 +00:00
|
|
|
if not self.session[settings.CART_SESSION_ID].get(str(item_id)):
|
2023-05-22 19:27:59 +00:00
|
|
|
self.session[settings.CART_SESSION_ID][item_id] = quantity
|
2023-05-28 16:35:08 +00:00
|
|
|
self.session.modified = True
|
2023-05-22 19:27:59 +00:00
|
|
|
else:
|
|
|
|
self.update_item_quantity(item_id, quantity)
|
|
|
|
|
2023-05-22 20:11:42 +00:00
|
|
|
def remove_item(self, item_id: int) -> None:
|
2023-05-22 19:27:59 +00:00
|
|
|
self.validate_item_id(item_id)
|
|
|
|
try:
|
|
|
|
self.session[settings.CART_SESSION_ID].pop(item_id)
|
2023-05-28 16:35:08 +00:00
|
|
|
self.session.modified = True
|
2023-05-22 19:27:59 +00:00
|
|
|
except KeyError:
|
|
|
|
# TODO - add logging
|
|
|
|
...
|
|
|
|
|
2023-06-08 17:49:19 +00:00
|
|
|
def update_item_quantity(self, item_id: int, new_quantity: int) -> None:
|
2023-05-22 19:27:59 +00:00
|
|
|
self.validate_item_id(item_id)
|
2023-06-08 17:49:19 +00:00
|
|
|
if new_quantity < 1:
|
|
|
|
self.remove_item(item_id)
|
|
|
|
return
|
2023-05-22 19:27:59 +00:00
|
|
|
try:
|
2023-06-08 17:49:19 +00:00
|
|
|
self.session[settings.CART_SESSION_ID][str(item_id)] = new_quantity
|
2023-05-28 16:35:08 +00:00
|
|
|
self.session.modified = True
|
2023-05-22 19:27:59 +00:00
|
|
|
except KeyError:
|
|
|
|
# TODO - add logging
|
2023-06-08 17:49:19 +00:00
|
|
|
self.add_item(item_id, new_quantity)
|
2023-05-22 19:27:59 +00:00
|
|
|
|
|
|
|
def get_items(self) -> List[CartItem]:
|
|
|
|
_items = []
|
|
|
|
for item_id, quantity in self.session[settings.CART_SESSION_ID].items():
|
|
|
|
_items.append(CartItem(quantity=quantity, product=Product.objects.get(id=item_id)))
|
2023-05-22 20:11:42 +00:00
|
|
|
return _items
|
2023-05-28 15:06:50 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def total_price(self):
|
|
|
|
total = 0
|
|
|
|
for item in self.get_items():
|
|
|
|
total += item.product.price * int(item.quantity)
|
2023-06-01 20:35:14 +00:00
|
|
|
return total
|
|
|
|
|
|
|
|
def is_empty(self) -> bool:
|
|
|
|
return not bool(self.session[settings.CART_SESSION_ID].items())
|
|
|
|
|
|
|
|
def clear(self) -> None:
|
|
|
|
self.session[settings.CART_SESSION_ID] = {}
|
|
|
|
self.session.modified = True
|