BookingService/booking/views.py

310 lines
12 KiB
Python

import datetime
from django.db.models import QuerySet
from django.shortcuts import get_object_or_404
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import generics
from rest_framework import permissions
from rest_framework.exceptions import ValidationError
from rest_framework.filters import SearchFilter, OrderingFilter
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
from . import models, serializers, filters, tasks
class SettingDetail(generics.RetrieveUpdateAPIView):
"""
获得设置
更新设置
"""
queryset = models.Setting.objects.all()
serializer_class = serializers.SettingSerializer
permission_classes = (permissions.IsAdminUser,)
class Room(generics.ListCreateAPIView):
"""
获得room列表
新建room
"""
queryset = models.Room.objects.all().order_by('name')
serializer_class = serializers.RoomSerializer
permission_classes = (permissions.IsAuthenticated,)
def perform_create(self, serializer):
data = serializer.validated_data
seat_count = data['get_seat_count']
del data['get_seat_count']
room = models.Room.objects.create(**data)
for i in range(1, 1 + seat_count):
seat = models.Seat.objects.create(room=room, name=str(i))
class RoomDetail(generics.RetrieveUpdateDestroyAPIView):
"""
获得指定room
更新指定room
删除指定room
"""
queryset = models.Room.objects.all()
serializer_class = serializers.RoomSerializer
permission_classes = (permissions.IsAdminUser,)
class Seat(generics.ListCreateAPIView):
"""
获得seat列表
新建seat
"""
queryset = models.Seat.objects.all().order_by('-created_datetime')
serializer_class = serializers.SeatSerializer
permission_classes = (permissions.IsAdminUser,)
filter_backends = (DjangoFilterBackend,)
filterset_fields = ['room__id']
def perform_create(self, serializer):
name = serializer.validated_data['name']
r = serializer.validated_data['room']
room = models.Room.objects.get(id=r.id)
models.Seat.objects.create(room=room, name=name)
class SeatDetail(generics.DestroyAPIView):
"""
删除指定seat
"""
queryset = models.Seat.objects.all()
serializer_class = serializers.SeatSerializer
permission_classes = (permissions.IsAdminUser,)
class Booking(generics.ListCreateAPIView):
"""
获得booking列表
新建booking
"""
queryset = models.Booking.objects.all().order_by('id')
# serializer_class = serializers.BookingSerializer
permission_classes = (permissions.IsAuthenticated,)
pagination_class = PageNumberPagination
filter_backends = (DjangoFilterBackend, SearchFilter, OrderingFilter)
filterset_class = filters.BookingFilter
search_fields = [
'id',
'user__username',
'room__name',
'date'
]
ordering_fields = [
'id',
'date',
'start_time',
'end_time',
]
def perform_create(self, serializer):
data = serializer.validated_data
start_time = data['start_time']
end_time = data['end_time']
setting = models.Setting.objects.get(id=1)
if start_time < setting.start_time or start_time > setting.end_time:
raise ValidationError(f'开始时间无效,应该在[{setting.start_time} - {setting.end_time}]之间。')
if end_time < setting.start_time or end_time > setting.end_time:
raise ValidationError(f'结束时间无效,应该在[{setting.start_time} - {setting.end_time}]之间。')
serializer.save()
tasks.createBooking.delay(serializer.data)
def get_serializer_class(self):
if self.request.stream and self.request.stream.method == 'POST':
return serializers.BookingCreateSerializer
else:
return serializers.BookingSerializer
class BookingDetail(generics.RetrieveUpdateDestroyAPIView):
"""
获得指定booking
更新指定booking
删除指定booking
"""
queryset = models.Booking.objects.all()
serializer_class = serializers.BookingSerializer
permission_classes = (permissions.IsAuthenticated,)
class BookingStatusList(generics.GenericAPIView):
"""
获得预约状态列表
"""
queryset = QuerySet()
permission_classes = (permissions.IsAuthenticated,)
def get(self, request):
status_list = []
for status in models.Booking.STATUS_CHIOCE:
status_list.append({
'id': status[0],
'name': status[1]
})
return Response(status_list)
class BookingCancel(generics.GenericAPIView):
"""
取消预约
"""
serializer_class = serializers.BookingCancelSerializer
permission_classes = (permissions.IsAdminUser,)
def post(self, request, pk):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
booking = self.get_queryset()
if not booking.status == 'SUCCESS':
raise ValidationError('未申请成功不能取消')
if booking.arrive_time:
raise ValidationError('签到后不能取消')
booking.status = 'CANCELED'
booking.cancel_by = request.user
booking.cancel_datetime = datetime.datetime.now()
booking.cancel_reason = serializer.validated_data['cancel_reason']
booking.save()
return Response(serializer.validated_data)
def get_queryset(self):
return models.Booking.objects.get(id=self.kwargs['pk'])
class RoomBookingStatus(generics.GenericAPIView):
"""
获得房间预约信息
"""
queryset = QuerySet()
serializer_class = (serializers.RoomSerializer)
permission_classes = (permissions.IsAuthenticated,)
def get(self, request):
try:
date = datetime.datetime.strptime(request.query_params.get('date'), '%Y-%m-%d').date()
except Exception as e:
raise ValidationError(e)
setting = models.Setting.objects.get(id=1)
start_datetime = datetime.datetime.combine(date, setting.start_time)
end_datetime = datetime.datetime.combine(date, setting.end_time)
step = datetime.timedelta(minutes=setting.booking_interval)
count_per_seat = int((end_datetime - start_datetime) / step)
count_total = 0
booked_count_total = 0
booking_count_total = 0
room_booking_status_list = []
for room in models.Room.objects.all():
seat_list = room.seat_set.all()
count_per_room = 0
booked_count = 0
booking_count = 0
for seat in seat_list:
count_per_room += count_per_seat
booking_list = models.Booking.objects.filter(date=date, room=room, seats__id=seat.id, status='SUCCESS')
for booking in booking_list:
s_datetime = datetime.datetime.combine(date, booking.start_time)
e_datetime = datetime.datetime.combine(date, booking.end_time)
s = int((s_datetime - start_datetime) / step)
e = int((e_datetime - start_datetime) / step)
booked_count += e - s
booking_count += 1
count_total += count_per_room
booked_count_total += booked_count
booking_count_total += booking_count
room_booking_status_list.append({
**self.get_serializer(room).data,
'count': count_per_room,
'booked_count': booked_count,
'booking_count': booking_count
})
return Response({
'count_total': count_total,
'booked_count_total': booked_count_total,
'booking_count_total': booking_count_total,
'results': room_booking_status_list
})
class RoomBookingStatusDetail(generics.GenericAPIView):
"""
获得指定房间的预约信息
"""
serializer_class = (serializers.RoomSerializer)
permission_classes = (permissions.IsAuthenticated,)
def get(self, request, pk):
setting = models.Setting.objects.get(id=1)
try:
date = datetime.datetime.strptime(request.query_params.get('date'), '%Y-%m-%d').date()
start_time = request.query_params.get('start_time')
end_time = request.query_params.get('end_time')
start_time = datetime.datetime.strptime(start_time, '%H:%M:%S').time() if start_time else setting.start_time
end_time = datetime.datetime.strptime(end_time, '%H:%M:%S').time() if end_time else setting.end_time
except Exception as e:
raise ValidationError(e)
room = get_object_or_404(models.Room, id=pk)
record = self.get_queryset()
count_total = 0
booked_count_total = 0
seat_list = []
for seat in room.seat_set.all().order_by('created_datetime'):
# 初始化数组
step = datetime.timedelta(minutes=setting.booking_interval)
booking_status_list = []
start_datetime = datetime.datetime.combine(date, start_time)
end_datetime = start_datetime + step
while end_datetime <= datetime.datetime.combine(date, end_time):
booking_status_list.append({
'start_time': start_datetime.strftime('%H:%M:%S'),
'end_time': end_datetime.strftime('%H:%M:%S'),
'booking': None
})
count_total += 1
start_datetime = end_datetime
end_datetime += step
# 检查预约记录
start_datetime = datetime.datetime.combine(date, start_time)
end_datetime = datetime.datetime.combine(date, end_time)
is_booked = False
for booking in record.select_related('user').filter(seats__id=seat.id):
s_datetime = max(start_datetime, datetime.datetime.combine(date, booking.start_time))
e_datetime = min(end_datetime, datetime.datetime.combine(date, booking.end_time))
s = int((s_datetime - start_datetime) / step)
e = int((e_datetime - start_datetime) / step)
booked_count_total += e - s
for i in range(s, e):
is_booked = True
booking_status_list[i]['booking'] = {
'id': booking.id,
'start_time': booking.start_time,
'end_time': booking.end_time,
'arrive_time': booking.arrive_time,
'leave_time': booking.leave_time,
'user': {
'id': booking.user.id,
'username': booking.user.username
}
}
seat_list.append({
'id': seat.id,
'name': seat.name,
'is_booked': is_booked,
'booking_status_list': booking_status_list
})
return Response({
**self.get_serializer(room).data,
'date': date,
'count_total': count_total,
'booked_count_total': booked_count_total,
'seat_list': seat_list
})
def get_queryset(self):
date = datetime.datetime.strptime(self.request.query_params.get('date'), '%Y-%m-%d').date()
return models.Booking.objects.filter(date=date, room=self.kwargs['pk'], status='SUCCESS')