You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

261 lines
8.6 KiB
Python

from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponse
from django.shortcuts import render
from django.urls import reverse
from django.views import View
from mixins.views import (
ObjectCreate,
ObjectDelete,
ObjectList,
ObjectRead,
ObjectUpdate,
)
from rest_framework import status
from two_factor.views.mixins import OTPRequiredMixin
from core.clients.aggregators.nordigen import NordigenClient
from core.clients.platforms.agora import AgoraClient
from core.forms import LinkGroupForm
from core.lib.money import Money
from core.management.commands.scheduling import withdrawal_job
from core.models import (
Aggregator,
LinkGroup,
OperatorWallets,
Platform,
Requisition,
User,
)
from core.views.helpers import synchronize_async_helper
class LinkGroupInfo(LoginRequiredMixin, OTPRequiredMixin, ObjectRead):
context_object_name_singular = "linkgroup"
context_object_name = "linkgroups"
detail_template = "partials/linkgroup-info.html"
def get_object(self, **kwargs):
pk = self.kwargs.get("pk")
linkgroup = LinkGroup.objects.filter(
user=self.request.user,
id=pk,
).first()
if not linkgroup:
return HttpResponse(status=status.HTTP_404_NOT_FOUND)
return linkgroup
def get_context_data(self):
context = super().get_context_data()
self.extra_buttons = [
{
"url": reverse(
"linkgroup_withdraw", kwargs={"pk": self.object.id, "type": "modal"}
),
"action": "withdraw",
"method": "get",
"label": "Withdraw profit",
"icon": "fa-solid fa-money-bill-transfer",
},
{
"url": reverse(
"linkgroup_simulate", kwargs={"pk": self.object.id, "type": "modal"}
),
"action": "simulate",
"method": "get",
"label": "Simulate withdrawal",
"icon": "fa-solid fa-play",
},
]
aggregators = Aggregator.objects.filter(
user=self.request.user,
link_group=self.object,
)
platforms = Platform.objects.filter(
user=self.request.user,
link_group=self.object,
)
requisitions = Requisition.objects.filter(
user=self.request.user,
aggregator__in=aggregators,
)
context["aggregators"] = aggregators
context["platforms"] = platforms
context["requisitions"] = requisitions
context["linkgroup"] = self.object
payees = self.object.payees()
simulation = {}
profit = 1000
profit_platform = profit * (self.object.platform_owner_cut_percentage / 100)
profit_requisition = profit * (
self.object.requisition_owner_cut_percentage / 100
)
profit_operator = profit * (self.object.operator_cut_percentage / 100)
pay_list = {}
platform_pay_list = []
if "platform" in payees:
for payee in payees["platform"]:
cast = {
"name": payee.name,
"address": payee.address,
"amount": profit_platform / len(payees["platform"]),
"max": profit_platform,
}
if payee not in pay_list:
pay_list[payee] = {}
if "amount" in pay_list[payee]:
pay_list[payee]["amount"] += cast["amount"]
else:
pay_list[payee] = dict(cast)
platform_pay_list.append(cast)
requisition_pay_list = []
if "requisition" in payees:
for payee in payees["requisition"]:
cast = {
"name": payee.name,
"address": payee.address,
"amount": profit_requisition / len(payees["requisition"]),
"max": profit_requisition,
}
if payee not in pay_list:
pay_list[payee] = {}
if "amount" in pay_list[payee]:
pay_list[payee]["amount"] += cast["amount"]
else:
pay_list[payee] = dict(cast)
requisition_pay_list.append(cast)
operator_pay_list = []
staff = User.objects.filter(
is_staff=True,
)
for user in staff:
wallets, _ = OperatorWallets.objects.get_or_create(user=user)
total_wallets = len(wallets.payees.all())
# Select all OperatorWallet instances with any distinct user attributes
for payee in wallets.payees.all():
cast = {
"name": payee.name,
"address": payee.address,
"amount": profit_operator / total_wallets,
"max": profit_operator,
}
print("CAST", cast)
if user not in pay_list:
pay_list[payee] = {}
if "amount" in pay_list[payee]:
pay_list[payee]["amount"] += cast["amount"]
else:
pay_list[payee] = dict(cast)
operator_pay_list.append(cast)
simulation[("Platform", profit_platform)] = platform_pay_list
simulation[("Requisition", profit_requisition)] = requisition_pay_list
simulation[("Operator", profit_operator)] = operator_pay_list
context["pay_list"] = pay_list
context["simulation"] = simulation
return context
class LinkGroupList(LoginRequiredMixin, OTPRequiredMixin, ObjectList):
list_template = "partials/linkgroup-list.html"
model = LinkGroup
page_title = "List of link groups"
page_subtitle = "Link groups are used to link aggregators and platforms"
list_url_name = "linkgroups"
list_url_args = ["type"]
submit_url_name = "linkgroup_create"
class LinkGroupCreate(LoginRequiredMixin, OTPRequiredMixin, ObjectCreate):
model = LinkGroup
form_class = LinkGroupForm
submit_url_name = "linkgroup_create"
class LinkGroupUpdate(LoginRequiredMixin, OTPRequiredMixin, ObjectUpdate):
model = LinkGroup
form_class = LinkGroupForm
submit_url_name = "linkgroup_update"
class LinkGroupDelete(LoginRequiredMixin, OTPRequiredMixin, ObjectDelete):
model = LinkGroup
class LinkGroupSimulation(LoginRequiredMixin, OTPRequiredMixin, ObjectRead):
context_object_name_singular = "linkgroupsim"
context_object_name = "linkgroupsim"
detail_template = "partials/linkgroup-info-sim.html"
def get_object(self, **kwargs):
pk = self.kwargs.get("pk")
linkgroup = LinkGroup.objects.filter(
user=self.request.user,
id=pk,
).first()
if not linkgroup:
return HttpResponse(status=status.HTTP_404_NOT_FOUND)
money = Money()
checks = synchronize_async_helper(
money.check_all(link_group=pk, nordigen=NordigenClient, agora=AgoraClient)
)
print("CHECKS", checks)
aggregators = Aggregator.objects.filter(
user=self.request.user,
link_group=linkgroup,
)
platforms = Platform.objects.filter(
user=self.request.user,
link_group=linkgroup,
)
requisitions = Requisition.objects.filter(
user=self.request.user,
aggregator__in=aggregators,
)
pay_list = money.get_pay_list(
linkgroup,
requisitions,
platforms,
self.request.user,
checks["total_profit"],
)
print("PAY LIST", pay_list)
collapsed = money.collapse_pay_list(pay_list)
print("COLLAPSED", collapsed)
self.extra_context = {"collapsed": collapsed}
self.extra_context["pay_list"] = pay_list
self.extra_context["total_profit"] = checks["total_profit_in_xmr"]
return pay_list
class LinkGroupWithdraw(LoginRequiredMixin, OTPRequiredMixin, View):
template_name = "mixins/partials/notify.html"
def get(self, request, **kwargs):
pk = self.kwargs.get("pk")
linkgroup = LinkGroup.objects.filter(
user=self.request.user,
id=pk,
).first()
if not linkgroup:
return HttpResponse(status=status.HTTP_404_NOT_FOUND)
run = synchronize_async_helper(withdrawal_job(linkgroup))
print("RUN", run)
context = {"class": "success", "message": "Withdrawal run"}
return render(request, self.template_name, context)