reservation_app.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. import typing
  2. import sqlalchemy
  3. import sqlalchemy.engine.base
  4. from .app_route import app_route_database
  5. from .product import product
  6. from .product_loader import product_loader
  7. from .exception import bad_request_exception
  8. from .exception import not_found_exception
  9. from .exception import access_denied_exception
  10. from .exception import database_exception
  11. from .exception import incorrect_target_exception
  12. from .users_collection import users_collection
  13. from .reservation import reservation
  14. from .reservation import reservation_factory
  15. from .reservation_loader import reservation_loader
  16. from .deep_request import deep_request
  17. from .reservations_collection import reservations_collection
  18. from .reservations_response import reservations_response
  19. class reservation_deep_request(deep_request):
  20. @property
  21. def has_product(self) -> bool:
  22. return self.target_barcode is not None or self.target_name is not None
  23. @property
  24. def has_email(self) -> bool:
  25. return self.email is not None
  26. @property
  27. def has_phone_number(self) -> bool:
  28. return self.phone_number is not None
  29. @property
  30. def has_apikey(self) -> bool:
  31. return self.apikey is not None
  32. class reservation_app(app_route_database):
  33. def __init__(
  34. self,
  35. connection: sqlalchemy.engine.base.Engine,
  36. users: users_collection
  37. ) -> None:
  38. super().__init__(connection)
  39. self.__users_collection = users
  40. def get_by_user(self, params: dict) -> dict:
  41. request = reservation_deep_request(params)
  42. try:
  43. with self.__reservation_loader as loader:
  44. collection = self.__load_by_user(request, loader)
  45. self.__reservation_user_filter(collection, request)
  46. reservations_list = reservations_response() \
  47. .collection(collection.results())
  48. return self._success(reservations = reservations_list)
  49. except Exception as error:
  50. return self.__catch(error)
  51. def get_by_product(self, params: dict) -> dict:
  52. request = reservation_deep_request(params)
  53. try:
  54. self.__login(request)
  55. item = self.__load_product(request)
  56. with self.__reservation_loader as loader:
  57. collection = loader.get_by_target(item)
  58. self.__reservation_user_filter(collection, request)
  59. reservations_list = reservations_response() \
  60. .collection(collection.results())
  61. return self._success(reservations = reservations_list)
  62. except Exception as error:
  63. return self.__catch(error)
  64. def rent_product(self, params: dict) -> dict:
  65. request = reservation_deep_request(params)
  66. try:
  67. self.__login(request)
  68. item = self.__load_product(request)
  69. rent = self.__create_factory(request).target(item).result()
  70. with self.__reservation_loader as loader:
  71. if not loader.store(rent):
  72. raise database_exception()
  73. return self._success()
  74. except Exception as error:
  75. return self.__catch(error)
  76. def give_back_product(self, params: dict) -> dict:
  77. request = reservation_deep_request(params)
  78. try:
  79. self.__login(request)
  80. target = self.__get_reservation(request)
  81. with self.__reservation_loader as loader:
  82. if loader.drop(target):
  83. return self._success()
  84. raise database_exception()
  85. except Exception as error:
  86. return self.__catch(error)
  87. def __reservation_user_filter(
  88. self,
  89. collection: reservations_collection,
  90. request: deep_request
  91. ) -> bool:
  92. if not request.has_email and not request.has_phone_number:
  93. return False
  94. if request.has_email:
  95. collection.by_email(request.email)
  96. if request.has_phone_number:
  97. collection.by_phone_number(request.phone_number)
  98. return True
  99. def __reservation_product_filter(
  100. self,
  101. collection: reservations_collection,
  102. request: deep_request
  103. ) -> bool:
  104. if not request.has_product:
  105. return False
  106. item = self.__load_product(request)
  107. collection.by_target(item)
  108. return True
  109. def __get_reservation(self, request: deep_request) -> reservation:
  110. with self.__reservation_loader as loader:
  111. item = self.__load_product(request)
  112. collection = loader.get_by_target(item)
  113. if not self.__reservation_user_filter(collection, request):
  114. raise bad_request_exception("Not contaim email or phone")
  115. result = collection.results()
  116. if len(result) == 0:
  117. raise not_found_exception()
  118. if len(result) > 1:
  119. raise incorrect_target_exception("Found too much targets.")
  120. return result[0]
  121. def __load_by_user(
  122. self,
  123. request: deep_request,
  124. loader: reservation_loader
  125. ) -> reservations_collection:
  126. if request.has_email:
  127. return loader.get_by_email(request.email)
  128. if request.has_phone_number:
  129. return loader.get_by_phone_number(request.phone_number)
  130. raise bad_request_exception("Has no email or phone number")
  131. def __create_factory(self, request: deep_request) -> reservation_factory:
  132. if not request.has_email and not request.has_phone_number:
  133. raise bad_request_exception("Not contain email or/and phone")
  134. factory = reservation_factory()
  135. if request.has_email:
  136. factory.email(request.email)
  137. if request.has_phone_number:
  138. factory.phone_number(request.phone_number)
  139. return factory
  140. def __login(self, request: deep_request) -> None:
  141. if not request.has_apikey:
  142. raise access_denied_exception()
  143. if self.__users_collection.get(request.apikey):
  144. return
  145. raise access_denied_exception()
  146. def __load_product(self, request: deep_request) -> product:
  147. if request.target_barcode is not None:
  148. return self.__product_by_barcode(request)
  149. if request.target_name is not None:
  150. return self.__product_by_name(request)
  151. raise bad_request_exception("Not contain barcode or name")
  152. def __product_by_barcode(self, request: deep_request) -> product:
  153. with self.__product_loader as loader:
  154. product = loader.get_by_barcode(request.target_barcode)
  155. if product is not None:
  156. return product
  157. raise not_found_exception()
  158. def __product_by_name(self, request: deep_request) -> product:
  159. with self.__product_loader as loader:
  160. product = loader.get_by_name(request.target_name)
  161. if product is not None:
  162. return product
  163. raise not_found_exception()
  164. def __catch(self, error: Exception) -> dict:
  165. return self._fail(str(error))
  166. @property
  167. def __reservation_loader(self):
  168. return reservation_loader(self._connection)
  169. @property
  170. def __product_loader(self):
  171. return product_loader(self._connection)