def approve_and_add(self, request, pk=None, format=None): stall = self.get_object() if stall.status != StallStatus.PENDING: raise BadRequest("Stall is not pending") if stall.election.polling_places_loaded is True: raise BadRequest("Election polling places already loaded") # Create polling place based on user-submitted location info pollingPlaceSerializer = PollingPlacesManagementSerializer(data={ "geom": stall.location_info["geom"], "name": stall.location_info["name"], "address": stall.location_info["address"], "state": stall.location_info["state"], "facility_type": None, "election": stall.election.id, "status": PollingPlaceStatus.ACTIVE, }) if pollingPlaceSerializer.is_valid() is True: pollingPlaceSerializer.save() else: raise BadRequest(pollingPlaceSerializer.errors) # Now that we have a polling place, add noms pollingPlaceWithNomsSerializer = PollingPlacesManagementSerializer(pollingPlaceSerializer.instance, data={"stall": { "noms": stall.noms, "name": stall.name, "description": stall.description, "opening_hours": stall.opening_hours, "website": stall.website, }, }, partial=True) if pollingPlaceWithNomsSerializer.is_valid() is True: pollingPlaceWithNomsSerializer.save() else: raise BadRequest(pollingPlaceWithNomsSerializer.errors) # Approve stall and link it to the new unofficial polling place we just added serializer = StallsManagementSerializer(stall, data={ "status": StallStatus.APPROVED, "approved_on": datetime.now(pytz.utc), "polling_place": pollingPlaceSerializer.instance.id }, partial=True) if serializer.is_valid() is True: serializer.save() send_stall_approved_email(Stalls.objects.get(id=stall.id)) return Response({}) else: raise BadRequest(serializer.errors)
def without_facility_type(self, request, format=None): election_id = request.query_params.get("election_id", None) if election_id is not None: serializer = self.serializer_class(self.queryset.filter(election_id=election_id).filter(facility_type__isnull=True), many=True) return Response(serializer.data) else: raise BadRequest("No election_id provided.")
def retrieve(self, request, *args, **kwargs): stall = self.get_object() if stall.election.is_active() is False: raise BadRequest("The {election_name} election has already finished.".format(election_name=stall.election.name)) return super(StallsViewSet, self).retrieve(request, *args, **kwargs)
def run(self): if self.can_loading_begin() is False: self.logger.error("Loading can't begin. There's probably pending stalls.") else: self.invoke_and_bail_if_errors("convert_to_demsausage_schema") self.invoke_and_bail_if_errors("check_file_validity") self.invoke_and_bail_if_errors("fix_polling_places") self.invoke_and_bail_if_errors("prepare_polling_places") self.invoke_and_bail_if_errors("geocode_missing_locations") self.invoke_and_bail_if_errors("check_polling_place_validity") self.invoke_and_bail_if_errors("dedupe_polling_places") with transaction.atomic(): self.invoke_and_bail_if_errors("write_draft_polling_places") self.invoke_and_bail_if_errors("migrate_noms") self.invoke_and_bail_if_errors("migrate") if self.is_dry_run() is True: # Regenerate GeoJSON because the loader does this and transactions don't help us here :) regenerate_election_geojson(self.election.id) raise BadRequest({"message": "Rollback", "logs": self.collects_logs()}) if self.is_dry_run() is False: # Use a transaction to speed up all of the update calls in here with transaction.atomic(): self.invoke_and_bail_if_errors("detect_facility_type") self.invoke_and_bail_if_errors("calculate_chance_of_sausage") self.invoke_and_bail_if_errors("cleanup") print("All done with loading")
def approve(self, request, pk=None, format=None): stall = self.get_object() if stall.status != StallStatus.PENDING: raise BadRequest("Stall is not pending") serializer = StallsManagementSerializer(self.get_object(), data={ "status": StallStatus.APPROVED, "approved_on": datetime.now(pytz.utc) }, partial=True) if serializer.is_valid() is True: serializer.save() send_stall_approved_email(Stalls.objects.get(id=stall.id)) return Response({}) else: raise BadRequest(serializer.errors)
def favourited(self, request, format=None): election_id = request.query_params.get("election_id", None) if election_id is not None: serializer = self.serializer_class(self.queryset.filter(election_id=election_id).filter(noms__isnull=False, noms__favourited=True).order_by("-noms__id"), many=True) return Response(serializer.data) else: raise BadRequest("No election_id provided.")
def set_primary(self, request, pk=None, format=None): self.get_queryset().filter(is_primary=True).update(is_primary=False) serializer = ElectionsSerializer(self.get_object(), data={"is_primary": True}, partial=True) if serializer.is_valid() is True: serializer.save() return Response({}) else: raise BadRequest(serializer.errors)
def is_valid(self): searchParams = list(self.get_fields().keys()) queryParams = list(self.request.query_params.keys()) if is_one_of_these_things_in_this_other_thing(searchParams, queryParams) is False: raise BadRequest("Please supply a filter criteria: {}".format( ", ".join(searchParams))) return super(PollingPlacesSearchFilter, self).is_valid()
def create(self, request, format=None): serializer = StallsManagementSerializer(data=request.data) if serializer.is_valid() is True: serializer.save() send_stall_submitted_email(Stalls.objects.get(id=serializer.instance.id)) return Response({}, status=status.HTTP_201_CREATED) else: raise BadRequest(serializer.errors)
def filter(self, qs, value): if value == []: raise BadRequest("Please supply at least one value to filter by") elif value is not None: for search_term in value: qs = qs.filter( Q(name__icontains=search_term) | Q(premises__icontains=search_term) | Q(address__icontains=search_term)) return qs
def nearby_bbox(self, request, format=None): """ Retrieve the bounding box of the 15 polling places closest to a given latitude, longitude. Uses the same parameters as /polling_places/nearby/ """ election_id = request.query_params.get("election_id", None) lonlat = request.query_params.get("lonlat", None) if election_id is None or election_id == "": raise BadRequest("No election_id provided.") if lonlat is None or lonlat == "": raise BadRequest("No lonlat provided.") polling_places_filter = LonLatFilter().filter(PollingPlaces.objects.filter(election_id=election_id).filter(status=PollingPlaceStatus.ACTIVE), lonlat) extent = polling_places_filter.annotate(geom_as_geometry=Func("geom", template="geom::geometry")).aggregate(Extent("geom_as_geometry")) return Response({"extent_wgs84": extent["geom_as_geometry__extent"]})
def update_and_resubmit(self, request, pk=None, format=None): stall = self.get_object() if stall.election.is_active() is False: raise BadRequest("The {election_name} election has already finished.".format(election_name=stall.election.name)) data = deepcopy(request.data) del data["token"] del data["signature"] if stall.status == StallStatus.APPROVED or stall.status == StallStatus.DECLINED: data["status"] = StallStatus.PENDING serializer = StallsUserEditSerializer(stall, data, partial=True) if serializer.is_valid() is True: serializer.save() send_stall_edited_email(Stalls.objects.get(id=stall.id)) return Response({}) else: raise BadRequest(serializer.errors)
def save_logs(self, logs): with open("/app/logs/pollingplaceloader-{}.json".format(datetime.now().strftime("%Y-%m-%dT%H:%M:%S")), "w") as f: json.dump(logs, f) serializer = PollingPlaceLoaderEventsSerializer(data={ "timestamp": datetime.now().strftime("%Y-%m-%dT%H:%M:%S"), "payload": logs }) if serializer.is_valid() is True: serializer.save() else: raise BadRequest("Error saving logs :(")
def stall_lookup(self, request, format=None): """ Lookup the details for an individual polling place by the id of the stall attached to it. """ stall_id = request.query_params.get("stall_id", None) if stall_id is not None: pollingPlace = find_by_stall(stall_id, self.queryset) if pollingPlace is not None: return Response(self.serializer_class(pollingPlace).data) return HttpResponseNotFound() else: raise BadRequest("No stall_id provided.")
def polling_places_rollback(self, request, pk=None, format=None): election = self.get_object() dry_run = True if request.data.get("dry_run", None) == "1" else False rollback = RollbackPollingPlaces(election, dry_run) rollback.run() if rollback.is_dry_run() is True: # Regenerate GeoJSON because the loader does this and transactions don't help us here :) regenerate_election_geojson(election.id) raise BadRequest({"message": "Rollback", "logs": rollback.collects_logs()}) rollback.collects_logs() return Response({})
def polling_places(self, request, pk=None, format=None): election = self.get_object() dry_run = True if str(request.data.get("dry_run", 0)) == "1" else False config = request.data.get("config", None) try: if config is not None and len(config) > 0: config = json.loads(config) except ValueError as e: raise BadRequest("Could not parse config: {}".format(e)) loader = LoadPollingPlaces(election, request.data["file"], dry_run, config) loader.run() return Response({"message": "Done", "logs": loader.collects_logs()})
def lookup(self, request, format=None): """ Lookup the details for an individual polling place by its name + premises + state or its ec_id field. """ election_id = request.query_params.get("election_id", None) lookup_terms = { "ec_id": request.query_params.get("ec_id", None), "name": request.query_params.get("name", None), "premises": request.query_params.get("premises", None), "state": request.query_params.get("state", None), } if election_id is not None: pollingPlace = find_by_lookup_terms(election_id, lookup_terms, self.queryset) if pollingPlace is not None: return Response(self.serializer_class(pollingPlace).data) return HttpResponseNotFound() else: raise BadRequest("No election_id provided.")
def filter(self, qs, value): if value not in (None, ""): from django.contrib.gis.geos import Point from demsausage.app.sausage.polling_places import find_by_distance try: lon, lat = [float(v) for v in value[0:1000].split(",")] search_point = Point(float(lon), float(lat), srid=4326) except Exception as e: raise BadRequest(e) polling_places_filter = find_by_distance(search_point, distance_threshold_km=50, limit=15, qs=qs) if polling_places_filter.count() == 0: polling_places_filter = find_by_distance( search_point, distance_threshold_km=1000, limit=15, qs=qs) return polling_places_filter return qs
def raise_exception_if_errors(self): if self.has_errors_messages() is True: print("Bailing with errors") raise BadRequest({"message": "Oh dear, looks like we hit a snag (get it - snag?!)", "logs": self.collects_logs()})
def filter(self, qs, value): if value == []: raise BadRequest("Please supply at least one value to filter by") else: return super(ValueInFilter, self).filter(qs, value)