Implement more payout management

This commit is contained in:
Mark Veidemanis 2023-05-06 11:52:42 +01:00
parent ddfee0b328
commit 6ea82857f2
Signed by: m
GPG Key ID: 5ACFCEED46C0904F
6 changed files with 128 additions and 18 deletions

View File

@ -263,6 +263,11 @@ urlpatterns = [
payouts.PayoutDelete.as_view(), payouts.PayoutDelete.as_view(),
name="payout_delete", name="payout_delete",
), ),
path(
"payouts/action/delete_all/",
payouts.PayoutDeleteAll.as_view(),
name="payout_delete_all",
),
# Link groups # Link groups
path( path(
"links/<str:type>/", "links/<str:type>/",

View File

@ -8,7 +8,14 @@ from core.clients.aggregators.nordigen import NordigenClient
from core.clients.platforms.agora import AgoraClient from core.clients.platforms.agora import AgoraClient
from core.lib.money import Money from core.lib.money import Money
from core.lib.notify import sendmsg from core.lib.notify import sendmsg
from core.models import INTERVAL_CHOICES, Aggregator, LinkGroup, Platform, Requisition from core.models import (
INTERVAL_CHOICES,
Aggregator,
LinkGroup,
Payout,
Platform,
Requisition,
)
from core.util import logs from core.util import logs
log = logs.get_logger("scheduling") log = logs.get_logger("scheduling")
@ -29,6 +36,16 @@ async def withdrawal_job(group=None):
checks = await money.check_all( checks = await money.check_all(
link_group=group, nordigen=NordigenClient, agora=AgoraClient link_group=group, nordigen=NordigenClient, agora=AgoraClient
) )
if checks["total_remaining"] > 0:
# More than 0 remaining, so we can't withdraw
await sendmsg(
group.user,
f"{checks['total_remaining']} left until you can withdraw.",
title="Balance update",
)
continue
print("CHECKS", checks) print("CHECKS", checks)
aggregators = Aggregator.objects.filter( aggregators = Aggregator.objects.filter(
user=group.user, user=group.user,
@ -63,8 +80,10 @@ async def withdrawal_job(group=None):
title="Your withdrawal is ready!", title="Your withdrawal is ready!",
) )
if not checks["total_profit_in_xmr"] >= 0: # TODO: UNCOMMENT
return # COMMENTED FOR TESTING
# if not checks["total_profit_in_xmr"] >= 0:
# return
total_withdrawal = sum(collapsed.values()) total_withdrawal = sum(collapsed.values())
if checks["total_xmr_agora"] < total_withdrawal: if checks["total_xmr_agora"] < total_withdrawal:
@ -84,21 +103,38 @@ async def withdrawal_job(group=None):
# run = await AgoraClient(platform) # run = await AgoraClient(platform)
otp_code = TOTP(platform.otp_token).now() otp_code = TOTP(platform.otp_token).now()
for wallet, amount in collapsed.items(): for wallet, pay_list_iter in pay_list.items():
print("ITER SEND", wallet, amount) for amount, reason in pay_list_iter:
cast = { print("ITER", wallet, pay_list_iter)
"address": wallet.address, print("ITER SENT", wallet, amount, reason)
"amount": amount,
"password": platform.password,
"otp": otp_code,
}
print("CAST ADDRESS", cast["address"]) # for wallet, amount in collapsed.items():
print("CAST AMOUNT", cast["amount"]) print("ITER SEND", wallet, amount)
print("CAST OTP TRUNCATED BY 2", cast["otp"][-2]) cast = {
"address": wallet.address,
"amount": amount,
"password": platform.password,
"otp": otp_code,
}
# sent = await run.call("wallet_send_xmr", **cast) print("CAST ADDRESS", cast["address"])
# print("SENT", sent) print("CAST AMOUNT", cast["amount"])
print("CAST OTP TRUNCATED BY 2", cast["otp"][-2])
# TODO: UNCOMMENT
# sent = await run.call("wallet_send_xmr", **cast)
# print("SENT", sent)
payout = Payout.objects.create( # noqa
user=group.user,
wallet=wallet,
amount=amount,
description=reason,
)
# TODO: UNCOMMENT
# payout.response = sent
# payout.save()
async def aggregator_job(): async def aggregator_job():

View File

@ -0,0 +1,18 @@
# Generated by Django 4.1.7 on 2023-05-06 10:33
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0037_payout'),
]
operations = [
migrations.AddField(
model_name='payout',
name='response',
field=models.JSONField(blank=True, default=dict, null=True),
),
]

View File

@ -662,6 +662,8 @@ class Payout(models.Model):
wallet = models.ForeignKey(Wallet, on_delete=models.CASCADE) wallet = models.ForeignKey(Wallet, on_delete=models.CASCADE)
amount = models.FloatField() amount = models.FloatField()
description = models.CharField(max_length=255, null=True, blank=True) description = models.CharField(max_length=255, null=True, blank=True)
response = models.JSONField(default=dict, null=True, blank=True)
ts = models.DateTimeField(auto_now_add=True) ts = models.DateTimeField(auto_now_add=True)

View File

@ -31,7 +31,32 @@
</a> </a>
</td> </td>
<td>{{ item.user }}</td> <td>{{ item.user }}</td>
<td>{{ item.wallet }}</td>
<td>
<div class="nowrap-parent">
<div class="nowrap-child">
<a
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-get="{% url 'wallet_update' type=type pk=item.wallet.id %}"
hx-trigger="click"
hx-target="#{{ type }}s-here"
hx-swap="innerHTML">
{{ item.wallet.name }}
</a>
</div>
<div class="nowrap-child">
<a
class="has-text-grey"
onclick="window.prompt('Copy to clipboard: Ctrl+C, Enter', '{{ item.wallet.address }}');">
<span class="icon" data-tooltip="Copy wallet address to clipboard">
<i class="fa-solid fa-copy" aria-hidden="true"></i>
</span>
</a>
</div>
</div>
</td>
<td>{{ item.amount }}</td> <td>{{ item.amount }}</td>
<td>{{ item.description }}</td> <td>{{ item.description }}</td>
<td>{{ item.ts }}</td> <td>{{ item.ts }}</td>

View File

@ -1,5 +1,13 @@
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from mixins.views import ObjectCreate, ObjectDelete, ObjectList, ObjectUpdate from django.shortcuts import render
from django.views import View
from mixins.views import (
ObjectCreate,
ObjectDelete,
ObjectList,
ObjectNameMixin,
ObjectUpdate,
)
from two_factor.views.mixins import OTPRequiredMixin from two_factor.views.mixins import OTPRequiredMixin
from core.forms import PayoutForm from core.forms import PayoutForm
@ -19,6 +27,7 @@ class PayoutList(LoginRequiredMixin, OTPRequiredMixin, ObjectList):
list_url_args = ["type"] list_url_args = ["type"]
submit_url_name = "payout_create" submit_url_name = "payout_create"
delete_all_url_name = "payout_delete_all"
# def get_context_data(self): # def get_context_data(self):
# context = super().get_context_data() # context = super().get_context_data()
@ -80,3 +89,18 @@ class PayoutUpdate(LoginRequiredMixin, OTPRequiredMixin, ObjectUpdate):
class PayoutDelete(LoginRequiredMixin, OTPRequiredMixin, ObjectDelete): class PayoutDelete(LoginRequiredMixin, OTPRequiredMixin, ObjectDelete):
model = Payout model = Payout
class PayoutDeleteAll(LoginRequiredMixin, OTPRequiredMixin, ObjectNameMixin, View):
template_name = "mixins/partials/notify.html"
model = Payout
def delete(self, request):
"""
Delete all payouts by the current user.
"""
Payout.objects.filter(user=request.user).delete()
context = {"message": "All payouts deleted", "class": "success"}
response = render(request, self.template_name, context)
response["HX-Trigger"] = f"{self.context_object_name_singular}Event"
return response