Example #1
0
def show_contact(request, key):
    """
    Shows details about a specific contact.
    
    It uses django's generic views.
    """
    return object_detail(request, Contact.all(), key)
Example #2
0
def delete_contacts(request):
    """
    Deletes all the contacts from the current google username.
    
    This view also deletes the entities associated with the contacts
    that are being deleted.
    """
    if request.method == 'POST':
        db.delete( Contact.all().filter("owner =", users.get_current_user()) )
        db.delete( ContactmapsImport.all().filter("owner =", users.get_current_user()) )
        return HttpResponseRedirect(reverse('contactmaps.views.list_contacts'))
    else:
        return render_to_response(
            request,
            'contact_confirm_delete.html',
            {'object': {'name': 'All contacts', 'key': 'all'}}
        )
Example #3
0
def get_contact_geoinfo(request):
    """
    This is the Task Queue worker that calculates geographical 
    information from contacts.
    
    This worker receives a 'key' POST parameter, which is the 
    key of the entity to calculate the geoinfo for.
    """
    # Ensure that the key parameter is present
    key = request.POST.get('key')
    if key is None:
        return HttpResponse(
            json.dumps({
                'success': False,
                'error': 'Key parameter not found in POST variables'
            })
        )
    
    # Get the contact entity using the input key
    contact = Contact.get(key)
    if contact is None:
        return HttpResponse(
            json.dumps({
                'success': False,
                'error': 'Invalid Contact key'
                })
        )
    
    # Calculate the geoinfo for the contact identified by key
    store_city_from_contact(contact)
    location = get_geoinfo(
        '%s, %s, %s, %s' %
        (contact.address, contact.city, contact.state, contact.country)
    )
    if location:
        contact.location = db.GeoPt(location['latitude'], location['longitude'])
        contact.put()
    
    return HttpResponse(
        json.dumps({
            'success': True,
        })
    )
Example #4
0
def list_contacts(request):
    """
    The list of contacts. This view also fetches the cities
    that the current contacts live in and the geographical postion
    of those cities.
    """
    # Set up the contacts query
    contacts = (
        Contact.all().
        filter("owner =", users.get_current_user()).
        order('creation_date')
    )
    
    # Paginate using django's pagination tools
    paginator = Paginator(contacts, settings.PAGINATE_BY)
    page = request.GET.get('page', 1)
    try:
        page_number = int(page)
    except ValueError:
        if page == 'last':
            page_number = paginator.num_pages
        else:
            # Page is not 'last', nor can it be converted to an int.
            raise Http404
    
    try:
        page_obj = paginator.page(page_number)
    except InvalidPage:
        raise Http404
    
    # Get the cities that the contacts live in
    _cities = []
    for contact in copy.deepcopy(page_obj.object_list):
        _cities.append(contact.city)
    cities = set(_cities)
    
    cities_list = []
    if len(cities):
        # Construct the cities string for our query
        cities_str = u'('
        for city in cities:
            cities_str += "'%s'," % city
        cities_str = cities_str.strip(',')
        cities_str += u')'
        
        # Create the cities query
        for city in City.gql("WHERE name IN %s" % cities_str):
            cities_list.append({
                'name': city.name,
                'latitude': city.location.lat,
                'longitude': city.location.lon
            })
    
    # Create the context and render the template with pagination
    # This part is adapted from django.views.generic.list_detail.oject_list
    context = RequestContext(request, {
        'object_list': page_obj.object_list,
        'paginator': paginator,
        'page_obj': page_obj,

        # Legacy template context stuff. New templates should use page_obj
        # to access this instead.
        'is_paginated': page_obj.has_other_pages(),
        'results_per_page': paginator.per_page,
        'has_next': page_obj.has_next(),
        'has_previous': page_obj.has_previous(),
        'page': page_obj.number,
        'next': page_obj.next_page_number(),
        'previous': page_obj.previous_page_number(),
        'first_on_page': page_obj.start_index(),
        'last_on_page': page_obj.end_index(),
        'pages': paginator.num_pages,
        'hits': paginator.count,
        'page_range': paginator.page_range,
        
        # The cities list
        'cities_list': cities_list
    })
    template = loader.get_template('contact_list.html')
    
    # Return the rendered template
    return HttpResponse(template.render(context))
Example #5
0
def import_contacts(request):
    """
    This view is called in a by the frontend app in oder to import
    contacts.
    
    It receives the following parameters via POST:
      - username: the freshbooks username
      - token: the freshbooks token
      - contacts: the list of id of freshbooks clients to import as a json obj
      - finalize: whether the import process must be finalized
    
    If there is some sort of error, this view returns a json response 
    like the following:: 
      {
        'success': False,
        'error': 'error msg' 
      }
    
    @todo: Checking if clients from a freshbooks account have
        already been imported MUST be done in the import_contacts_setup view
    """
    # Ensure that the username and token are valid
    username = request.POST.get('username')
    token = request.POST.get('token')
    
    if None in (username, token) or '' in (username, token):
        return HttpResponse(json.dumps({
            'success': False,
            'error': 'Invalid Parameters'
        }))
    
    # Ensure that we have not imported contacts from this freshbooks account
    already_imported = (
        ContactmapsImport.all().
        filter('owner =', users.get_current_user()).
        filter('freshbooks_username ='******'success': False,
            'error': 'Clients from the Freshmaps account %s.freshbooks.com have already been imported as contacts' % username
        }))
    
    # Other parameters
    try:
        contacts = json.loads( request.POST.get('contacts', '[]') )
    except ValueError:
        contacts = []
        
    finalize = request.POST.get('finalize')
    if finalize:
        # Mark that the current google user has already imported
        # contacts from the input freshbooks account.
        ContactmapsImport(
            owner=users.get_current_user(),
            freshbooks_username=username
        ).put()
        
        contacts = [] # Prevent processing contacts. There should be none, though
    
    
    # Set up the Freshmaps account to import from
    freshbooks.setup('%s.freshbooks.com' % username, token)
    
    for contact_id in contacts:
        _contact = freshbooks.Client.get(contact_id)
        
        _name = '%s %s' % (_contact.first_name, _contact.last_name)
        if not _name.strip():
            _name = 'Unknown Name'
                
        # Save the contact in the datastore
        contact = Contact(
            owner=users.get_current_user(),
            name=_name,
            company=_contact.organization,
            address=_contact.p_street1,
            city=_contact.p_city,
            state=_contact.p_state,
            country=_contact.p_country,
            zip_code=_contact.p_code,
        )
        contact.put()
        
        # Add a task in order to calculate the contact's geoinfo
        # This uses AppEngine Task Queues.
        try:
            taskqueue.add(url='/contact-geo-info/', params={'key': contact.key()})
        except TransientError:
            # Sometimes a weird TransientError is thrown by the API, so retrying
            # might recover from that.
            taskqueue.add(url='/contact-geo-info/', params={'key': contact.key()})
    
    return HttpResponse(
        json.dumps({
            'success': True,
        })
    )