Как выполнить вычисление в 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)
        )
    )

Я чувствую, что, возможно, мне нужен подзапрос, чтобы получить только процент для данного клиента, но я просто не уверен.

Вернуться на верх