I'm really struggling to update the quantity of the jewelry. My project is a e-commerce site which sells jewelry for online customers. When a customer buys jewelry, the jewelry quantity should be updated automatically. As a Example -> 10 Rings available and 2 are bought, the db should be updated as 8 remaining. But if the Ring goes below 0 then a warning should appear "Out of stock".

Inventory/models.py

class jType(models.Model):
    jtype=models.CharField(max_length=100)

    def __str__(self):
       return format(self.jtype)

class jewelry(models.Model):

    category = models.ForeignKey(jType, on_delete=models.CASCADE, null=True)
    slug = models.SlugField(blank=True, unique=True)
    date = models.DateField(default=datetime.now, blank=True)
    description = models.CharField(max_length=500, blank=True)
    charges = models.FloatField()
    stoneType = models.ForeignKey(stone, on_delete=models.CASCADE, null=True)
    NoOfStones = models.IntegerField()
    weight = models.FloatField()
    quantity = models.IntegerField()
    craftsman_id = models.ForeignKey(craftsmen, on_delete=models.CASCADE, null=True)

    choices = (
      ('AVAILABLE', 'Item ready to be purchased'),
      ('SOLD', 'Item Sold'),
      ('RESTOCKING', 'Item restocking in few days')
    )
    status = models.CharField(max_length=10, choices=choices, default="AVAILABLE")
    issues = models.CharField(max_length=100, default="No issues")
    image = models.ImageField(upload_to='jewelry_image/', null=True, blank=True)

    @property
    def net_price(self):
       return self.charges * 50

    @property
       def total_net_price(self):
       return self.quantity *  self.net_price

    def get_absolute_url(self):
       return "/products/list/{slug}/".format(slug=self.slug)

    def buy_item(self, q):
       # decrease quantity
       self.quantity -= q


    def __str__(self):
       return 'cat : {0} charges : {1}'.format(self.category, self.charges)

def jewelry_presave_receiver(sender, instance, *args, **kwargs):
  if not instance.slug:
      instance.slug = unique_slug_generator(instance)
pre_save.connect(jewelry_presave_receiver, sender=jewelry)

Carts/models.py

from inventory.models import jewelry
User = settings.AUTH_USER_MODEL

class CartManager(models.Manager):
    def new_or_get(self, request):
        cart_id = request.session.get("cart_id", None)
        qs = self.get_queryset().filter(id=cart_id)
        if qs.count() == 1:
            new_obj = False
            cart_obj = qs.first()
            if request.user.is_authenticated and cart_obj.user is None:
                cart_obj.user = request.user
                cart_obj.save()
        else:
            cart_obj = Cart.objects.new(user=request.user)
            new_obj = True
            request.session['cart_id'] = cart_obj.id
        return cart_obj, new_obj

    def new(self, user=None):
        user_obj = None
        if user is not None:
            if user.is_authenticated:
                user_obj = user
        return self.model.objects.create(user=user_obj)

class Cart(models.Model):
    user = models.ForeignKey(User, null=True, blank=True, on_delete=models.PROTECT)
    jewelries = models.ManyToManyField(jewelry, blank=True)
    subtotal = models.DecimalField(default=0.00, max_digits=100, decimal_places=2)
    total = models.DecimalField(default=0.00, max_digits=100, decimal_places=2)
    updated = models.DateTimeField(auto_now=True)
    timestamp = models.DateTimeField(auto_now_add=True)

    objects = CartManager()

    def __str__(self):
        return str(self.id)


def m2m_changed_cart_receiver(sender, instance, action, *args, **kwargs):
    if action == 'post_add' or action == 'post_remove' or action == 'post_clear':
        jewelries = instance.jewelries.all()
        total = 0
        for x in jewelries:
            total += x.net_price

        if instance.subtotal != total:
            instance.subtotal = total
            instance.save()


m2m_changed.connect(m2m_changed_cart_receiver, sender=Cart.jewelries.through)


def pre_save_cart_receiver(sender, instance, *args, **kwargs):
    if instance.subtotal > 0:
        instance.total = instance.subtotal + 10
    else:
        instance.total = 0.00


pre_save.connect(pre_save_cart_receiver, sender=Cart)

Carts/views.py

from django.http import JsonResponse
from django.shortcuts import render, redirect
from inventory.models import jewelry
from .models import Cart
from order.models import Order
from billing.models import BillingProfile
from addresses.models import Address
from accounts.forms import LoginForm, GuestForm
from accounts.models import GuestEmail
from addresses.forms import AddressForm
from delivery.forms import DeliveryAddressForm

def cart_detail_api_view(request):
    cart_obj, new_obj = Cart.objects.new_or_get(request)
    products = [{"name": x.category, "price": x.charges} for x in cart_obj.jewelries.all()]
    cart_data = {"subtotal": cart_obj.subtotal, "total": cart_obj.total, }
    return JsonResponse(cart_data)


def cart_home(request):
    cart_obj, new_obj = Cart.objects.new_or_get(request)
    return render(request, 'cart/home.html', {"cart": cart_obj})


def cart_update(request):
    product_id = request.POST.get('product_id')
    if product_id is not None:
        try:
            product_obj = jewelry.objects.get(id=product_id)
        except jewelry.DoesNotExist:
            print("Show message to user, product is gone")
            return redirect("home")
        cart_obj, new_obj = Cart.objects.new_or_get(request)
        if product_obj in cart_obj.jewelries.all():
            cart_obj.jewelries.remove(product_obj)
            added = False
        else:
            cart_obj.jewelries.add(product_obj)
            added = True
        request.session['cart_items'] = cart_obj.jewelries.count()
        if request.is_ajax():#Asynchronus javascript and xml / json
            print("Ajax request")
            json_data = {
                "added": added,
                "removed": not added,
                "cartItemCount": cart_obj.jewelries.count(),
            }
            return JsonResponse(json_data)
    return redirect("home")

def checkout_home(request):
    cart_obj, cart_created = Cart.objects.new_or_get(request)
    order_obj = None
    if cart_created or cart_obj.jewelries.count() == 0:
        return redirect("home")
    login_form = LoginForm()
    guest_form = GuestForm()
    address_form = AddressForm()
    delivery_address_form = DeliveryAddressForm()
    billing_address_id = request.session.get("billing_address_id", None)
    delivering_address_id = request.session.get("delivering_address_id", None)
    delivering_address = request.session.get("delivering_address")

    billing_profile, billing_profile_created = BillingProfile.objects.new_or_get(request)
    if billing_profile is not None:
        order_obj, order_obj_created = Order.objects.new_or_get(billing_profile, cart_obj)
        if delivering_address_id:
            order_obj.delivering_address = delivering_address
            del request.session["delivering_address_id"]
            order_obj.save()
        if billing_address_id:
            order_obj.billing_address = Address.objects.get(id=billing_address_id)
            del request.session["billing_address_id"]
        if billing_address_id or delivering_address_id:
            order_obj.save()

    if request.method == "POST":
        if order_obj.delivering_address:
            pass
        else:
            order_obj.assign_delivering_address_to_none()
        "Check that order is done"
        is_done = order_obj.check_done()
        if is_done:
            # TODO: decrease inventory
            # jewelry.objects.get().buy_item(value)
            order_obj.mark_paid()
            request.session['cart_items'] = 0
            del request.session['cart_id']
            print(request.session.get("cart_items"))
            return redirect("success")
        else:
            print("is done is returning False")

    context = {
        "object": order_obj,
        "billing_profile": billing_profile,
        "login_form": login_form,
        "guest_form": guest_form,
        "address_form": address_form,
        "delivery_address_form": delivery_address_form,
    }
    return render(request, "order/checkout.html", context)


def checkout_done_view(request):
    return render(request, 'cart/checkout-done.html', {})

0 Answers