From 817e56a5f44717d102ed7218c76f151f04cf5c51 Mon Sep 17 00:00:00 2001 From: evgeny Date: Sat, 20 Jun 2020 17:51:44 +0500 Subject: [PATCH] added user currencies getter --- config.py | 3 +- src/DAL/auth.py | 32 ++++++++++++++++++++ src/DAL/client.py | 61 ++++++++++---------------------------- src/DAL/currencies.py | 21 +++++++++++++ src/DAL/user_currencies.py | 30 +++++++++++++++++++ src/models/currency.py | 9 ++++++ src/view/login_window.py | 5 ++-- src/view/main_window.py | 43 +++++++++++---------------- 8 files changed, 129 insertions(+), 75 deletions(-) create mode 100644 src/DAL/auth.py create mode 100644 src/DAL/currencies.py create mode 100644 src/DAL/user_currencies.py diff --git a/config.py b/config.py index 4af5efb..bafd296 100644 --- a/config.py +++ b/config.py @@ -4,6 +4,7 @@ class ServiceSettings(BaseSettings): host: str port: int + max_workers: int -service_settings = ServiceSettings(host='localhost',port=5000) +service_settings = ServiceSettings(host='localhost',port=5000,max_workers=20) diff --git a/src/DAL/auth.py b/src/DAL/auth.py new file mode 100644 index 0000000..faae5b8 --- /dev/null +++ b/src/DAL/auth.py @@ -0,0 +1,32 @@ +from abc import ABC, abstractmethod +from http import HTTPStatus +from typing import Any, Dict + +import requests +from requests import Response + +from src.models.user import User +from src.urls import Urls + + +class AbstractAuthorization(ABC): + @abstractmethod + def sign_in(self, username: str) -> User: + pass + + +class ConcreteAuthorization(AbstractAuthorization): + def _deserialize(self, json_: Dict[str, Any]): + return User.parse_obj(json_) + + def _get_user(self, username: str) -> User: + response: Response = requests.get( + Urls.USERS.value, params={'user_name': username} + ) + return self._deserialize(response.json()) + + def sign_in(self, username: str) -> User: + response: Response = requests.post(Urls.USERS.value, json={'login': username}) + if response.status_code == HTTPStatus.BAD_REQUEST: + return self._get_user(username) + return self._deserialize(response.json()) diff --git a/src/DAL/client.py b/src/DAL/client.py index 74619d5..5b0be03 100644 --- a/src/DAL/client.py +++ b/src/DAL/client.py @@ -1,49 +1,13 @@ -from abc import ABC, abstractmethod -from http import HTTPStatus -from typing import Any, Dict, List - -import requests -from requests import Response - -from src.models.currency import Currency +from typing import List + +from src.DAL.auth import AbstractAuthorization, ConcreteAuthorization +from src.DAL.currencies import AbstractCurrenciesGetter, ConcreteCurrencyGetter +from src.DAL.user_currencies import ( + AbstractUserCurrencyGetter, + ConcreteUserCurrencyGetter, +) +from src.models.currency import Currency, UserCurrency from src.models.user import User -from src.urls import Urls -from pydantic import parse_obj_as - - -class AbstractAuthorization(ABC): - @abstractmethod - def sign_in(self, username: str) -> User: - pass - - -class AbstractCurrenciesGetter(ABC): - @abstractmethod - def get(self) -> List[Currency]: - pass - - -class ConcreteAuthorization(AbstractAuthorization): - def _deserialize(self, json_: Dict[str, Any]): - return User.parse_obj(json_) - - def _get_user(self, username: str) -> User: - response: Response = requests.get( - Urls.USERS.value, params={'user_name': username} - ) - return self._deserialize(response.json()) - - def sign_in(self, username: str) -> User: - response: Response = requests.post(Urls.USERS.value, json={'login': username}) - if response.status_code == HTTPStatus.BAD_REQUEST: - return self._get_user(username) - return self._deserialize(response.json()) - - -class ConcreteCurrencyGetter(AbstractCurrenciesGetter): - def get(self) -> List[Currency]: - response: Response = requests.get(Urls.CURRENCIES.value) - return parse_obj_as(List[Currency], response.json()) class Client: @@ -51,12 +15,17 @@ def __init__( self, authorization: AbstractAuthorization = ConcreteAuthorization(), currencies_getter: AbstractCurrenciesGetter = ConcreteCurrencyGetter(), + user_currencies_getter: AbstractUserCurrencyGetter = ConcreteUserCurrencyGetter(), ): self._authorization: AbstractAuthorization = authorization self._currencies_getter: AbstractCurrenciesGetter = currencies_getter + self._user_currencies_getter = user_currencies_getter - def get_currencies(self) -> List[Currency]: + def get_all_currencies(self) -> List[Currency]: return self._currencies_getter.get() + def get_user_currencies(self, user_id: int) -> List[UserCurrency]: + return self._user_currencies_getter.get(user_id) + def sign_in(self, username: str) -> User: return self._authorization.sign_in(username) diff --git a/src/DAL/currencies.py b/src/DAL/currencies.py new file mode 100644 index 0000000..89db48e --- /dev/null +++ b/src/DAL/currencies.py @@ -0,0 +1,21 @@ +from abc import ABC, abstractmethod +from typing import List + +import requests +from pydantic import parse_obj_as +from requests import Response + +from src.models.currency import Currency +from src.urls import Urls + + +class AbstractCurrenciesGetter(ABC): + @abstractmethod + def get(self) -> List[Currency]: + pass + + +class ConcreteCurrencyGetter(AbstractCurrenciesGetter): + def get(self) -> List[Currency]: + response: Response = requests.get(Urls.CURRENCIES.value) + return parse_obj_as(List[Currency], response.json()) diff --git a/src/DAL/user_currencies.py b/src/DAL/user_currencies.py new file mode 100644 index 0000000..4bdee1e --- /dev/null +++ b/src/DAL/user_currencies.py @@ -0,0 +1,30 @@ +from abc import ABC, abstractmethod +from concurrent.futures.thread import ThreadPoolExecutor +from typing import List, Iterator + +import requests +from requests import Response + +from config import service_settings +from src.models.currency import UserCurrency, Currency, CurrencyItem +from src.urls import Urls +from pydantic import parse_obj_as + + +class AbstractUserCurrencyGetter(ABC): + @abstractmethod + def get(self, user_id: int) -> List[UserCurrency]: + pass + + +class ConcreteUserCurrencyGetter(AbstractUserCurrencyGetter): + def _get_currency(self, currency_item: CurrencyItem) -> UserCurrency: + response: Response = requests.get(f'{Urls.CURRENCIES.value}/{currency_item.currency_id}') + currency = Currency.parse_obj(response.json()) + return UserCurrency(**currency.dict(), amount=currency_item.amount) + + def get(self, user_id: int) -> List[UserCurrency]: + response: Response = requests.get(f'{Urls.USERS.value}/{user_id}/currencies') + user_currencies = parse_obj_as(List[CurrencyItem], response.json()) + with ThreadPoolExecutor(max_workers=service_settings.max_workers) as executor: + return list(executor.map(lambda item: self._get_currency(item), user_currencies)) \ No newline at end of file diff --git a/src/models/currency.py b/src/models/currency.py index e75d2d6..ecf17db 100644 --- a/src/models/currency.py +++ b/src/models/currency.py @@ -9,3 +9,12 @@ class Currency(BaseModel): purchasing_price: Decimal selling_price: Decimal time: str + +class CurrencyItem(BaseModel): + id: int + user_id: int + currency_id: int + amount: Decimal + +class UserCurrency(Currency): + amount: Decimal diff --git a/src/view/login_window.py b/src/view/login_window.py index 70e0938..d9ebab5 100644 --- a/src/view/login_window.py +++ b/src/view/login_window.py @@ -16,8 +16,6 @@ def __init__(self): self.confirmButton.clicked.connect(self.auth) self.cancelButton.clicked.connect(lambda: self.close()) - self.mainWindow = MainWindow(self) - def init(self): self.show() @@ -27,6 +25,7 @@ def auth(self): self.close() try: user = self._authorize.sign_in(self.login.text()) - self.mainWindow.init(user) + self.mainWindow = MainWindow(user, self) + self.mainWindow.init() except ConnectionError: QMessageBox(text=Message.CONNECTION_ERROR.value).exec() diff --git a/src/view/main_window.py b/src/view/main_window.py index 8104315..7d15ee7 100644 --- a/src/view/main_window.py +++ b/src/view/main_window.py @@ -10,10 +10,6 @@ from ui.main import Ui_MainWindow -class CurrencyData(NamedTuple): - name: str - price: int - change: str class OperationData(NamedTuple): @@ -23,17 +19,7 @@ class OperationData(NamedTuple): account: str -all_currencies_data = [ - CurrencyData('Крипта', 1, '+1%'), - CurrencyData('Биток', 2, '-10%'), - CurrencyData('Эфирbvbvbdfsbbsfbbaasdadadadasdfb', 20, '+210%'), -] -my_currencies_data = [ - CurrencyData('Крипта', 1, '+1%'), - CurrencyData('Биток', 2, '-10%'), - CurrencyData('Эфирbvbvbdfsbbsfbbfb', 20, '+210%'), -] operation_data = [ OperationData('Продажа', 'Биток', 20, '+ 20 у. е.'), @@ -61,14 +47,15 @@ class OperationData(NamedTuple): OperationData('Продажа', 'Биток', 20, '+ 20 у. е.'), OperationData('Продажа', 'Биток', 20, '+ 20 у. е.'), OperationData('Продажа', 'Биток', 20, '+ 20 у. е.'), - OperationData('Продажа', 'Биток', 20, '+ 20 у. е.') + OperationData('Продажа', 'Биток', 20, '+ 20 у. е.'), ] class MainWindow(Ui_MainWindow, QMainWindow): - def __init__(self, parent): + def __init__(self, user: User,parent): super().__init__(parent, Qt.WindowCloseButtonHint | Qt.WindowMinimizeButtonHint) self.setupUi(self) + self.user: User = user self.searchButton.clicked.connect(self.search_item) self.refreshButton.clicked.connect(self.refresh_tables) @@ -90,7 +77,7 @@ def refresh_tables(self): def fill_all_currencies(self): self.allCurrenciesTable.clear() - currencies = self._client.get_currencies() + currencies = self._client.get_all_currencies() labels = ['Название', 'Цена продажи', 'Цена покупки', ''] create_headers(self.allCurrenciesTable, labels) @@ -102,17 +89,22 @@ def fill_all_currencies(self): self.allCurrenciesTable.setRowCount(row + 1) self.allCurrenciesTable.setItem(row, 0, QTableWidgetItem(i.name)) - self.allCurrenciesTable.setItem(row, 1, QTableWidgetItem(str(i.selling_price))) - self.allCurrenciesTable.setItem(row, 2, QTableWidgetItem(str(i.purchasing_price))) + self.allCurrenciesTable.setItem( + row, 1, QTableWidgetItem(str(i.selling_price)) + ) + self.allCurrenciesTable.setItem( + row, 2, QTableWidgetItem(str(i.purchasing_price)) + ) self.allCurrenciesTable.setCellWidget(row, 3, detail_button) def fill_my_currencies(self): self.myCurrenciesTable.clear() - labels = ['Название', 'Колличество','Цена продажи', 'Цена покупки', ''] + labels = ['Название', 'Колличество', 'Цена продажи', 'Цена покупки', ''] create_headers(self.myCurrenciesTable, labels) - for i in my_currencies_data: + currencies = self._client.get_user_currencies(self.user.id) + for i in currencies: detail_button = QPushButton('Подробнее') detail_button.clicked.connect(self.show_details) @@ -120,10 +112,11 @@ def fill_my_currencies(self): self.myCurrenciesTable.setRowCount(row + 1) self.myCurrenciesTable.setItem(row, 0, QTableWidgetItem(i.name)) - self.myCurrenciesTable.setItem(row, 1, QTableWidgetItem(str(i.price))) - self.myCurrenciesTable.setItem(row, 2, QTableWidgetItem(str(i.price))) + self.myCurrenciesTable.setItem(row, 1, QTableWidgetItem(str(i.amount))) + self.myCurrenciesTable.setItem(row, 2, QTableWidgetItem(str(i.selling_price))) + self.myCurrenciesTable.setItem(row, 3, QTableWidgetItem(str(i.purchasing_price))) - self.myCurrenciesTable.setCellWidget(row, 3, detail_button) + self.myCurrenciesTable.setCellWidget(row, 4, detail_button) def fill_operations(self): self.operationsTable.clear() @@ -144,7 +137,7 @@ def fill_operations(self): def show_details(self): self.currencyWindow.init() - def init(self, user: User): + def init(self): self.fill_all_currencies() self.fill_my_currencies() self.fill_operations()