Django e-commerce part53 Cart Total & Taxes
カートにトータルと消費税をつける
carts/models.py にフィールド追加
tax_total, totalを追記しておく do_tax_and_total_receiver には、subtotalなどの計算式を入れておく pre_save signalで、Cartからpre_save signalが来たらdo_tax_and_total_receiverに接続する。
class Cart(models.Model): user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True) items = models.ManyToManyField(Variation, through=CartItem) timestamp = models.DateTimeField(auto_now=False, auto_now_add=True) updated = models.DateTimeField(auto_now=True, auto_now_add=False) subtotal = models.DecimalField(max_digits=50, decimal_places=0, default=0) tax_total = models.DecimalField(max_digits=50, decimal_places=0, default=0) total = models.DecimalField(max_digits=50, decimal_places=0, default=0) def __str__(self): return str(self.id) def update_subtotal(self): subtotal = 0 items = self.cartitem_set.all() for item in items: subtotal += item.line_item_total self.subtotal = subtotal self.save() def do_tax_and_total_receiver(sender, instance, *args, **kwargs): subtotal = instance.subtotal tax_total = round(subtotal * Decimal(0.08),0) total = round(subtotal + tax_total,0) instance.tax_total = tax_total instance.total = total # instance.save pre_save.connect(do_tax_and_total_receiver, sender=Cart)
carts/views.py を編集
def get(self, request, *args, **kwargs): ... if request.is_ajax(): try: total = cart_item.line_item_total except: total = None try: subtotal = cart_item.cart.subtotal except: subtotal = None try: cart_total = cart_item.cart.total except: cart_total = None try: tax_total = cart_item.cart.tax_total except: tax_total = None try: total_items = cart_item.cart.items.count() except: total_items = 0 ... data = { "deleted": delete_item, "item_added": item_added, "line_total": total, "subtotal": subtotal, "cart_total": cart_total, "tax_total": tax_total, "flash_message": flash_message, "total_items": total_items, } return JsonResponse(data)
total, tax_totalを追記する。それをjsonデータとして渡す。
views.html
cartのviewに、消費税などを追記する。
<tr> <td id='subtotal' colspan='4' class='text-right'><span id='subtotal'>小計(税抜): {{ object.subtotal }}</span></td> </tr> <tr> <td colspan='4' class='text-right'>消費税: <span id='taxtotal'>{{ object.tax_total }}</span></td> </tr> <tr> <td colspan='4' class='text-right'>合計(税込): <span id='carttotal'>{{ object.total }}</span></td> </tr>
view.html のajaxを修正する。
$.ajax({ type: "GET", //"POST" url: "{% url 'cart' %}", data: data, success: function(data){ $("#jquery-message").text("Added " + data.item_added + " Deleted " + data.deleted); if (data.deleted){ $("#item-"+item).fadeOut(); $("#subtotal").text(data.subtotal); $("#taxtotal").text(data.tax_total); $("#carttotal").text(data.cart_total); } else { $("#item-line-total-"+item).text(data.line_total); $("#subtotal").text(data.subtotal); $("#taxtotal").text(data.tax_total); $("#carttotal").text(data.cart_total); } if (data.total_items == 0) { $(".table").fadeOut() var template = "{% include 'carts/empty_cart.html' %}"; $(".main-content").html(template); } var message = "" if ( data.item_added){ message = "新しいアイテムが追加されました" } else if ( data.deleted ){ message = "アイテムが削除されました" } else { message = "アイテムが更新されました" } showFlashMessage(message); updateCartItemCount(); }, error: function(response, error){ // console.log(response) // console.log(error) $("#add-form").submit() }, })
tax_percentageをcarts/models.py に追記
class Cart(models.Model): ... tax_percentage = models.DecimalField(max_digits=10, decimal_places=5, default=0.08) ...
それに伴い、do_tax_and_total_receiverの内容も少し修正。
def do_tax_and_total_receiver(sender, instance, *args, **kwargs): subtotal = instance.subtotal tax_total = round(subtotal * Decimal(instance.tax_percentage),0)
tax_percentageを変更するには??
carts/views.py で操作してみる。 試しに、cart idがnoneの時に、tax_percentageが変わるように設定。
class CartView(SingleObjectMixin, View): model = Cart template_name = "carts/view.html" #こっちは、singleObjectMixinのメソッド def get_object(self, *args, **kwargs): self.request.session.set_expiry(0) cart_id = self.request.session.get("cart_id") if cart_id == None: cart = Cart() cart.tax_percentage = 0.03
request.sessionなどの内容を通じて、taxrateなどを変更することも可能。