Beispiel #1
0
    def delete(self, request, username, parcel_id, format=None):
        """
        Do a soft-delete on a user's favorite.
        """

        CODLogger.instance().log_api_call(name=__name__, msg=request.path)

        if not request.is_secure():
            return Response({"error": "must be secure"},
                            status=status.HTTP_403_FORBIDDEN)

        parcel_id = get_parcel_id(request.path, 5)

        users = User.objects.using('photo_survey').filter(username=username)
        if not users:
            return Response({"User not found": username},
                            status=status.HTTP_404_NOT_FOUND)

        favorites = Survey.objects.filter(
            survey_type__survey_template_id='bridging_neighborhoods').filter(
                user_id=users[0].id).filter(parcel__parcel_id=parcel_id)
        if not favorites:
            return Response({"favorite not found": parcel_id},
                            status=status.HTTP_404_NOT_FOUND)

        for favorite in favorites:
            favorite.status = 'deleted'
            favorite.save()

        return Response(status=status.HTTP_204_NO_CONTENT)
Beispiel #2
0
def get_dte_active_connection(request, parcel_id, param=None):
    """
    Returns data cached for the given data source, updating the data whenever necessary.
    """

    CODLogger.instance().log_api_call(name=__name__, msg=request.path)

    # Only allow certain servers to call this endpoint
    if security.block_client(request):  # pragma: no cover
        remote_addr = request.META.get('REMOTE_ADDR')
        SlackMsgHandler().send_admin_alert(
            "Address {} was blocked from subscribing waste alerts".format(
                remote_addr))
        return Response("Invalid caller ip or host name: " + remote_addr,
                        status=status.HTTP_403_FORBIDDEN)

    # Only call via https...
    if not request.is_secure():
        return Response({"error": "must be secure"},
                        status=status.HTTP_403_FORBIDDEN)

    parcel_id = get_parcel_id(request.path, 4)

    if not DTEActiveGasSite.objects.filter(parcel_id=parcel_id).exists():
        raise Http404("No parcel " + parcel_id +
                      " found with active connection")

    return Response({"active": True})
Beispiel #3
0
def get_survey_count(request, parcel_id):
    """
    Get number of surveys that exist currently for the given parcel.
    """

    CODLogger.instance().log_api_call(name=__name__, msg=request.path)

    parcel_id = get_parcel_id(request.path, 3)

    count = Survey.objects.filter(parcel__parcel_id=parcel_id).exclude(
        status='deleted').count()
    content = {"count": count}

    return Response(content)
Beispiel #4
0
def get_latest_survey(request, parcel_id):
    """
    Returns latest survey data for the parcel.
    TODO return latest survey that has a 'good' status.
    """

    CODLogger.instance().log_api_call(name=__name__, msg=request.path)

    parcel_id = get_parcel_id(request.path, 4)

    survey = Survey.objects.filter(parcel__parcel_id=parcel_id).exclude(
        status='deleted').last()

    content = get_survey_data(survey) if survey else {}

    return Response(content)
Beispiel #5
0
def get_parcel(request, pnum=None, format=None):
    """
    Return parcel data from the assessors dataset
    """

    CODLogger.instance().log_api_call(name=__name__, msg=request.path)

    # clean up the pnum
    pnum = get_parcel_id(request.path, 3)

    # excecute the search
    parcels = BSAPARCELDATA.objects.filter(PARCELNO=pnum)
    if not parcels:
        raise Http404("Parcel id " + pnum + " not found")

    content = parcels[0].to_json()
    content['field_descriptions'] = util.get_parcel_descriptions()

    return Response(content)
Beispiel #6
0
def get_images(request, pnum=None, format=None):
    """
    Retrieve all images for the given parcel.
    """

    # REVIEW TODO add frank's suggestions

    CODLogger.instance().log_api_call(name=__name__, msg=request.path)

    # clean up the pnum
    pnum = get_parcel_id(request.path, 2)
    sketch_data = Sketch.objects.filter(pnum=pnum).order_by('-date')
    content = []

    # REVIEW (TODO) remove the call to move_files() ...

    for sketch in sketch_data:

        content.append(sketch.to_json())

    return Response(content)
Beispiel #7
0
def get_sales_property(request, pnum=None, years_back=None, format=None):
    """
    Retrieve property info via parcel id (aka 'pnum')
    """

    CODLogger.instance().log_api_call(name=__name__, msg=request.path)

    pnum = get_parcel_id(request.path, 2)

    # Search for parcels with the given parcel num
    # pnum = request.path_info.split('/')[2]
    results = Sales.objects.filter(pnum__iexact=pnum)

    # filter recent-years only?
    if years_back != None:
        results = filter_years_back(results, years_back)

    # if no results found, return 404
    if len(results) == 0:
        raise Http404("Parcel id " + pnum + " not found")

    return get_parcels(results)
Beispiel #8
0
def get_metadata(request, parcel_id):
    """
    Get photos and survey data for the given parcel
    """

    CODLogger.instance().log_api_call(name=__name__, msg=request.path)

    parcel_id = get_parcel_id(request.path, 2)

    # TODO possibly optimize the images on the disk?
    # https://hugogiraudel.com/2013/07/29/optimizing-with-bash/
    # e.g., jpegtran -progressive image_raw.jpg small.jpg

    images = []
    image_metadata = ImageMetadata.objects.filter(parcel__parcel_id=parcel_id)
    for img_meta in image_metadata:
        url = request.build_absolute_uri(
            location='/data/photo_survey/images/' + img_meta.image.file_path)
        images.append(url)

    surveys = [
        survey.id for survey in Survey.objects.filter(
            parcel__parcel_id=parcel_id).exclude(status='deleted')
    ]

    # Is this parcel publicly owned?
    # TODO: make sure the dataset for this eventually 'goes live' (currently we load it
    # whenever dexter slusarski gets a new csv with this content)
    public_property_data = PublicPropertyData.objects.filter(
        parcelno=parcel_id)
    publicly_owned = len(public_property_data) > 0

    return Response({
        "images": images,
        "surveys": surveys,
        "publicly_owned": publicly_owned
    })
Beispiel #9
0
    def post(self, request, parcel_id, format=None):
        """
        Post results of a field survey
        """

        CODLogger.instance().log_api_call(name=__name__, msg=request.path)

        if not request.is_secure():
            return Response({"error": "must be secure"},
                            status=status.HTTP_403_FORBIDDEN)

        # TODO remove this once we get mod_wsgi passing the authorization header through properly
        auth_meta = request.META.get('HTTP_AUTHORIZATION')
        if auth_meta:
            print(auth_meta)
        else:
            print('saw no http auth meta')

        data = json.loads(request.body.decode('utf-8'))

        # What user is posting this?
        user = self.get_surveyor(request, data)

        if user == None:
            return Response({"error": "user not authorized"},
                            status=status.HTTP_401_UNAUTHORIZED)

        survey_template_id = self.get_survey_template_id(data)
        parcel_id = get_parcel_id(request.path, self.get_parcel_id_offset())
        answer_errors = {}

        # Is the parcel id valid?
        if not ParcelMaster.objects.filter(pnum__iexact=parcel_id).exists():
            return Response({"invalid parcel id": parcel_id},
                            status=status.HTTP_400_BAD_REQUEST)

        # What are our questions and answers?
        questions = SurveyQuestion.objects.filter(
            survey_type__survey_template_id=survey_template_id).order_by(
                'question_number')
        if not questions:
            return Response({"invalid survey": data['survey_id']},
                            status=status.HTTP_400_BAD_REQUEST)

        answers = {answer['question_id']: answer for answer in data['answers']}

        # Report any answers that did not match a question_id
        question_ids = {question.question_id for question in questions}
        orphaned_answers = {
            key
            for key in answers.keys() if key not in question_ids
        }
        if orphaned_answers:
            return Response({"invalid question ids": list(orphaned_answers)},
                            status=status.HTTP_400_BAD_REQUEST)

        # Validate each answer
        for question in questions:
            answer = answers.get(question.question_id)
            if answer and answer.get('answer'):
                if not question.is_valid(answer['answer']):
                    answer_errors[
                        question.question_id] = "question answer is invalid"
                elif question.answer_trigger and question.answer_trigger_action:
                    # TODO clean this up - add 'skip to question' feature
                    if re.fullmatch(
                            question.answer_trigger, answer['answer']
                    ) and question.answer_trigger_action == 'exit':
                        break
            elif SurveyorView.is_answer_required(question, answers):
                answer_errors[
                    question.question_id] = "question answer is required"

        # Report invalid content?
        if answer_errors:
            return Response(answer_errors, status=status.HTTP_400_BAD_REQUEST)

        parcel, created = ParcelMetadata.objects.get_or_create(
            parcel_id=parcel_id)

        # Create the survey
        survey_type = SurveyType.objects.get(
            survey_template_id=survey_template_id)
        survey = Survey(survey_type=survey_type,
                        user_id=str(user.id),
                        parcel=parcel,
                        common_name=data.get('common_name', ''),
                        note=data.get('note', ''),
                        status=data.get('status', ''),
                        image_url=data.get('image_url', ''))
        survey.save()

        # Save all the answers
        for survey_question in questions:
            answer = answers.get(survey_question.question_id)
            if answer and answer['answer']:
                survey_answer = SurveyAnswer(survey=survey,
                                             survey_question=survey_question,
                                             answer=answer['answer'],
                                             note=answer.get('answer', None))
                survey_answer.save()

        # Indicate number of surveys present for each parcel id in the request
        parcel_info = self.check_parcels(data.get('parcel_ids', []))

        return Response({
            "answers": answers,
            "parcel_survey_info": parcel_info
        },
                        status=status.HTTP_201_CREATED)