2

I want to calculate the monthly based profit with the following models using django queryset methods.
The tricky point is that I have a freightselloverride field in the order table. It overrides the sum of freightsell in the orderItem table. An order may contain multiple orderItems. That's why I have to calculate order based profit first and then calculate the monthly based profit. Because if there is any order level freightselloverride data I should take this into consideration.

Below I gave a try using annotate method but could not resolve how to reach this SQL. Does Django allow this kind of nested aggregate queries?


select sales_month
    ,sum(sumSellPrice-sumNetPrice-sumFreighNet+coalesce(FreightSellOverride,sumFreightSell)) as profit
from
    (
    select CAST(DATE_FORMAT(b.CreateDate, '%Y-%m-01 00:00:00') AS DATETIME) AS `sales_month`,
        a.order_id,b.FreightSellOverride
        ,sum(SellPrice) as sumSellPrice,sum(NetPrice) as sumNetPrice
        ,sum(FreightNet) as sumFreighNet,sum(FreightSell) as sumFreightSell
    from OrderItem a
    inner join Order b
    on a.order_id=b.id
    group by 1,2,3
    ) c
group by sales_month

I tried this

result = (OrderItem.objects
        .annotate(sales_month=TruncMonth('order__CreateDate'))
        .values('sales_month','order','order__FreightSellOverride')
        .annotate(sumSellPrice=Sum('SellPrice'),sumNetPrice=Sum('NetPrice'),sumFreighNet=Sum('FreightNet'),sumFreightSell=Sum('FreightSell'))
        .values('sales_month')
        .annotate(profit=Sum(F('sumSellPrice')-F('sumNetPrice')-F('sumFreighNet')+Coalesce('order__FreightSellOverride','sumFreightSell')))
        )

but get this error

Exception Type: FieldError
Exception Value:    
Cannot compute Sum('<CombinedExpression: F(sumSellPrice) - F(sumNetPrice) - F(sumFreighNet) + Coalesce(F(ProjectId__FreightSellOverride), F(sumFreightSell))>'): '<CombinedExpression: F(sumSellPrice) - F(sumNetPrice) - F(sumFreighNet) + Coalesce(F(ProjectId__FreightSellOverride), F(sumFreightSell))>' is an aggregate
from django.db import models
from django.db.models import F, Count, Sum
from django.db.models.functions import TruncMonth, Coalesce

class Order(models.Model):
    CreateDate = models.DateTimeField(verbose_name="Create Date")
    FreightSellOverride = models.FloatField()

class OrderItem(models.Model):
    SellPrice = models.DecimalField(max_digits=10,decimal_places=2)
    FreightSell = models.DecimalField(max_digits=10,decimal_places=2)
    NetPrice = models.DecimalField(max_digits=10,decimal_places=2)
    FreightNet = models.DecimalField(max_digits=10,decimal_places=2)
    order = models.ForeignKey(Order,on_delete=models.DO_NOTHING,related_name="Item")

Ozzy Black
  • 53
  • 6
  • Do you test this code? You can test `annotate(profit=Sum(F('SellPrice')-F('NetPrice')-F('FreightNet')+Coalesce('FreightSell', 'order__FreightSellOverride'))` – mrash Oct 23 '21 at 03:12
  • 1
    Thanks @mrash but an order may contain more than one item. That's why I have to aggregate order based firstly, after that coalesce will come up. – Ozzy Black Oct 23 '21 at 14:04

0 Answers0