701 lines
35 KiB
Python
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,
|
|
|
|
}
|