def cancel_delivery_by_owner(self): """Cancel delivery as the current user, the owner""" if self.request.status == Status.ACCEPTED: assistant_uid = self.request.assistant.uid assistant = UserGetter.get_by_id(assistant_uid) with Firestore.batch('users') as batch: batch.update( assistant_uid, {'balance': assistant.balance + self.request.money_lock}) with Firestore.batch('packages') as batch: batch.update(self.request.uid, { 'status': Status.AVAILABLE, 'assistant': {} }) with Firestore.batch('users/' + assistant_uid + "/deliveries") as batch: batch.delete(self.request.uid) elif self.request.status == Status.AVAILABLE: with Firestore.batch('packages') as batch: batch.update(self.request.uid, { 'status': Status.CANCELLED_BY_OWNER, }) with Firestore.batch('users') as batch: batch.update( UserMeGetter._user_id, {'balance': UserMeGetter.user.balance + self.request.reward}) toast("Delivery cancelled.") self._back_button_handler()
def cancel_delivery_by_assistant(self): """Cancel delivery as the current user, the assistant""" assistant = UserMeGetter.user with Firestore.batch('packages') as batch: batch.update(self.request.uid, { 'status': Status.AVAILABLE, 'assistant': {} }) with Firestore.batch('users') as batch: batch.update( UserMeGetter._user_id, {'balance': assistant.balance + self.request.money_lock}) owner_uid = self.request.assistant.uid owner = UserGetter.get_by_id(owner_uid) with Firestore.batch('users') as batch: batch.update(owner_uid, {'balance': owner.balance + self.request.reward}) with Firestore.batch('users/' + UserMeGetter._user_id + "/deliveries") as batch: batch.delete(self.request.uid) toast("Delivery cancelled.") self._back_button_handler()
def confirm_delivery(self): """ Confirm the delivery as delivered, as the current user. Also withdraw money. """ with Firestore.batch('packages') as batch: batch.update(self.request.uid, { 'status': Status.DELIVERED, }) assistant_ref = Firestore.get_raw('users').document( self.request.assistant.uid).get() assistant_balance = assistant_ref._data['balance'] with Firestore.batch('users') as batch: batch.update( self.request.assistant.uid, { 'balance': assistant_balance + self.request.money_lock + self.request.reward, }) toast("Package confirmed as delivered.") self._back_button_handler()
def update(self, **kwargs): """ Updates the specified props to the user model and firebase :param kwargs: Can be name, mail, phonenumber etc """ if 'name' in kwargs: self.name = kwargs['name'] if 'mail' in kwargs: self.mail = kwargs['mail'] if 'phonenumber' in kwargs: self.phonenumber = kwargs['phonenumber'] if 'avatar' in kwargs: self.avatar = kwargs['avatar'] if 'balance' in kwargs: self.balance = kwargs['balance'] if 'packages' in kwargs: self.packages: List[DeliveryRequest] = kwargs['packages'] if 'deliveries' in kwargs: self.deliveries: List[DeliveryRequest] = kwargs['deliveries'] with Firestore.batch('users') as batch: batch.set( self._uid, { "mail": self.mail, "name": self.name, "phonenumber": self.phonenumber, "avatar": self.avatar, "balance": self.balance }) for listener in self._update_listeners: listener()
def test_batching(self): delivery_request = create_delivery_request() with Firestore.batch('packages') as batch: dr_dict = delivery_request.to_dict() uid = batch.create_with_random_id(dr_dict) batch.update(uid, { 'status': Status.ACCEPTED, 'assistant': 'pIAeLAvHXp0KZKWDzTMz' }) batch.set(uid, dr_dict) self.assertTrue( any(request.to_dict()['uid'] == "TEST" for request in Firestore.get('packages'))) with Firestore.batch('packages') as batch: batch.delete(uid)
def confirm_pickup(self): """Confirm the delivery as picked up, as the current user.""" with Firestore.batch('packages') as batch: batch.update(self.request.uid, { 'status': Status.TRAVELLING, }) toast("Delivery picked up. Package is now traveling.") self._back_button_handler()
def get_by_id(delivery_request_id: Text) -> DeliveryRequest: """ Get a specific DeliveryRequest from Firestore :param delivery_request_id: The id of the delivery request. """ data = Firestore.get_raw('packages').document( delivery_request_id).get().to_dict() data['uid'] = delivery_request_id data['status'] = Status(data['status']) return DeliveryRequest(**data)
def upload(request: DeliveryRequest): """ Upload a delivery request to Firebase. :param request: The delivery request to upload. :type request: DeliveryRequest """ request_dict = request.to_dict() with Firestore.batch("packages") as batch: batch.create_with_random_id(request_dict)
def get_by_id(user_id: Text) -> Optional[User]: """ Get a specific User from Firestore :param user_id: The id of the user. """ if user_id == "": return None data = Firestore.get_raw('users').document(user_id).get().to_dict() if data is not None: return User(_uid=user_id, **data) else: return None
def accept_delivery(self): """Accept the delivery as the current user.""" assistant_balance = UserMeGetter.user.balance assistant = UserMeGetter.user.to_minified() # Not enough money if assistant_balance < self.request.money_lock: toast("Insufficient balance to accept this delivery.") return with Firestore.batch('packages') as batch: batch.update(self.request.uid, { 'status': Status.ACCEPTED, 'assistant': assistant.to_dict() }) with Firestore.batch('users') as batch: batch.update( assistant.uid, {'balance': assistant_balance - self.request.money_lock}) toast("Delivery accepted. See my deliveries.") self._back_button_handler()
def sign_up(mail, password, name, phonenumber): """ Creates an account with the given data. Saves to firebase. Doesn't sign in. :param mail: A valid mail :param password: A valid password at least 8 in length :param name: The name of the new user :param phonenumber: The phonenumber of the new user :return: The user id for the new user """ sign_up_url = "https://www.googleapis.com/identitytoolkit" \ "/v3/relyingparty/signupNewUser?key=" + webApiKey sign_up_payload = { "email": mail, "password": password, "returnSecureToken": True } sign_up_request = requests.post(sign_up_url, data=sign_up_payload) if sign_up_request.ok: sign_up_data = json.loads(sign_up_request.content.decode()) token = sign_up_data['idToken'] refresh_token = sign_up_data['refreshToken'] user_id = sign_up_data['localId'] with Firestore.batch("users") as batch: batch.set( user_id, { "mail": mail, "name": name, "phonenumber": phonenumber, "avatar": "", "balance": 0 }) Auth.sign_in_with_tokens(token, refresh_token, user_id) else: error_data = json.loads(sign_up_request.content.decode()) error_message = error_data["error"]['message'] print(error_data) print(error_message) if error_message == "EMAIL_EXISTS": print("This mail is already registered") elif error_message == "WEAK_PASSWORD": print("Passwords must be at least 6 characters long")
def query(field_path: Text, op_str: Text, value: Any) -> List[DeliveryRequest]: """ Get a list of DeliveryRequest objects by querying Firestore :param field_path: The path being filtered on. :param op_str: The comparison operation being made :param value: The value which each entry is being compared to. """ docs = Firestore.get_raw('packages').where(field_path, op_str, value).stream() delivery_requests = [] for doc in docs: data = doc.to_dict() data['uid'] = doc.id data['status'] = Status(data['status']) delivery_requests.append(DeliveryRequest(**data)) return delivery_requests
def test_query(self): user = UserGetter.get_by_id('xUQeyplJshTzco4vyHHVoytT3FD2') delivery_requests = DeliveryRequestGetter.query( u'owner.uid', u'==', u'xUQeyplJshTzco4vyHHVoytT3FD2') self.assertGreaterEqual(len(delivery_requests), 1, msg="Expected at least 1 match.") # Clean up DRs for dr in delivery_requests: if not dr.uid == 'DLpVc0QmbOHzfDo24Hpp': with Firestore.batch('packages') as batch: batch.delete(dr.uid) delivery_requests = DeliveryRequestGetter.query( u'owner.uid', u'==', u'xUQeyplJshTzco4vyHHVoytT3FD2') self.assertEqual(len(delivery_requests), 1, msg="Expected 1 match.") expected = DeliveryRequest( uid='DLpVc0QmbOHzfDo24Hpp', item='Xbox controller', description='I AM USED FOR TESTS. DO NOT REMOVE', origin=Location("Odenvägen 1, SE-194 63 Odenslunda, Sweden", latitude=59.51224, longitude=17.93536).to_dict(), destination=Location("Rolsmo 1, SE-360 24 Linneryd, Sweden", latitude=56.64989, longitude=15.16624).to_dict(), reward=123, weight=0, fragile=False, status=Status.AVAILABLE, money_lock=23, owner=user.to_minified().to_dict(), assistant=dict(), image_path='') self.assertDictEqual.__self__.maxDiff = None self.assertDictEqual(delivery_requests[0].to_dict(), expected.to_dict())
def test_subscription(self): event = threading.Event() callback_with_event = functools.partial(lambda *_: event.set(), event) Firestore.subscribe("packages", callback_with_event) request = create_delivery_request() self.assertIsNotNone(request) DeliveryRequestUploader.upload(request) event.wait() self.assertTrue(event.is_set()) Firestore.unsubscribe("packages") Firestore.unsubscribe("some_invalid_thing_to_unsubscribe_from")
def set_me(new_user_id: Text): """ Sets up a new subscription for the given user id :param new_user_id: The signed in user """ if UserMeGetter._user_id is not "": Firestore.unsubscribe( u'users/{user_id}/'.format(user_id=new_user_id)) Firestore.unsubscribe( u'users/{user_id}/packages'.format(user_id=new_user_id)) Firestore.unsubscribe( u'users/{user_id}/deliveries'.format(user_id=new_user_id)) UserMeGetter._user_id = new_user_id if new_user_id != "": UserMeGetter.user = UserGetter.get_by_id(new_user_id) Firestore.subscribe_document("users", new_user_id, UserMeGetter._on_snapshot_user) Firestore.subscribe( u'users/{user_id}/packages'.format(user_id=new_user_id), UserMeGetter._on_snapshot_user_packages) Firestore.subscribe( u'users/{user_id}/deliveries'.format(user_id=new_user_id), UserMeGetter._on_snapshot_user_deliveries)
def test_batch_exception(self): with self.assertRaises(TypeError), Firestore.batch( 'packages') as batch: batch.delete(1524)
def test_get_packages(self): delivery_requests = Firestore.get("packages") for delivery_request in delivery_requests: self.assertIsNotNone(delivery_request.get("item"))
def __init__(self, **kwargs): """Initializes the delivery list""" super(MyDeliveries, self).__init__(**kwargs) Firestore.subscribe( u'users/{}/deliveries'.format(UserMeGetter._user_id), self._pre_update_content)