Skip to content

Commit

Permalink
Merge pull request #30 from belatrix/develop
Browse files Browse the repository at this point in the history
Version 2.0 to production
  • Loading branch information
neosergio authored Jun 4, 2018
2 parents 69a703f + a4f9c92 commit eb38574
Show file tree
Hide file tree
Showing 43 changed files with 2,000 additions and 243 deletions.
21 changes: 20 additions & 1 deletion BxEvents/settings/base.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# encoding: utf-8
"""
Django settings for BxEvents project.
Expand Down Expand Up @@ -90,6 +91,24 @@
CONSTANCE_CONFIG = {
'TEAM_MIN_SIZE': (5, 'Mininum number of team members.', int),
'TEAM_MAX_SIZE': (8, 'Maximum number of team members.', int),
'PARTICIPANT_REGISTERED': ('El participante ya está registrado',
'Participant already registered', str),
'IDEA_DELETED': ('Idea eliminada', 'Idea deletion message', str),
'IDEA_EDIT_RESTRICTION': ('No puedes editar o borrar esta idea',
'Idea edit or delete restriction', str),
'IDEA_EXISTS': ('Esta idea ya existe', 'Idea already exists', str),
'CANDIDATE_ALREADY': ('Ya se registró como candidato',
'User already register as a candidate', str),
'PARTICIPANT_IDEA_RESTRICTION': ('Ya se registro en una idea para este evento.',
'Restriction message to avoid multiple registers for ideas in same event', str),
'TEAM_MAX_SIZE_MESSAGE': ('Se alcanzó el número máximo de participantes por idea o ya está completo.',
'Team max size reached', str),
'TEAM_MIN_SIZE_MESSAGE': ('No se tiene el número mínimo de integrantes.',
'Team min size not reached', str),
'NOT_IDEA_OWNER': ('No eres el autor de la idea.', 'Not owner idea message', str),
'USER_VOTED': ('Ya has registrado previamente tu voto', 'Message to user who already voted', str),
'IDEA_EVALUATED': ('Esta idea ya fue evaluada en esta categoría',
'Message to jury who already evaluate this idea in this category', str)
}

# Database
Expand Down Expand Up @@ -135,7 +154,7 @@

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'
TIME_ZONE = 'America/Lima'

USE_I18N = True

Expand Down
14 changes: 13 additions & 1 deletion events/admin.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from django.contrib import admin
from .models import City, Event, Interaction, Location, EventParticipant
from .models import Meeting, Attendance


class CityAdmin(admin.ModelAdmin):
list_display = ('name', )


class EventAdmin(admin.ModelAdmin):
list_display = ('title', 'datetime', 'image', 'details', 'is_upcoming', 'is_featured', 'get_cities')
list_display = ('title', 'datetime', 'image', 'details', 'is_upcoming', 'is_featured', 'get_cities', 'is_active')


class EventParticipantAdmin(admin.ModelAdmin):
Expand All @@ -22,8 +23,19 @@ class LocationAdmin(admin.ModelAdmin):
list_display = ('name', 'latitude', 'longitude')


class MeetingAdmin(admin.ModelAdmin):
list_display = ('name', 'start_date', 'end_date', 'event', 'is_over', 'is_active')


class AttendanceAdmin(admin.ModelAdmin):
list_display = ('datetime', 'meeting', 'participant')
search_fields = ['participant__email']


admin.site.register(City, CityAdmin)
admin.site.register(Event, EventAdmin)
admin.site.register(EventParticipant, EventParticipantAdmin)
admin.site.register(Interaction, InteractionAdmin)
admin.site.register(Location, LocationAdmin)
admin.site.register(Meeting, MeetingAdmin)
admin.site.register(Attendance, AttendanceAdmin)
41 changes: 40 additions & 1 deletion events/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.8 on 2018-04-19 11:27
# Generated by Django 1.10.8 on 2018-05-13 02:10
from __future__ import unicode_literals

from django.conf import settings
Expand All @@ -16,6 +16,16 @@ class Migration(migrations.Migration):
]

operations = [
migrations.CreateModel(
name='Attendance',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('datetime', models.DateTimeField(auto_now_add=True)),
],
options={
'ordering': ['-datetime'],
},
),
migrations.CreateModel(
name='City',
fields=[
Expand Down Expand Up @@ -86,9 +96,38 @@ class Migration(migrations.Migration):
'verbose_name_plural': 'locations',
},
),
migrations.CreateModel(
name='Meeting',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100, unique=True)),
('start_date', models.DateTimeField()),
('end_date', models.DateTimeField()),
('is_active', models.BooleanField(default=True)),
('is_over', models.BooleanField(default=False)),
('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='events.Event')),
],
options={
'ordering': ['-start_date'],
},
),
migrations.AddField(
model_name='event',
name='location',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='events.Location'),
),
migrations.AddField(
model_name='attendance',
name='meeting',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='events.Meeting'),
),
migrations.AddField(
model_name='attendance',
name='participant',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AlterUniqueTogether(
name='attendance',
unique_together=set([('meeting', 'participant')]),
),
]
26 changes: 26 additions & 0 deletions events/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,29 @@ class Meta(object):
ordering = ['-pk']
verbose_name = 'interaction item'
verbose_name_plural = 'interaction items'


@python_2_unicode_compatible
class Meeting(models.Model):
name = models.CharField(max_length=100, unique=True)
event = models.ForeignKey(Event)
start_date = models.DateTimeField()
end_date = models.DateTimeField()
is_active = models.BooleanField(default=True)
is_over = models.BooleanField(default=False)

def __str__(self):
return self.name

class Meta(object):
ordering = ['-start_date']


class Attendance(models.Model):
meeting = models.ForeignKey(Meeting)
participant = models.ForeignKey('participants.User')
datetime = models.DateTimeField(auto_now_add=True)

class Meta(object):
unique_together = ('meeting', 'participant')
ordering = ["-datetime"]
22 changes: 22 additions & 0 deletions events/permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from rest_framework import permissions
from rest_framework.compat import is_authenticated

from .models import Attendance


SAFE_METHODS = ('GET', 'HEAD', 'OPTIONS')


class IsAttendee(permissions.BasePermission):
message = 'Attendee restricted'

def has_permission(self, request, view):
if request.user.is_anonymous:
return (
request.method in SAFE_METHODS or
request.user and
is_authenticated(request.user)
)
attendees = Attendance.objects.filter(participant__email=request.user.email).count()
if attendees > 0:
return True
13 changes: 12 additions & 1 deletion events/serializers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from rest_framework import serializers
from .models import City, Event, Interaction
from .models import City, Event, Interaction, Meeting


class CitySerializer(serializers.ModelSerializer):
Expand All @@ -19,3 +19,14 @@ class InteractionSerializer(serializers.ModelSerializer):
class Meta(object):
model = Interaction
fields = '__all__'


class MeetingSerializer(serializers.ModelSerializer):
class Meta(object):
model = Meeting
fields = '__all__'


class AttendanceRegisterSerializer(serializers.Serializer):
meeting_id = serializers.IntegerField()
user_email = serializers.CharField()
3 changes: 3 additions & 0 deletions events/urls.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .views import event_detail, event_list, event_upcoming_list, event_past_list, event_featured, event_city_list
from .views import meeting_list, register_attendance
# from .views import event_interaction, event_interaction_vote
from django.conf.urls import url
from ideas.views import idea_list, idea_vote
Expand All @@ -13,6 +14,8 @@
url(r'^featured/$', event_featured, name='event_featured'),
# url(r'^interaction/(?P<interaction_id>\d+)/vote$', event_interaction_vote, name='event_interaction_vote'),
url(r'^list/$', event_list, name='event_list'),
url(r'^meeting/list/$', meeting_list, name='meeting_list'),
url(r'^upcoming/list/$', event_upcoming_list, name='event_upcoming_list'),
url(r'^past/list/$', event_past_list, name='event_past_list'),
url(r'^register/attendance/$', register_attendance, name='register_attendance'),
]
97 changes: 94 additions & 3 deletions events/views.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
from constance import config
from django.shortcuts import get_object_or_404
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.decorators import api_view, permission_classes
from rest_framework.exceptions import NotAcceptable
from rest_framework.pagination import PageNumberPagination
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from utils.random_item import random_element_list
from .models import Event, Interaction, City
from .serializers import CitySerializer, EventSerializer, InteractionSerializer

from ideas.models import IdeaParticipant
from ideas.serializers import IdeaParticipantsIdeasSerializer
from participants.models import User
from participants.permissions import IsStaff
from participants.serializers import UserSerializer

from .models import Event, Interaction, City, Meeting, Attendance
from .serializers import CitySerializer, EventSerializer, InteractionSerializer, MeetingSerializer
from .serializers import AttendanceRegisterSerializer


@api_view(['GET', ])
Expand All @@ -32,6 +43,14 @@ def event_detail(request, event_id):
def event_featured(request):
"""
Returns event featured
---
GET:
parameters:
- name: city
description: set city_id to filter events by city
type: string
required: false
paramType: query
"""
events = Event.objects.filter(is_active=True, is_featured=True)

Expand Down Expand Up @@ -68,6 +87,14 @@ def event_featured(request):
def event_interaction(request, event_id):
"""
Returns event interactions
---
GET:
parameters:
- name: pagination
description: set true if you want paginated results
type: string
required: false
paramType: query
"""
event = get_object_or_404(Event, pk=event_id, is_active=True)
interactions = Interaction.objects.filter(event=event, is_active=True)
Expand Down Expand Up @@ -102,6 +129,14 @@ def event_interaction_vote(request, interaction_id):
def event_list(request):
"""
Returns event list
---
GET:
parameters:
- name: city
description: set city_id to filter events by city
type: string
required: false
paramType: query
"""
events = Event.objects.all()
if request.GET.get('city'):
Expand All @@ -126,6 +161,14 @@ def event_list(request):
def event_upcoming_list(request):
"""
Returns upcoming event list
---
GET:
parameters:
- name: city
description: set city_id to filter events by city
type: string
required: false
paramType: query
"""
events = Event.objects.filter(is_upcoming=True, is_active=True)
if request.GET.get('city'):
Expand All @@ -150,6 +193,14 @@ def event_upcoming_list(request):
def event_past_list(request):
"""
Returns past event list
---
GET:
parameters:
- name: city
description: set city_id to filter events by city
type: string
required: false
paramType: query
"""
events = Event.objects.filter(is_upcoming=False, is_active=True)
if request.GET.get('city'):
Expand All @@ -168,3 +219,43 @@ def event_past_list(request):
else:
serializer = EventSerializer(events, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)


@api_view(['GET', ])
@permission_classes((IsAuthenticated, IsStaff))
def meeting_list(request):
"""
Returns meetings list to register attendance
---
GET:
response_serializer: events.serializers.MeetingSerializer
"""
meetings = Meeting.objects.all().filter(is_active=True)
serializer = MeetingSerializer(meetings, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)


@api_view(['POST', ])
@permission_classes((IsAuthenticated, IsStaff))
def register_attendance(request):
"""
Register attendance to a meeting
---
POST:
serializer: events.serializers.AttendanceRegisterSerializer
"""
serializer = AttendanceRegisterSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
meeting = get_object_or_404(Meeting, pk=serializer.validated_data['meeting_id'])
user = get_object_or_404(User, email=serializer.validated_data['user_email'])
try:
Attendance.objects.create(meeting=meeting, participant=user)
except Exception as e:
print(e)
raise NotAcceptable(config.PARTICIPANT_REGISTERED)

idea_participant = IdeaParticipant.objects.filter(user=user)
user_serializer = UserSerializer(user)
idea_serializer = IdeaParticipantsIdeasSerializer(idea_participant, many=True)
return Response({'user': user_serializer.data,
'ideas': idea_serializer.data}, status=status.HTTP_200_OK)
Loading

0 comments on commit eb38574

Please sign in to comment.