F expression conjunction with Sum() is not working as expected - django

class Order(models.Model):
pass
class OrderItems(models.Model):
order = models.ForiegnKey(Order, related_name="items")
name = models.CharField(max_length=255, null=False)
quantity = models.DecimalField(max_digits=5, decimal_places=2)
supplier = models.CharField(max_length=255, null=False)
purchase_price = models.DecimalField(max_digits=10, decimal_places=2)
trade_price = models.DecimalField(max_digits=10, decimal_places=2,blank=False, null=False , default = 0.00)
retail_price = models.DecimalField(max_digits=10, decimal_places=2)
class OrderItemSalesTax(models.Model):
order_item = models.ForiegnKey(OrderItems, related_name="sales_tax")
name = models.CharField(max_length=255)
percentage = models.DecimalField(max_digits=6, decimal_places=2)
class OrderItemDiscount(models.Model):
order_item = models.OneToOneField(OrderItem, primary_key=True, on_delete=models.CASCADE, related_name='discount')
name = models.CharField(max_length=255)
discount = models.DecimalField(max_digits=6, decimal_places=2)
in_percentage = models.BooleanField()
I am using this query to calculate the total amount, but also deducting discount and adding Sales tax.
Sum(F('items__sales_tax__percentage')) value is 25, and I have verified it, querying the database. Right now I have only One order and two Items and Items have two Sales Taxes and One Discount
I am trying to Sum the Sales taxes to apply on discounted price, but I am getting the wrong result results. If I manually write 25 by replacing Sum(F('items__sales_tax__percentage')) then results are correct, is there anything wrong with my query ?
Order.objects.filter(customer__zone__distribution=get_user_distribution(request.user.id))\
.annotate(
trade_price=Sum(F('items__trade_price') * F('items__quantity')),
tax = Sum(F('items__sales_tax__percentage')),
discounted_price = F('trade_price') * ExpressionWrapper(0.01 * (100 - Sum(F('items__discount__discount'))), output_field=DecimalField()),
total = F('discounted_price') + F('discounted_price') * Sum(F('items__sales_tax__percentage')) / 100
)

Related

Join two models and group with SUM in Django

I have two model name ProductDetails and InventorySummary. I want to join this two model and wants to group with product name and SUM product quantity. The quantity should be multiplication with product price. My models are given bellow:
class ProductDetails(models.Model):
id = models.AutoField(primary_key=True)
product_name = models.CharField(max_length=100, unique=True)
purchase_price = models.DecimalField(max_digits=7, decimal_places=2)
dealer_price = models.DecimalField(max_digits=7, decimal_places=2)
retail_price = models.DecimalField(max_digits=7, decimal_places=2)
remarks = models.CharField(max_length=255, blank=True)
def __str__(self):
return self.product_name
class InventorySummary(models.Model):
id = models.AutoField(primary_key=True)
date = models.DateField(default=date.today)
product_name = models.ForeignKey(ProductDetails, on_delete=models.CASCADE)
quantity = models.IntegerField()
def __str__(self):
return str(self.product_name)
My views are given bellow:
def stockPrice(request):
stock = InventorySummary.objects.select_related('product_name').
values('product_name').annotate(quantity=Sum('quantity'))
return render(request, 'inventory_price.html', {'stock': stock})
I can achieve this with the F expression. I'm not sure what you refer to by "product price", so I took purchase_price:
from django.db.models import Sum, F
stock = (
InventorySummary.objects.values("product_name__product_name")
.order_by("product_name__product_name")
.annotate(quantity=Sum(F("product_name__purchase_price") * F("quantity")))
)

Calculate the sum and multiply with the quantity to get the total in django

I have the code which calculates the sum just fine, now my question is it possible to multiple each price by quantity and then get the total sum after that in a cart on my website. I have tried with all of my logic but i have failed. The idea is to get the price of an item added to cart and multiply it by quantity and then get the total.
Here is my cart mode. models.py:
#cart model
class Cart(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE)
number_of_items = models.IntegerField(default=0)
user = models.ForeignKey(User, on_delete=models.CASCADE)
added_datetime = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.item.name
#Item model
class Item(models.Model):
CONDITION = (
('new', 'new'),
('used', 'used'),
('not applicable', 'not applicable'),
)
name = models.CharField(max_length=250)
owner = models.CharField(max_length=250, default='Ludocs-emark')
category = models.ForeignKey(ItemCategories, on_delete=models.CASCADE)
sub_category = models.ForeignKey(SubCategory, on_delete=models.CASCADE)
tag = models.ForeignKey(Tag, on_delete=models.CASCADE)
Condition = models.CharField(max_length=250, null=True, choices=CONDITION)
price= models.IntegerField(default=0)
number_of_items = models.IntegerField(blank=True)
specification_one = models.CharField(max_length=250, blank=True)
specification_two = models.CharField(max_length=250, blank=True)
specification_three = models.CharField(max_length=250, blank=True)
specification_four = models.CharField(max_length=250, blank=True)
specification_five = models.CharField(max_length=250, blank=True)
specification_six = models.CharField(max_length=250, blank=True)
available_colors = models.CharField(max_length=250, blank=True)
description = RichTextField()
thumbnail = models.ImageField(default='default.png', upload_to='images/')
image_one = models.ImageField(upload_to='images/')
image_two = models.ImageField(upload_to='images/')
image_three = models.ImageField(upload_to='images/')
image_four = models.ImageField(upload_to='images/')
added_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
views.py file that i used to calculate the sum:
#This is the file where that i want to use to get the items added in cart and then multiply each by it's quantity and then get the total of the calculations when multiplied.
cart_sum = Cart.objects.filter(user=request.user).aggregate(Sum('item__price')).get('item__price__sum')
Yes, You can do that.
Try this
cart_sum = Cart.objects.filter(user=request.user).aggregate(Sum('item__price', field='item__price * number_of_items')).get('item__price__sum')
Assuming number_of_items as the quantity for the item from the Cart model.
Also you can return a total value so that if this gives any error for two different fields then you can do this
cart_sum = Cart.objects.filter(user=request.user).aggregate(total_price=Sum('item__price', field='item__price * number_of_items')).get('total_price')

Calculate percentage In Django Database Query

I am trying to calculate the total cost of all the services with taxes in the bill using a single query. I don't understand where I am going wrong.
MODELS:
class Bill(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
number = models.CharField(max_length=100, blank=True)
class BillService(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
bill = models.ForeignKey(Bill, related_name='billservices', on_delete=models.CASCADE)
service = models.ForeignKey(Service, on_delete=models.CASCADE)
class Service(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
business = models.ForeignKey(Business, related_name='services', on_delete=models.CASCADE, blank=True)
short_code = models.IntegerField(default=0)
class ServiceTax(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
service = models.ForeignKey(Service, on_delete=models.CASCADE, related_name="servicetaxes")
tax = models.ForeignKey(Tax, on_delete=models.CASCADE)
class Tax(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
business = models.ForeignKey(Business, related_name='taxes', on_delete=models.CASCADE)
name = models.CharField(max_length=50)
tax = models.FloatField(validators=[MinValueValidator(0), MaxValueValidator(100)], default=0)
MY QUERY TO GET A SINGLE VALUE, THAT IS TOTAL COST OF THE BILL
value = bill.billservices.all()
.annotate(sum_of_taxed_percentages=Subquery(
Service.objects.filter(billservice=OuterRef('id'))
.annotate(total_tax_value=Subquery(
ServiceTax.objects.filter(service=OuterRef('id'))
.values('tax')
.annotate(total_tax=Sum('tax__tax', output_field=FloatField()))
.values('total_tax')
)).annotate(taxed_value=F('price') + ((F('price') * F('total_tax_value')) / 100))
.values('taxed_value')
.annotate(total_services_taxed_value=Sum('taxed_value', output_field=FloatField()))
.values('total_services_taxed_value')
))
print(value[0].sum_of_taxed_percentages)
ERROR:
'ManyToOneRel' object has no attribute 'select_format'
If this is where you're calculating the percentage:
taxed_value=F('price') + ((F('price') * F('total_tax_value')) / 100)
on this trench:
((F('price') * F('total_tax_value')) / 100
i think you need to change some parentheses:
(F('price') * (F('total_tax_value') / 100))
because you first need to divide the percentage you have stored to 100 and then you multiply that by the price of the object to then sum to the current value of it:
taxed_value=F('price') + (F('price') * (F('total_tax_value') / 100))
Check if it works, i'm not sure, it seems that is a simple formula problem...
After many trial and errors, I found the solution.
service_tax = ServiceTax.objects.filter(service=OuterRef('service')) \
.values('tax__tax')
value = bill.billservices.all() \
.annotate(service_taxes=SQSum(service_tax)) \
.annotate(service_price=F('service__price')) \
.aggregate(total=Sum(F('service_price') + ((F('service_price') * F('service_taxes')) / 100),
output_field=FloatField()))
print(value)
class SQSum(Subquery):
template = "(SELECT SUM(tax) FROM (%(subquery)s) _sum)"
output_field = models.FloatField()

how to sum all the consummations?

I already calculate, the total of one consummation, now i just want to sum all the consumations
class Consommation(models.Model):
food = models.ManyToManyField(Food)
consomme_le = models.DateTimeField(default=timezone.now, editable=False)
vipcustomer = models.ForeignKey(VipCustomer, models.CASCADE, null=True,
blank=True, verbose_name='Client prestigieux',
related_name='vip_consommations')
to calculate one consummation:
def total(self):
return self.food.aggregate(total=Sum('price'))['total']
Food class :
class Food(models.Model):
nom = models.CharField(max_length=100, verbose_name='Mon menu')
price = models.PositiveIntegerField(verbose_name='Prix')
category = models.ForeignKey(FoodCategory, models.CASCADE,
verbose_name="Categorie")
vipcustomer class:
class VipCustomer(models.Model):
first_name = models.CharField(max_length=150, verbose_name='Prénom')
last_name = models.CharField(max_length=100, verbose_name='Nom')
matricule = models.PositiveIntegerField(verbose_name='Matricule',
default=0)
adresse = models.CharField(max_length=200, verbose_name='Adresse',
blank=True)
telephone = PhoneField()
company = models.CharField(max_length=100, verbose_name='La société')
service = models.CharField(max_length=100, verbose_name='Service',
null=True, blank=True)
numero_badge = models.IntegerField(verbose_name='Numero du badge',
null=True, blank=True)
My goal is to calculate the total of all the consummations.
For a given VipCustomers, you can query with:
my_vip_customer.vip_consommations.aggregate(
total=Sum('food__price')
)['total']
We thus aggregate over the set of related Consommations, and we then aggregate over all the related Foods of these Consommations, and their corresponding price.
If there are no related Consommations, or no related Foods of these Consommations, then the sum will return None, instead of 0. We can add or 0 to convert a None to an 0 here:
my_vip_customer.vip_consommations.aggregate(
total=Sum('food__price')
)['total'] or 0
or for all Customers, we can annotate this with:
VipCustomer.objects.annotate(
total=Sum('vip_consommations__food__price')
)
Here the VipCustomers that arise from this, will have an extra attribute .total that contains the sum of the prices of the related Foods of the related Consommations.

django queryset aggregate multiple operations fields

model.py
class Fatture(models.Model):
numero = models.CharField(max_length=30, null=True, blank=True)
data = models.DateField()
iva = models.PositiveIntegerField()
commissione = models.DecimalField(max_digits=6, decimal_places=2, null=True, blank=True)
class Ddts(models.Model):
fattura = models.ForeignKey('Fatture')
class DdtsArticoli(models.Model):
ddt = models.ForeignKey('Ddts')
articolo = models.ForeignKey('Articoli')
quantita = models.DecimalField(max_digits=6, decimal_places=2)
prezzo = models.DecimalField(max_digits=6, decimal_places=2, null=True, blank=True)
colli = models.PositiveIntegerField()
I have to make a query that calculate this total:
aggregate table DdtsArticoli SUM(quantita * prezzo)
aggregate table DdtsArticoli ((quantita * prezzo) / (1 + (iva of table
Fatture)/100 ))
resut of 1) - result of 2)
See the Django docs on aggregation for detail but 1. should be something like:
from django.db.models import Sum
DdtsArticoli.objects.all().aggregate(
your_key=Sum(F('quantita') * F('prezzo'), output_field=FloatField()))
Number 2. is no aggragation, you can simply calculate it:
(obj.quantita * obj.prezzo) / (1 + (obj.ddt.fattura.iva/100.0))
Where obj is your object aka. your database row.
Number 3. should be trivial then.