| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 | import typingimport sqlalchemyimport sqlalchemy.engine.basefrom .app_route import app_route_databasefrom .product import product from .product_loader import product_loaderfrom .exception import bad_request_exceptionfrom .exception import not_found_exceptionfrom .exception import access_denied_exceptionfrom .exception import database_exceptionfrom .exception import incorrect_target_exceptionfrom .users_collection import users_collectionfrom .reservation import reservation from .reservation import reservation_factoryfrom .reservation_loader import reservation_loaderfrom .deep_request import deep_requestfrom .reservations_collection import reservations_collectionfrom .reservations_response import reservations_responseclass reservation_deep_request(deep_request):    @property    def has_product(self) -> bool:          return self.target_barcode is not None or self.target_name is not None    @property     def has_email(self) -> bool:        return self.email is not None    @property    def has_phone_number(self) -> bool:        return self.phone_number is not None    @property    def has_apikey(self) -> bool:        return self.apikey is not Noneclass reservation_app(app_route_database):    def __init__(        self,        connection: sqlalchemy.engine.base.Engine,        users: users_collection    ) -> None:        super().__init__(connection)        self.__users_collection = users    def get_by_user(self, params: dict) -> dict:        request = reservation_deep_request(params)                try:            with self.__reservation_loader as loader:                collection = self.__load_by_user(request, loader)                self.__reservation_user_filter(collection, request)                reservations_list = reservations_response() \                    .collection(collection.results())                return self._success(reservations = reservations_list)                except Exception as error:            return self.__catch(error)    def get_by_product(self, params: dict) -> dict:        request = reservation_deep_request(params)        try:            self.__login(request)            item = self.__load_product(request)                        with self.__reservation_loader as loader:                collection = loader.get_by_target(item)                 self.__reservation_user_filter(collection, request)                 reservations_list = reservations_response() \                    .collection(collection.results())                return self._success(reservations = reservations_list)                except Exception as error:            return self.__catch(error)    def rent_product(self, params: dict) -> dict:        request = reservation_deep_request(params)                try:            self.__login(request)            item = self.__load_product(request)            rent = self.__create_factory(request).target(item).result()                        with self.__reservation_loader as loader:                if not self.__product_avairable(item):                    raise bad_request_exception("Item already not avairable")                 if not loader.store(rent):                    raise database_exception()            return self._success()        except Exception as error:            return self.__catch(error)    def give_back_product(self, params: dict) -> dict:        request = reservation_deep_request(params)        try:            self.__login(request)            target = self.__get_reservation(request)            with self.__reservation_loader as loader:                if loader.drop(target):                    return self._success()                                raise database_exception()                except Exception as error:            return self.__catch(error)    def __reservation_user_filter(        self,         collection: reservations_collection,         request: deep_request    ) -> bool:        if not request.has_email and not request.has_phone_number:            return False        if request.has_email:            collection.by_email(request.email)        if request.has_phone_number:            collection.by_phone_number(request.phone_number)        return True    def __reservation_product_filter(        self,        collection: reservations_collection,        request: deep_request    ) -> bool:        if not request.has_product:            return False        item = self.__load_product(request)        collection.by_target(item)        return True    def __get_reservation(self, request: deep_request) -> reservation:        with self.__reservation_loader as loader:            item = self.__load_product(request)            collection = loader.get_by_target(item)                        if not self.__reservation_user_filter(collection, request):                raise bad_request_exception("Not contaim email or phone")            result = collection.results()            if len(result) == 0:                    raise not_found_exception()                        if len(result) > 1:                raise incorrect_target_exception("Found too much targets.")            return result[0]    def __load_by_user(        self,         request: deep_request,        loader: reservation_loader    ) -> reservations_collection:        if request.has_email:            return loader.get_by_email(request.email)        if request.has_phone_number:            return loader.get_by_phone_number(request.phone_number)        raise bad_request_exception("Has no email or phone number")    def __create_factory(self, request: deep_request) -> reservation_factory:        if not request.has_email and not request.has_phone_number:            raise bad_request_exception("Not contain email or/and phone")        factory = reservation_factory()        if request.has_email:            factory.email(request.email)        if request.has_phone_number:            factory.phone_number(request.phone_number)        return factory    def __login(self, request: deep_request) -> None:        if not request.has_apikey:            raise access_denied_exception()        if self.__users_collection.get(request.apikey):            return         raise access_denied_exception()    def __load_product(self, request: deep_request) -> product:          if request.target_barcode is not None:            return self.__product_by_barcode(request)        if request.target_name is not None:            return self.__product_by_name(request)        raise bad_request_exception("Not contain barcode or name")    def __product_by_barcode(self, request: deep_request) -> product:        with self.__product_loader as loader:            product = loader.get_by_barcode(request.target_barcode)            if product is not None:                return product            raise not_found_exception()    def __product_avairable(self, target: product) -> bool:        with self.__product_loader as loader:            return loader.get_by_barcode(target.barcode).on_stock > 0    def __product_by_name(self, request: deep_request) -> product:        with self.__product_loader as loader:            product = loader.get_by_name(request.target_name)             if product is not None:                product.on_stock                return product                        raise not_found_exception()    def __catch(self, error: Exception) -> dict:        return self._fail(str(error))    @property    def __reservation_loader(self):        return reservation_loader(self._connection)    @property    def __product_loader(self):        return product_loader(self._connection)        
 |