示例#1
0
    def post(self, request, gateway, account_pk):
        # Importa dinamicamente o modulo do gateway configurado para a moeda
        gateway_module = importlib.import_module(
            'exchange_payments.gateways.{}'.format(gateway))
        gateway = gateway_module.Gateway()
        account = Accounts.objects.get(pk=account_pk)

        # Validates if transaction already exists in our system
        if Statement.objects.filter(tx_id=request.POST['txn_id']).exists():
            raise Exception('Transaction already exists!')

        # Checa se o deposito pode ser feito
        if gateway.can_deposit(account, request.POST):
            # Adiciona o saldo na conta do usuario, e cria a entrada no extrato
            with transaction.atomic():
                account.deposit += gateway.deposit_amount
                account.save()

                statement = Statement()
                statement.account = account
                statement.description = 'Deposit'
                statement.amount = gateway.deposit_amount
                statement.type = Statement.TYPES.deposit
                statement.tx_id = gateway.tx_id
                statement.save()

                return {'amount': statement.amount}

        return {'error': _("Deposit can't be done.")}
示例#2
0
def check_transaction(output):
    with transaction.atomic():
        accounts = Accounts.objects.filter(address=output['address'])

        if not accounts.exists():
            return

        account = accounts.first()
        print('Processando conta do usuario {}'.format(account.user.username))

        if Statement.objects.filter(account=account,
                                    tx_id=output['id']).exists():
            return

        satoshis = Decimal(output['value'])

        if satoshis < 0:
            return

        amount = satoshis / Decimal('100000000')
        account.deposit += amount
        account.save()

        statement = Statement()
        statement.account = account
        statement.tx_id = output['id']
        statement.amount = amount
        statement.description = 'Deposit'
        statement.type = Statement.TYPES.deposit
        statement.save()

        print("Transfering {} to {} account".format(amount, account.pk))
示例#3
0
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"))
示例#4
0
    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'
            }
示例#5
0
    def post(self, request):
        if not Investments.get_active_by_user(request.user):
            return {'title': _("Error!"), 'message': _("You are not a investor yet, please make a Xfactor investment plan first and go back here to get your card."), 'type': 'error'}
        
        if not Graduations.objects.filter(type=Graduations._advisor, user=request.user).exists():
            return {'title': _("Error!"), 'message': _("You need be a investment advisor first, to request your card."), 'type': 'error'}

        course_subscription_form = CourseSubscriptionForm(request.POST, user=request.user)

        if Statement.objects.filter(account__user=request.user, type='advisor_card_request').exists():
            return {'title': _("Warning!"), 'message': _("Your already have requested your card."), 'type': 'warning'}

        if not course_subscription_form.is_valid():
            return {'errors': course_subscription_form.errors}

        amount = Decimal('0.01')
        checking_account = request.user.accounts.filter(currency__type=Currencies.TYPES.checking).first()

        if amount > checking_account.deposit:
            return {'title': _("Error!"), 'message': _("You not have enought balance for request your card."), 'type': 'error'}
        
        with transaction.atomic():
            statement = Statement()
            statement.description = 'Advisor card request'
            statement.account = checking_account
            statement.type = 'advisor_card_request'
            statement.amount = Decimal('0') - amount
            statement.save()

            checking_account.takeout(amount)

            return {'title': _("Congratulations!"), 'message': _("Your card request has been successfully made."), 'type': 'success'}
示例#6
0
    def handle(self, *args, **options):
        while True:
            with transaction.atomic():
                advisors = Graduations.objects.select_related('user').filter(type=Graduations._advisor).order_by('user__created')
                savings = Plans.objects.get(name__iexact='savings')

                for advisor in advisors:
                    referral_advisors = Statement.objects.filter(type__in=['course_subscription', 'advisor_card_request'], account__user__referral__promoter=advisor.user).count()
                    investment = Investments.get_active_by_user(advisor.user)

                    if referral_advisors < 5:
                        continue

                    if not investment:
                        continue

                    _1 = get_descents([advisor.user], LINE_1_LIMIT)
                    _2 = get_descents(_1, LINE_2_LIMIT)
                    _3 = get_descents(_2, LINE_3_LIMIT)

                    comission_amount = len(_1 + _2 + _3) * savings.membership_fee

                        investment_account = Accounts.objects.get(user=advisor.user, currency__type='investment')
                        items = Statement.objects.filter(account=investment_account, type='profit_sharing_bonus', **date_kwargs)
                        discount = Decimal('0')

                        for item in items:
                            discount += item.amount

                        comission_amount -= discount

                        if comission_amount <= Decimal('0'):
                            continue

                        investment_account.to_deposit(comission_amount)

                        s = Statement()
                        s.account = investment_account
                        s.amount = comission_amount
                        s.description = 'Profit sharing bonus'
                        s.type = 'profit_sharing_bonus'
                        s.save()

                        comission = Comissions()
                        comission.amount = comission_amount
                        comission.investment = investment
                        comission.fk = s.pk
                        comission.save()

                        print('Paying {} of profit sharing to {}'.format(comission_amount, advisor.user.username))

                raise Exception('iasjdaisjdiasd')
示例#7
0
    def post(self, request):
        account = Accounts.objects.filter(user=request.user,
                                          currency__code='BTC',
                                          currency__type='checking').first()
        br_account = Accounts.objects.filter(user=request.user,
                                             currency__code='BRL').first()
        form = RechargeForm(request.POST, user=request.user)

        if not form.is_valid():
            return {'errors': form.errors}

        usd = CurrencyPrice('coinbase')
        br = CurrencyPrice('mercadobitcoin')
        address = request.user.addresses.first()

        if address and address.country.name.lower() == 'brazil':
            quote = br.to_br(1)
        else:
            quote = usd.to_usd(1)

        quote = quote * Decimal('0.93')
        recharge = form.save(commit=False)
        recharge.quote = quote
        btc_amount = round(recharge.amount / quote, 8)

        if btc_amount > account.deposit:
            form.add_error('amount', _("You does not have enought balance"))
            return {'errors': form.errors}

        with transaction.atomic():
            recharge.amount = btc_amount
            recharge.deposit = account.deposit
            recharge.reserved = account.reserved
            recharge.quote = quote
            recharge.card = Cards.objects.filter(
                account__user=request.user).first()
            recharge.save()

            account.takeout(btc_amount)
            amount = Decimal('0') - btc_amount
            statement = Statement(account=account,
                                  amount=amount,
                                  fk=recharge.pk)
            statement.description = 'Card Recharge'
            statement.type = 'card_recharge'
            statement.save()

            card = recharge.card
            card.deposit += recharge.quote_amount
            card.save()

            br_account.to_deposit(recharge.quote_amount)

            return {
                'message_type':
                'success',
                'message_text':
                _("Your recharge has been processed by our team and will be available in your card within 24 hours"
                  )
            }
示例#8
0
    def new_income(self, account, amount, tx_id, fk, date):
        # Transfere o rendimento para a conta do investidor
        account.deposit += amount
        account.save()

        # Cria o extrato do rendimento para o investidor
        statement = Statement(account_id=self.pk,
                              amount=amount,
                              tx_id=tx_id,
                              fk=fk)
        statement.account = account
        statement.description = 'Income'
        statement.type = Statement.TYPES.income
        statement.created = date
        statement.modified = date
        statement.save()

        return statement
示例#9
0
    def handle(self, *args, **options):
        while True:
            txs = rpc_proxy._call('listtransactions')

            for tx in txs:
                with transaction.atomic():
                    # Valida se o tipo e o valor da transacao atendedem os requisitos para deposito
                    if tx['category'] != 'receive' or tx['amount'] <= 0:
                        continue

                    # Pega a conta TCOIN do usuario usando a carteira dele
                    currency = Currencies.objects.get(
                        code=settings.BITCOINZ_CURRENCY_CODE)
                    accounts = Accounts.objects.filter(currency=currency,
                                                       address=tx['address'])

                    # Se a conta para a carteira nao existir, vai para a proxima transacao
                    if not accounts.exists():
                        continue

                    account = accounts.first()

                    # Valida se a transacao ja foi processada
                    statements = Statement.objects.filter(account=account,
                                                          tx_id=tx['txid'])
                    if statements.exists():
                        continue

                    # Deposita o valor para o usuario
                    statement = Statement()
                    statement.account = account
                    statement.amount = Decimal(tx['amount'])
                    statement.description = 'Deposit'
                    statement.type = Statement.TYPES.deposit
                    statement.tx_id = tx['txid']
                    statement.save()

                    account.deposit += Decimal(tx['amount'])
                    account.save()

                    print('Pagando {} para a conta Bitcoin Z do usuario {}'.
                          format(tx['amount'], account.user.username))

            time.sleep(settings.BITCOINZ_CONFIRM_PAYMENTS_WAIT_SECONDS)
示例#10
0
    def post(self, request):
        # Valor a ser emprestado
        amount = round(Decimal(request.POST.get('amount').replace(',', '.')),
                       8)

        investment = Investments.get_active_by_user(request.user)
        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 credit['overdraft']['available'] >= amount and amount >= Decimal(
                '0.001'):
            with transaction.atomic():
                checking_account.to_deposit(amount)

                statement = Statement()
                statement.account = checking_account
                statement.description = 'New overdraft'
                statement.amount = amount
                statement.type = 'overdraft'
                statement.save()

                # Cria o novo credito
                overdraft = Overdrafts()
                overdraft.account = investment.account
                overdraft.statement = statement
                overdraft.borrowed_amount = amount
                overdraft.total_amount = amount
                overdraft.due_date = timezone.now() + timedelta(
                    days=investment.plan_grace_period.plan.overdraft_free_days)
                overdraft.save()

            return {
                'message_text':
                _("Your credit application was created with success!"),
                'message_type':
                'success'
            }
示例#11
0
    def post(self, request):
        account = Accounts.objects.filter(user=request.user,
                                          currency__code='BRL',
                                          currency__type='checking').first()
        form = BankSlipForm(request.POST, user=request.user)

        if not form.is_valid():
            return {'errors': form.errors}

        amount = form.cleaned_data['amount']
        if amount > account.deposit:
            form.add_error('amount', _("You does not have enought balance"))
            return {'errors': form.errors}

        with transaction.atomic():
            boleto = form.save(commit=False)
            boleto.card = Cards.objects.filter(
                account__user=request.user).first()
            boleto.payer_name = request.user.name
            boleto.payer_document = request.user.document_1
            boleto.save()

            account.takeout(amount)
            amount = Decimal('0') - amount
            statement = Statement(account=account, amount=amount, fk=boleto.pk)
            statement.description = 'Bank slip payment'
            statement.type = 'bank_slip_payment'
            statement.save()

            card = boleto.card
            card.deposit -= abs(boleto.amount)
            card.save()

            account.takeout(abs(boleto.amount))

            return {
                'message_type':
                'success',
                'message_text':
                _("Your bank slip has been processed by our team and will be paid within 24 hours"
                  )
            }
示例#12
0
    def post(self, request):
        coin = request.POST['coin']
        # O POST e imutavel por default, sendo assim,
        # precisamos alterar essa caracteristica do object para alterar seus valores
        request.POST._mutable = True

        # Define um valor padrao para o address caso o deposito seja em reais
        # Fazemos isto, pois esse campo precisa passar pela validacao do formulario
        if coin == settings.BRL_CURRENCY_CODE:
            request.POST['address'] = 'whatever'
        # Define um valor padrao para code do two factor, caso o usuario nao tenha configurado ele ainda
        # Fazemos isto, pois esse campo precisa passar pela validacao do formulario
        if not user_has_device(request.user):
            request.POST['code'] = '123'

        account = Accounts.objects.get(user=request.user,
                                       currency__code=coin,
                                       currency__type=CHECKING_TYPE)
        withdraw_form = NewWithdrawForm(request.POST,
                                        user=request.user,
                                        account=account)

        if not withdraw_form.is_valid():
            return {'status': 'error', 'errors': withdraw_form.errors}

        fee = (withdraw_form.cleaned_data['amount'] *
               (account.currency.withdraw_fee /
                100)) + account.currency.withdraw_fixed_fee
        system_accounts = Accounts.objects.filter(
            address=withdraw_form.cleaned_data['address'])
        is_tbsa = False

        if coin != settings.BRL_CURRENCY_CODE and system_accounts.exists():
            fee = (withdraw_form.cleaned_data['amount'] *
                   (account.currency.tbsa_fee /
                    100)) + account.currency.tbsa_fixed_fee
            amount_with_fee = abs(withdraw_form.cleaned_data['amount']) - fee

            if amount_with_fee < 0:
                amount_with_fee = 0

            system_account = system_accounts.first()
            system_account.deposit += amount_with_fee
            system_account.save()

            tbsa_statement = Statement()
            tbsa_statement.account = system_account
            tbsa_statement.description = 'TBSA'
            tbsa_statement.type = Statement.TYPES.tbsa
            tbsa_statement.amount = abs(withdraw_form.cleaned_data['amount'])
            tbsa_statement.save()

            is_tbsa = True

        with transaction.atomic():
            if coin == settings.BRL_CURRENCY_CODE:
                withdraw = BankWithdraw()
            else:
                withdraw = CryptoWithdraw()

            withdraw.account = account
            withdraw.deposit = account.deposit
            withdraw.reserved = account.reserved
            withdraw.amount = Decimal(
                '0.00') - withdraw_form.cleaned_data['amount']
            withdraw.fee = fee

            if coin == settings.BRL_CURRENCY_CODE:
                br_bank_account = request.user.br_bank_account

                withdraw.bank = br_bank_account.bank
                withdraw.agency = br_bank_account.agency
                withdraw.agency_digit = br_bank_account.agency_digit
                withdraw.account_type = br_bank_account.account_type
                withdraw.account_number = br_bank_account.account_number
                withdraw.account_number_digit = br_bank_account.account_number_digit
            else:
                withdraw.address = withdraw_form.cleaned_data['address']

            withdraw.save()

            if coin != settings.BRL_CURRENCY_CODE and not is_tbsa:
                withdraw_hash = encrypt(settings.SECRET_KEY,
                                        str(withdraw.pk)).hex()
                approve_link = settings.DOMAIN + reverse(
                    'payments>approve-withdraw',
                    kwargs={'withdraw_hash': withdraw_hash})

                # Sends withdraw confirmation e-mail to admin
                send_templated_mail(
                    template_name='approve-withdraw',
                    from_email=settings.DEFAULT_FROM_EMAIL,
                    context={
                        'withdraw': withdraw,
                        'approve_link': approve_link
                    },
                    recipient_list=settings.WITHDRAW_APPROVE_EMAILS)

                if settings.WITHDRAW_USER_SEND_CONFIRMATION:
                    # Sends withdraw confirmation e-mail to user
                    send_templated_mail(template_name='approve-withdraw',
                                        from_email=settings.DEFAULT_FROM_EMAIL,
                                        context={
                                            'withdraw': withdraw,
                                            'approve_link': approve_link
                                        },
                                        recipient_list=[request.user.email])

            account.deposit -= abs(withdraw.amount)
            account.save()

            statement = Statement()
            statement.account = account
            statement.description = 'Withdraw'
            statement.type = Statement.TYPES.withdraw
            statement.amount = Decimal('0.00') - abs(withdraw.amount)
            statement.save()

            return {'status': 'success', 'amount': withdraw.amount}
示例#13
0
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))
示例#14
0
    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.")
        }
示例#15
0
    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
        }
示例#16
0
    def post(self, request):
        coin = request.POST['coin']
        # O POST e imutavel por default, sendo assim, 
        # precisamos alterar essa caracteristica do object para alterar seus valores
        request.POST._mutable = True
        # Fazemos isto, pois esse campo precisa passar pela validacao do formulario
        request.POST['address'] = 'whatever'
        # Define um valor padrao para code do two factor, caso o usuario nao tenha configurado ele ainda
        # Fazemos isto, pois esse campo precisa passar pela validacao do formulario
        if not user_has_device(request.user):
            request.POST['code'] = '123'

        account = Accounts.objects.get(user=request.user, currency__code='BTC', currency__type=Currencies.TYPES.investment)
        withdraw_form = NewWithdrawForm(request.POST, user=request.user, account=account)

        if not withdraw_form.is_valid():
            return {'status': 'error', 'errors': withdraw_form.errors}

        fee = (withdraw_form.cleaned_data['amount'] * (account.currency.withdraw_fee / 100)) + account.currency.withdraw_fixed_fee
        checking_account = Accounts.objects.get(user=request.user, currency__code='BTC', currency__type=Currencies.TYPES.checking)

        with transaction.atomic():
            amount = abs(withdraw_form.cleaned_data['amount'])

            statement = Statement()
            statement.account = account
            statement.amount = Decimal('0.00') - amount
            statement.description = 'Income Withdrawal'
            statement.type = 'income_withdraw'
            statement.save()

            account.takeout(amount)

            statement = Statement()
            statement.account = checking_account
            statement.amount = (amount - abs(fee))
            statement.description = 'Income Deposit'
            statement.type = 'income_deposit'
            statement.save()

            checking_account.to_deposit((amount - abs(fee)) )

            return {'status': 'success', 'amount': amount}