У меня есть два запроса, и оба дают мне правильный результат.
Я попытался объединить их, но затем результаты получаются неправильными (числа умножаются).
qs2 = Customer.objects.filter(
opportunity__turnover__date__range=[start, end]
).annotate(
month=TruncMonth('opportunity__turnover__date')
).annotate(
turnover=Sum(
"opportunity__turnover__value",
filter=(
Q(opportunity__turnover__type='Project')
)
),
).order_by(
'name','month'
).values('name','month','turnover')
qs = Customer.objects.filter(
project__worklog__day__range=[start, end]
).annotate(
month=TruncMonth('project__worklog__day')
).annotate(
hours=Sum("project__worklog__effort")/60/60,
hoursBilled=Sum(
"project__worklog__effort",
filter=(
Q(project__worklog__account__category='Abrechenbar')
| Q(project__worklog__account__category='Billable')
)
)/60/60,
).order_by(
'name','month'
).values('name','hours','month','hoursBilled')
df = pd.DataFrame(list(qs2)).merge(pd.DataFrame(list(qs)))
В настоящее время я преобразовываю оба результата в пазы данных Pandas и объединяю их - чтоработает, но не хорошо, так как мне не нужно, чтобы это был фрейм данных.
Соответствующие модели выглядят так:
class Opportunity(models.Model):
id = models.IntegerField(primary_key=True) #CRMID
customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
probability = models.FloatField(null=True, blank=True, default=None)
closeDate = models.DateField(null=True, blank=True, default=None)
duration = models.IntegerField()
value = models.FloatField(null=True, blank=True, default=None)
name = models.CharField(max_length=200, null=False, blank=False)
type = models.CharField(max_length=100, null=True, blank=True)
class Turnover(models.Model):
opportunity = models.ForeignKey(Opportunity, on_delete=models.CASCADE)
type = models.CharField(max_length=100)
date = models.DateField(null=True, blank=True, default=None)
value = models.FloatField(null=True, blank=True, default=None)
class Worklog(models.Model):
worker = models.ForeignKey(Person, on_delete=models.CASCADE)
day = models.DateField(null=True, blank=True, default=None)
effort = models.FloatField() #timeSpentSeconds
account = models.ForeignKey(Account, on_delete=models.CASCADE, null=True, blank=True)
comment = models.TextField(null=True)
project = models.ForeignKey(Project, on_delete=models.CASCADE)
issue = models.CharField(max_length=200)
class Project(models.Model):
key = models.CharField(max_length=200, primary_key=True)
name = models.CharField(max_length=200, null=False, blank=False)
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, null=True) #this has to come via project category description field
class Customer(models.Model):
id = models.IntegerField(primary_key=True) #CRMID
name = models.CharField(max_length=200, null=True, blank=True, default=None)
Это мое текущее состояние наличия всего в одном наборе запросов:
qs3 = Customer.objects.filter(
Q(project__worklog__day__range=[start, end])
| Q(opportunity__turnover__date__range=[start, end])
).annotate(
month=TruncMonth('project__worklog__day'),
monthOpp=TruncMonth('opportunity__turnover__date')
).filter(
month=F('monthOpp')
).annotate(
turnover=Sum(
"opportunity__turnover__value",
filter=(
Q(opportunity__turnover__type='Project')
)
),
hours=Sum("project__worklog__effort")/60/60,
hoursBilled=Sum(
"project__worklog__effort",
filter=(
Q(project__worklog__account__category='Abrechenbar')
| Q(project__worklog__account__category='Billable')
)
)/60/60,
).order_by(
'name','month'
).values('name','hours','month','hoursBilled','turnover')
Я получаю следующий результат:
hours hoursBilled month name turnover
0 1640.00 1415.00 2019-01-01 Customer Number ONE 5094288.00
1 1581.67 1482.92 2019-02-01 Customer Number ONE 5801496.00
2 1117.50 1042.50 2019-03-01 Customer Number ONE 2226822.72
3 911.67 557.92 2019-04-01 Customer Number ONE 1395000.00
4 20749.22 14487.72 2019-01-01 Customer The Second 128129544.48
5 15762.83 14163.33 2019-02-01 Customer The Second 194805059.94
6 15550.50 12145.00 2019-03-01 Customer The Second 79077900.00
7 525.00 525.00 2019-04-01 Customer The Second 190400.00
, но ожидаю этого результата:
hours hoursBilled month name turnover
0 328.00 283.00 2019-01-01 Customer Number ONE 33961.92
1 316.33 296.58 2019-02-01 Customer Number ONE 35592.00
2 223.50 208.50 2019-03-01 Customer Number ONE 25020.48
3 182.33 111.58 2019-04-01 Customer Number ONE 15500.00
4 1482.09 1034.84 2019-01-01 Customer The Second 99479.46
5 1125.92 1011.67 2019-02-01 Customer The Second 248793.18
6 1110.75 867.50 2019-03-01 Customer The Second 102300.00
7 37.50 37.50 2019-04-01 Customer The Second 5440.00
Задача состоит в том, чтобы рассмотреть две даты:
project__worklog__day
и opportunity__turnover__date
Ожидаемый результат - список всех клиентов с соответствующей суммой рабочих журналов в месяц иОборот за месяц.
Идеально заполняет «пропущенный» месяц, так что есть для каждого клиента, например, январь, февраль, мар, апрель, хотя у клиента нет ни оборота, ни рабочих журналов в феврале и марте - однакомои текущие запросы также пока не делают этого.
Спасибо!