예제 #1
0
    def get_balance(self, currency=None, with_bonus=False):
        # type: (Currency, bool) -> Tuple[float, Currency]
        from platforms.converter import convert_currency
        balance = normalize(self, self.api.account_balance(self))

        #if we should return value as it is, return with original currency
        if not currency:
            return balance, self.currency

        return convert_currency(balance, self.currency, currency)
예제 #2
0
    def clean(self):
        amount = convert_currency(self.cleaned_data["amount"],
                                  self.cleaned_data["currency"], "RUR")[0]

        if amount > 15000:
            self.add_error(
                "amount",
                ValidationError(
                    _("You cannot withdraw more than %(amount)s in one request"
                      ) % {
                          "amount": display_amount(15000),
                      }))

        return super(WithdrawForm, self).clean()
예제 #3
0
    def clean(self):
        if 'currency' in self.cleaned_data and 'amount' in self.cleaned_data:
            amount = convert_currency(self.cleaned_data['amount'],
                                      self.cleaned_data['currency'],
                                      'RUB',
                                      for_date=datetime.now().date())[0]
            # if amount > 15000:
            #     self.add_error('amount', _("QIWI doesn't support one-time payments of more "
            #                                "than 15000 roubles. If you need to deposit more "
            #                                "money via QIWI, just commit several payments."))
            if amount < 5:
                self.add_error('amount', _("Amount should be above 5 roubles"))

        return super(DepositForm, self).clean()
예제 #4
0
 def save(self, **kwargs):
     if not self.pk:
         try:  # This can fail at a query to MT4 (for example Webmoney fails like this)
             self._is_automatic = self.automatic
         except:  # But we nevertheless should save it no matter what
             pass
         if self.account.currency != self.currency:
             self.conversion_rate = convert_currency(
                 1, self.currency, self.account.currency)[0]
     if isinstance(self, DepositRequest):
         c = self.payment_system.DepositForm.calculate_commission(self)
         self.commission = c.commission
         self.currency = c.currency
     return super(BaseRequest, self).save(**kwargs)
예제 #5
0
    def _calculate_commission(cls, request):
        from decimal import Decimal
        from platforms.converter import convert_currency

        commission = 40

        commission = Decimal(
            convert_currency(commission,
                             from_currency=EUR,
                             to_currency=request.currency,
                             for_date=request.creation_ts)[0])

        return CommissionCalculationResult(amount=request.amount,
                                           commission=commission,
                                           currency=request.currency)
예제 #6
0
 def to(self, currency, for_date=None, cache_key=None):
     currency = get_currency(currency)  # ensure currency object
     if self.currency == currency:
         return copy(self)
     try:
         amount = float(convert_currency(
             self.amount,
             from_currency=self.currency,
             to_currency=currency,
             for_date=for_date,
             cache_key=cache_key or self._convert_cache_key)[0])
     except Exception as e:
         from django.conf import settings
         if not settings.DEBUG:
             raise e
         print e
         return NoneMoney()
     return Money(amount, currency)
예제 #7
0
def convert_balances(accounts, to_currency):
    results = {}

    for acc_id, acc in accounts.iteritems():
        if acc["balance"] is None:
            continue
        elif to_currency is None:
            b, c = acc["balance"], acc["currency"]
        else:
            b, c = convert_currency(acc["balance"], acc["currency"],
                                    to_currency)

        results[acc_id] = {
            "balance":
            c.display_amount(b, with_slug=c.slug) if b is not None else "",
            "currency": c.slug
        }

    return results
예제 #8
0
def get_account_requests_stats(account=None):
    from collections import defaultdict
    from datetime import datetime, timedelta
    from payments.models import DepositRequest
    from platforms.models import TradingAccount
    from platforms.converter import convert_currency

    if account.is_ib:
        agents = account.agent_clients.values_list("login", flat=True)
        accounts_list = TradingAccount.objects.filter(mt4_id__in=list(agents))
    else:
        accounts_list = account.user.accounts.all()

    stats = defaultdict(float)
    systems = {}
    for acc in accounts_list:
        x = [(x.payment_system, x.amount, x.currency)
             for x in DepositRequest.objects.filter(account=acc, is_committed=True)]

        for system, amount, currency in x:
            if isinstance(system, basestring):
                system = load_payment_system("payments.system.%s" % system)
                if system is None:
                    continue

            sys_name = unicode(system)
            stats[sys_name] += float(convert_currency(amount=amount, from_currency=currency, to_currency="USD",
                                                      for_date=datetime.today()-timedelta(2))[0])
            if sys_name not in systems:
                systems[sys_name] = system

    summ = sum(stats.values())
    res = []

    for system in stats:
        percent = int(stats[system]/summ*100) if summ > 0 else 0
        res.append((systems[system], round(stats[system], 2), percent))

    return res
예제 #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
예제 #10
0
def utm_report(request):
    if request.POST:
        form = UtmReportForm(request.POST)
        if form.is_valid():
            utms = UtmAnalytics.objects.all()
            if form.cleaned_data['utm_source']:
                utms = utms.filter(
                    utm_source__in=form.cleaned_data['utm_source'])
            if form.cleaned_data['utm_medium']:
                utms = utms.filter(
                    utm_medium__in=form.cleaned_data['utm_medium'])
            if form.cleaned_data['utm_campaign']:
                utms = utms.filter(
                    utm_campaign__in=form.cleaned_data['utm_campaign'])
            user_count = utms.filter(
                user__date_joined__gte=form.cleaned_data['date_from'],
                user__date_joined__lte=form.cleaned_data['date_to'],
            ).count()
            mt4_accounts = TradingAccount.objects.filter(
                user__utm_analytics__in=utms,
                creation_ts__gte=form.cleaned_data['date_from'],
                creation_ts__lte=form.cleaned_data['date_to'],
            )
            groups_accounts = {}
            # Okay, that seems like a slow code, but we don't have any better means to reliably determine group
            for mt4_acc in mt4_accounts:
                groups_accounts.setdefault(mt4_acc.group, []).append(mt4_acc)
            groups_count = {
                group: len(accounts)
                for group, accounts in groups_accounts.iteritems()
            }
            groups_deposit = {}
            for group, accs in groups_accounts.iteritems():
                deposits = DepositRequest.objects.filter(
                    is_committed=True,
                    is_payed=True,
                    account__pk__in=map(lambda x: x.pk, accs),
                )
                sum_usd = 0
                for deposit in deposits:
                    sum_usd += convert_currency(
                        deposit.amount,
                        from_currency=deposit.currency,
                        to_currency='USD',
                        for_date=form.cleaned_data['date_from'])[0]
                groups_deposit[group] = sum_usd

            groups = sorted(groups_count.keys())

            return {
                'form': form,
                'should_show_form': True,
                'report': {
                    'data': {
                        'groups':
                        groups,
                        'user_count':
                        user_count,
                        'groups_count':
                        (groups_count[group] for group in groups),
                        'groups_deposit':
                        (groups_deposit[group] for group in groups),
                    }
                }
            }

    else:
        form = UtmReportForm()

    return {'form': form, 'should_show_form': True}
예제 #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
예제 #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()
예제 #13
0
    def make_payment(self, comment=None):
        log.debug("Making payment ID = %s..." % self.id)
        if self.is_committed:
            log.debug("Oops, already committed; terminating")
            return

        if isinstance(self, DepositRequest):
            form = self.payment_system.DepositForm
            is_deposit = True
            self.is_committed = True  # We must take all care to not process same deposit twice
            self.save(refresh_state=True)
            c = self.payment_system.DepositForm.calculate_commission(self)
            c_full = self.payment_system.DepositForm.calculate_commission(
                self, full_commission=True)
            amount = c_full.amount - c_full.commission  # Will be deposited as ExternalPay
            bonus_amount = c.amount - c.commission - amount  # Commission compensation, deposited as BonusPaid
            if bonus_amount < Decimal("0.01"):
                bonus_amount = 0
        elif isinstance(self, WithdrawRequest):
            is_deposit = False
            amount = -self.amount
            bonus_amount = 0
            form = self.payment_system.WithdrawForm
        else:
            log.debug("Oops, unknown request type; terminating")
            raise TypeError("Unknown request type: %r" % type(self))

        if self.account.currency != self.currency:
            if self.conversion_rate:
                amount = float(amount) * self.conversion_rate
                bonus_amount = float(bonus_amount) * self.conversion_rate
            else:
                amount = convert_currency(amount,
                                          from_currency=self.currency,
                                          to_currency=self.account.currency)[0]
                bonus_amount = convert_currency(
                    bonus_amount,
                    from_currency=self.currency,
                    to_currency=self.account.currency)[0]
                mail_admins(
                    u"Payment request id={} processed without saved exchange rate!"
                    .format(self.pk), "")

        try:
            comment = comment or form.generate_mt4_comment(self)
        except Exception as e:
            log.debug("Oops, couldnt generate comment: %s; terminating" %
                      unicode(e))
            comment = unicode(self.id)

        try:
            log.debug("Sending change_balance command to TradingAccount...")
            res = self.account.change_balance(
                amount=amount,
                request_id=form.generate_mt4_request_id(self),
                comment=comment,
                transaction_type="ExternalPay")
            if bonus_amount:
                self.account.change_balance(
                    amount=bonus_amount,
                    request_id=form.generate_mt4_request_id(self) + 'B',
                    comment=comment,
                    transaction_type="BonusPaid")

            if is_deposit \
                    and self.needs_verification \
                    and not (self.params.get('cardnumber') and
                             self.account.user.profile.is_card_verified(self.params['cardnumber'])):
                self.account.block(
                    block_reason=TradingAccount.REASON_CHARGEBACK)
                self.params['chargeback_suspect'] = True
                user_profile = self.account.user.profile
                if not user_profile.manager:
                    user_profile.autoassign_manager(force=True)
                # self.account.user.gcrm_contact.add_task(u"Client's account blocked to prevent chargeback. "
                #                                          u"Monitor the situation.")

                notification.send(
                    [self.account.user], "deposit_needs_verification", {
                        "paymentrequest": self,
                        'usd_amount': self.amount_money.to("USD")
                    })

        except PlatformError as e:

            log.debug("Command change_balance failed: %s" % unicode(e))

            if is_deposit:
                self.is_committed = None
            else:
                self.is_payed = False

                send_mail(
                    u"Withdraw request failed",
                    u"Withdraw request failed:\n"
                    u"https://%s%s\n\n"
                    u"Error: %s" %
                    (settings.ROOT_HOSTNAME, get_admin_url(self), unicode(e)),
                    from_email=settings.SERVER_EMAIL,
                    recipient_list=[x[1] for x in settings.ADMINS])

                Logger(user=None,
                       content_object=self,
                       ip=None,
                       event=Events.WITHDRAW_REQUEST_FAILED,
                       params={
                           'error': e.message
                       }).save()
            self.save()
            raise e
        else:
            if res is not None:
                self.refresh_state()
                self.trade_id = res.get("order_id")
                self.save(refresh_state=False)
                log.debug("Payment OK. OrderID = %s" % self.trade_id)
            else:
                log.debug("Payment OK, but OrderID is unknown :(")

            Logger(user=None,
                   content_object=self,
                   ip=None,
                   event=Events.WITHDRAW_REQUEST_PAYED).save()
예제 #14
0
    def init_data(self, request):
        if not request.user.accounts.alive().non_demo().exists():
            return Response({"has_no_accounts": True})
        most_recent_deposit = DepositRequest.objects \
            .filter(account__in=request.user.accounts.all()) \
            .exclude(payment_system="office").last()
        if most_recent_deposit:
            most_recent_deposit = most_recent_deposit.payment_system

        most_recent_withdraw = WithdrawRequest.objects \
            .filter(account__in=request.user.accounts.all()) \
            .exclude(payment_system="office").last()
        if most_recent_withdraw:
            most_recent_withdraw = most_recent_withdraw.payment_system

        symbols = Mt4Quote.objects \
            .filter(symbol__in=['USDEURconv', 'USDRUBconv']) \
            .only('symbol', 'bid', 'ask', 'digits')

        columns = [
            s[3:6] for s in symbols.exclude(
                symbol='USDUAHconv').values_list('symbol', flat=True)
        ]
        columns.insert(0, u'USD')

        table = {}

        for row in [u'USD', u'RUB', u'EUR']:
            table[row] = []
            for column in columns:
                if row == column:
                    value = (1, 1)
                else:
                    if column == "XAG":
                        column = "SILVER"
                    elif column == "XAU":
                        column = "GOLD"
                    try:
                        value = (
                            round(convert_currency(1, row, column)[0], 4),
                            round(1 / convert_currency(1, column, row)[0], 4),
                        )
                    except:
                        value = (0, 0)
                table[row].append(value)
        systems_list = get_payment_systems()

        # Convers payment system objects to simple object
        for op, op_data in systems_list.items():
            for psgroup, psgroup_data in op_data.items():
                for sys, sys_data in psgroup_data["systems"].items():
                    psgroup_data["systems"][sys] = {
                        'slug': sys,
                        'name': u'%s' % sys_data.name,
                        'deposit_redirect': sys_data.deposit_redirect
                    }
        return Response({
            "systems_list": systems_list,
            "most_recent": {
                "deposit": most_recent_deposit,
                "withdraw": most_recent_withdraw
            },
            "conversionTable": table,
            "columns": columns,
            "PAYMENTS_RECEIVER": settings.PAYMENTS_RECEIVER
        })