mirror of
				https://github.com/fspc/workstand.git
				synced 2025-10-31 00:15:35 -04:00 
			
		
		
		
	Big refactor of views.
This commit is contained in:
		
							parent
							
								
									ec68c34701
								
							
						
					
					
						commit
						b6d2f5e88c
					
				
							
								
								
									
										83
									
								
								bikeshop_project/registration/tests/test_utils.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								bikeshop_project/registration/tests/test_utils.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,83 @@ | ||||
| from datetime import timedelta | ||||
| 
 | ||||
| from django.test import TestCase | ||||
| from django.utils import timezone | ||||
| from model_mommy import mommy | ||||
| 
 | ||||
| from core.models import Visit | ||||
| from registration.models import Member | ||||
| from registration.utils import signin_member, AlreadySignedInError, member_signed_in, get_signed_in_members | ||||
| 
 | ||||
| 
 | ||||
| class GetSignedInMembersTests(TestCase): | ||||
|     def setUp(self): | ||||
|         self.now = timezone.now() | ||||
| 
 | ||||
|         self.member1 = mommy.make(model=Member) | ||||
|         self.member2 = mommy.make(model=Member) | ||||
|         self.member3 = mommy.make(model=Member) | ||||
| 
 | ||||
|         three_hours_ago = self.now - timedelta(hours=3) | ||||
|         five_hours_ago = self.now - timedelta(hours=5) | ||||
| 
 | ||||
|         self.visit1 = Visit.objects.create(member=self.member1, purpose=Visit.DONATE, created_at=self.now) | ||||
|         self.visit2 = Visit.objects.create(member=self.member2, purpose=Visit.DONATE, created_at=three_hours_ago) | ||||
|         self.visit3 = Visit.objects.create(member=self.member3, purpose=Visit.DONATE, created_at=five_hours_ago) | ||||
| 
 | ||||
|     def test_get_signed_in_members(self): | ||||
|         """ | ||||
|         Only members signed-in in the window are returned | ||||
|         """ | ||||
|         result1 = get_signed_in_members(end=self.now)  # default window=4 | ||||
|         self.assertEqual(len(result1), 2) | ||||
| 
 | ||||
|         result2 = get_signed_in_members(window=2, end=self.now) | ||||
|         self.assertEqual(len(result2), 1) | ||||
| 
 | ||||
|         result3 = get_signed_in_members(window=5, end=self.now) | ||||
|         self.assertEqual(len(result3), 3) | ||||
| 
 | ||||
| 
 | ||||
| class SigninMember(TestCase): | ||||
|     def test_not_signed_in(self): | ||||
|         """ | ||||
|         A member who hasn't signed-in in 4 hours is signed-in. | ||||
|         """ | ||||
|         member = mommy.make(Member) | ||||
|         purpose = Visit.FIX | ||||
|         visit = signin_member(member, purpose) | ||||
| 
 | ||||
|         self.assertIsInstance(visit, Visit) | ||||
| 
 | ||||
|     def test_signed_in(self): | ||||
|         """ | ||||
|         A member who has signed-in in 4 hours is not signed-in. | ||||
|         """ | ||||
|         member = mommy.make(Member) | ||||
|         purpose = Visit.FIX | ||||
|         signin_member(member, purpose) | ||||
| 
 | ||||
|         with self.assertRaises(AlreadySignedInError): | ||||
|             signin_member(member, purpose) | ||||
| 
 | ||||
| 
 | ||||
| class CheckMemberSignedIn(TestCase): | ||||
|     def test_member_not_signed_in(self): | ||||
|         """ | ||||
|         Returns false when member is not signed-in | ||||
|         """ | ||||
|         not_signed_member = mommy.make(model=Member) | ||||
|         result = member_signed_in(not_signed_member) | ||||
| 
 | ||||
|         self.assertFalse(result) | ||||
| 
 | ||||
|     def test_member_signed_in(self): | ||||
|         """ | ||||
|         Returns true when member is signed-in | ||||
|         """ | ||||
| 
 | ||||
|         member = mommy.make(model=Member) | ||||
|         Visit.objects.create(member=member, purpose=Visit.DONATE) | ||||
|         result = member_signed_in(member) | ||||
| 
 | ||||
|         self.assertTrue(result) | ||||
							
								
								
									
										37
									
								
								bikeshop_project/registration/utils.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								bikeshop_project/registration/utils.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | ||||
| from datetime import datetime, timedelta | ||||
| from typing import Optional | ||||
| 
 | ||||
| from django.db.models import QuerySet | ||||
| from django.utils import timezone | ||||
| 
 | ||||
| from core.models import Visit | ||||
| from registration.models import Member | ||||
| 
 | ||||
| 
 | ||||
| class AlreadySignedInError(ValueError): | ||||
|     pass | ||||
| 
 | ||||
| 
 | ||||
| def signin_member(member: Member, purpose: str) -> Visit: | ||||
|     """ | ||||
|     Signs in a member, creating a new `Visit` | ||||
|     :param member: the member to be signed in | ||||
|     :param purpose: The reason for visit. E.g. Fix a bike or volunteer | ||||
|     :return: a new `Visit` | ||||
|     :raise: `AlreadySignedInError` or `ValidationError` | ||||
|     """ | ||||
|     if not member_signed_in(member): | ||||
|         return Visit.objects.create(member=member, purpose=purpose) | ||||
| 
 | ||||
|     raise AlreadySignedInError | ||||
| 
 | ||||
| 
 | ||||
| def member_signed_in(member: Member, window: int = 4) -> bool: | ||||
|     return get_signed_in_members(window=window).filter(id__in=[member.id]).exists() | ||||
| 
 | ||||
| 
 | ||||
| def get_signed_in_members(window: int = 4, end: Optional[datetime] = None) -> QuerySet: | ||||
|     new_end = end if end else timezone.now() | ||||
|     start = new_end - timedelta(hours=window) | ||||
|     visits = Visit.objects.filter(created_at__lte=new_end, created_at__gte=start) | ||||
|     return visits | ||||
| @ -1,27 +1,23 @@ | ||||
| import json | ||||
| import logging | ||||
| from datetime import timedelta | ||||
| 
 | ||||
| from django.contrib.auth.decorators import login_required | ||||
| from django.core.urlresolvers import reverse | ||||
| from django.http import HttpResponse, HttpResponseRedirect, JsonResponse | ||||
| from django.shortcuts import get_object_or_404 | ||||
| from django.template.response import TemplateResponse | ||||
| from django.utils import timezone | ||||
| from django.utils.decorators import method_decorator | ||||
| from django.views.decorators.csrf import csrf_exempt | ||||
| from django.views.generic import TemplateView, View | ||||
| from haystack.query import SearchQuerySet | ||||
| from rest_framework import serializers | ||||
| from rest_framework.renderers import JSONRenderer | ||||
| from rest_framework.serializers import ModelSerializer | ||||
| 
 | ||||
| from core.models import Visit | ||||
| from haystack.query import SearchQuerySet | ||||
| 
 | ||||
| from registration.utils import signin_member, get_signed_in_members | ||||
| from .forms import MemberForm | ||||
| from .models import Member | ||||
| 
 | ||||
| logger = logging.getLogger('bikeshop') | ||||
| 
 | ||||
| 
 | ||||
| @method_decorator(login_required, name='dispatch') | ||||
| class MemberFormView(View): | ||||
| @ -69,17 +65,23 @@ class MemberSearchView(View): | ||||
| 
 | ||||
| 
 | ||||
| class MemberSerializer(ModelSerializer): | ||||
|     first_name = serializers.CharField(allow_blank=True, required=False) | ||||
|     last_name = serializers.CharField(allow_blank=True, required=False) | ||||
| 
 | ||||
|     class Meta: | ||||
|         model = Member | ||||
|         fields = ('full_name', 'email', 'id') | ||||
|         fields = ('first_name', 'last_name', 'email', 'id') | ||||
| 
 | ||||
| 
 | ||||
| class VisitSerializer(ModelSerializer): | ||||
|     member = MemberSerializer() | ||||
| 
 | ||||
|     class Meta: | ||||
|         model = Visit | ||||
|         fields = ('created_at', 'purpose', 'member') | ||||
|         depth = 1 | ||||
| 
 | ||||
| 
 | ||||
| class MemberSignIn(View): | ||||
|     @method_decorator(csrf_exempt) | ||||
|     def dispatch(self, request, *args, **kwargs): | ||||
| @ -87,21 +89,17 @@ class MemberSignIn(View): | ||||
| 
 | ||||
|     def post(self, request): | ||||
|         member = get_object_or_404(Member, id=request.POST.get('id')) | ||||
|         Visit.objects.create(member=member, purpose=request.POST.get('purpose')) | ||||
|         data = json.dumps(dict(results=dict(id=member.id))) | ||||
|         visit = signin_member(member, request.POST.get('purpose')) | ||||
|         data = json.dumps(dict(results=dict(id=member.id, created_at=visit.created_at.isoformat()))) | ||||
| 
 | ||||
|         return JsonResponse(data=data, safe=False, status=201) | ||||
| 
 | ||||
|     def get(self, request): | ||||
|         start = timezone.now() | ||||
|         end = start + timedelta(hours=4) | ||||
|         visits = Visit.objects.filter(created_at__lte=end, | ||||
|                                       created_at__gte=start).prefetch_related() | ||||
| 
 | ||||
|         visits = get_signed_in_members().prefetch_related() | ||||
|         serializer = VisitSerializer(visits, many=True) | ||||
|         json = JSONRenderer().render(serializer.data) | ||||
|         results_json = JSONRenderer().render(serializer.data) | ||||
| 
 | ||||
|         return JsonResponse(data=json.decode(), safe=False, status=200) | ||||
|         return JsonResponse(data=results_json.decode(), safe=False, status=200) | ||||
| 
 | ||||
| 
 | ||||
| @method_decorator(login_required, name='dispatch') | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user