Esempio n. 1
0
    def update(self, request, pk):
        """
        Update a taxlot
        ---
        parameters:
            - name: cycle_id
              description: The cycle id for filtering the taxlot view
              required: true
              paramType: query
        """
        data = request.data
        cycle_pk = request.query_params.get('cycle_id', None)
        if not cycle_pk:
            return JsonResponse({
                'status':
                'error',
                'message':
                'Must pass in cycle_id as query parameter'
            })
        result = self._get_taxlot_view(pk, cycle_pk)
        if result.get('status', None) != 'error':
            taxlot_view = result.pop('taxlot_view')
            taxlot_state_data = TaxLotStateSerializer(taxlot_view.state).data
            new_taxlot_state_data = data['state']

            changed = True
            for key, val in new_taxlot_state_data.iteritems():
                if val == '':
                    new_taxlot_state_data[key] = None
            changed_fields = get_changed_fields(taxlot_state_data,
                                                new_taxlot_state_data)
            if not changed_fields:
                changed = False
            if not changed:
                result.update({
                    'status': 'error',
                    'message': 'Nothing to update'
                })
                status_code = 422  # status.HTTP_422_UNPROCESSABLE_ENTITY
            else:
                log = TaxLotAuditLog.objects.select_related().filter(
                    state=taxlot_view.state).order_by('-id').first()

                if 'extra_data' in new_taxlot_state_data.keys():
                    taxlot_state_data['extra_data'].update(
                        new_taxlot_state_data.pop('extra_data'))
                taxlot_state_data.update(new_taxlot_state_data)

                if log.name == 'Import Creation':
                    # Add new state
                    taxlot_state_data.pop('id')
                    new_taxlot_state_serializer = TaxLotStateSerializer(
                        data=taxlot_state_data)
                    if new_taxlot_state_serializer.is_valid():
                        new_state = new_taxlot_state_serializer.save()
                        taxlot_view.state = new_state
                        taxlot_view.save()

                        TaxLotAuditLog.objects.create(
                            organization=log.organization,
                            parent1=log,
                            parent2=None,
                            parent_state1=log.state,
                            parent_state2=None,
                            state=new_state,
                            name='Manual Edit',
                            description=None,
                            import_filename=log.import_filename,
                            record_type=AUDIT_USER_EDIT)

                        result.update({
                            'state':
                            new_taxlot_state_serializer.validated_data
                        })
                        # Removing organization key AND import_file key because they're not JSON-serializable
                        # TODO find better solution
                        result['state'].pop('organization')
                        result['state'].pop('import_file')
                        status_code = status.HTTP_201_CREATED
                    else:
                        result.update({
                            'status': 'error',
                            'message': 'Invalid Data'
                        })
                        status_code = 422  # status.HTTP_422_UNPROCESSABLE_ENTITY
                elif log.name in [
                        'Manual Edit', 'Manual Match', 'System Match',
                        'Merge current state in migration'
                ]:
                    # Override previous edit state or merge state
                    state = taxlot_view.state
                    for key, value in new_taxlot_state_data.iteritems():
                        setattr(state, key, value)
                    state.save()

                    result.update({'state': TaxLotStateSerializer(state).data})
                    # Removing organization key AND import_file key because they're not JSON-serializable
                    # TODO find better solution
                    result['state'].pop('organization')
                    result['state'].pop('import_file')

                    status_code = status.HTTP_201_CREATED
                else:
                    result = {
                        'status': 'error',
                        'message': 'Unrecognized audit log name: ' + log.name
                    }
                    status_code = 422
                    return JsonResponse(result, status=status_code)

        else:
            status_code = status.HTTP_404_NOT_FOUND
        return JsonResponse(result, status=status_code)
Esempio n. 2
0
    def update(self, request, pk):
        """
        Update a taxlot
        ---
        parameters:
            - name: organization_id
              description: The organization_id for this user's organization
              required: true
              paramType: query
        """
        data = request.data

        result = self._get_taxlot_view(pk)
        if result.get('status', 'error') != 'error':
            taxlot_view = result.pop('taxlot_view')
            taxlot_state_data = TaxLotStateSerializer(taxlot_view.state).data

            # get the taxlot state information from the request
            new_taxlot_state_data = data['state']

            # set empty strings to None
            for key, val in new_taxlot_state_data.iteritems():
                if val == '':
                    new_taxlot_state_data[key] = None

            changed_fields = get_changed_fields(taxlot_state_data,
                                                new_taxlot_state_data)
            if not changed_fields:
                result.update({
                    'status': 'success',
                    'message': 'Records are identical'
                })
                return JsonResponse(result, status=status.HTTP_204_NO_CONTENT)
            else:
                # Not sure why we are going through the pain of logging this all right now... need to
                # reevaluate this.
                log = TaxLotAuditLog.objects.select_related().filter(
                    state=taxlot_view.state).order_by('-id').first()

                if 'extra_data' in new_taxlot_state_data.keys():
                    taxlot_state_data['extra_data'].update(
                        new_taxlot_state_data.pop('extra_data'))
                taxlot_state_data.update(new_taxlot_state_data)

                if log.name == 'Import Creation':
                    # Add new state by removing the existing ID.
                    taxlot_state_data.pop('id')
                    new_taxlot_state_serializer = TaxLotStateSerializer(
                        data=taxlot_state_data)
                    if new_taxlot_state_serializer.is_valid():
                        # create the new property state, and perform an initial save / moving relationships
                        new_state = new_taxlot_state_serializer.save()

                        # then assign this state to the property view and save the whole view
                        taxlot_view.state = new_state
                        taxlot_view.save()

                        TaxLotAuditLog.objects.create(
                            organization=log.organization,
                            parent1=log,
                            parent2=None,
                            parent_state1=log.state,
                            parent_state2=None,
                            state=new_state,
                            name='Manual Edit',
                            description=None,
                            import_filename=log.import_filename,
                            record_type=AUDIT_USER_EDIT)

                        result.update(
                            {'state': new_taxlot_state_serializer.data})

                        return JsonResponse(result, status=status.HTTP_200_OK)
                    else:
                        result.update({
                            'status':
                            'error',
                            'message':
                            'Invalid update data with errors: {}'.format(
                                new_taxlot_state_serializer.errors)
                        })
                        return JsonResponse(
                            result,
                            status=status.HTTP_422_UNPROCESSABLE_ENTITY)
                elif log.name in [
                        'Manual Edit', 'Manual Match', 'System Match',
                        'Merge current state in migration'
                ]:
                    # Convert this to using the serializer to save the data. This will override the previous values
                    # in the state object.

                    # Note: We should be able to use partial update here and pass in the changed fields instead of the
                    # entire state_data.
                    updated_taxlot_state_serializer = TaxLotStateSerializer(
                        taxlot_view.state, data=taxlot_state_data)
                    if updated_taxlot_state_serializer.is_valid():
                        # create the new property state, and perform an initial save / moving relationships
                        updated_taxlot_state_serializer.save()

                        result.update(
                            {'state': updated_taxlot_state_serializer.data})

                        return JsonResponse(result, status=status.HTTP_200_OK)
                    else:
                        result.update({
                            'status':
                            'error',
                            'message':
                            'Invalid update data with errors: {}'.format(
                                updated_taxlot_state_serializer.errors)
                        })
                        return JsonResponse(
                            result,
                            status=status.HTTP_422_UNPROCESSABLE_ENTITY)
                else:
                    result = {
                        'status': 'error',
                        'message': 'Unrecognized audit log name: ' + log.name
                    }
                    return JsonResponse(result,
                                        status=status.HTTP_204_NO_CONTENT)

            # save the tax lot view, even if it hasn't changed so that the datetime gets updated on the taxlot.
            # Uhm, does this ever get called? There are a bunch of returns in the code above.
            taxlot_view.save()
        else:
            return JsonResponse(result, status=status.HTTP_404_NOT_FOUND)

        return JsonResponse(result, status=status.HTTP_404_NOT_FOUND)
Esempio n. 3
0
    def update(self, request, pk):
        """
        Update a taxlot and run the updated record through a match and merge
        round within it's current Cycle.
        ---
        parameters:
            - name: organization_id
              description: The organization_id for this user's organization
              required: true
              paramType: query
        """
        data = request.data

        result = self._get_taxlot_view(pk)
        if result.get('status', 'error') != 'error':
            taxlot_view = result.pop('taxlot_view')
            taxlot_state_data = TaxLotStateSerializer(taxlot_view.state).data

            # get the taxlot state information from the request
            new_taxlot_state_data = data['state']

            # set empty strings to None
            for key, val in new_taxlot_state_data.items():
                if val == '':
                    new_taxlot_state_data[key] = None

            changed_fields, previous_data = get_changed_fields(
                taxlot_state_data, new_taxlot_state_data)
            if not changed_fields:
                result.update({
                    'status': 'success',
                    'message': 'Records are identical'
                })
                return JsonResponse(result, status=status.HTTP_204_NO_CONTENT)
            else:
                # Not sure why we are going through the pain of logging this all right now... need to
                # reevaluate this.
                log = TaxLotAuditLog.objects.select_related().filter(
                    state=taxlot_view.state).order_by('-id').first()

                # if checks above pass, create an exact copy of the current state for historical purposes
                if log.name == 'Import Creation':
                    # Add new state by removing the existing ID.
                    taxlot_state_data.pop('id')
                    # Remove the import_file_id for the first edit of a new record
                    # If the import file has been deleted and this value remains the serializer won't be valid
                    taxlot_state_data.pop('import_file')
                    new_taxlot_state_serializer = TaxLotStateSerializer(
                        data=taxlot_state_data)
                    if new_taxlot_state_serializer.is_valid():
                        # create the new property state, and perform an initial save / moving relationships
                        new_state = new_taxlot_state_serializer.save()

                        # then assign this state to the property view and save the whole view
                        taxlot_view.state = new_state
                        taxlot_view.save()

                        TaxLotAuditLog.objects.create(
                            organization=log.organization,
                            parent1=log,
                            parent2=None,
                            parent_state1=log.state,
                            parent_state2=None,
                            state=new_state,
                            name='Manual Edit',
                            description=None,
                            import_filename=log.import_filename,
                            record_type=AUDIT_USER_EDIT)

                        result.update(
                            {'state': new_taxlot_state_serializer.data})

                        # save the property view so that the datetime gets updated on the property.
                        taxlot_view.save()
                    else:
                        result.update({
                            'status':
                            'error',
                            'message':
                            'Invalid update data with errors: {}'.format(
                                new_taxlot_state_serializer.errors)
                        })
                        return JsonResponse(
                            result,
                            status=status.HTTP_422_UNPROCESSABLE_ENTITY)

                # redo assignment of this variable in case this was an initial edit
                taxlot_state_data = TaxLotStateSerializer(
                    taxlot_view.state).data

                if 'extra_data' in new_taxlot_state_data:
                    taxlot_state_data['extra_data'].update(
                        new_taxlot_state_data['extra_data'])

                taxlot_state_data.update({
                    k: v
                    for k, v in new_taxlot_state_data.items()
                    if k != 'extra_data'
                })

                log = TaxLotAuditLog.objects.select_related().filter(
                    state=taxlot_view.state).order_by('-id').first()

                if log.name in [
                        'Manual Edit', 'Manual Match', 'System Match',
                        'Merge current state in migration'
                ]:
                    # Convert this to using the serializer to save the data. This will override the
                    # previous values in the state object.

                    # Note: We should be able to use partial update here and pass in the changed
                    # fields instead of the entire state_data.
                    updated_taxlot_state_serializer = TaxLotStateSerializer(
                        taxlot_view.state, data=taxlot_state_data)
                    if updated_taxlot_state_serializer.is_valid():
                        # create the new property state, and perform an initial save / moving
                        # relationships
                        updated_taxlot_state_serializer.save()

                        result.update(
                            {'state': updated_taxlot_state_serializer.data})

                        # save the property view so that the datetime gets updated on the property.
                        taxlot_view.save()

                        Note.create_from_edit(request.user.id, taxlot_view,
                                              new_taxlot_state_data,
                                              previous_data)

                        merge_count, link_count, view_id = match_merge_link(
                            taxlot_view.id, 'TaxLotState')

                        result.update({
                            'view_id': view_id,
                            'match_merged_count': merge_count,
                            'match_link_count': link_count,
                        })

                        return JsonResponse(result, status=status.HTTP_200_OK)
                    else:
                        result.update({
                            'status':
                            'error',
                            'message':
                            'Invalid update data with errors: {}'.format(
                                updated_taxlot_state_serializer.errors)
                        })
                        return JsonResponse(
                            result,
                            status=status.HTTP_422_UNPROCESSABLE_ENTITY)
                else:
                    result = {
                        'status': 'error',
                        'message': 'Unrecognized audit log name: ' + log.name
                    }
                    return JsonResponse(result,
                                        status=status.HTTP_204_NO_CONTENT)
        else:
            return JsonResponse(result, status=status.HTTP_404_NOT_FOUND)
Esempio n. 4
0
    def update(self, request, pk=None):
        """
        Update a property and run the updated record through a match and merge
        round within it's current Cycle.

        - looks up the property view
        - casts it as a PropertyState
        - builds a hash with all the same keys as the original property state
        - checks if any fields have changed
        - if nothing has changed, return 422 - Really?  Not sure how I feel about that one, it *is* processable
        - get the property audit log for this property state
        - if the new property state has extra_data, the original extra_data is update'd
        - and then whoa stuff about the audit log?
        - I'm going to assume 'Import Creation' is the key I'm looking for
        - create a serializer for the new property state
        - if it's valid, save this new serialized data to the db
        - assign it to the original property view and save the property view
        - create a new property audit log for this change
        - return a 200 if created

        ---
        parameters:
            - name: organization_id
              description: The organization_id for this user's organization
              required: true
              paramType: query
        """
        data = request.data

        result = self._get_property_view(pk)
        if result.get('status', None) != 'error':
            property_view = result.pop('property_view')
            property_state_data = PropertyStateSerializer(
                property_view.state).data

            # get the property state information from the request
            new_property_state_data = data['state']

            # set empty strings to None
            for key, val in new_property_state_data.items():
                if val == '':
                    new_property_state_data[key] = None

            changed_fields = get_changed_fields(property_state_data,
                                                new_property_state_data)
            if not changed_fields:
                result.update({
                    'status': 'success',
                    'message': 'Records are identical'
                })
                return JsonResponse(result, status=status.HTTP_204_NO_CONTENT)
            else:
                # Not sure why we are going through the pain of logging this all right now... need to
                # reevaluate this.
                log = PropertyAuditLog.objects.select_related().filter(
                    state=property_view.state).order_by('-id').first()

                if 'extra_data' in new_property_state_data:
                    property_state_data['extra_data'].update(
                        new_property_state_data.pop('extra_data'))
                property_state_data.update(new_property_state_data)

                if log.name == 'Import Creation':
                    # Add new state by removing the existing ID.
                    property_state_data.pop('id')
                    new_property_state_serializer = PropertyStateSerializer(
                        data=property_state_data)
                    if new_property_state_serializer.is_valid():
                        # create the new property state, and perform an initial save / moving relationships
                        new_state = new_property_state_serializer.save()

                        # Since we are creating a new relationship when we are manually editing the Properties, then
                        # we need to move the relationships over to the new manually edited record.
                        new_state = self._move_relationships(
                            property_view.state, new_state)
                        new_state.save()

                        # then assign this state to the property view and save the whole view
                        property_view.state = new_state
                        property_view.save()

                        PropertyAuditLog.objects.create(
                            organization=log.organization,
                            parent1=log,
                            parent2=None,
                            parent_state1=log.state,
                            parent_state2=None,
                            state=new_state,
                            name='Manual Edit',
                            description=None,
                            import_filename=log.import_filename,
                            record_type=AUDIT_USER_EDIT)

                        result.update(
                            {'state': new_property_state_serializer.data})

                        # save the property view so that the datetime gets updated on the property.
                        property_view.save()

                        count, view_id = match_merge_in_cycle(
                            property_view.id, 'PropertyState')

                        if view_id is not None:
                            result.update({
                                'view_id': view_id,
                                'match_merged_count': count,
                            })

                        return JsonResponse(result,
                                            encoder=PintJSONEncoder,
                                            status=status.HTTP_200_OK)
                    else:
                        result.update({
                            'status':
                            'error',
                            'message':
                            'Invalid update data with errors: {}'.format(
                                new_property_state_serializer.errors)
                        })
                        return JsonResponse(
                            result,
                            encoder=PintJSONEncoder,
                            status=status.HTTP_422_UNPROCESSABLE_ENTITY)
                elif log.name in [
                        'Manual Edit', 'Manual Match', 'System Match',
                        'Merge current state in migration'
                ]:
                    # Convert this to using the serializer to save the data. This will override the previous values
                    # in the state object.

                    # Note: We should be able to use partial update here and pass in the changed fields instead of the
                    # entire state_data.
                    updated_property_state_serializer = PropertyStateSerializer(
                        property_view.state, data=property_state_data)
                    if updated_property_state_serializer.is_valid():
                        # create the new property state, and perform an initial save / moving
                        # relationships
                        updated_property_state_serializer.save()

                        result.update(
                            {'state': updated_property_state_serializer.data})

                        # save the property view so that the datetime gets updated on the property.
                        property_view.save()

                        count, view_id = match_merge_in_cycle(
                            property_view.id, 'PropertyState')

                        if view_id is not None:
                            result.update({
                                'view_id': view_id,
                                'match_merged_count': count,
                            })

                        return JsonResponse(result,
                                            encoder=PintJSONEncoder,
                                            status=status.HTTP_200_OK)
                    else:
                        result.update({
                            'status':
                            'error',
                            'message':
                            'Invalid update data with errors: {}'.format(
                                updated_property_state_serializer.errors)
                        })
                        return JsonResponse(
                            result,
                            encoder=PintJSONEncoder,
                            status=status.HTTP_422_UNPROCESSABLE_ENTITY)
                else:
                    result = {
                        'status': 'error',
                        'message': 'Unrecognized audit log name: ' + log.name
                    }
                    return JsonResponse(
                        result, status=status.HTTP_422_UNPROCESSABLE_ENTITY)
        else:
            return JsonResponse(result, status=status.HTTP_404_NOT_FOUND)