Luke Plant avatar Luke Plant committed 409a47e

Added AJAX enhancements to admin Booking edit page, so that account data can be copied in easily

Also fixed bug in user_passes_test_improved that was caught by tests.

Comments (0)

Files changed (7)

cciw/bookings/tests.py

 from cciw.cciwmain.common import get_thisyear
 from cciw.cciwmain.models import Camp
 from cciw.cciwmain.tests.mailhelpers import read_email_url
+from cciw.officers.tests.references import OFFICER_USERNAME, OFFICER_PASSWORD, BOOKING_SEC_USERNAME, BOOKING_SEC_PASSWORD
 from cciw.sitecontent.models import HtmlChunk
 
 
     # Basic tests to ensure that the views that serve AJAX return something
     # sensible
 
-    fixtures = ['basic.json']
+    fixtures = ['basic.json', 'officers_users.json']
 
     def test_places_json(self):
         self.login()
         json = simplejson.loads(resp.content)
         self.assertEqual(json['account']['address'], '123 Main Street')
 
+    def test_all_account_json(self):
+        acc1 = BookingAccount.objects.create(email="foo@foo.com",
+                                             post_code="ABC",
+                                             name="Mr Foo")
+        acc2 = BookingAccount.objects.create(email="goo@foo.com",
+                                             post_code="XYZ",
+                                             name="Mr Goo")
+
+        self.client.login(username=OFFICER_USERNAME, password=OFFICER_PASSWORD)
+        resp = self.client.get(reverse('cciw.bookings.views.all_account_json'))
+        self.assertEqual(resp.status_code, 403)
+
+        # Now as booking secretary
+        self.client.login(username=BOOKING_SEC_USERNAME, password=BOOKING_SEC_PASSWORD)
+        resp = self.client.get(reverse('cciw.bookings.views.all_account_json') + "?id=%d" % acc1.id)
+        self.assertEqual(resp.status_code, 200)
+
+        json = simplejson.loads(resp.content)
+        self.assertEqual(json['account']['post_code'], 'ABC')
+
 
 class TestAccountOverview(CreatePlaceMixin, TestCase):
 

cciw/bookings/urls.py

              (r'^edit-place/(?P<id>\d+)/$', 'edit_place'),
              (r'^places-json/$', 'places_json'),
              (r'^account-json/$', 'account_json'),
+             (r'^all-account-json/$', 'all_account_json'),
              (r'^checkout/$', 'list_bookings'),
              (r'^pay/$', 'pay'),
              (r'^pay/done/$', 'pay_done'),

cciw/bookings/views.py

 from django.views.generic.edit import ProcessFormView, FormMixin, ModelFormMixin, BaseUpdateView, BaseCreateView
 from paypal.standard.forms import PayPalPaymentsForm
 
+from cciw.auth import is_booking_secretary
 from cciw.cciwmain.common import get_thisyear, DefaultMetaData, AjaxyFormMixin, get_current_domain
 from cciw.cciwmain.decorators import json_response
 from cciw.cciwmain.models import Camp
+from cciw.utils.views import user_passes_test_improved
 
 from cciw.bookings.email import send_verify_email, check_email_verification_token
 from cciw.bookings.forms import EmailForm, AccountDetailsForm, AddPlaceForm
     return view
 
 
+booking_secretary_required = user_passes_test_improved(is_booking_secretary)
+
+
 def is_booking_open(year):
     """
     When passed a given year, returns True if booking is open.
     'phone_number',
 ]
 
+booking_to_dict = lambda b: dict((k, getattr(b, k)) for k in BOOKING_PLACE_PUBLIC_ATTRS)
+account_to_dict = lambda acc: dict((k, getattr(acc, k))
+                                   for k in ACCOUNT_PUBLIC_ATTRS)
+
 @booking_account_required
 @json_response
 def places_json(request):
             qs = qs.exclude(id=exclude_id)
         except ValueError:
             pass
-    retval['places'] = [dict((k, getattr(b, k)) for k in BOOKING_PLACE_PUBLIC_ATTRS)
-                        for b in qs]
+    retval['places'] = [booking_to_dict(b) for b in qs]
     return retval
 
 
 @json_response
 def account_json(request):
     retval = {'status': 'success'}
-    retval['account'] = dict((k, getattr(request.booking_account, k))
-                             for k in ACCOUNT_PUBLIC_ATTRS)
+    retval['account'] = account_to_dict(request.booking_account)
+    return retval
+
+
+@booking_secretary_required
+@json_response
+def all_account_json(request):
+    acc = BookingAccount.objects.get(id=int(request.GET['id']))
+    retval = {'status': 'success'}
+    retval['account'] = account_to_dict(acc)
     return retval
 
 

cciw/officers/fixtures/officers_users.json

     }, 
     {
         "fields": {
+            "name": "Booking secretaries", 
+            "permissions": [
+                [
+                    "add_booking", 
+                    "bookings", 
+                    "booking"
+                ], 
+                [
+                    "change_booking", 
+                    "bookings", 
+                    "booking"
+                ], 
+                [
+                    "delete_booking", 
+                    "bookings", 
+                    "booking"
+                ], 
+                [
+                    "add_bookingaccount", 
+                    "bookings", 
+                    "bookingaccount"
+                ], 
+                [
+                    "change_bookingaccount", 
+                    "bookings", 
+                    "bookingaccount"
+                ]
+            ]
+        }, 
+        "model": "auth.group", 
+        "pk": 4
+    }, 
+    {
+        "fields": {
             "username": "mrofficer2", 
             "first_name": "Mr", 
             "last_name": "Officer2", 
         }, 
         "model": "auth.user", 
         "pk": 4
+    },
+    {
+        "fields": {
+            "username": "booker", 
+            "first_name": "Mr", 
+            "last_name": "Booking Secretary", 
+            "is_active": true, 
+            "is_superuser": false, 
+            "is_staff": true, 
+            "last_login": "2008-04-23 14:49:25", 
+            "groups": [
+                4
+            ], 
+            "user_permissions": [], 
+            "password": "sha1$1b3b9$a8a863f2f021582d972b6e50629c8f8588de7bba", 
+            "email": "booker@booker.com", 
+            "date_joined": "2008-03-21 16:48:46"
+        }, 
+        "model": "auth.user", 
+        "pk": 4
     }
+
 ]

cciw/officers/tests/references.py

 LEADER_EMAIL = 'leader@somewhere.com'
 LEADER = (LEADER_USERNAME, LEADER_PASSWORD)
 
+
+BOOKING_SEC_USERNAME = 'booker'
+BOOKING_SEC_PASSWORD = 'test_normaluser_password'
+BOOKING_SEC = (BOOKING_SEC_USERNAME, BOOKING_SEC_PASSWORD)
+
 # Data: Applications 1 to 3 are in year 2000, for camps in summer 2000
 # Application 4 is for 2001
 #

cciw/utils/views.py

 from functools import wraps
 import urlparse
 
+from django.conf import settings
+from django.contrib.auth import REDIRECT_FIELD_NAME
 from django.contrib.auth.views import redirect_to_login
 from django.http import HttpResponse, HttpResponseForbidden
 
     return HttpResponse("""<!DOCTYPE html><html><head><title>Close</title><script type="text/javascript">window.close()</script></head><body></body></html>""")
 
 
-def user_passes_test_improved(test_func):
+def user_passes_test_improved(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
     """
     Like user_passes_test, but doesn't redirect user to login screen if they are
     already logged in.

templates/admin/bookings/booking/change_form.html

+{% extends "admin/change_form.html" %}
+{% load url from future %}
+{% block after_related_objects %}
+{# Some javascript enhancements  #}
+<script type="text/javascript">
+$(document).ready(function() {
+    $('#id_address').parent().append('<input type="submit" value="Copy address details from account"' +
+                                     'id="id_use_account_for_camper">');
+    $('#id_contact_name').parent().append('<input type="submit" value="Copy contact details from account"' +
+                                     'id="id_use_account_for_contact">');
+
+
+    var getCurrentAccountId = function() {
+        var val = $('#id_hidden_account').val();
+        val = parseInt(val, 10);
+        // NaN madness
+        if (val == val) {
+            return val;
+        } else {
+            return undefined;
+        }
+    }
+
+    $('#id_use_account_for_camper').click(function(ev) {
+        ev.preventDefault();
+        var accId = getCurrentAccountId();
+        if (accId == undefined) return;
+        $.ajax({
+            type: "GET",
+            url: '{% url "cciw.bookings.views.all_account_json" %}?id=' + accId.toString(),
+            dataType: "json",
+            success: function(json) {
+                $('#id_address').val(json.account.address);
+                $('#id_post_code').val(json.account.post_code);
+                $('#id_phone_number').val(json.account.phone_number);
+            }
+        })
+    });
+
+    $('#id_use_account_for_contact').click(function(ev) {
+        ev.preventDefault();
+        var accId = getCurrentAccountId();
+        if (accId == undefined) return;
+        $.ajax({
+            type: "GET",
+            url: '{% url "cciw.bookings.views.all_account_json" %}?id=' + accId.toString(),
+            dataType: "json",
+            success: function(json) {
+                $('#id_contact_name').val(json.account.name);
+                $('#id_contact_phone_number').val(json.account.phone_number);
+            }
+        })
+    });
+
+
+});
+</script>
+{% endblock %}
+
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.