iralex-backend/ppp.py

701 lines
35 KiB
Python

import datetime
from django.db.models import Q, Sum, F, Count
from account.views import get_fullname
from bank_account.Interface import SubAccountInterface, TransactionInterface
from bank_account.models import BankAccount, SubAccount, Transaction
from billing.models import Bill
from django.db import transaction
from billing.serializers import BillSerializer
from const.models import Const
from contact.models import Contact
from contact.serializers import ContactSerializer
from core.dictionary.models import PracticeArea
from core.filter_parser.FilterParser import FilterParser
from matter.models import Matter
from report.Report import Report
from account.models import LawyerUser
from billing.models import TimeEntry, ExpenseEntry
class BillingPayment:
def __init__(self, request, destination: BankAccount, source=None):
_inp = request.bodyDict
self.billing = _inp['billings']
self._inp = _inp
self.source = source
self.request = request
self.destination = destination
def valid_source(self, source):
if not SubAccountInterface.authorize_object(request=self.request, owner_id=source.owner_id, _type=source.type):
raise Exception(f'Not Authorize destination or source.')
def do_payment(self):
with transaction.atomic():
for bill_id in self.billing:
bill = self.IdToBilling(bill_id)
description = False
if bill.status == 4:
raise Exception("Bill Early Payed.")
amount = float(self.billing[bill_id])
if bill.total_amount < amount:
raise Exception("Amount More Than Bill Amount Not Enough.")
if self.source and isinstance(self.source, SubAccount) and bill.type != 2:
sub_interface = SubAccountInterface(owner_id=self.source.owner_id, _type=self.source.type,
bank_account_id=self.source.bank_account_id)
TransactionInterface(sub_account=sub_interface, _deposit=False, _inp={
"amount": amount,
"type": 1,
"description": self._inp['description'] if 'description' in self._inp else '',
"creator": self._inp['creator'],
"bill": bill.pk
})
else:
description = f'Direct payment for invoice #{bill.factor_no}.'
# if bill.type == 2:
if len(bill.matters.all()) > 0:
dest_owner_id = bill.matters.first().pk
dest_type = 3
else:
dest_owner_id = bill.to_contact.pk
dest_type = 2
# else:
# if bill.
# dest_owner_id = self.source.owner_id if self.source else self.destination.pk
# dest_type = self.source.type if self.source else 1
dest_sub_account = SubAccountInterface(owner_id=dest_owner_id, bank_account_id=self.destination.pk,
_type=dest_type)
_inp = {
"amount": amount,
"description": description if description else '',
"created_at": self._inp['created_at'] if 'created_at' in self._inp else datetime.datetime.now(),
"creator": self._inp['creator'],
"bill": bill.pk
}
_transaction = TransactionInterface(sub_account=dest_sub_account, _inp=_inp, _deposit=True).transaction
if not _transaction:
raise Exception("error")
bill.payed_amount += amount
if bill.payed_amount >= bill.total_amount:
bill.status = 4
bill.save()
return True
def IdToBilling(self, _id):
return Bill.List(self.request).get(pk=_id)
class BillReport:
@staticmethod
def get_matter_aging(matter_id):
bills = Bill.objects.filter(matters__in=[matter_id]).filter(~Q(status=1)).all()
final_res = []
for bill in bills:
res = {
"0-30": 0,
"31-60": 0,
"61-90": 0,
"+91": 0,
"current": 0,
"bill_id": None,
"status": None
}
for item in bill.transaction_set.filter(amount__gt=0).all():
delay = (item.created_at.date() - bill.due_date).days
if delay < 31:
res['0-30'] += item.amount
elif delay < 61:
res['31-60'] += item.amount
elif delay < 91:
res['61-90'] += item.amount
else:
res['+91'] += item.amount
res['current'] = bill.total_amount
res['bill_id'] = bill.factor_no
res['status'] = bill.status
final_res.append(res)
return final_res
@staticmethod
def receivable(request):
group_by = request.bodyDict['group_by'] if 'group_by' in request.bodyDict else None
final_res = {}
if group_by == 1:
fields = {"matters__id", "to_contact__id"}
res = FilterParser(request=request,
baseQuery=Bill.objects.values(*fields).filter(~Q(status=1)).filter(
matters__isnull=False).filter(
Q(creator__id=request.lawyerUser.id) | Q(
creator__main__id=request.lawyerUser.GetMain().id), is_removed=False),
ModelClass=Bill).Execute(
returnQuerySetWithoutPaginate=True,
withoutOrderBy=True
)
inserted_matters = []
for result in res:
matter = Matter.objects.filter(pk=result['matters__id']).first()
if result['to_contact__id'] not in final_res:
final_res[result['to_contact__id']] = {
"matters": [{
'name': matter.title if matter else '-',
'bills': BillSerializer(
instance=matter.bill_set.filter(is_removed=False, status__gt=1).all(), many=True).data
}],
"contact": get_fullname(Contact.objects.get(pk=result['to_contact__id']), True)
}
inserted_matters.append(matter.id) if matter else False
else:
if result['matters__id'] not in inserted_matters:
final_res[result['to_contact__id']]['matters'].append({
"name": Matter.objects.get(pk=result['matters__id']).title if matter else '-',
'bills': BillSerializer(
instance=matter.bill_set.filter(is_removed=False, status__gt=1).all(),
many=True).data
})
inserted_matters.append(result['matters__id'])
elif group_by == 2:
fields = {"matters__id", "matters__practice_area"}
res = FilterParser(request=request,
baseQuery=Bill.objects.values(*fields).filter(matters__isnull=False).filter(
Q(creator__id=request.lawyerUser.id) | Q(
creator__main__id=request.lawyerUser.GetMain().id), is_removed=False),
ModelClass=Bill).Execute(
returnQuerySetWithoutPaginate=True,
withoutOrderBy=True
)
inserted_matters = []
for result in res:
matter = Matter.objects.filter(pk=result['matters__id']).first()
pa = PracticeArea.objects.get(pk=result['matters__practice_area'])
if result['matters__practice_area'] not in final_res:
final_res[result['matters__practice_area']] = {
"matters": [{
'name': matter.title if matter else '-',
'bills': BillSerializer(
instance=matter.bill_set.filter(is_removed=False, status__gt=1).all(),
many=True).data
}],
"practice_area": pa.title if pa else '-'
}
inserted_matters.append(matter.id) if matter else False
else:
if result['matters__id'] not in inserted_matters:
final_res[result['matters__practice_area']]['matters'].append({
"name": Matter.objects.get(pk=result['matters__id']).title if matter else '-',
'bills': BillSerializer(
instance=matter.bill_set.filter(is_removed=False, status__gt=1).all(),
many=True).data
})
inserted_matters.append(result['matters__id'])
elif group_by == 3:
fields = {"matters__id", "matters__responsible__id"}
res = FilterParser(request=request,
baseQuery=Bill.objects.values(*fields).filter(matters__isnull=False).filter(
Q(creator__id=request.lawyerUser.id) | Q(
creator__main__id=request.lawyerUser.GetMain().id), is_removed=False),
ModelClass=Bill).Execute(
returnQuerySetWithoutPaginate=True,
withoutOrderBy=True
)
inserted_matters = []
for result in res:
matter = Matter.objects.filter(pk=result['matters__id']).first()
lawyer = LawyerUser.objects.get(pk=result['matters__responsible__id']) if result[
'matters__responsible__id'] else None
if result['matters__responsible__id'] not in final_res:
final_res[result['matters__responsible__id']] = {
"matters": [{
'name': matter.title if matter else '-',
'bills': BillSerializer(
instance=matter.bill_set.filter(is_removed=False, status__gt=1).all(),
many=True).data
}],
"lawyer": get_fullname(lawyer) if lawyer else '-'
}
inserted_matters.append(matter.id) if matter else False
else:
if result['matters__id'] not in inserted_matters:
final_res[result['matters__responsible__id']]['matters'].append({
"name": Matter.objects.get(pk=result['matters__id']).title if matter else '-',
'bills': BillSerializer(
instance=matter.bill_set.filter(is_removed=False, status__gt=1).all(),
many=True).data
})
inserted_matters.append(result['matters__id'])
return final_res
@staticmethod
def aging(request):
fields = {"matters__id", "to_contact__id"}
res = FilterParser(request=request,
baseQuery=Bill.objects.values(*fields).filter(~Q(status=1)).filter(
Q(creator__id=request.lawyerUser.id) | Q(
creator__main__id=request.lawyerUser.GetMain().id)).filter(matters__isnull=False,
is_removed=False),
ModelClass=Bill).Execute(
returnQuerySetWithoutPaginate=True,
withoutOrderBy=True)
final_res = {}
inserted_matters = []
for result in res:
if result['to_contact__id'] not in final_res:
matter = Matter.objects.filter(pk=result['matters__id']).first()
final_res[result['to_contact__id']] = {
"matters": [{'name': matter.title,
'aging': BillReport.get_matter_aging(result['matters__id'])}],
"contact": get_fullname(Contact.objects.get(pk=result['to_contact__id']), True)
}
inserted_matters.append(matter.id) if matter else False
else:
if result['matters__id'] not in inserted_matters:
final_res[result['to_contact__id']]['matters'].append({
"name": Matter.objects.get(pk=result['matters__id']).title,
'aging': BillReport.get_matter_aging(result['matters__id'])
})
inserted_matters.append(result['matters__id'])
return final_res
@staticmethod
def summery(request):
group_by = request.bodyDict['group_by'] if 'group_by' in request.bodyDict else None
final_res = {}
if group_by == 1:
fields = {"matters__id", "to_contact__id"}
work_progress = FilterParser(request=request,
baseQuery=TimeEntry.objects.values(*fields).filter(
is_used_in_invoice=False).filter(
matters__isnull=False).filter(
Q(creator__id=request.lawyerUser.id) | Q(
creator__main__id=request.lawyerUser.GetMain().id), is_removed=False),
ModelClass=TimeEntry).Execute(
returnQuerySetWithoutPaginate=True,
withoutOrderBy=True
)
inserted_matters = []
for result in work_progress:
matter = Matter.objects.filter(pk=result['matters__id']).first()
if result['to_contact__id'] not in final_res:
final_res[result['to_contact__id']] = {
"matters": [{
'name': matter.title if matter else '-',
**BillReport.get_matter_summery(request, matter=matter)
}],
"contact": get_fullname(Contact.objects.get(pk=result['to_contact__id']), True)
}
inserted_matters.append(matter.id) if matter else False
else:
if result['matters__id'] not in inserted_matters:
final_res[result['to_contact__id']]['matters'].append({
'name': matter.title if matter else '-',
**BillReport.get_matter_summery(request, matter=matter)
})
inserted_matters.append(result['matters__id'])
if group_by == 3:
fields = {"matters__id", "matters__responsible__id"}
res = FilterParser(request=request,
baseQuery=Bill.objects.values(*fields).filter(matters__isnull=False).filter(
Q(creator__id=request.lawyerUser.id) | Q(
creator__main__id=request.lawyerUser.GetMain().id), is_removed=False),
ModelClass=Bill).Execute(
returnQuerySetWithoutPaginate=True,
withoutOrderBy=True
)
inserted_matters = []
for result in res:
matter = Matter.objects.filter(pk=result['matters__id']).first()
if result['matters__responsible__id'] not in final_res:
final_res[result['matters__responsible__id']] = {
"matters": [{
'name': matter.title if matter else '-',
**BillReport.get_matter_summery(request, matter=matter)
}],
"lawyer": get_fullname(LawyerUser.objects.get(pk=result['matters__responsible__id']) if result[
'matters__responsible__id'] else '-')
}
inserted_matters.append(matter.id) if matter else False
else:
if result['matters__id'] not in inserted_matters:
final_res[result['matters__responsible__id']]['matters'].append({
'name': matter.title if matter else '-',
**BillReport.get_matter_summery(request, matter=matter)
})
inserted_matters.append(result['matters__id'])
return final_res
@staticmethod
def invoice_payments(request):
try:
res = FilterParser(request=request,
baseQuery=Bill.objects.values("id").filter(~Q(status=1)).filter(
matters__isnull=False).filter(
Q(creator__id=request.lawyerUser.id) | Q(
creator__main__id=request.lawyerUser.GetMain().id), is_removed=False),
ModelClass=Bill).Execute(
returnQuerySetWithoutPaginate=True,
withoutOrderBy=True
)
transactions = Transaction.objects.filter(bill__in=res, amount__lt=0).order_by('created_at').all()
# TODO : Cache invoice matter and client
final_res = []
for _transaction in transactions:
final_res.append(BillReport.get_transaction_details(_transaction))
return final_res
except Exception as e:
return str(e)
@staticmethod
def bill_tax(request):
group_by = request.bodyDict['group_by'] if 'group_by' in request.bodyDict else None
final_res = {}
if group_by == 1:
fields = {"matters__id", "to_contact__id"}
res = FilterParser(request=request,
baseQuery=Bill.objects.values(*fields).filter(~Q(status=1)).filter(
matters__isnull=False).filter(
Q(creator__id=request.lawyerUser.id) | Q(
creator__main__id=request.lawyerUser.GetMain().id), is_removed=False),
ModelClass=Bill).Execute(
returnQuerySetWithoutPaginate=True,
withoutOrderBy=True
)
inserted_matters = []
for result in res:
matter = Matter.objects.filter(pk=result['matters__id']).first()
if result['to_contact__id'] not in final_res:
final_res[result['to_contact__id']] = {
"matters": [{
'name': matter.title if matter else '-',
**BillReport.get_matter_summery(request, matter=matter)
}],
"contact": get_fullname(Contact.objects.get(pk=result['to_contact__id']), True)
}
inserted_matters.append(matter.id) if matter else False
else:
if result['matters__id'] not in inserted_matters:
final_res[result['to_contact__id']]['matters'].append({
'name': matter.title if matter else '-',
**BillReport.get_matter_summery(request, matter=matter)
})
inserted_matters.append(result['matters__id'])
if group_by == 3:
fields = {"matters__id", "matters__responsible__id"}
res = FilterParser(request=request,
baseQuery=Bill.objects.values(*fields).filter(~Q(status=1)).filter(
matters__isnull=False).filter(
Q(creator__id=request.lawyerUser.id) | Q(
creator__main__id=request.lawyerUser.GetMain().id), is_removed=False),
ModelClass=Bill).Execute(
returnQuerySetWithoutPaginate=True,
withoutOrderBy=True
)
inserted_matters = []
for result in res:
matter = Matter.objects.filter(pk=result['matters__id']).first()
if result['matters__responsible__id'] not in final_res:
final_res[result['matters__responsible__id']] = {
"matters": [{
'name': matter.title if matter else '-',
**BillReport.get_matter_summery(request, matter=matter)
}],
"lawyer": get_fullname(LawyerUser.objects.get(pk=result['matters__responsible__id']) if result[
'matters__responsible__id'] else '-')
}
inserted_matters.append(matter.id) if matter else False
else:
if result['matters__id'] not in inserted_matters:
final_res[result['matters__responsible__id']]['matters'].append({
'name': matter.title if matter else '-',
**BillReport.get_matter_summery(request, matter=matter)
})
inserted_matters.append(result['matters__id'])
return final_res
@staticmethod
def get_matter_summery(request, matter):
receivable = Bill.objects.filter(
Q(creator__id=request.lawyerUser.id) | Q(
creator__main__id=request.lawyerUser.GetMain().id)).filter(
Q(status=2) | Q(status=3)).filter(
due_date__lt=datetime.date.today(), matters__in=[matter.pk], is_removed=False).aggregate(
Sum('total_amount'),
Sum('payed_amount'))
progress = Bill.objects.filter(
Q(creator__id=request.lawyerUser.id) | Q(
creator__main__id=request.lawyerUser.GetMain().id)).filter(
Q(status=2) | Q(status=3)).filter(
due_date__gte=datetime.date.today(), matters__in=[matter.pk], is_removed=False).aggregate(
Sum('total_amount'),
Sum('payed_amount'))
draft = Bill.objects.filter(
Q(creator__id=request.lawyerUser.id) | Q(
creator__main__id=request.lawyerUser.GetMain().id)).filter(
Q(status=2) | Q(status=3)).filter(
due_date__gte=datetime.date.today(), matters__in=[matter.pk], is_removed=False).aggregate(
Sum('total_amount'))
return {
'account_receivable': float(
receivable['total_amount__sum'] if receivable['total_amount__sum'] else 0) - float(
receivable['payed_amount__sum'] if receivable['payed_amount__sum'] else 0),
'work_in_progress': float(progress['total_amount__sum'] if progress['total_amount__sum'] else 0) - float(
progress['payed_amount__sum'] if progress['payed_amount__sum'] else 0),
'expenses_progress': float(draft['total_amount__sum'] if draft['total_amount__sum'] else 0)
}
@staticmethod
def get_matter_summery_main(request, matter):
work = TimeEntry.objects.filter(
Q(creator__id=request.lawyerUser.id) | Q(
creator__main__id=request.lawyerUser.GetMain().id)).filter(is_used_in_invoice=False,
is_no_billable=False,
is_removed=False).aggregate(
Sum('total_amount'),
Sum('payed_amount'))
@staticmethod
def get_transaction_details(_transaction: Transaction):
percent = abs(_transaction.amount / _transaction.bill.total_amount)
res = {
"bill": _transaction.bill.id,
"transaction_id": _transaction.pk,
"created_at": _transaction.created_at,
"matter": {
"name": _transaction.bill.matters.first().title,
"id": _transaction.bill.matters.first().pk
},
"client": {
"name": get_fullname(_transaction.bill.to_contact, True),
"id": _transaction.bill.to_contact_id
},
"details": [
{
"amount": _transaction.amount,
"credit": False
}
]
}
details = []
for activity in _transaction.bill.expense_entries.all():
details.append({
"amount": "{:.2f}".format(abs(activity.amount * percent)),
"credit": True,
"description": activity.description,
"full_name": get_fullname(activity.creator),
"expense": True
})
for entry in _transaction.bill.time_entries.all():
details.append({
"amount": "{:.2f}".format(abs(TimeEntry.get_amount(entry) * percent)),
"credit": True,
"description": entry.description,
"full_name": get_fullname(entry.creator),
"expense": False
})
if _transaction.bill.discount > 0:
details.append({
"amount": "{:.2f}".format(_transaction.bill.discount * percent),
"description": "discount",
"credit": False,
})
if _transaction.bill.tax_value > 0:
details.append({
"amount": "{:.2f}".format(_transaction.bill.tax_value * percent),
"description": "Tax",
"credit": True,
})
if _transaction.bill.second_tax > 0:
details.append({
"amount": "{:.2f}".format(_transaction.bill.second_tax_value * percent),
"description": "Tax",
"credit": True,
})
res['details'] = res['details'] + details
return res
@staticmethod
def revenue(request):
request.bodyDict["order_by"] = '-created_at'
_now = datetime.date.today()
_from = request.bodyDict['from'] if 'from' in request.bodyDict else datetime.date(year=_now.year,
month=_now.month, day=1)
_to = request.bodyDict['to'] if 'to' in request.bodyDict else datetime.date(year=_now.year, month=_now.month,
day=30)
rows = FilterParser(request=request,
baseQuery=Bill.objects.filter(created_at__lte=_to, created_at__gte=_from).filter(
Q(creator__id=request.lawyerUser.id) | Q(
creator__main__id=request.lawyerUser.GetMain().id), ~Q(status=1), is_removed=False,
type=1),
ModelClass=Bill).Execute(
returnQuerySetWithoutPaginate=True,
withoutOrderBy=True)
total_tax = 0
total = 0
total_disbursement = 0
total_expense = 0
for bill in rows:
expense = bill.expense_entries.all()
disbarment = 0
operation = 0
for ex in expense:
if ex.expense_type == 1:
disbarment += ex.amount
elif ex.expense_type == 2:
operation += ex.amount
total_tax += bill.tax_value if bill.tax_value else 0
total_tax += bill.second_tax_value if bill.second_tax_value else 0
total += bill.total_amount
total_disbursement += disbarment
total_expense += operation
expenses = ExpenseEntry.objects.filter(created_at__lte=_to, created_at__gte=_from).filter(
Q(creator__id=request.lawyerUser.id) | Q(
creator__main__id=request.lawyerUser.GetMain().id), is_removed=False,
expense_type=2)
expenses = expenses.filter(
user_id=request.bodyDict['user_id']).all() if 'user_id' in request.bodyDict else expenses.all()
for ex in expenses:
total_expense += ex.amount
final_res = {"total_tax": total_tax, "total": total, "total_disbursement": total_disbursement,
"total_expense": total_expense, "from": _from, "to": _to,
"profit": float(total - total_disbursement - total_expense - total_tax)}
return final_res
@staticmethod
def tax(request):
_now = datetime.date.today()
_from = request.bodyDict['from'] if 'from' in request.bodyDict else datetime.date(year=_now.year - 1,
month=_now.month, day=1)
_to = request.bodyDict['to'] if 'to' in request.bodyDict else datetime.date(year=_now.year, month=_now.month,
day=30)
request.bodyDict["order_by"] = '-created_at'
BillReport.chek_tax_rule(request, _to, _from)
rows = FilterParser(request=request,
baseQuery=Bill.objects.filter(created_at__lte=_to, created_at__gte=_from).filter(
Q(creator__id=request.lawyerUser.id) | Q(
creator__main__id=request.lawyerUser.GetMain().id), ~Q(status=1), is_removed=False,
type=1).filter(Q(second_tax_value__gt=0) | Q(tax_value__gt=0)),
ModelClass=Bill).Execute(
returnQuerySetWithoutPaginate=True,
withoutOrderBy=True)
total_tax_1 = 0
total_tax_2 = 0
total = 0
bills = []
for bill in rows:
# bill_status = {
# "bill_id": bill.pk,
# "total": bill.total_amount,
# "date": bill.created_at,
# "tax_1": bill.tax_value,
# # "tax_2": bill.second_tax_value,
# # "total_tax": bill.tax_value + bill.second_tax_value,
# "tax_1_rate": bill.tax,
# # "tax_2_rate": bill.second_tax
# }
# bills.append(bill_status)
total_tax_1 += bill.tax_value if bill.tax_value else 0
# total_tax_2 += bill.second_tax_value if bill.second_tax_value else 0
total += bill.total_amount
final_res = {"total_tax": total_tax_1, "total": total,
"rate": Const.objects.filter(key='tax_1_default').first().value, "from": _from, "to": _to}
return final_res
@staticmethod
def chek_tax_rule(request, _to, _from):
bills = Bill.objects.filter(created_at__lte=_to, created_at__gte=_from).filter(
Q(creator__id=request.lawyerUser.id) | Q(
creator__main__id=request.lawyerUser.GetMain().id), ~Q(status=1), is_removed=False,
type=1).filter(Q(second_tax_value__gt=0) | Q(tax_value__gt=0)).all().values('id').annotate(
total=Count('id')).order_by('tax')
if len(bills) > 1:
raise Exception(f'two tax rate exists in {_from} to {_to}')
class RevenueReport:
@staticmethod
def Revenue(request):
final_res = {}
fields = {"matters__id", "to_contact__id"}
res = FilterParser(request=request,
baseQuery=Bill.objects.values(*fields).filter(matters__isnull=False).filter(
Q(creator__id=request.lawyerUser.id) | Q(
creator__main__id=request.lawyerUser.GetMain().id), is_removed=False),
ModelClass=Bill).Execute(
returnQuerySetWithoutPaginate=True,
withoutOrderBy=True
)
inserted_matters = []
for result in res:
matter = Matter.objects.filter(pk=result['matters__id']).first()
if result['to_contact__id'] not in final_res:
final_res[result['to_contact__id']] = {
"matters": [{
'name': matter.title if matter else '-',
'statistics': None
}],
"contact": get_fullname(Contact.objects.get(pk=result['to_contact__id']), True)
}
inserted_matters.append(matter.id) if matter else False
else:
if result['matters__id'] not in inserted_matters:
final_res[result['to_contact__id']]['matters'].append({
"name": Matter.objects.get(pk=result['matters__id']).title if matter else '-',
'statistics': None
})
inserted_matters.append(result['matters__id'])
@staticmethod
def get_revenue_statistic(matter_id):
return {
"unbilled_time":
TimeEntry.objects.filter(matter_id=matter_id, is_used_in_invoice=False, is_removed=False).aggregate(
total=Sum(F('rate') * F('duration')))['total'],
"unbilled_hours":
TimeEntry.objects.filter(matter_id=matter_id, is_used_in_invoice=False, is_removed=False).aggregate(
total=Sum('duration'))['total'],
"unbilled_expense":
ExpenseEntry.objects.filter(matter_id=matter_id, is_used_in_invoice=False, is_removed=False).aggregate(
total=Sum('amount'))[
'total'],
"billed_time":
TimeEntry.objects.filter(matter_id=matter_id, is_used_in_invoice=True, is_removed=False).aggregate(
total=Sum(F('rate') * F('duration')))['total'],
"billed_hours":
TimeEntry.objects.filter(matter_id=matter_id, is_used_in_invoice=True, is_removed=False).aggregate(
total=Sum('duration'))['total'],
"billed_expense":
ExpenseEntry.objects.filter(matter_id=matter_id, is_used_in_invoice=True, is_removed=False).aggregate(
total=Sum('amount'))[
'total'],
"billed_tax_1": Bill.objects.filter(matters__in=[matter_id], is_removed=False).aggregate(
total=Sum('tax_value'))[
'total'],
"discount": Bill.objects.filter(matters__in=[matter_id], status=4, is_removed=False).aggregate(
total=Sum('discount'))['total'],
"collected_time":
TimeEntry.objects.filter(matter_id=matter_id, is_used_in_invoice=True, is_removed=False).aggregate(
total=Sum(F('rate') * F('duration')))['total'],
"collected_expense": None,
"collected_tax_1": None,
}