class User(DomainModel): class Meta: collection_name = "users" name = attrs.bproperty() email = attrs.bproperty() _id = attrs.bproperty(data_key="id", import_enabled=False) @classmethod def get(cls, *args, doc_id=None, transaction=None, **kwargs): doc_ref = cls.ref_from_id(doc_id=doc_id) if transaction is None: snapshot = doc_ref.get() else: snapshot = doc_ref.get(transaction=transaction) return cls.from_dict( d=snapshot.to_dict(), transaction=transaction, **kwargs, doc_id=snapshot.reference.id, ) @_id.getter def _id(self): return self.doc_id
class Order(DomainModel): """ "created_at": "2019-11-07T21:50:12+00:00", "status": "NEW", "dropoff": { "address": null, "latitude": 47.84284957575306, "longitude": 35.10294444859028 }, "pickup": { "address": null, "latitude": 47.835803, "longitude": 35.11009362 }, "rider": { "role": "rider", "device_id": null, "name": "Ms. Rider", "phone_number": null } """ class Meta: case_conversion = False exclude = ("obj_type", "doc_id", "doc_ref") created_at = attrs.bproperty() status = attrs.bproperty() rider = attrs.embed(obj_cls=Rider) driver = attrs.embed(obj_cls=Driver) dropoff = attrs.embed(obj_cls=Dropoff) pickup = attrs.embed(obj_cls=Pickup)
class Place(Serializable): address = attrs.bproperty() latitude = attrs.bproperty() longitude = attrs.bproperty() class Meta: case_conversion = False exclude = ("obj_type", "doc_id", "doc_ref")
class RideHostUserView(ViewModel): user = attrs.bproperty(import_required=True, export_enabled=False) name = attrs.bproperty() @name.getter def name(self): return self.user.name
class UserLocation(Location): sublocations = attrs.relation(nested=False, many=True, initialize=True) @sublocations.init def sublocations(self): self._attrs.sublocations = [] place_id = attrs.bproperty(import_required=False, export_required=False) place_name = attrs.bproperty(import_required=False, export_required=False) user_id = attrs.bproperty(import_required=False, export_required=False) @property def latitude(self): return self.coordinates["latitude"] @property def longitude(self): return self.coordinates["longitude"] @classmethod def add_sublocation(cls, location, sublocations): """ Add sublocation to a location (runs as a step in a transaction). :param location_id: :param sublocation_ids: :return: """ for sublocation in sublocations: location._add_sublocation(sublocation) location.save() # _ = [sublocation.save(transaction=transaction) # for sublocation in sublocations ] @classmethod @run_transaction def add_sublocation_with_id(cls, location_id, sublocation_ids, transaction): """ Add sublocation to a location (runs in a separate transaction). :param location_id: :param sublocation_ids: :return: """ location = cls.get(doc_id=location_id) for sublocation_id in sublocation_ids: sublocation = Sublocation.get(doc_id=sublocation_id, ) location._add_sublocation(sublocation) location.save() def _add_sublocation(self, sublocation): self.sublocations.append(sublocation.doc_ref)
class Location(domain_model.DomainModel): coordinates = attrs.bdict() address = attrs.bproperty() @staticmethod def _to_address(coordinates): res = gmaps.reverse_geocode(latlng=(coordinates["latitude"], coordinates["longitude"]), result_type=[ "route", ]) return res[0]["formatted_address"] @address.getter def address(self): if not getattr(self, "_address", None): if self.coordinates: return self._to_address(self.coordinates) else: raise AttributeError else: return self._address @address.setter def address(self, value): self._address = value class Meta: # schema_cls = LocationSchema collection_name = "locations" def to_coordinate_str(self): return "{},{}".format(self.coordinates["latitude"], self.coordinates["longitude"])
class Sublocation(Location): road_name = attrs.bproperty(import_required=False, export_required=False) @road_name.getter def road_name(self): if hasattr(self._attrs, "road_name"): return self._attrs.road_name else: return self.address @classmethod def get_with_latlng(cls, *, latitude, longitude): res = gmaps.reverse_geocode(latlng=(latitude, longitude), result_type=[ "route", ]) return cls.new(coordinates={ "latitude": res[0]["geometry"]["location"]["lat"], "longitude": res[0]["geometry"]["location"]["lng"] }, address=res[0]["formatted_address"], road_name=res[0]['address_components'][0]["short_name"]) def to_view_dict(self): return dict(latitude=self.coordinates["latitude"], longitude=self.coordinates["longitude"], address=self.address) def to_trip_place(self): return dict(latitude=self.coordinates["latitude"], longitude=self.coordinates["longitude"], address=self.road_name)
class CoriderView(ViewModel): user = attrs.bproperty(import_required=True, export_enabled=False) booking: RiderBooking = attrs.bproperty(import_required=True, export_enabled=False) pickup_location: Sublocation = attrs.bproperty(import_required=True, export_enabled=False) dropoff_location: Sublocation = attrs.bproperty(import_required=True, export_enabled=False) name = attrs.bproperty() pickup_address = attrs.bproperty() dropoff_address = attrs.bproperty() @pickup_address.getter def pickup_address(self): return self.pickup_location.road_name @dropoff_address.getter def dropoff_address(self): return self.dropoff_location.road_name @name.getter def name(self): return self.user.name
class Rider(Serializable): """ "device_id": "", "id": obj._driver.user._id, "name": obj._driver.name, "phone_number": "", "role": "rider" """ device_id = attrs.bproperty() _id = attrs.bproperty(data_key="id") name = attrs.bproperty() phone_number = attrs.bproperty() role = attrs.bproperty() class Meta: case_conversion = False exclude = ("obj_type", "doc_id", "doc_ref") @role.getter def role(self): return "rider"
class OrbitView(ViewModel): coriders = attrs.bproperty() host_user = attrs.bproperty() status = attrs.bproperty() timeline = attrs.bproperty() _id = attrs.bproperty(data_key="id") @_id.getter def _id(self): return self.store.orbit.doc_id @status.getter def status(self): return self.store.orbit.status @property def _coriders(self) -> Dict[str, CoriderView]: res = dict() for user_id, ticket in self.store.orbit.user_ticket_pairs.items(): if ticket["userWillDrive"]: continue user = User.get(doc_id=user_id) pickup_location = Sublocation.get( doc_id=ticket["pickupSublocationId"]) dropoff_location = Sublocation.get( doc_id=ticket["dropoffSublocationId"]) booking_id = ticket["bookingId"] booking = self.store.bookings[booking_id] view = CoriderView.new(user=user, pickup_location=pickup_location, dropoff_location=dropoff_location, booking=booking) res[user_id] = view return res @coriders.getter def coriders(self): return {key: val.to_view_dict() for key, val in self._coriders.items()} @property def _driver(self) -> RideHostUserView: for user_id, ticket in self.store.orbit.user_ticket_pairs.items(): if not ticket["userWillDrive"]: continue user = User.get(doc_id=user_id) return RideHostUserView.new(user=user) @host_user.getter def host_user(self): return self._driver.to_view_dict() @timeline.getter def timeline(self): from gravitate.domain.matcher.timeline import Timeline return Timeline.new(orbit=self.store.orbit).timeline @classmethod def new(cls, snapshot=None, **kwargs): orbit = snapshot_to_obj(snapshot=snapshot) struct = Struct(schema_obj=OrbitViewBpss()) struct["orbit"] = (Orbit, orbit.doc_id) for item in orbit.bookings: struct["bookings"][item.doc_id] = (RiderBooking, item.doc_id) if orbit.ride_host is not None: struct["ride_host"] = (RideHost, orbit.ride_host.doc_id) return cls.get(struct_d=struct, **kwargs) def save(self, **kwargs): for _, booking in self.store.bookings.items(): doc_ref = CTX.db.document("users/{}/bookings/{}/orbits/{}".format( booking.user_id, booking.doc_id, self.store.orbit.doc_id)) super().save(doc_ref=doc_ref, save_rel=False, **kwargs) if hasattr(self.store, "ride_host"): ride_host = self.store.ride_host doc_ref = CTX.db.document("users/{}/hostings/{}/orbits/{}".format( ride_host.user_id, ride_host.doc_id, self.store.orbit.doc_id)) super().save(doc_ref=doc_ref, save_rel=False, **kwargs)
class AirportLocation(Location): airport_code = attrs.bproperty()
class UcLocation(Location): campus_code = attrs.bproperty() campus_name = attrs.bproperty()
class SocialEventLocation(Location): event_name = attrs.bproperty()