Home > Enterprise >  How can I Implement withdraw amount from investment balance using Django?
How can I Implement withdraw amount from investment balance using Django?

Time:06-20

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)

enter image description here

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.

  • Related