mirror of
https://github.com/RoboSats/robosats.git
synced 2024-12-13 19:06:26 +00:00
Add preliminary daily accounting
This commit is contained in:
parent
3d9ef5fc58
commit
d4023bfd0d
@ -121,6 +121,7 @@ class UserProfileAdmin(AdminChangeLinksMixin, admin.ModelAdmin):
|
|||||||
"num_disputes",
|
"num_disputes",
|
||||||
"lost_disputes",
|
"lost_disputes",
|
||||||
)
|
)
|
||||||
|
list_editable = ["pending_rewards", "earned_rewards"]
|
||||||
list_display_links = ("avatar_tag", "id")
|
list_display_links = ("avatar_tag", "id")
|
||||||
change_links = ["user"]
|
change_links = ["user"]
|
||||||
readonly_fields = ["avatar_tag"]
|
readonly_fields = ["avatar_tag"]
|
||||||
|
@ -111,7 +111,7 @@ def follow_send_payment(lnpayment):
|
|||||||
lnpayment.save()
|
lnpayment.save()
|
||||||
order.status = Order.Status.FAI
|
order.status = Order.Status.FAI
|
||||||
order.expires_at = timezone.now() + timedelta(
|
order.expires_at = timezone.now() + timedelta(
|
||||||
seconds=Order.t_to_expire[Order.Status.FAI])
|
seconds=order.t_to_expire(Order.Status.FAI))
|
||||||
order.save()
|
order.save()
|
||||||
context = {
|
context = {
|
||||||
"routing_failed":
|
"routing_failed":
|
||||||
@ -127,7 +127,7 @@ def follow_send_payment(lnpayment):
|
|||||||
lnpayment.save()
|
lnpayment.save()
|
||||||
order.status = Order.Status.SUC
|
order.status = Order.Status.SUC
|
||||||
order.expires_at = timezone.now() + timedelta(
|
order.expires_at = timezone.now() + timedelta(
|
||||||
seconds=Order.t_to_expire[Order.Status.SUC])
|
seconds=order.t_to_expire(Order.Status.SUC))
|
||||||
order.save()
|
order.save()
|
||||||
return True, None
|
return True, None
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ def follow_send_payment(lnpayment):
|
|||||||
lnpayment.save()
|
lnpayment.save()
|
||||||
order.status = Order.Status.FAI
|
order.status = Order.Status.FAI
|
||||||
order.expires_at = timezone.now() + timedelta(
|
order.expires_at = timezone.now() + timedelta(
|
||||||
seconds=Order.t_to_expire[Order.Status.FAI])
|
seconds=order.t_to_expire(Order.Status.FAI))
|
||||||
order.save()
|
order.save()
|
||||||
context = {"routing_failed": "The payout invoice has expired"}
|
context = {"routing_failed": "The payout invoice has expired"}
|
||||||
return False, context
|
return False, context
|
||||||
|
@ -22,7 +22,8 @@ class AccountingDayAdmin(ImportExportModelAdmin):
|
|||||||
"outstanding_pending_disputes",
|
"outstanding_pending_disputes",
|
||||||
"lifetime_rewards_claimed",
|
"lifetime_rewards_claimed",
|
||||||
"outstanding_earned_rewards",
|
"outstanding_earned_rewards",
|
||||||
"pending_disputes",
|
"earned_rewards",
|
||||||
|
"disputes",
|
||||||
"rewards_claimed",
|
"rewards_claimed",
|
||||||
)
|
)
|
||||||
change_links = ["day"]
|
change_links = ["day"]
|
||||||
|
@ -32,7 +32,7 @@ class AccountingDay(models.Model):
|
|||||||
# Balance change from last day on earned rewards (referral rewards, slashed bonds and solved disputes)
|
# Balance change from last day on earned rewards (referral rewards, slashed bonds and solved disputes)
|
||||||
earned_rewards = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
earned_rewards = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||||
# Balance change on pending disputes (not resolved yet)
|
# Balance change on pending disputes (not resolved yet)
|
||||||
pending_disputes = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
disputes = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||||
# Rewards claimed on day
|
# Rewards claimed on day
|
||||||
rewards_claimed = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
rewards_claimed = models.DecimalField(max_digits=15, decimal_places=3, default=0, null=False, blank=False)
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ from control.models import AccountingDay, AccountingMonth
|
|||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from django.db.models import Sum
|
from django.db.models import Sum
|
||||||
|
from decouple import config
|
||||||
|
|
||||||
@shared_task(name="do_accounting")
|
@shared_task(name="do_accounting")
|
||||||
def do_accounting():
|
def do_accounting():
|
||||||
@ -17,8 +18,10 @@ def do_accounting():
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
last_accounted_day = AccountingDay.objects.latest('day').day.date()
|
last_accounted_day = AccountingDay.objects.latest('day').day.date()
|
||||||
|
accounted_yesterday = AccountingDay.objects.latest('day')
|
||||||
except:
|
except:
|
||||||
last_accounted_day = None
|
last_accounted_day = None
|
||||||
|
accounted_yesterday = None
|
||||||
|
|
||||||
if last_accounted_day == today:
|
if last_accounted_day == today:
|
||||||
return {'message':'no days to account for'}
|
return {'message':'no days to account for'}
|
||||||
@ -30,11 +33,11 @@ def do_accounting():
|
|||||||
|
|
||||||
day = initial_day
|
day = initial_day
|
||||||
result = {}
|
result = {}
|
||||||
accounted_yesterday = None
|
|
||||||
while day <= today:
|
while day <= today:
|
||||||
day_payments = all_payments.filter(created_at__gte=day,created_at__lte=day+timedelta(days=1))
|
day_payments = all_payments.filter(created_at__gte=day,created_at__lte=day+timedelta(days=1))
|
||||||
day_ticks = all_ticks.filter(timestamp__gte=day,timestamp__lte=day+timedelta(days=1))
|
day_ticks = all_ticks.filter(timestamp__gte=day,timestamp__lte=day+timedelta(days=1))
|
||||||
|
|
||||||
|
# Coarse accounting based on LNpayment objects
|
||||||
contracted = day_ticks.aggregate(Sum('volume'))['volume__sum']
|
contracted = day_ticks.aggregate(Sum('volume'))['volume__sum']
|
||||||
num_contracts = day_ticks.count()
|
num_contracts = day_ticks.count()
|
||||||
inflow = day_payments.filter(type=LNPayment.Types.HOLD,status=LNPayment.Status.SETLED).aggregate(Sum('num_satoshis'))['num_satoshis__sum']
|
inflow = day_payments.filter(type=LNPayment.Types.HOLD,status=LNPayment.Status.SETLED).aggregate(Sum('num_satoshis'))['num_satoshis__sum']
|
||||||
@ -52,9 +55,6 @@ def do_accounting():
|
|||||||
day = day,
|
day = day,
|
||||||
contracted = contracted,
|
contracted = contracted,
|
||||||
num_contracts = num_contracts,
|
num_contracts = num_contracts,
|
||||||
net_settled = 0,
|
|
||||||
net_paid = 0,
|
|
||||||
net_balance = 0,
|
|
||||||
inflow = inflow,
|
inflow = inflow,
|
||||||
outflow = outflow,
|
outflow = outflow,
|
||||||
routing_fees = routing_fees,
|
routing_fees = routing_fees,
|
||||||
@ -62,6 +62,31 @@ def do_accounting():
|
|||||||
rewards_claimed = rewards_claimed,
|
rewards_claimed = rewards_claimed,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Fine Net Daily accounting based on orders
|
||||||
|
# Only account for orders where everything worked out right
|
||||||
|
payouts = day_payments.filter(type=LNPayment.Types.NORM,concept=LNPayment.Concepts.PAYBUYER, status=LNPayment.Status.SUCCED)
|
||||||
|
escrows_settled = 0
|
||||||
|
payouts_paid = 0
|
||||||
|
routing_cost = 0
|
||||||
|
for payout in payouts:
|
||||||
|
escrows_settled += payout.order_paid.trade_escrow.num_satoshis
|
||||||
|
payouts_paid += payout.num_satoshis
|
||||||
|
routing_cost += payout.fee
|
||||||
|
|
||||||
|
# account for those orders where bonds were lost
|
||||||
|
# + Settled bonds / bond_split
|
||||||
|
bonds_settled = day_payments.filter(type=LNPayment.Types.HOLD,concept__in=[LNPayment.Concepts.TAKEBOND,LNPayment.Concepts.MAKEBOND], status=LNPayment.Status.SETLED)
|
||||||
|
|
||||||
|
if len(bonds_settled) > 0:
|
||||||
|
collected_slashed_bonds = (bonds_settled.aggregate(Sum('num_satoshis'))['num_satoshis__sum'])* float(config('SLASHED_BOND_REWARD_SPLIT'))
|
||||||
|
else:
|
||||||
|
collected_slashed_bonds = 0
|
||||||
|
|
||||||
|
accounted_day.net_settled = escrows_settled + collected_slashed_bonds
|
||||||
|
accounted_day.net_paid = payouts_paid + routing_cost
|
||||||
|
accounted_day.net_balance = accounted_day.net_settled - accounted_day.net_paid
|
||||||
|
|
||||||
|
# Differential accounting based on change of outstanding states and disputes unreslved
|
||||||
if day == today:
|
if day == today:
|
||||||
pending_disputes = Order.objects.filter(status__in=[Order.Status.DIS,Order.Status.WFR])
|
pending_disputes = Order.objects.filter(status__in=[Order.Status.DIS,Order.Status.WFR])
|
||||||
if len(pending_disputes) > 0:
|
if len(pending_disputes) > 0:
|
||||||
@ -74,8 +99,9 @@ def do_accounting():
|
|||||||
accounted_day.lifetime_rewards_claimed = Profile.objects.all().aggregate(Sum('claimed_rewards'))['claimed_rewards__sum']
|
accounted_day.lifetime_rewards_claimed = Profile.objects.all().aggregate(Sum('claimed_rewards'))['claimed_rewards__sum']
|
||||||
if accounted_yesterday != None:
|
if accounted_yesterday != None:
|
||||||
accounted_day.earned_rewards = accounted_day.outstanding_earned_rewards - accounted_yesterday.outstanding_earned_rewards
|
accounted_day.earned_rewards = accounted_day.outstanding_earned_rewards - accounted_yesterday.outstanding_earned_rewards
|
||||||
accounted_day.pending_disputes = outstanding_pending_disputes - accounted_yesterday.outstanding_earned_rewards
|
accounted_day.disputes = outstanding_pending_disputes - accounted_yesterday.outstanding_earned_rewards
|
||||||
|
|
||||||
|
# Close the loop
|
||||||
accounted_day.save()
|
accounted_day.save()
|
||||||
accounted_yesterday = accounted_day
|
accounted_yesterday = accounted_day
|
||||||
result[str(day)]={'contracted':contracted,'inflow':inflow,'outflow':outflow}
|
result[str(day)]={'contracted':contracted,'inflow':inflow,'outflow':outflow}
|
||||||
@ -83,13 +109,4 @@ def do_accounting():
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@shared_task(name="account_day")
|
|
||||||
def account_day():
|
|
||||||
'''
|
|
||||||
Does daily accounting since last accounted day.
|
|
||||||
To be run daily.
|
|
||||||
'''
|
|
||||||
|
|
||||||
return
|
|
Loading…
Reference in New Issue
Block a user