示例#1
0
    def transferMoney(cls, request: Request, **kwargs):
        """
        :param request:
        :param kwargs:
        :return:
        """
        token = request.get("token")
        login = microservice("http://auth/auth", {"token": token}, "result")
        from_base_currency = request.get("from_base_currency")

        to_login = request.get("to_login")
        to_base_currency = request.get("to_base_currency")

        amount = request.get("amount")
        conversion_rate_uuid_1 = request.get("conversion_rate_uuid_1", None)
        conversion_rate_uuid_2 = request.get("conversion_rate_uuid_2", None)

        return microservice(
            "http://wallets/transfer",
            {
                "from_login": login, "from_base_currency": from_base_currency,
                "to_login": to_login, "to_base_currency": to_base_currency,
                "amount": amount,
                "conversion_rate_uuid_1": conversion_rate_uuid_1,
                "conversion_rate_uuid_2": conversion_rate_uuid_2
            },
            "result"
        )
示例#2
0
    def topUpBalance(cls, request: Request, **kwargs):
        """
        :param request:
        :param kwargs:
        :return:
        """
        login = request.get("login")
        base_currency = request.get("base_currency")
        amount = request.get("amount")
        microservice("http://wallets/topup", {
            "login": login,
            "base_currency": base_currency,
            "amount": amount
        }, "result")

        return True
示例#3
0
 def getSupportedCurrencies(cls, request: Request, **kwargs):
     """
     :param request:
     :param kwargs:
     :return:
     """
     return microservice("http://wallets/get_currencies", {}, "result")
示例#4
0
 def createWallet(cls, request: Request, **kwargs):
     """
     :param request:
     :param kwargs:
     :return:
     """
     token = request.get("token")
     login = microservice("http://auth/auth", {"token": token}, "result")
     base_currency = request.get("base_currency")
     return microservice(
         "http://wallets/create",
         {
             "login": login,
             "base_currency": base_currency
         },
         "result"
     )
示例#5
0
 def getMe(cls, request: Request, **kwargs):
     """
     :param request:
     :param kwargs:
     :return:
     """
     token = request.get("token")
     login = microservice("http://auth/auth", {"token": token}, "result")
     wallets = microservice("http://wallets/get_wallets", {"login": login}, "result")
     user = microservice("http://users/get", {"login": login}, "result")
     user["country_name"] = microservice(
         "http://geo/get_country", {"id": user["country_id"]}, "result.name"
     )
     user["city_name"] = microservice(
         "http://geo/get_city", {"id": user["city_id"], "country_id": user["country_id"]}, "result.name"
     )
     return {**user, "wallets": wallets}
示例#6
0
 def saveRatesBulk(cls, request: Request, **kwargs):
     """
     :param request:
     :param kwargs:
     :return:
     """
     data = request.get("data")
     return microservice("http://converter/save_bulk", {"data": data},
                         "result")
示例#7
0
 def auth(cls, request: Request, **kwargs):
     """
     :param request:
     :param kwargs:
     :return:
     """
     login = request.get("login")
     password = request.get("password")
     return microservice("http://auth/auth", {"login": login, "password": password}, "result")
示例#8
0
 def getConvertionRates(cls, request: Request, **kwargs):
     """
     :param request:
     :param kwargs:
     :return:
     """
     from_base_currency = request.get("from_base_currency")
     to_base_currency = request.get("to_base_currency")
     conversion_rate1 = microservice(
         "http://converter/get_last_value", {"base_currency": from_base_currency}, "result"
     )
     conversion_rate2 = microservice(
         "http://converter/get_last_value", {"base_currency": to_base_currency}, "result"
     )
     return {
         "conversion_rate1": conversion_rate1,
         "conversion_rate2": conversion_rate2
     }
示例#9
0
 def saveRate(cls, request: Request, **kwargs):
     """
     :param request:
     :param kwargs:
     :return:
     """
     base_currency = request.get("base_currency")
     value = request.get("value")
     datetime = request.get("datetime")
     return microservice("http://converter/save", {
         "base_currency": base_currency,
         "value": value,
         "datetime": datetime
     }, "result")
示例#10
0
 def getTransactions(cls, request: Request, **kwargs):
     """
     :param request:
     :param kwargs:
     :return:
     """
     login = request.get("login")
     period_starts = request.get("period_starts", None)
     period_ends = request.get("period_ends", None)
     return microservice(
         "http://wallets/get_transactions", {
             "login": login,
             "period_starts": period_starts,
             "period_ends": period_ends
         }, "result")
示例#11
0
    def createAccount(cls, request: Request, **kwargs):
        """
        :param request:
        :param kwargs:
        :return:
        """
        login = request.get("login")
        password = request.get("password")
        name = request.get("name")
        country = request.get("country_id", request.get("country_name"))
        city = request.get("city_id", request.get("city_name"))
        base_currency = request.get("base_currency")

        microservice("http://auth/create", {"login": login, "password": password}, "result")

        country_id = microservice(
            "http://geo/get_country",
            {"id": country if country.isnumeric() else None, "name": country if not country.isnumeric() else None},
            "result.id"
        )

        city_id = microservice(
            "http://geo/get_city",
            {"id": city if city.isnumeric() else None, "name": city if not city.isnumeric() else None,
             "country_id": country_id},
            "result.id"
        )

        microservice(
            "http://users/create",
            {"login": login, "name": name, "country_id": country_id, "city_id": city_id},
            "result"
        )

        microservice(
            "http://wallets/create",
            {"login": login, "base_currency": base_currency},
            "result"
        )

        return True
示例#12
0
    def getTransactionsCsvReport(cls, request: Request, **kwargs):
        """
        :param request:
        :param kwargs:
        :return:
        """
        login = request.get("login")
        period_starts = request.get("period_starts", None)
        period_ends = request.get("period_ends", None)
        transactions = microservice(
            "http://wallets/get_transactions", {
                "login": login,
                "period_starts": period_starts,
                "period_ends": period_ends
            }, "result")
        all_transactions = [tx + ["+"] for tx in transactions["incoming"]] + \
                           [tx + ["-"] for tx in transactions["outgoing"]]
        all_transactions.sort(key=lambda tx: datetime.strptime(tx[5], "%c"))

        csv_header = [
            "tx_uuid", "login", "base_currency", "amount",
            "convertion_rate_uuid", "tx_datetime", "mode"
        ]
        csv_body = [csv_header]

        for tx in all_transactions:
            csv_body.append(tx)

        file = io.StringIO()
        writer = csv.writer(file, delimiter=",")
        writer.writerows(csv_body)
        result = file.getvalue()

        request.response.add_header("Content-Type", 'application/vnd.ms-excel')
        request.response.add_header(
            "Content-disposition",
            'attachment; filename=transactions-%s.csv' % login)
        return result
示例#13
0
    class Converter:
        """
        Utility class for working with currencies and and convertion rates
        """
        get_last_value = lambda bc: microservice("http://converter/get_last_value", {"base_currency": bc}, "result")
        get_by_uuid = lambda uuid: microservice("http://converter/get_by_uuid", {"uuid": uuid}, "result")

        @staticmethod
        def get_convertion_rate_value(original_currency, convertion_rate_uuid):
            """ Retrieving and validation convertion rate """
            # noinspection PyCallByClass
            conversion_rate = Currencies.Converter.get_by_uuid(convertion_rate_uuid)
            conversion_rate_datetime = datetime.strptime(conversion_rate["datetime"], "%c")
            convertion_rate_expired_datetime = datetime.now() - timedelta(
                seconds=Currencies.CONVERSION_RATE_TIMEOUT_TOLERANCE
            )
            if conversion_rate_datetime < convertion_rate_expired_datetime:
                raise ConvertionRateExpired()

            if conversion_rate["base_currency"] != original_currency:
                raise InvalidConvertionRate()

            return conversion_rate["value"]

        @staticmethod
        def convert(
                amount: float,
                from_base_currency: int, to_base_currency: int,
                convertion_rate_uuid_1: str=None, convertion_rate_uuid_2: str=None) -> float:
            """ Converts currencies based on given convertion rates with validation """

            # No convertion required:
            if from_base_currency == to_base_currency:
                convertion_rate_value_1 = 1
                convertion_rate_value_2 = 1

            # At least one convertion required:
            else:
                # From USD to Other Currency (1 convertion):
                if from_base_currency == Currencies.USD:
                    convertion_rate_value_1 = 1
                    if not convertion_rate_uuid_2:
                        raise NoConversionRateProvided()
                    else:
                        convertion_rate_value_2 = Currencies.Converter.get_convertion_rate_value(
                            to_base_currency, convertion_rate_uuid_2
                        )
                # From Some Currency to USD (1 convertion):
                elif to_base_currency == Currencies.USD:
                    convertion_rate_value_2 = 1
                    if not convertion_rate_uuid_1:
                        raise NoConversionRateProvided()
                    else:
                        convertion_rate_value_1 = Currencies.Converter.get_convertion_rate_value(
                            from_base_currency, convertion_rate_uuid_1
                        )
                # From Some Currency to Other Currency, not USD (2 convertions):
                else:
                    if not convertion_rate_uuid_1 or not convertion_rate_uuid_2:
                        raise NoConversionRateProvided()
                    convertion_rate_value_1 = Currencies.Converter.get_convertion_rate_value(
                        from_base_currency, convertion_rate_uuid_1
                    )
                    convertion_rate_value_2 = Currencies.Converter.get_convertion_rate_value(
                        to_base_currency, convertion_rate_uuid_2
                    )

            return amount * convertion_rate_value_1 / convertion_rate_value_2
示例#14
0
    def test_successfull_scenario(self):
        """ Lets test successfull sceanrio of using the app """

        # Registration:
        registration_result = microservice(
            "http://public_api/createAccount", {
                "login": "******",
                "password": "******",
                "name": "Andrey",
                "country_name": "Russia",
                "city_name": "Moscow",
                "base_currency": 1
            }, "result")
        self.assertTrue(registration_result)

        # Authenticatation:
        token = microservice("http://public_api/auth", {
            "login": "******",
            "password": "******"
        }, "result")

        # Getting user data back, including list of wallets:
        user_data = microservice("http://public_api/getMe", {"token": token},
                                 "result")
        self.assertDictEqual(
            {
                "city_id":
                1,  # Here we can see that our geo-info now have ids,
                "city_name":
                "Moscow",  # so it could be reused by other users
                "country_id":
                1,  # with some help from the front-end
                "country_name":
                "Russia",
                "login":
                "******",
                "name":
                "Andrey",
                # Also we have our first wallet for USD right after registration:
                "wallets": [{
                    "balance": 0.0,
                    "base_currency": 1,
                    "login": "******"
                }]
            },
            user_data)

        # Let's try to create another wallet for different currency...
        # First of all, we need to know what currencies are currently supported by the platform:
        supported_currencies = microservice(
            "http://public_api/getSupportedCurrencies", {}, "result")
        self.assertDictEqual({
            "1": "USD",
            "2": "EUR",
            "3": "CAD",
            "4": "CNY"
        }, supported_currencies)

        # We already have a USD-wallet, so let's create CNY:
        new_wallet_creation = microservice("http://public_api/createWallet", {
            "token": token,
            "base_currency": 4
        }, "result")
        self.assertTrue(new_wallet_creation)

        #Let's check our wallets now:
        user_wallets = microservice("http://public_api/getMe",
                                    {"token": token}, "result.wallets")
        self.assertEqual([{
            "balance": 0.0,
            "base_currency": 1,
            "login": "******"
        }, {
            "balance": 0.0,
            "base_currency": 4,
            "login": "******"
        }], user_wallets)

        # Ok, so far so good...
        # But to test further we need to get some money into one of our wallets...
        # We can do that by using private_api, that should be only accessible for trusted persons:
        topping_up_result = microservice("http://private_api/topUpBalance", {
            "login": "******",
            "base_currency": 1,
            "amount": 100
        }, "result")
        self.assertTrue(topping_up_result)

        # Have we become a millionaires already? Lets find out:
        user_wallets = microservice("http://public_api/getMe",
                                    {"token": token}, "result.wallets")
        self.assertEqual([{
            "balance": 100.0,
            "base_currency": 1,
            "login": "******"
        }, {
            "balance": 0.0,
            "base_currency": 4,
            "login": "******"
        }], user_wallets)

        # Awesome!!! 100$!!! =)
        # We need CNY for travelling though... no problem - using public api again we can make a transfer:

        # But wait the minute... our platform doesn't know anything about current convertion rates yet...
        # Let's fix this via our private-api too:
        update_dt = datetime.now().strftime("%c")
        updating_convertion_rates = microservice(
            "http://private_api/saveRatesBulk",
            {
                "data": [
                    {
                        "base_currency": 2,
                        "value": 1.24,
                        "datetime": update_dt
                    },  # 1EUR = 1.24USD
                    {
                        "base_currency": 4,
                        "value": 0.25,
                        "datetime": update_dt
                    },  # 1CNY = 0.25USD
                ]
            },
            "result")
        self.assertTrue(updating_convertion_rates)

        # And now, as user, we need to know current convertion rates and see if it works for us:
        # We are going to transfer USD to CNY, so:
        convertion_rates = microservice("http://public_api/getConvertionRates",
                                        {
                                            "token": token,
                                            "from_base_currency": 1,
                                            "to_base_currency": 4,
                                        }, "result")

        cny_uuid = convertion_rates["conversion_rate2"]["uuid"]
        self.assertDictEqual(
            {
                "conversion_rate1": {
                    "uuid": None,
                    "value": 1,
                    "datetime": None,
                    "base_currency": 1
                },
                "conversion_rate2": {
                    "uuid": cny_uuid,
                    "value": 0.25,
                    "datetime": update_dt,
                    "base_currency": 4
                }
            }, convertion_rates)

        # I hope that front-end will represent this information in a more understandable way... =)

        # But, let's make our transfer already!
        transfer_result = microservice(
            "http://public_api/transferMoney",
            {
                "token": token,
                "from_base_currency": 1,
                "to_login": "******",
                "to_base_currency": 4,
                "amount": 100,
                "conversion_rate_uuid_1": None,
                "conversion_rate_uuid_2":
                cny_uuid  # this is important, this should not be too old (< 30 seconds)
            },
            "result")
        tx_uuid = transfer_result["uuid"]
        tx_datetime = transfer_result["datetime"]

        # Final checking:
        user_wallets = microservice("http://public_api/getMe",
                                    {"token": token}, "result.wallets")
        self.assertEqual([{
            "balance": 0.0,
            "base_currency": 1,
            "login": "******"
        }, {
            "balance": 400.0,
            "base_currency": 4,
            "login": "******"
        }], user_wallets)

        # And last thing to check... getting reports on transactions via private api:
        transactions_history = microservice(
            "http://private_api/getTransactions", {"login": "******"},
            "result")

        self.assertDictEqual(
            {
                "incoming":
                [[tx_uuid, "MyLogin", 4, 400.0, cny_uuid, tx_datetime]],
                "outgoing": [[tx_uuid, "MyLogin", 1, 100.0, '', tx_datetime]],
            }, transactions_history)

        # Aaand downloading csv report:
        import requests
        res = requests.post("http://private_api/getTransactionsCsvReport",
                            json={"login": "******"})

        # Looks like csv and should be downloadable:
        self.assertEqual("application/vnd.ms-excel",
                         res.headers.get("Content-Type"))
        self.assertEqual("attachment; filename=transactions-MyLogin.csv",
                         res.headers.get("Content-Disposition"))

        # What about content:
        csv_content = res.content.decode()
        lines = csv_content.split("\r\n")
        csv_header = lines.pop(0)
        body = [line.split(",") for line in lines]

        self.assertEqual([
            "tx_uuid", "login", "base_currency", "amount",
            "convertion_rate_uuid", "tx_datetime", "mode"
        ], csv_header.split(","))
        self.assertIn(
            [tx_uuid, "MyLogin", "4", "400.0", cny_uuid, tx_datetime, "+"],
            body)
        self.assertIn([tx_uuid, "MyLogin", "1", "100.0", "", tx_datetime, "-"],
                      body)