Djangoroidの奮闘記

python,django,angularJS1~三十路過ぎたプログラマーの奮闘記

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などを変更することも可能。