Django Product price calculation - django

Here I am having a product detail.
class product(models.Model):
Product_name = models.CharField(max_length=50, null=True)
product_description = models.TextField(max_length=170, null=True)
product_price = models.SmallIntegerField(null=True)
def __str__(self):
return self.Product_name
Depending on the product selection the value "30" has to change dynamically pending on the product. So that It will calculate price automatically. Please help me.
if form.is_valid():
user = form.save(commit=False)
products = form.cleaned_data['Product']
Quantity = form.cleaned_data['Quantity']
shoping_product = product.objects.filter(Product_name= products)
sub_total = 30 * Quantity
user.Gst = 30 * (1 + 0.18)
user.Price = sub_total + user.Gst
user.save()
messages.success(request, 'Registration successful.')
return redirect('home')

30 is the unit price of the product ?
shoping_product = product.objects.filter(Product_name= products).first()
sub_total = shoping_product.product_price * Quantity
user.Gst = shoping_product.product_price * (1 + 0.18)
user.Price = sub_total + user.Gst

Related

How can I update my Django model using signals?

How can I keep adding to the total price, when a new instance is created in the CartItem model and also deduct the price when an item is deleted ? , at the moment my current signals is only showing the price of the current product that I update or create.
signals.py
#receiver([post_save, post_delete], sender=CartItem, dispatch_uid="update_total")
def add_cart_receiver(sender, instance, *args, **kwargs):
total = 0
product_price = instance.item.price
quantity = instance.quantity
updated_total = Decimal(product_price) * int(quantity)
total += updated_total
if instance.items_cart.subtotal != total:
instance.items_cart.subtotal = total
instance.items_cart.save()
models.py
class CartItem(models.Model):
item = models.ForeignKey(Product, on_delete=models.CASCADE, blank=True, null=True)
items_cart = models.ForeignKey('Cart', blank=True, on_delete=models.CASCADE, null=True)
quantity = models.IntegerField(null=True, blank=True)
updated = models.DateTimeField(auto_now=True)
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return 'item:{} cart:{} quantity:{}'.format(self.item, self.items_cart, self.quantity)
class Cart(models.Model):
user = models.ForeignKey(User, null=True, blank=True, on_delete=models.CASCADE)
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, null=True)
def __str__(self):
return 'id:{} user:{} subtotal:{} total:{} updated:{}'.format(self.id, self.user, self.subtotal, self.total, self.updated)
views.py
def cart_add(request):
product_id = request.POST.get('product_id')
try:
product_obj = Product.objects.get(id=product_id)
quantity = request.POST.get('quantity_field')
cart_obj, new_obj = Cart.objects.new_or_get(request)
last_qty = CartItem.objects.filter(item=product_obj, items_cart=cart_obj).reverse()[0].delete()
new_qty = CartItem(item=product_obj, items_cart=cart_obj, quantity=quantity)
new_qty.save()
return redirect("cart:home")
except ValueError:
print("Unable to increase quantity")
return redirect("cart:home")
I figured out the problem I was having, below is my solution, to keep accumulating the total price of all items in my current cart, I have done this by looping over a Queryset of 'cart_items' and calculating the price * quantity, then adding it to a counter ('total'), then saving it to my 'Cart' model field 'total'. The receiver is collecting 'post_save' and 'post_delete' signals. Hopefully this will help someone else.
signals.py
#receiver([post_save,post_delete], sender=CartItem, dispatch_uid="update_total")
def add_cart_receiver(sender, instance, **kwargs):
cart = instance.items_cart.id
cart_items = CartItem.objects.filter(items_cart=cart)
cart_total = 0
for element in cart_items:
cart_total += (Decimal(element.item.price) * int(element.quantity))
instance.items_cart.subtotal = cart_total
instance.items_cart.save()

save with signals on same model on django

I would like to merge these methods on figure_1 so i can get the figure_2 and use signals to save the results on the same model. something is wrong so results are not saved on the model
figure_1 :
class Invoice(models.Model):
date = models.DateField(default=timezone.now)
amount_gtotal = models.DecimalField(max_digits=20, decimal_places=2, default=0)
amount_gtax = models.DecimalField(max_digits=20, decimal_places=2, default=0)
amount_gamount = models.DecimalField(max_digits=20, decimal_places=2, default=0)
def amount_gtotal(self):
items = self.invoiceitem_set.all()
amount_gtotal = 0.00
for item in items:
amount_gtotal += item.price * item.quantity
return amount_gtotal
def amount_gtax(self):
items = self.invoiceitem_set.all()
amount_gtax = 0
for item in items:
amount_gtax += item.price_sell * item.quantity * item.vat
return amount_gtax
def amount_gamount(self):
amount_gamount = self.amount_gtotal() + self.amount_gtax()
return amount_gamount
figure_2 :
def calculate(self):
invoiceitems = self.invoiceitem_set.all()
amount_gtotal = 0
amount_gtax = 0
amount_gamount = 0
for invoiceitem in invoiceitems:
amount_gtotal += item.price * item.quantity
amount_gtax += item.price_sell * item.quantity * item.vat
amount_gamount += amount_gtotal + amount_gtax
totals = {
'amount_gtotal': amount_gtotal,
'amount_gtax': amount_gtax,
'amount_gamount': amount_gamount,
}
for k,v in totals.items():
setattr(self, k, v)
if save == True:
self.save()
return totals
def invoice_pre_save(sender, instance, *args, **kwargs):
instance.calculate()
pre_save.connect(invoice_pre_save, sender=Invoice)
class InvoiceItem(models.Model):
invoice = models.ForeignKey('Invoice', on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.PROTECT)
price_sell = models.DecimalField(max_digits=20, decimal_places=2)
quantity = models.DecimalField(max_digits=20, decimal_places=2)
vat = models.DecimalField(max_digits=5, decimal_places=2)
I would like to merge these methods on figure_1 so i can get the figure_2 and use signals to save the results on the same model. something is wrong so results are not saved on the model
I think you need to pass in the calculate func a default parameter for save variable, like this:
def calculate(self, save=False):
Then in signal func you can pass again save, like this:
def invoice_pre_save(sender, instance, *args, **kwargs):
instance.calculate(save=False)
pre_save.connect(invoice_pre_save, sender=Order)
And now you should be able to call calulate(save=True)

Why add() method for m2m not working for single object - django

I am trying to add object to m2m with add method but neither its showing error nor adding item, I can't understand why
Here is my view :
class UpdateCartView(generic.UpdateView):
model = Cart
fields = ['products']
template_name = 'update_cart.html'
success_url = reverse_lazy('carts:home')
def form_valid(self,form):
product = ProductCreateModel.objects.get(pk = self.request.POST.get('product'))
size = Size.objects.get(pk = self.request.POST.get('size'))
colour = Colour.objects.get(pk = self.request.POST.get('colour'))
products = Products.objects.create(product = product,
size = size,
quantity = int(self.request.POST.get('quantity')),
colour = colour)
product.save()
cart = self.get_object()
print(products)
cart.products.add(products)
cart.save()
return super(UpdateCartView,self).form_valid(form)
def get_object(self):
cart_obj, cart_created = Cart.objects.new_or_get(self.request)
return cart_obj
Here is my models :
class Products(models.Model):
product = models.ForeignKey(ProductCreateModel,on_delete=models.CASCADE,related_name='cart_product')
quantity = models.PositiveIntegerField(default=1,validators=[MinValueValidator(1)])
size = models.ForeignKey(Size,related_name='cart_product_size',on_delete=models.CASCADE,null=True,blank=False)
colour = models.ForeignKey(Colour,related_name='cart_product_colour',on_delete=models.CASCADE,null=True,blank=False)
def __str__(self):
return '{product}({quantity})'.format(product=self.product,quantity=self.quantity)
class Cart(models.Model):
MESSAGE_CHOICES = (
('A' , 'Items are added to you cart'),
('R' , 'Items are removed from cart'),
('PC' , 'Price of some items has changed'),
)
messages = models.CharField(max_length=1, choices=MESSAGE_CHOICES,null=True,blank=True)
user = models.ForeignKey(User, null=True, blank=True, on_delete=models.CASCADE)
products = models.ManyToManyField(Products, 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':
products = instance.products.all()
total = 0
for x in products:
total += (x.product.final_price * x.quantity)
if instance.subtotal != total:
instance.subtotal = total
instance.save()
def pre_save_cart_receiver(sender, instance, *args, **kwargs):
if instance.subtotal > 0:
instance.total = Decimal(instance.subtotal) * Decimal(1.08) # 8% tax
else:
instance.total = 0.00
Everything is working fine, no errors, also print the products but in my admin panel its showing empty cart means cart.products.add(products) not added products why ?

Django queryset question

class Ticket(models.Model):
event = models.ForeignKey(Event)
name = models.CharField('Name', max_length=255)
price = models.FloatField('Price', blank=True)
class CartItem(models.Model):
cart = models.ForeignKey(Cart)
ticket = models.ForeignKey(Ticket)
quantity = models.IntegerField()
How do I get Ticket.price * CartItem.Quantity where event = event
You'll need to add error checking but you could do something like this logic-wise:
total = 0
cart_items = CartItem.objects.filter(ticket__event=event) # assuming there are multiple cart items per event
for cart_item in cart_items:
new_total = cart_item.ticket.price * cart_item.quantity
total = total + new_total
That should give you total revenue for an event.

Django inlineformset - custom save method

This is my models.py
class Invoices(models.Model):
...
sum_w_vat = models.DecimalField(max_digits=7, decimal_places=2, default=0)
sum_wo_vat = models.DecimalField(max_digits=7, decimal_places=2, default=0)
sum_discount = models.DecimalField(max_digits=7, decimal_places=2, default=0)
sum_vat = models.DecimalField(max_digits=7, decimal_places=2, default=0)
sum_paid = models.DecimalField(max_digits=7, decimal_places=2, default=0)
...
class InvoiceItems(models.Model):
invoice = models.ForeignKey(Invoices)
quantity = models.DecimalField(max_digits=9, decimal_places=2)
unit = models.ForeignKey(StocklistUnits, verbose_name='Merska enota')
price = models.DecimalField(max_digits=9, decimal_places=2)
vat = models.DecimalField(max_digits=4, decimal_places=3)
discount = models.DecimalField(max_digits=3, decimal_places=1)
def save(self, **kwargs):
self.invoice.sum_w_vat += (self.price * self.quantity * self.vat) * self.discount
self.invoice.sum_wo_vat += (self.price * self.quantity) * self.discount
self.invoice.sum_discount += (self.price * self.quantity) * ( self.discount / 100 )
self.invoice.sum_vat += ((self.price * self.quantity * self.vat) * self.discount) - ((self.price * self.quantity) * self.discount)
super(InvoicesItems, self).save(**kwargs)
I don't know how to save the calculated data in the InvoiceItems redefined save function... this obviously doesn't work, because Invoices get saved first...
views.py
def edit(request, id = None):
InvoiceFormSet = inlineformset_factory(Invoices, InvoicesItems)
if id == None:
initial_data = ''
data = Invoices()
else:
data = get_object_or_404(Invoices, pk=id)
initial_data = ''
if request.method == 'POST':
created_invoice = InvoicesForm(request.POST, instance=data)
form = InvoiceFormSet(request.POST, instance=data)
if not form.is_valid() and not created_invoice.is_valid():
//json err msg
else:
created_invoice.save()
form.save()
json = simplejson.dumps(response, ensure_ascii=False)
return HttpResponse(json, mimetype="application/json")
else:
form = InvoicesForm(instance=data, initial=initial_data)
form_items = InvoiceFormSet(instance=data)
c = {'form':form, 'form_items':form_items}
c.update(csrf(request))
return render_to_response('crud_invoice_edit.html', c)
How can I iterate through the InvoiceItems and calculate the field which then need to be inserted into Invoices. I'm new to django...
Thank you!
I don't know if this is the right way... but it works...
All I had to do was to save the created_invoice again... so
created_invoice.save()
form.save()
created_invoice.save()