2022-04-14 21:28:28 -06:00

135 lines
4.4 KiB
Python

import logging
from decimal import Decimal
from django.conf import settings
from core.models import Product, OrderLine, Coupon
from .payments import CreateOrder
from core import (
DiscountValueType,
VoucherType,
TransactionStatus,
OrderStatus,
ShippingMethodType
)
logger = logging.getLogger(__name__)
class Cart:
def __init__(self, request):
self.session = request.session
self.coupon_code = self.session.get('coupon_code')
cart = self.session.get(settings.CART_SESSION_ID)
if not cart:
cart = self.session[settings.CART_SESSION_ID] = {}
self.cart = cart
def add(self, product, quantity=1, grind='', update_quantity=False):
product_id = str(product.id)
if product_id not in self.cart:
self.cart[product_id] = {
'quantity': 0,
'grind': grind,
'price': str(product.price)
}
if update_quantity:
self.cart[product_id]['quantity'] = quantity
else:
self.cart[product_id]['quantity'] += quantity
self.save()
def save(self):
self.session[settings.CART_SESSION_ID] = self.cart
self.session.modified = True
logger.info(f'\nCart:\n{self.cart}\n')
def remove(self, product):
product_id = str(product.id)
if product_id in self.cart:
del self.cart[product_id]
self.save()
def __iter__(self):
product_ids = self.cart.keys()
products = Product.objects.filter(id__in=product_ids)
for product in products:
self.cart[str(product.id)]['product'] = product
for item in self.cart.values():
item['price'] = Decimal(item['price'])
item['total_price'] = item['price'] * item['quantity']
yield item
def __len__(self):
return sum(item['quantity'] for item in self.cart.values())
def get_total_price(self):
return sum(Decimal(item['price']) * item['quantity'] for item in self.cart.values())
def clear(self):
del self.session[settings.CART_SESSION_ID]
try:
del self.session['coupon_code']
except KeyError:
pass
self.session.modified = True
def build_order_params(self):
return \
{
'items': self,
'total_price': f'{self.get_total_price_after_discount()}',
'item_total': f'{self.get_total_price()}',
'discount': f'{self.get_discount()}',
'shipping_price': '0',
'tax_total': '0',
'shipping_method': 'US POSTAL SERVICE',
'shipping_address': self.build_shipping_address(self.session.get('shipping_address')),
}
def create_order(self):
params = self.build_order_params()
logger.info(f'\nParams: {params}\n')
response = CreateOrder().create_order(params, debug=True)
return response
def build_bulk_list(self, order):
bulk_list = [OrderLine(
order=order,
product=item['product'],
customer_note=item['grind'],
unit_price=item['price'],
quantity=item['quantity'],
tax_rate=2,
) for item in self]
return bulk_list
def build_shipping_address(self, address):
return \
{
'address_line_1': f'{address["street_address_1"]}',
'address_line_2': f'{address["street_address_2"]}',
'admin_area_2': f'{address["city"]}',
'admin_area_1': f'{address["state"]}',
'postal_code': f'{address["postal_code"]}',
'country_code': 'US'
}
@property
def coupon(self):
if self.coupon_code:
return Coupon.objects.get(code=self.coupon_code)
return None
def get_discount(self):
if self.coupon:
if self.coupon.discount_value_type == DiscountValueType.FIXED:
return round(self.coupon.discount_value, 2)
elif self.coupon.discount_value_type == DiscountValueType.PERCENTAGE:
return round((self.coupon.discount_value / Decimal('100')) * self.get_total_price(), 2)
return Decimal('0')
def get_total_price_after_discount(self):
return round(self.get_total_price() - self.get_discount(), 2)