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_in_xmr"], ) 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)