Example #1
0
def convert_currency_mt4(amount, from_currency, to_currency='USD'):
    """Convert amount from one currency to another, no caching"""
    from platforms.mt4.external.models_other import Mt4Quote

    def get_quote(currency):
        try:
            return Mt4Quote.objects.get(
                symbol="USD{}".format(currency.instrument_name))
        except Mt4Quote.DoesNotExist:
            pass
        quote = Mt4Quote.objects.get(
            symbol="{}USD".format(currency.instrument_name))
        return Mt4Quote(ask=1.0 / quote.bid, bid=1.0 / quote.ask)

    to_currency = currencies.get_currency(to_currency)
    from_currency = currencies.get_currency(from_currency)

    if to_currency.slug == "USD":
        rate = 1.0 / get_quote(from_currency).ask
    elif from_currency.slug == "USD":
        rate = get_quote(to_currency).bid
    else:
        rate = get_quote(to_currency).bid / get_quote(from_currency).ask

    if rate == 0:
        raise ValueError("Conversion rate cannot be 0")

    return amount * rate, to_currency
Example #2
0
def convert_currency(amount,
                     from_currency,
                     to_currency,
                     silent=True,
                     for_date=None,
                     cache_key=None):
    """Convert amount from one currency to another, with caching for old rates
    """
    from_currency = currencies.get_currency(from_currency)
    to_currency = currencies.get_currency(to_currency)

    # пришли некорректные валюты
    if from_currency is None or to_currency is None:
        return None, None

    if amount is None:
        log.error(
            'Recieved ammout for currency convert is None most likely connect to accounts db is broken'
        )

    amount = float(amount)

    if from_currency == to_currency:
        return amount, from_currency

    if amount == 0:
        return 0, to_currency

    if for_date is not None and type(for_date) is datetime:
        for_date = for_date.date()

    return convert_currency_mt4(amount, from_currency, to_currency)
Example #3
0
    def test_has_all_attributes(self):
        attrs = ["slug", "verbose_name", "group_regex", "instrument_name", "symbol"]

        r = c.get_currency("USD")
        self.assertTrue(all(map(lambda a: hasattr(r, a), attrs)))

        r = c.get_currency("KUKU")
        self.assertFalse(all(map(lambda a: hasattr(r, a), attrs)))
Example #4
0
    def test_get_currency(self):
        r = c.get_currency("USD")
        self.assertEqual(r, c.USD)

        r = c.get_currency("KUKU")
        self.assertEqual(r, None)

        r = c.get_currency("KUKU", create=True)
        self.assertEqual(r, c.Currency.register["KUKU"])
Example #5
0
def balance(request):
    """
    Returns balance for a given account in the requested currency,
    which defaults to USD, unless no_default_currency is set
    """
    only_digits = re.compile("^[0-9]+$")
    accounts = map(
        int,
        [x for x in request.GET.getlist("accounts[]") if only_digits.match(x)])

    currency = currencies.get_currency(request.GET.get("currency", "USD"))

    accounts = TradingAccount.objects.filter(
        mt4_id__in=accounts, user=request.user).order_by("mt4_id")

    if accounts:
        accounts = {
            account.mt4_id: {
                "balance": account.balance_money.amount,
                "currency": account.currency
            }
            for account in accounts
        }
    else:
        accounts = None

    return convert_balances(accounts, currency) if accounts else None
Example #6
0
    def render(self, context):
        try:
            amount = self.amount.resolve(context)
        # This happens if the balance cannot be calculated
        except (AttributeError, VariableDoesNotExist):
            return ''
        if amount is None:
            return ''

        currency = self.currency.resolve(context)
        currency = currencies.get_currency(currency)

        precision = self.extra_context['precision']

        if isinstance(precision, FilterExpression):
            precision = precision.var.resolve(context)
        return currency.display_amount(amount, precision=precision)
Example #7
0
    def bank_preview_items(self, form):
        items = []

        currency = get_currency(self.currency)

        key = _("Sender")
        val = [self.params["name"]]

        if self.params.get("bank"):
            val.append([
                self.params["country"], self.params["city"],
                self.params["address"]
            ])

        items.append([key, ", ".join(val)])

        if self.params.get("passport_data"):
            items.append([_("Passport data"), self.params["passport_data"]])

        key = _("Amount")
        items.append([key, currency.display_amount(self.amount)])

        for param, value in form.get_bank():
            items.append([_(param), value])

        if self.params.get("bank"):
            items.append([_("Intermediary Bank’s code"), self.params["swift"]])
            items.append([
                _("Payment Details"),
                "According to client agreement %s" % self.account.mt4_id
            ])
        else:
            items.append([
                _("Payment Details"),
                u"%s №%s" %
                (form.get_bank_base(self.account)[5][1], self.account.mt4_id)
            ])
        return [[unicode(k), v] for k, v in items]
Example #8
0
    def save(self, **kwargs):
        log.info("Saving internal transfer issue")
        amount = self.cleaned_data['amount']
        recipient = self.recipient
        sender = self.cleaned_data['sender']
        currency = get_currency(self.cleaned_data["currency"])
        manual = self.cleaned_data["mode"] == "manual"
        log.info(
            "Transfering {amount} {curr} from {sender} to {recipient}".format(
                amount=amount,
                curr=currency,
                sender=sender,
                recipient=recipient))

        if manual and not self.internal:
            # If manual then only issue is created
            result = super(InternalTransferForm, self).save(**kwargs)
            log.debug("Notification: manual_transfer_submitted")
            notification.send(
                [sender.user], "manual_transfer_submitted", {
                    'sender': sender,
                    'recipient': recipient,
                    'amount': amount,
                    'issue': result,
                })
            send_mail(
                "New issue for internal transfer created",
                'sender: {}, recipient: {}\namount: {}, issuetracker: {}'.
                format(
                    sender, recipient, amount, 'arumcapital.eu' +
                    reverse("admin:issuetracker_internaltransferissue_change",
                            args=(result.pk, ))), settings.SERVER_EMAIL,
                settings.BACKOFFICE)
            return result

        withdraw_done = False
        deposit_done = False
        bonus_amount = -1

        try:
            sender.check()
            recipient.check()
            log.info("Withdrawing {}".format(sender))
            sender.change_balance(-float(amount),
                                  amount_currency=currency,
                                  comment="Wdraw IT '%s'" % recipient.mt4_id,
                                  request_id=0,
                                  transaction_type="InternalTransfer")
            withdraw_done = True

            log.info("Depositing {}".format(recipient))
            recipient.change_balance(float(amount),
                                     amount_currency=currency,
                                     comment="Deposit IT '%s'" % sender.mt4_id,
                                     request_id=0,
                                     transaction_type="InternalTransfer")
            deposit_done = True

            # нужно вернуть что-то отличное от None
            return "ok"

        except PlatformError as e:
            log.error("Error transfering funds: {}".format(e.message))
            if e.code == e.NOT_ENOUGH_MONEY:
                if self.internal:
                    self.errors["__all__"] = _(
                        "Sender equity level is insufficient for this operation."
                    )

            msg = "During funds transfer %(from)s => %(to)s error happened. Exactly:\n\n"

            if withdraw_done:
                msg += "- successful withdrawal of %(from_amount)s from %(from)s\n"

                if deposit_done:
                    msg += "- successful deposition of %(to_amount)s to %(to)s\n"
                else:
                    msg += "- failed deposition of %(to_amount)s to %(to)s [" + unicode(
                        e) + u"]\n"
            else:
                msg += "- failed withdrawal of %(from_amount)s from %(from)s [" + unicode(
                    e) + u"]\n"

            kwargs = {
                "from":
                sender,
                "to":
                recipient,
                "from_amount":
                currency.display_amount(amount),
                "to_amount":
                currency.display_amount(amount),
                "bonus_amount":
                sender.currency.display_amount(bonus_amount)
                if bonus_amount is not None else "",
            }

            log.info("Sending emails about failed transfer")
            log.debug("To: {}".format(settings.MANAGERS))
            log.debug("Text: {}".format(msg % kwargs))
            send_mail("Internal transfer %(from)s -> %(to)s FAIL" % kwargs,
                      msg % kwargs, settings.SERVER_EMAIL,
                      [x[1] for x in settings.MANAGERS])
            if self.internal:
                self.errors["__all__"] = (msg % kwargs)
Example #9
0
    def clean(self):
        log.debug("Form clean")
        if self.errors:
            log.debug("There are errors!")
            return self.cleaned_data

        sender = self.cleaned_data["sender"]
        amount = self.cleaned_data["amount"]
        mode = self.cleaned_data["mode"]
        currency = get_currency(self.cleaned_data["currency"])
        log.debug("sender={} amount={} mode={} curr={}".format(
            sender, amount, mode, currency))

        # Delete in Arum?
        if sender.group == RealIBAccountType and not sender.verification.exists(
        ):
            self._errors["sender"] = [
                mark_safe(
                    _('You should <a href="%(link)s" target="_blank">complete the verification process</a> '
                      'before withdrawing from account %(account)s') % {
                          'account':
                          sender.mt4_id,
                          'link':
                          reverse("referral_verify_partner") + "?next=" +
                          self.request.path
                      })
            ]
            return self.cleaned_data

        try:
            log.debug("Checking sender balance")
            from payments.systems.base import WithdrawForm
            withdraw_limit, bonuses = WithdrawForm.get_withdraw_limit_data(
                sender)
            withdraw_limit = withdraw_limit.to(currency)
        except:
            log.error("Can't get balance for sender {}".format(sender))
            self._errors["sender"] = [
                _("Error while getting allowed transfer amount for the "
                  "chosen account. Contact the administrator.")
            ]
            return self.cleaned_data

        if amount > Decimal(withdraw_limit.amount).quantize(Decimal("0.01")):
            log.warn("User asked sum greater then available ({}>{})".format(
                amount, withdraw_limit))
            self._errors["amount"] = [
                _("The maximum amount of money you can transfer from the chosen "
                  "account is %(limit_value)s ") % {
                      "limit_value": withdraw_limit
                  }
            ]

        log.debug("Converting currency")
        converted_amount, currency = convert_currency(amount,
                                                      currency,
                                                      sender.currency,
                                                      silent=False)

        if converted_amount < 0.01:
            log.warn("Sum is less then one cent after conversion!")
            self._errors["amount"] = [
                _("You cannot transfer less than 0.01 in chosen currency")
            ]

        if mode == "manual":
            log.debug("Manual mode")
            recipient_field_name = "recipient_manual" if self.internal else "recipient_auto"

            if not self.cleaned_data[recipient_field_name]:
                self._errors[recipient_field_name] = [
                    _("This field is required")
                ]
                return self.cleaned_data
            # ♿ the problem is we sent other data type when we use self.internal through admin panel
            recipient_id = self.cleaned_data[
                recipient_field_name] if self.internal else self.cleaned_data[
                    recipient_field_name].mt4_id
            recipients = TradingAccount.objects.filter(mt4_id=recipient_id)

            if recipients:
                recipient = recipients[0]
                log.debug("Recepient: {}".format(recipient))
            else:
                self._errors["recipient_manual"] = [
                    _("This account seems not to be registered in the private office. Register it first."
                      )
                ]
                return self.cleaned_data
        else:
            log.debug("Auto mode")
            recipient_field_name = "recipient_auto"

            if not self.cleaned_data[recipient_field_name]:
                self._errors[recipient_field_name] = [
                    _("This field is required")
                ]
                return self.cleaned_data

            recipient = self.cleaned_data[recipient_field_name]
            log.debug("Recepient: {}".format(recipient))

        if recipient.is_demo or recipient.no_inout:
            self._errors[recipient_field_name] = [
                _("You can't transfer money to demo account")
            ]

        if recipient.group is None:
            log.warn("Cant find group for recepient acc: {}".format(recipient))
            self._errors[recipient_field_name] = [
                _('Cannot determine the group of recipient account')
            ]

        # Making sure that a user can't request a transfer, using a single
        # account as both recipient and sender.
        if sender.mt4_id == recipient.mt4_id:
            self._errors[recipient_field_name] = [
                _("Using the same account for both "
                  "recipient and sender is not allowed.")
            ]

        self.recipient = recipient
        self.cleaned_data["recipient"] = recipient.mt4_id

        return self.cleaned_data
Example #10
0
 def clean_currency(self):
     value = self.cleaned_data['currency']
     return currencies.get_currency(value)
Example #11
0
    def clean(self):

        for key in ('account', 'amount', 'currency'):
            if key not in self.cleaned_data:
                return self.cleaned_data
        account = self.cleaned_data["account"]

        if account.is_ib and not account.verification.exists():
            self._errors["account"] = [
                mark_safe(
                    _('You should <a href="%(link)s" target="_blank">complete the verification process</a> '
                      'before withdrawing from account %(account)s') % {
                          'account':
                          account.mt4_id,
                          'link':
                          reverse("referral_verify_partner") + "?next=" +
                          self.request.path
                      })
            ]

        if account.is_disabled:
            self._errors["account"] = [
                _("You can't withdraw funds from this account")
            ]

        # Allow withdrawals only to systems which had successful deposits or to bank
        if not (self.payment_system.slug in ("bankusd", "bankeur", "bankrur")
                or DepositRequest.objects.filter(
                    payment_system=self.payment_system,
                    account__user=account.user,
                    is_committed=True).exists()):
            self._errors["account"] = [
                _("Please withdraw funds using the system which you used for deposit, or "
                  "using wire transfer")
            ]

        # для вебмани все конвертируем в валюту счета,
        # для остальных валюта выбирается в форме
        if self.payment_system.slug == "webmoney":
            to_currency = account.currency
        else:
            to_currency = currencies.get_currency(
                self.cleaned_data["currency"])

        amount = self.cleaned_data['amount']

        min_amount = self._get_min_amount(account)
        if min_amount:
            # получаем минимальное число средств в некоторой валюте
            min_amount, currency = min_amount
            # его нужно сконвертировать в валюту платежной системы
            min_amount, currency = convert_currency(min_amount,
                                                    currency,
                                                    to_currency,
                                                    silent=False)

            if amount < min_amount:
                self._errors["amount"] = [
                    _("Minimal amount of money you can withdraw "
                      "with this payment system is %(limit_value)s%(currency)s"
                      ) % {
                          "limit_value": currencies.round_floor(min_amount),
                          "currency": currency.slug
                      }
                ]
        else:
            if not amount > 0:
                self._errors["amount"] = [_("Enter amount more than %s") % 0]

        try:
            withdraw_limit, bonuses = WithdrawForm.get_withdraw_limit_data(
                account)

            if amount > Decimal(withdraw_limit.amount).quantize(
                    Decimal("0.01")):
                self._errors["amount"] = [_(
                    "Maximal amount of money you can withdraw for a chosen "
                    "account is %(limit_value)s%(currency)s ") % \
                                         {"limit_value": withdraw_limit.amount,
                                              "currency": withdraw_limit.currency.slug}]
        except:
            self._errors["account"] = [
                _('Cannot determine the account balance. Try again later or contact support'
                  )
            ]
        return self.cleaned_data
Example #12
0
    def clean(self):
        """
        Validate deposit request.
        """

        account = (self.cleaned_data["account"])
        # if not DepositRequest.objects.filter(account=account, is_committed=True).exists():
        if self.MAX_AMOUNT and "amount" in self.cleaned_data and "currency" in self.cleaned_data:
            amount = self.cleaned_data["amount"]
            currency = self.cleaned_data["currency"]
            max_amount, max_amount_currency = self.MAX_AMOUNT
            converted_max_amount = convert_currency(max_amount,
                                                    max_amount_currency,
                                                    currency)
            if converted_max_amount[0] < Decimal(
                    amount) - self.total_commision().commission:
                self._errors["amount"] = [
                    _("You cant deposit more than %(amount)s with %(system)s")
                    % {
                        "amount":
                        converted_max_amount[1].display_amount(
                            converted_max_amount[0]),
                        "system":
                        self.payment_system.name
                    }
                ]

        if self.MIN_AMOUNT and "amount" in self.cleaned_data and "currency" in self.cleaned_data:
            amount = self.cleaned_data["amount"]
            currency = self.cleaned_data["currency"]
            min_amount, min_amount_currency = self.MIN_AMOUNT
            converted_min_amount = convert_currency(min_amount,
                                                    min_amount_currency,
                                                    currency)
            if converted_min_amount[0] > Decimal(
                    amount) - self.total_commision().commission:
                self._errors["amount"] = [
                    _("You cant deposit less than %(amount)s with %(system)s")
                    % {
                        "amount":
                        converted_min_amount[1].display_amount(
                            converted_min_amount[0]),
                        "system":
                        self.payment_system.name
                    }
                ]

        cleaned_amount = self.cleaned_data.get("amount")
        cleaned_account = self.cleaned_data.get("account")
        cleaned_currency = self.cleaned_data.get("currency")

        is_first_deposit = not DepositRequest.objects.filter(
            account=account, is_committed=True).exists()

        if cleaned_amount is not None and cleaned_account and cleaned_currency:
            cleaned_amount = float(cleaned_amount)

            if cleaned_amount <= 0:
                self._errors["amount"] = [_('Wrong amount')]

            if cleaned_account.group.min_deposit and self.payment_system.slug != "qiwi":  # If minimum deposit is defined for the account
                to_currency = currencies.get_currency(cleaned_currency)
                account_balance = cleaned_account.get_balance(
                    currency=to_currency, with_bonus=True)[0]
                if account_balance is not None:
                    min_deposit = convert_currency(
                        cleaned_account.group.min_deposit, 'USD',
                        to_currency)[0]

                    if not self.request.user.is_superuser and (
                            account_balance < min_deposit
                            or not is_first_deposit):
                        min_deposit_amount = min_deposit - account_balance
                        if Decimal(cleaned_amount) - self.total_commision(
                        ).commission < min_deposit_amount:
                            self._errors["amount"] = [
                                _('Minimum deposit amount is %(amount)s %(currency)s'
                                  ) % {
                                      'amount': str(round(min_deposit_amount)),
                                      'currency': str(to_currency)
                                  }
                            ]

                else:
                    self._errors["account"] = [
                        _('Cannot determine the account balance. Try again later or contact support'
                          )
                    ]

        return super(DepositForm, self).clean()