Django, how to get total sum of methods with agregate sum - django

how to get total sum of methods in django using agregate ? I used this for fields and it work fine but for method it doesn t return anything.
class Invoice(models.Model):
date = models.DateField(default=timezone.now)
client = models.ForeignKey('Client',on_delete=models.PROTECT)
def total(self):
total = self.invoiceitem_set.aggregate(sum=Sum('subtotal'))
return round(total[("sum")] or 0, 2)
class InvoiceItem(models.Model):
invoice = models.ForeignKey('Invoice', on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.PROTECT)
price = models.DecimalField(max_digits=20, decimal_places=2)
quantity = models.DecimalField(max_digits=20, decimal_places=2)
def subtotal(self):
return self.price * self.quantity

You can not reference a method, since the database does not know anything about subtotal. You thus should work with F objects [Django-doc] to multiply the price with the quantity:
from django.db.models import F
class Invoice(models.Model):
date = models.DateField(default=timezone.now)
client = models.ForeignKey('Client',on_delete=models.PROTECT)
def total(self):
return round(self.invoiceitem_set.aggregate(
sum=Sum(F('price') * F('quantity'))
)['sum'] or 0, 2)
With an F object, you refer to a field with that name.

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")))
)

Get value from django field and change it dynamically

I have created two models with two fields which are quantity and quantity_given, so I want to change the value of quantity field by adding the value of quantity + quantity given. For example
if quantity = 4 and quantity_given = 8
therefore the new value of quantity field will be 12.
Here are the source code for my models
class Stock(models.Model):
`name = models.CharField(max_length=30)`
def __str__(self):
return self.name
class Medicine(models.Model):
stock = models.ForeignKey(Stock, on_delete=models.CASCADE)
name = models.CharField(max_length=30)
quantity = models.IntegerField()
def __str__(self):
return self.name
class MedicineGiven(models.Model):
medicine = models.ForeignKey(Medicine, on_delete=models.CASCADE)
quantity_given = models.IntegerField()
You can have a method in MedicineGiven, like:
class MedicineGiven(models.Model):
medicine = models.ForeignKey(Medicine, on_delete=models.CASCADE)
quantity_given = models.IntegerField()
#property
def quantity(self):
return self.quantity_given + int(self.medicine.quantity)
In your views, you can get quantity of MedicineGiven like:
medicine_given = MedicineGiven.objects.get(pk=id) # Just a example code
medicine_given.quantity
EDIT
If you want to save the quantity in database, then you can override save() method:
class MedicineGiven(models.Model):
medicine = models.ForeignKey(Medicine, on_delete=models.CASCADE)
quantity_given = models.IntegerField()
def save(self, *args, **kwargs):
quantity = self.quantity_given + int(self.medicine.quantity)
self.medicine.quantity = quantity
self.medicine.save()
super().save(*args, **kwargs)

Sum and store values in another table

I am new to Django. My query is
I store some quantity of components in a table. I want to sum the quantity sorting it by components and then use the summed quantity in some other table to do further calculations. How can I achieve this..
#views.py
class PurchaseCreateView(CreateView):
model = Purchase
fields = '__all__'
success_url = reverse_lazy("purchase_form")
def get_context_data(self,**kwargs):
context = super().get_context_data(**kwargs)
context['purchases'] = Purchase.objects.all()
return context
#models.py
class Purchase(models.Model):
purchase_date = models.DateField()
invoice_no = models.CharField(max_length=200,unique=True)
supplier =models.ForeignKey(Supplier,on_delete=models.CASCADE)
components = models.ForeignKey(Components,on_delete=models.CASCADE)
quantity = models.PositiveIntegerField()
remarks = models.TextField(max_length=500,blank=True,null=True)
def __str__(self):
return str(self.pk)
# Below is the Model where I want to use the summed quantity for further calc
class IntermediateStage(models.Model):
producttype = models.ForeignKey(ProductType,on_delete=models.CASCADE)
components = models.ForeignKey(Components,on_delete=models.CASCADE)
processingstage = models.ForeignKey(ProcessingStage,on_delete=models.CASCADE)
unitsrequired = models.PositiveIntegerField()
quantity = models.PositiveIntegerField(blank = True)**#want to store summed qty here**
total_quantity = models.IntegerField(blank= True)
class Meta:
unique_together = [['producttype','components','processingstage']]
def __str__(self):
return str(self.id)
#Components Model
class Components(models.Model):
name = models.CharField(max_length=100,unique=True)
producttype = models.ManyToManyField(ProductType, through='IntermediateStage')
def __str__(self):
return self.name

Django Aggregation: Summation of Multiplication of two fields with ForienKey

I have two model as below
class Product(models.Model):
title = models.CharField(max_length=128)
slug = models.SlugField()
price = models.DecimalField(default=0.0,decimal_places=2,max_digits=15,validators=[MinValueValidator(Decimal('0.00'))])
def __str__(self):
return str(self.title)
class OrderItem(models.Model):
product = models.ForeignKey(Product,on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
def __str__(self):
return f"{self.quantity} of {self.product.title}"
def subtotal(self):
return self.quantity * self.product.price
I want the total of all subtotal using aggregate but
total1 = OrderItem.objects.all().aggregate(total=Sum(F('product.price') * F('quantity')))['total']
returns Cannot resolve keyword 'product.price' into field. Choices are: id, order, product, product_id, quantity and
total2 = OrderItem.objects.all().aggregate(total=Sum(F('subtotal') * F('quantity')))['total']
returns Cannot resolve keyword 'subtotal' into field. Choices are: id, order, product, product_id, quantity, error
After some research I found that
from django.db.models import Sum, F
total = OrderItem.objects.all().aggregate(total=Sum(F('product__price') * F('quantity')))['total']
will do the work

Difference between two Foreign key model fields

I have a model named 'CarAdd', and two other models are connected with a foreign key to this CarAdd model that are ShippingDetails, MaintenanceDetails. and each foreign key model has an item and price field." foreign key have more than 2 items under one id"
I need to find the profit amount of each car
profit = sold_amount - (purchased amount + total shipping cost + total maintenance cost)
class CarAdd(models.Model):
# Car Details
name = models.CharField(max_length=60)
purchased_amount = models.DecimalField()
# there 3 choices in STATUS shipped, maintenance, sold
status = models.CharField(max_length=12, choices=STATUS)
sold_amount = models.DecimalField(max_digits=15, decimal_places=1)
profit_amount = models.DecimalField(max_digits=15, decimal_places=1)
def save(self, *args, **kwargs):
if self.status == 'sold':
sum_invested = self.purchased_amount + ShippingDetails.price + MaintenanceDetails.price
profit = self.sold_amount - sum_invested
self.profit_amount = profit
super().save(*args, **kwargs)
class ShippingDetails(models.Model):
car = models.ForeignKey(CarAdd, related_name='shipping_details', on_delete=models.CASCADE)
item = models.CharField(max_length=60)
price = models.DecimalField(max_digits=15, decimal_places=1,)
class MaintenanceDetails(models.Model):
car = models.ForeignKey(CarAdd, related_name='maintenance_details', on_delete=models.CASCADE)
item = models.CharField(max_length=60)
price = models.DecimalField(max_digits=15, decimal_places=1)
how do I calculate the profit amount if status is 'sold' and save to profit_amount field
You need to aggregate on the related models:
from django.db.models import Sum
from django.db.models.functions import Coalesce
sum_invested = self.purchased_amount
+ self.shipping_details.aggregate(total_price=Coalesce(Sum('price'), 0))['total_price']
+ self.maintenance_details.aggregate(total_price=Coalesce(Sum('price'), 0))['total_price']