Here is my Model
I have spent countless hours trying to implement "withdraw from investment" without success. print(investment.investment_return)
shows the exact amount is being deducted but I don't know why its not updating Available Balance or
total_available_balance
from the dashboard. Dashboard Image Attached.
This is where I want the money to be deducted from
total_available_balance = Investment.objects.filter(is_active=False).aggregate(
total_available_balance=Sum('investment_return'))['total_available_balance']
I also want the money withdrawned when due. I used this line of code to set the investment period. How can I ensure the user withdraw only when due?
self.due_date = datetime.now() timedelta(seconds=5)
to ensure
from django.db import models
from django.db.models import Max, Sum, F
from datetime import datetime, timedelta
class Investment(models.Model):
PLAN_CHOICES = (
("Basic - Daily 2% for 180 Days", "Basic - Daily 2% for 180 Days"),
("Premium - Daily 4% for 360 Days", "Premium - Daily 4% for 360 Days"),
)
plan = models.CharField(max_length=100, choices=PLAN_CHOICES, null=True)
deposit_amount = models.IntegerField(default=0, null=True)
basic_interest = models.IntegerField(default=0, null=True)
premium_interest = models.IntegerField(default=0, null=True)
investment_return = models.IntegerField(default=0, null=True)
withdraw_amount = models.IntegerField(default=0, null=True, blank=True)
balance = models.IntegerField(default=0, null=True, blank=True)
total_available_balance = models.IntegerField(default=0, null=True, blank=True)
locked_balance = models.IntegerField(default=0, null=True, blank=True)
investment_id = models.CharField(max_length=10, null=True, blank=True)
is_active = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now=True, null=True)
due_date = models.DateTimeField(null=True)
def save(self, *args, **kwargs):
if self.plan == "Basic - Daily 2% for 180 Days":
self.basic_interest = self.deposit_amount * 365 * 0.02/2
self.investment_return = self.deposit_amount self.basic_interest
self.due_date = datetime.now() timedelta(seconds=5)
else:
self.premium_interest = self.deposit_amount*365*0.04
self.investment_return = self.deposit_amount self.premium_interest
self.due_date = datetime.now() timedelta(seconds=5)
super(Investment, self).save(*args, **kwargs)
Here are my Model Forms
from django import forms
from .models import Investment
class DateInput(forms.DateInput):
input_type = 'date'
class InvestmentForm(forms.ModelForm):
class Meta:
model = Investment
fields = ['deposit_amount', 'plan']
class WithdrawalForm(forms.ModelForm):
class Meta:
model = Investment
fields = ['withdraw_amount']
Here are my views
from django.shortcuts import get_object_or_404, redirect, render
from django.db.models import Sum, F
from django.contrib import messages
from .forms import (
WithdrawalForm,
InvestmentForm,
)
from .models import (
Investment,
)
def create_investment_view(request):
if request.method == 'POST':
investment_form = InvestmentForm(request.POST)
if investment_form.is_valid():
investment = investment_form.save(commit=False)
investment.is_active = True
investment.save()
messages.success(request, 'your investment of {} is successfull '.format(investment.deposit_amount))
else:
messages.success(request, 'your investment is not successfull! Try again.')
else:
investment_form = InvestmentForm()
context = {'investment_form': investment_form}
return render(request, 'create-investment.html', context)
def create_withdrawal_view(request):
if request.method == 'POST':
withdraw_form = WithdrawalForm(request.POST)
if withdraw_form.is_valid():
investment = withdraw_form.save(commit=False)
investment.investment_return -= investment.withdraw_amount
investment.save()
messages.success(request, 'your Withdrawal is successfull')
else:
messages.success(request, 'Your withdrawal is unsuccesfull. Try again')
else:
withdraw_form = WithdrawalForm()
context = {'withdraw_form': withdraw_form}
return render(request, 'create-withdrawal.html', context)
def list_investments(request):
investments = Investment.objects.all()
total_invested = Investment.objects.aggregate(
total_invested=Sum('deposit_amount'))
total_withdrawned = Investment.objects.aggregate(
total_withdrawned=Sum('withdraw_amount'))
locked_total_balance = Investment.objects.filter(is_active=True).aggregate(
locked_total_balance=Sum('investment_return'))['locked_total_balance']
total_available_balance = Investment.objects.filter(is_active=False).aggregate(
total_available_balance=Sum('investment_return'))['total_available_balance']
context = {
'total_invested': total_invested,
'total_withdrawned': total_withdrawned,
'locked_total_balance': locked_total_balance,
'total_available_balance': total_available_balance,
}
return render(request, 'list-investments.html', context)
CodePudding user response:
If we follow your program logic - in the event of a withdrawal first we hit your view
investment = withdraw_form.save(commit=False)
investment.investment_return -= investment.withdraw_amount
investment.save()
Then investment.save() takes us to your overridden save function, which has something like this
self.premium_interest = self.deposit_amount*365*0.04
self.investment_return = self.deposit_amount self.premium_interest
self.due_date = datetime.now() timedelta(seconds=5)
super(Investment, self).save(*args, **kwargs)
So the save function is overriding the value of investment_return before it gets saved by the call to super.
Because the save() method is used in a lot of contexts that you might not necessarily want to tinker with, rather than pass an argument to your new save method in this case, I'd recommend setting up a special_save() method for your investment model instead, that does exactly want you want to happen in this context and then calls super().save()
As far as getting things to happen when they are due goes - django doesn't handle timed events particularly well without outside help. There are modules for scheduled events such as celery, but they may be overkill. The simplest solution is to use a scheduled event on the operating system, like a cron_job that calls a django admin command, or a module like schedule, that looks for expired events and performs some action on them.