Как выполнить вычисление в Django ORM по подмодели
Я пытаюсь понять, как получить определенным клиентам процентную долю дохода, который может быть разделен между несколькими владельцами или поделен поровну. Модели (упрощенные) следующие:
class Client(Model):
...
class Loan(Model):
applicants = ManyToManyField(Client)
class Income(Model):
loan = ForeignKey(Loan)
amount = DecimalField()
income_type = CharField(choices=['INVESTMENT', ...])
proportions = CharField(default='EQUAL', choices=['EQUAL', 'SPECIFIED'])
class IncomeOwner(Model):
income = ForeignKey(Income, related_name='owners')
client = ForeignKey(Client)
percent = DecimalField()
На основе этих моделей я пытаюсь рассчитать доли дохода по категориям для заданной комбинации клиент/кредит. Важно отметить, что отношение владельцев имеет значение только в том случае, если пропорции 'SPECIFIED' - в противном случае все заявители имеют равные доли. По соображениям производительности я пытаюсь сохранить логику в ORM:
def get_income(loan, client):
# This income can be associated with multiple applicants as follows:
# - If the "proportions" are "EQUAL" then assign this applicant an equal split
# between the other applicants (amount / num_applicants)
# - Otherwise use the amount directly assigned to the income owner
# The percentage based on number of applicants or taken from the owner percent field
equal_share_percent = ExpressionWrapper(100 / F('num_applicants'), output_field=PercentageValueField())
applicant_share_percent = Case(
When(proportions='SPECIFIED', then=F('owners__percent')), <-- ONLY WANT % FOR THIS CLIENT
default=equal_share_percent
)
# Total amount applicant receives
applicant_amount = ExpressionWrapper(
F('applicant_percent') / 100 * F('amount'), output_field=models.DecimalField(decimal_places=2)
)
loan_income_summary = Income.objects.filter(
loan=loan
).annotate(
# number of people with a share of the income
num_applicants=Count('applicants', output_field=models.IntegerField()),
).annotate(
# applicant's percentage share
applicant_percent=applicant_share_percent
).aggregate(
# Investments
total_investment=Sum(
applicant_amount,
filter=Q(income_type='INVESTMENT'),
output_field=models.DecimalField(decimal_places=2)
)
)
Я чувствую, что, возможно, мне нужен подзапрос, чтобы получить только процент для данного клиента, но я просто не уверен.