Рассчитать процент в Django Запрос к базе данных - PullRequest
0 голосов
/ 23 апреля 2020

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

МОДЕЛИ:

class Bill(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    number = models.CharField(max_length=100, blank=True)


class BillService(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    bill = models.ForeignKey(Bill, related_name='billservices', on_delete=models.CASCADE)
    service = models.ForeignKey(Service, on_delete=models.CASCADE)

class Service(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    business = models.ForeignKey(Business, related_name='services', on_delete=models.CASCADE, blank=True)
    short_code = models.IntegerField(default=0)

class ServiceTax(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    service = models.ForeignKey(Service, on_delete=models.CASCADE, related_name="servicetaxes")
    tax = models.ForeignKey(Tax, on_delete=models.CASCADE)

class Tax(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    business = models.ForeignKey(Business, related_name='taxes', on_delete=models.CASCADE)
    name = models.CharField(max_length=50)
    tax = models.FloatField(validators=[MinValueValidator(0), MaxValueValidator(100)], default=0)

МОЙ ЗАПРОС, ЧТОБЫ ПОЛУЧИТЬ ЕДИНСТВЕННОЕ ЗНАЧЕНИЕ, ЭТО ПОЛНАЯ СТОИМОСТЬ БИЛЛА

    value = bill.billservices.all()
                .annotate(sum_of_taxed_percentages=Subquery(
                        Service.objects.filter(billservice=OuterRef('id'))
                        .annotate(total_tax_value=Subquery(
                            ServiceTax.objects.filter(service=OuterRef('id'))
                            .values('tax')
                            .annotate(total_tax=Sum('tax__tax', output_field=FloatField()))
                            .values('total_tax')
                        )).annotate(taxed_value=F('price') + ((F('price') * F('total_tax_value')) / 100))
                       .values('taxed_value')
                       .annotate(total_services_taxed_value=Sum('taxed_value', output_field=FloatField()))
                       .values('total_services_taxed_value')
             ))

             print(value[0].sum_of_taxed_percentages)

ОШИБКА:

'ManyToOneRel' object has no attribute 'select_format'

Ответы [ 2 ]

0 голосов
/ 24 апреля 2020

После многих проб и ошибок я нашел решение.

   service_tax = ServiceTax.objects.filter(service=OuterRef('service')) \
                .values('tax__tax')
   value = bill.billservices.all() \
                .annotate(service_taxes=SQSum(service_tax)) \
                .annotate(service_price=F('service__price')) \
                .aggregate(total=Sum(F('service_price') + ((F('service_price') * F('service_taxes')) / 100),
                                     output_field=FloatField()))
   print(value)



class SQSum(Subquery):
    template = "(SELECT SUM(tax) FROM (%(subquery)s) _sum)"
    output_field = models.FloatField()
0 голосов
/ 23 апреля 2020

Если вы рассчитываете процент:

taxed_value=F('price') + ((F('price') * F('total_tax_value')) / 100)

в этом траншеи:

((F('price') * F('total_tax_value')) / 100

я думаю, вам нужно изменить некоторые скобки:

(F('price') * (F('total_tax_value') / 100))

потому что сначала вам нужно разделить сохраненный вами процент на 100, а затем умножить его на цену объекта, чтобы затем суммировать с его текущим значением:

taxed_value=F('price') + (F('price') * (F('total_tax_value') / 100))

Проверьте, если он работает, я не уверен, кажется, что это простая проблема формулы ...

...