def update(self, request, pk=None): """ Update a property --- parameters: - name: cycle_id description: The cycle id for filtering the property view required: true paramType: query """ 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' }) data = request.data result = self._get_property_view(pk, cycle_pk) if result.get('status', None) != 'error': property_view = result.pop('property_view') property_state_data = PropertyStateSerializer( property_view.state).data new_property_state_data = data['state'] changed = True for key, val in new_property_state_data.iteritems(): if val == '': new_property_state_data[key] = None changed_fields = get_changed_fields(property_state_data, new_property_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 = PropertyAuditLog.objects.select_related().filter( state=property_view.state).order_by('-id').first() if 'extra_data' in new_property_state_data.keys(): 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 property_state_data.pop('id') new_property_state_serializer = PropertyStateSerializer( data=property_state_data) if new_property_state_serializer.is_valid(): new_state = new_property_state_serializer.save() 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.validated_data }) # Removing organization key AND import_file key because they're not JSON-serializable # TODO find better solution if 'organization' in result['state']: result['state'].pop('organization') if 'import_file' in result['state']: 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 = property_view.state for key, value in new_property_state_data.iteritems(): setattr(state, key, value) state.save() result.update( {'state': PropertyStateSerializer(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)
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)