I am trying to design a checkout process where the tax information needs to go through a lookup table to get the appropriate tax rate based on parameters like buyer_address, product_price, etc.
I am trying to avoid storing the tax rate as a property of the cart as a model field in the database because this value changes on the fly as the checkout form values change (cart line items change or shipping address changes). It's not solely a property of the cart or cart line item but depends on other paramters.
I tried using a local variable in the class, and during the checkout process, once the customer clicks on PlaceOrder (POST to PaymentDetailsView), on the backend, a tax lookup will be done and added to the cart accordingly by setting that property. I am having a hard time understanding why the variable value remains None even after setting it. The lookup right now returns an example number of 0.8 as but I would have a more detailed method for the lookup that later.
MODELS
class BagLine(models.Model):
_unitTax = None
bag = models.ForeignKey(Bag,
on_delete=models.CASCADE,
related_name='lines')
product = models.ForeignKey(ProductDesign,
on_delete=models.CASCADE,
related_name='bagLines')
quantity = models.PositiveIntegerField(default=1)
@property
def unitTax(self):
return self._unitTax
@unitTax.setter
def unitTax(self, value):
self._unitTax = value
@property
def isTaxKnown(self):
print("unit tax is ", self._unitTax)
if self._unitTax is None:
return False
return True
class Bag(models.Model):
ownerConsumer = models.ForeignKey(ConsumerClient, null=True, blank=True,
on_delete=models.CASCADE, related_name="bags")
@property
def isTaxKnown(self):
for line in self.lines.all():
print("found a line with unit tax", line.unitTax)
print("is tax known", line.isTaxKnown)
return all([line.isTaxKnown for line in self.lines.all()])
VIEWS
class PaymentDetailsView(OrderPlacementMixin, APIView):
def post(self, request, *args, **kwargs):
return self.handle_place_order_submission(request)
def handle_place_order_submission(self, request):
return self.submit(**self.build_submission())
def submit(self, user, bag, shipping_address, shipping_method,
shipping_charge, billing_address, order_total,
payment_kwargs=None, order_kwargs=None, surcharges=None):
# Taxes must be known at this point
assert bag.isTaxKnown, (
"Bag tax must be set before a user can place an order")
assert shipping_charge.isTaxKnown, (
"Shipping charge tax must be set before a user can place an order")
# Tax Lookup Method
def apply_taxes_to_bag(self, bag, shipping_address):
for line in bag.lines.all():
line.unitTax = 0.8
line.save()
print("LINE unitTax", line.unitTax)
print("LINE isTaxKnown", line.isTaxKnown)
bag.save()
print("BAG TAX KNOWN ", bag.isTaxKnown)
def build_submission(self, **kwargs):
"""
Return a dict of data that contains everything required for an order
submission. This includes payment details (if any).
This can be the right place to perform tax lookups and apply them to
the bag.
"""
account_info = Account.get_account(self.request)
bag = Bag().get_from_account(account_info)
shipping_address = self.get_shipping_address(bag)
self.apply_taxes_to_bag(bag, shipping_address)
shipping_method = self.get_shipping_method(
bag, shipping_address)
billing_address = self.get_billing_address(shipping_address)
submission = {
'user': self.request.user,
'bag': bag,
'shipping_address': shipping_address,
'shipping_method': shipping_method,
'billing_address': billing_address,
}
return submission
Result
I am receiving this assertion error that I have included:
"Bag tax must be set before a user can place an order"
My expectation is that bag.IsTaxKnown to be defined, but I am not understanding why the value of the _unitTax variable is still None or turns into None after setting it.
This is the output from the console:
LINE unitTax 0.8
unit tax is 0.8
LINE isTaxKnown True
found a line with unit tax None
unit tax is None
is tax known False
unit tax is None
BAG TAX KNOWN False