def reverse_crypto_withdraw(_, request, queryset): with transaction.atomic(): for withdraw in queryset.select_related('account__user', 'account__currency'): with transaction.atomic(): if withdraw.status == CryptoWithdraw.STATUS.reversed: continue if Statement.objects.filter( fk=withdraw.pk, type=Statement.TYPES.reversed).exists(): continue account = withdraw.account account.deposit += abs(withdraw.amount) account.save() statement = Statement() statement.account = account statement.type = Statement.TYPES.reversed statement.description = "Reverse" statement.amount = abs(withdraw.amount) statement.fk = withdraw.pk statement.save() withdraw.status = CryptoWithdraw.STATUS.reversed withdraw.save() messages.success(request, _("Withdraw successfully reversed"))
def post(self, request): # Valor a ser emprestado amount = round(Decimal(request.POST.get('amount').replace(',', '.')), 8) # Numero de parcelas do empréstimo segundo a tabela times = int(request.POST.get('times')) investment = Investments.get_active_by_user(request.user) installments = generate_fixed_loan_table(investment, amount, times=times, raw_date=True) checking_account = Accounts.objects.filter( user=request.user, currency__code=investment.account.currency.code, currency__type=Currencies.TYPES.checking).first() credit = Investments.get_credit_by_user(request.user) if times <= len(installments['data']) and credit['loan'][ 'available'] >= amount and amount >= Decimal('0.001'): # Faz tudo via transação no banco with transaction.atomic(): checking_account.to_deposit(amount) # Cria um novo empréstimo associando o saldo negativo a ele loan = Loans() loan.account = investment.account loan.borrowed_amount = amount loan.total_amount = installments['data'][0]['total_amount'] loan.times = times loan.save() # Cria o saldo negativo do empréstimo statement = Statement() statement.account = checking_account statement.description = 'New loan' statement.type = 'loan' statement.amount = amount statement.fk = loan.pk statement.save() for installment in installments['data']: # Cria as parcelas inst = Installments() inst.loan = loan inst.order = installment['times'] inst.due_date = installment['payment_date'] inst.interest_percent = installment['interest_percent'] inst.amount = Decimal(installment['amount']) inst.save() return { 'message_text': _("Your loan application was created with success!"), 'message_type': 'success' }
def withdraw_investments(): for item in Investments.objects.order_by('paid_date'): with transaction.atomic(): reinvestments_qs = Reinvestments.objects.filter(investment=item, status=Reinvestments.STATUS.paid).order_by('created') reinvestment = reinvestments_qs.first() main_investment_was_paid = Statement.objects.filter(fk=item.pk, type=STATEMENT_TYPE).exists() remaining_days = item.remaining_days foreign_key = item.pk message_amount = item.amount if not reinvestment and item.status == Investments.STATUS.consumed: continue if reinvestment and main_investment_was_paid: remaining_days = reinvestment.remaining_days foreign_key = reinvestment.pk if Statement.objects.filter(type=foreign_key).exists(): continue # Skip if investment grace period not ends yet if not remaining_days <= 0: continue account = item.account withdraw_fee = item.account.currency.withdraw_fee withdraw_fixed_fee = item.account.currency.withdraw_fixed_fee total_amount = account.deposit + account.reserved reserved = 0 if reinvestment: if main_investment_was_paid: message_amount = reinvestment.amount reserved = account.reserved - reinvestment.amount total_amount = total_amount - reserved reinvestment.status = Reinvestments.STATUS.consumed reinvestment.save() else: message_amount = reinvestment.amount_before reserved = account.reserved - reinvestment.amount_before total_amount = total_amount - reserved discount = (total_amount * (withdraw_fee / 100)) + withdraw_fixed_fee pay_amount = total_amount - discount account.deposit = 0 account.reserved = reserved account.save() checking_account = Accounts.objects.filter(user=account.user, currency__type=Currencies.TYPES.checking).first() checking_account.to_deposit(pay_amount) statement = Statement() statement.amount = Decimal('0') - total_amount statement.description = 'Termination of investment plan' statement.type = STATEMENT_TYPE statement.account = account statement.fk = foreign_key statement.save() statement = Statement() statement.amount = pay_amount statement.description = 'Return of invested amount' statement.type = STATEMENT_TYPE_RETURN statement.account = checking_account statement.fk = foreign_key statement.save() still_has_reinvestments = reinvestments_qs.exists() item.amount = reserved item.save() if not still_has_reinvestments: item.status = Investments.STATUS.consumed item.save() else: # Downgrade plan plan = Plans.get_by_amount(reserved) if plan.pk != item.plan_grace_period.plan.pk: plan_grace_period = PlanGracePeriods.objects.get(plan=plan, grace_period=item.plan_grace_period.grace_period) item.plan_grace_period = plan_grace_period item.save() # Remove all incomes and recalc them start_date = timezone.now() + timedelta(days=1) last_reinvestment = Reinvestments.objects.filter(investment=item).order_by('-created').first() end_date = last_reinvestment.end_date Incomes.objects.filter(investment=item, date__gte=start_date.date(), date__lte=end_date.date()).delete() if last_reinvestment.remaining_months <= 0: continue range_dates = list(rrule(DAILY, dtstart=start_date, until=end_date)) income_amount = (item.amount * (plan_grace_period.income_percent / 100)) * last_reinvestment.remaining_months income_table = decimal_split(income_amount, len(range_dates), 98, 100) date_index = 0 bulk_incomes = [] for dt in range_dates: income = Incomes() income.date = dt income.amount = income_table[date_index] income.investment = item bulk_incomes.append(income) date_index += 1 Incomes.objects.bulk_create(bulk_incomes) print('Auto withdraw (re)investment of {} from {} user'.format(message_amount, item.account.user.username))
def post(self, request): if Investments.get_active_by_user(self.request.user): return {'message': _("ERROR! You already have a investment")} grace_period_pk = request.POST['grace_period'] grace_period = PlanGracePeriods.objects.get(pk=grace_period_pk) checking_account = Accounts.objects.get( user=request.user, currency__code=grace_period.currency.code, currency__type=Currencies.TYPES.checking) investment_account = Accounts.objects.get( user=request.user, currency=grace_period.currency) amount = request.POST.get('amount', '0.00').replace(',', '.') amount = ''.join(c for c in amount if c.isdigit() or c == '.') if not amount: amount = '0.00' amount = Decimal(amount) amount_with_fee = amount + grace_period.plan.membership_fee min_invest = grace_period.plan.min_down max_invest = grace_period.plan.max_down if min_invest > amount or max_invest < amount: return { 'message': _("ERROR! The investment amount it is out of the plan limit") } elif amount_with_fee > checking_account.deposit: return { 'message': _("ERROR! Your {} account does not have enought deposit amount" .format(checking_account.currency.name)) } else: with transaction.atomic(): investment = Investments() investment.plan_grace_period = grace_period investment.account = investment_account investment.amount = amount investment.status = Investments.STATUS.paid investment.membership_fee = grace_period.plan.membership_fee investment.paid_date = timezone.now() investment.save() if grace_period.grace_period.months > 0: start_date = datetime.now() + timedelta(days=1) end_date = start_date + relativedelta( months=grace_period.grace_period.months) range_dates = list( rrule(DAILY, dtstart=start_date, until=end_date)) income_amount = (amount * (grace_period.income_percent / 100)) * grace_period.grace_period.months income_table = decimal_split(income_amount, len(range_dates), 98, 100) date_index = 0 bulk_incomes = [] for dt in range_dates: income = Incomes() income.date = dt income.amount = income_table[date_index] income.investment = investment bulk_incomes.append(income) date_index += 1 Incomes.objects.bulk_create(bulk_incomes) checking_account.deposit -= amount_with_fee checking_account.save() investment_account.reserved += amount investment_account.save() statement = Statement() statement.account = checking_account statement.amount = Decimal('0.00') - amount_with_fee statement.type = Statement.TYPES.investment statement.description = 'New investment' statement.fk = investment.pk statement.save() statement = Statement() statement.account = investment_account statement.amount = amount statement.type = Statement.TYPES.investment statement.description = 'New investment' statement.fk = investment.pk statement.save() return { 'message': _("Congratulations! Your investing plan was created."), 'redirect': True } return { 'message': _("Someting in your new investment plan didn't work as expected.") }
def post(self, request): investment = Investments.get_by_user(request.user) reinvestment_old_invest = investment.plan_grace_period reinvestment_amount_before = investment.account.reserved reinvestment_incomes = investment.account.deposit grace_period_pk = request.POST['grace_period'] grace_period = PlanGracePeriods.objects.get(pk=grace_period_pk) use_checking = request.POST['use_checking'] in ['true', '1'] if grace_period.grace_period.months < investment.plan_grace_period.grace_period.months: return {'message': _("ERROR! Selected grace period is not valid.")} checking_account = Accounts.objects.get( user=request.user, currency__code=grace_period.currency.code, currency__type=Currencies.TYPES.checking) investment_account = Accounts.objects.get( user=request.user, currency=grace_period.currency) amount = request.POST.get('amount', '0.00').replace(',', '.') amount = ''.join(c for c in amount if c.isdigit() or c == '.') if not amount: amount = '0.00' amount = Decimal(amount) reinvestment_amount = amount membership_fee = Decimal('0.00') amount_with_fee = amount + membership_fee amount_with_investment = amount + investment.amount reinvest_plan = Plans.objects.filter( min_down__lte=amount_with_investment, max_down__gte=amount_with_investment).order_by( '-max_down').first() min_reinvest = grace_period.plan.min_reinvest months = grace_period.grace_period.months grace_period = PlanGracePeriods.objects.get( plan=reinvest_plan, grace_period__months=months) reinvestment_new_invest = grace_period # Se for um upgrade, soma a diferenca do membership_fee if reinvest_plan and reinvest_plan.pk != investment.plan_grace_period.plan.pk: membership_fee = (reinvest_plan.membership_fee - investment.plan_grace_period.plan.membership_fee) amount_with_fee = amount + membership_fee reinvestment_membership_fee = membership_fee # Saldo para validacao do reinvestimento balance = investment_account.deposit if use_checking: balance += checking_account.deposit # Valida se o valor minimo de reinvestimento e compativel com o reinvestimento desejado if min_reinvest > amount: return { 'message': _("ERROR! The min reinvestment for this plan is {}").format( min_reinvest) } if amount_with_fee > balance: return {'message': _("ERROR! You does not have enought balance")} with transaction.atomic(): investment.plan_grace_period = grace_period investment.amount = amount_with_investment investment.status = Investments.STATUS.paid investment.membership_fee = membership_fee investment.paid_date = timezone.now() investment.save() if grace_period.grace_period.months > 0: start_date = datetime.now() + timedelta(days=1) end_date = start_date + relativedelta( months=grace_period.grace_period.months) Incomes.objects.filter(investment=investment, date__gte=start_date.date(), date__lte=end_date.date()).delete() range_dates = list( rrule(DAILY, dtstart=start_date, until=end_date)) income_amount = (amount_with_investment * (grace_period.income_percent / 100)) * grace_period.grace_period.months income_table = decimal_split(income_amount, len(range_dates), 98, 100) date_index = 0 bulk_incomes = [] for dt in range_dates: income = Incomes() income.date = dt income.amount = income_table[date_index] income.investment = investment bulk_incomes.append(income) date_index += 1 Incomes.objects.bulk_create(bulk_incomes) discount_amount = investment_account.deposit - amount_with_fee if discount_amount < Decimal('0.00'): statement = Statement() statement.account = investment_account statement.amount = Decimal('0.00') - investment_account.deposit statement.type = 'reinvestment' statement.description = 'New reinvestment' statement.fk = investment.pk statement.save() investment_account.deposit = Decimal('0.00') investment_account.save() else: statement = Statement() statement.account = investment_account statement.amount = Decimal('0.00') - amount_with_fee statement.type = 'reinvestment' statement.description = 'New reinvestment' statement.fk = investment.pk statement.save() investment_account.takeout(amount_with_fee) if use_checking and discount_amount < Decimal('0.00'): checking_account.takeout(abs(discount_amount)) statement = Statement() statement.account = checking_account statement.amount = discount_amount statement.type = 'reinvestment' statement.description = 'New reinvestment' statement.fk = investment.pk statement.save() investment_account.reserved += amount investment_account.save() statement = Statement() statement.account = investment_account statement.amount = amount statement.type = 'reinvestment' statement.description = 'New reinvestment' statement.fk = investment.pk statement.save() reinvestment = Reinvestments() reinvestment.old_invest = reinvestment_old_invest reinvestment.new_invest = reinvestment_new_invest reinvestment.amount = reinvestment_amount reinvestment.amount_before = reinvestment_amount_before reinvestment.incomes = reinvestment_incomes reinvestment.membership_fee = reinvestment_membership_fee reinvestment.investment = investment reinvestment.save() return { 'message': _("Congratulations! Your reinvesting plan was created."), 'redirect': True }