def attach_files_to_feedback(request, feedback, files):
    for file in files:
        abs_url = ''.join([request.build_absolute_uri('/')[:-1], settings.MEDIA_URL, file.file.name])
        media_url = MediaURL(feedback=feedback, media_url=abs_url)
        media_url.save()
        feedback.media_urls.add(media_url)
        # Attach the file to feedback - not needed if using external Open311!
        feedback.media_files.add(file)

    # Update the single media_url field to point to the 1st image
    feedback.media_url = feedback.media_urls.all()[0].media_url
    feedback.save()
def save_feedback(f):
    existing_feedback = get_existing_feedback(f['service_request_id'])
    # Maybe just say Feedback(**f) or the like?
    updated_feedback = Feedback(
            service_request_id=f['service_request_id'],
            status_notes=f.get('status_notes', ''),
            status=f['status'],
            service_code=f.get('service_code', ''),
            service_name=f.get('service_name', ''),
            description=f.get('description', ''),
            agency_responsible=f.get('agency_responsible', ''),
            service_notice=f.get('service_notice', ''),
            requested_datetime=f.get('requested_datetime', ''),
            updated_datetime=f.get('updated_datetime', ''),
            address_string=f.get('address', ''),
            media_url=f.get('media_url', ''),

            email=f.get('email', ''),
            first_name=f.get('first_name', ''),
            last_name=f.get('last_name', ''),
            phone=f.get('phone', ''),

            # Extension information
            service_object_id=f.get('service_object_id', ''),
            service_object_type=f.get('service_object_type', ''),

            location=GEOSGeometry('SRID=4326;POINT(' + str(f.get('long', 0)) + ' ' + str(f.get('lat', 0)) + ')'),

            synchronized=True
    )

    if existing_feedback:
        updated_feedback.id = existing_feedback.id
        Task.objects.filter(feedback_id=existing_feedback.id).delete()
        MediaURL.objects.filter(feedback_id=existing_feedback.id).delete()

    extended_attributes = f.get('extended_attributes', None)
    if extended_attributes:
        updated_feedback.title = extended_attributes.get('title', '')
        updated_feedback.detailed_status = extended_attributes.get('detailed_status', '')

    updated_feedback.save()

    if extended_attributes:
        media_urls_json = extended_attributes.get('media_urls', None)
        if media_urls_json:
            for media_url_json in media_urls_json:
                media_url = MediaURL(feedback_id=updated_feedback.id, media_url=media_url_json)
                media_url.save()

        tasks_json = extended_attributes.get('tasks', None)
        if tasks_json:
            for task_json in tasks_json:
                task = Task(
                        feedback_id=updated_feedback.id,
                        task_state=task_json.get('task_state', ''),
                        task_type=task_json.get('task_type', ''),
                        owner_name=task_json.get('owner_name', ''),
                        task_modified=task_json.get('task_modified', ''),
                        task_created=task_json.get('task_created', '')
                )
                task.save()
def save_feedback(f):
    existing_feedback = get_existing_feedback(f['service_request_id'])

    expected_datetime = f.get('expected_datetime', None)
    requested_datetime = f.get('requested_datetime', None)
    if expected_datetime is None and requested_datetime is not None:
        requested_datetime = parse(requested_datetime)
        median = timedelta(milliseconds=calc_fixing_time(f.get('service_code', '')))
        if median.total_seconds() > 0:
            expected_datetime = requested_datetime + median

    updated_feedback = Feedback(
            service_request_id=f['service_request_id'],
            status_notes=f.get('status_notes', ''),
            status=f['status'],
            service_code=f.get('service_code', ''),
            service_name=f.get('service_name', ''),
            description=f.get('description', ''),
            agency_responsible=f.get('agency_responsible', ''),
            service_notice=f.get('service_notice', ''),
            requested_datetime=f.get('requested_datetime', ''),
            updated_datetime=f.get('updated_datetime', ''),
            expected_datetime=expected_datetime,
            address_string=f.get('address', ''),
            media_url=f.get('media_url', ''),

            email=f.get('email', ''),
            first_name=f.get('first_name', ''),
            last_name=f.get('last_name', ''),
            phone=f.get('phone', ''),

            # Extension information
            service_object_id=f.get('service_object_id', ''),
            service_object_type=f.get('service_object_type', ''),

            location=GEOSGeometry('SRID=4326;POINT(' + str(f.get('long', 0)) + ' ' + str(f.get('lat', 0)) + ')'),

            synchronized=True
    )

    if existing_feedback:
        updated_feedback.id = existing_feedback.id
        Task.objects.filter(feedback_id=existing_feedback.id).delete()
        MediaURL.objects.filter(feedback_id=existing_feedback.id).delete()

    extended_attributes = f.get('extended_attributes', None)
    if extended_attributes:
        updated_feedback.title = extended_attributes.get('title', '')
        updated_feedback.detailed_status = extended_attributes.get('detailed_status', '')

    updated_feedback.save()

    if extended_attributes:
        media_urls_json = extended_attributes.get('media_urls', None)
        if media_urls_json:
            for media_url_json in media_urls_json:
                media_url = MediaURL(feedback_id=updated_feedback.id, media_url=media_url_json)
                media_url.save()

        tasks_json = extended_attributes.get('tasks', None)
        if tasks_json:
            for task_json in tasks_json:
                task = Task(
                        feedback_id=updated_feedback.id,
                        task_state=task_json.get('task_state', ''),
                        task_type=task_json.get('task_type', ''),
                        owner_name=task_json.get('owner_name', ''),
                        task_modified=task_json.get('task_modified', ''),
                        task_created=task_json.get('task_created', '')
                )
                task.save()

    if settings.SEND_STATUS_UPDATE_NOTIFICATIONS \
            and existing_feedback and feedback_status_was_changed(existing_feedback, updated_feedback):
        send_email_notification(updated_feedback)