310 lines
12 KiB
Python
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')
|