259 lines
9.5 KiB
Python
259 lines
9.5 KiB
Python
from django.shortcuts import render
|
||
from apps.utils.viewsets import CustomModelViewSet, CustomGenericViewSet
|
||
from .models import Mroom, MroomBooking, MroomSlot, LendingSeal, VehicleUse, VehicleSlot, VehicleReg, FileRecord, BorrowRecord, Publicity
|
||
|
||
from .serializers import (MroomSerializer, MroomBookingSerializer, MroomSlotSerializer, LendingSealSerializer,
|
||
VehicleUseSerializer, VehicleRecordSerializer, VehSlotSerializer, FileRecordSerializer, BorrowRecordSerializer, PublicitySerializer)
|
||
from apps.utils.mixins import CustomListModelMixin
|
||
from rest_framework.exceptions import ParseError
|
||
from apps.ofm.filters import MroomBookingFilterset, SealFilter, BorrowRecordFilter, VehicleFilterset
|
||
from rest_framework.response import Response
|
||
|
||
class MroomViewSet(CustomModelViewSet):
|
||
"""list: 会议室
|
||
|
||
会议室
|
||
"""
|
||
queryset = Mroom.objects.all()
|
||
serializer_class = MroomSerializer
|
||
|
||
|
||
class MroomBookingViewSet(CustomModelViewSet):
|
||
"""list: 会议室预订
|
||
|
||
会议室预订
|
||
"""
|
||
queryset = MroomBooking.objects.all()
|
||
serializer_class = MroomBookingSerializer
|
||
select_related_fields = ["create_by", "ticket", "belong_dept"]
|
||
filterset_class = MroomBookingFilterset
|
||
|
||
def add_info_for_list(self, data):
|
||
booking_ids = [d["id"] for d in data]
|
||
slots = MroomSlot.objects.filter(booking__in=booking_ids).order_by("booking", "mroom", "mdate", "slot")
|
||
booking_info = {}
|
||
for slot in slots:
|
||
booking_id = slot.booking.id
|
||
|
||
if booking_id not in booking_info:
|
||
booking_info[booking_id] = {
|
||
"mdate": slot.mdate.strftime("%Y-%m-%d"), # 格式化日期
|
||
"mroom": slot.mroom.id,
|
||
"mroom_name": slot.mroom.name, # 会议室名称
|
||
"time_ranges": [], # 存储时间段(如 ["8:00-9:00", "10:00-11:30"])
|
||
"current_slots": [], # 临时存储连续的slot(用于合并)
|
||
}
|
||
|
||
# 检查是否连续(当前slot是否紧接上一个slot)
|
||
current_slots = booking_info[booking_id]["current_slots"]
|
||
if not current_slots or slot.slot == current_slots[-1] + 1:
|
||
current_slots.append(slot.slot)
|
||
else:
|
||
# 如果不连续,先把当前连续的slot转换成时间段
|
||
if current_slots:
|
||
start_time = self._slot_to_time(current_slots[0])
|
||
end_time = self._slot_to_time(current_slots[-1] + 1)
|
||
booking_info[booking_id]["time_ranges"].append(f"{start_time}-{end_time}")
|
||
current_slots.clear()
|
||
current_slots.append(slot.slot)
|
||
|
||
# 处理最后剩余的连续slot
|
||
for info in booking_info.values():
|
||
if info["current_slots"]:
|
||
start_time = self._slot_to_time(info["current_slots"][0])
|
||
end_time = self._slot_to_time(info["current_slots"][-1] + 1)
|
||
info["time_ranges"].append(f"{start_time}-{end_time}")
|
||
info["slots"] = info.pop("current_slots") # 清理临时数据
|
||
|
||
for item in data:
|
||
item.update(booking_info.get(item["id"], {}))
|
||
return data
|
||
|
||
@staticmethod
|
||
def _slot_to_time(slot):
|
||
"""将slot (0-47) 转换为 HH:MM 格式的时间字符串"""
|
||
hours = slot // 2
|
||
minutes = (slot % 2) * 30
|
||
return f"{hours:02d}:{minutes:02d}"
|
||
|
||
def perform_update(self, serializer):
|
||
ins:MroomBooking = self.get_object()
|
||
ticket = ins.ticket
|
||
if ticket is None or ticket.state.type == 1:
|
||
pass
|
||
else:
|
||
raise ParseError("存在审批单,不允许修改")
|
||
if ins.create_by and ins.create_by != self.request.user:
|
||
raise ParseError("只允许创建者修改")
|
||
return super().perform_update(serializer)
|
||
|
||
def perform_destroy(self, instance):
|
||
if instance.create_by and instance.create_by != self.request.user:
|
||
raise ParseError("只允许创建者删除")
|
||
ticket = instance.ticket
|
||
if ticket is None or ticket.state.type == 1:
|
||
pass
|
||
else:
|
||
raise ParseError("存在审批单,不允许删除")
|
||
if ticket:
|
||
ticket.delete()
|
||
instance.delete()
|
||
|
||
|
||
class MroomSlotViewSet(CustomListModelMixin, CustomGenericViewSet):
|
||
"""list:
|
||
|
||
会议室预订时段
|
||
"""
|
||
queryset = MroomSlot.objects.all()
|
||
serializer_class = MroomSlotSerializer
|
||
filterset_fields = ["mroom", "mdate", "booking", "is_inuse"]
|
||
|
||
|
||
class LendingSealViewSet(CustomModelViewSet):
|
||
"""list: 印章外出
|
||
|
||
印章外出
|
||
"""
|
||
queryset = LendingSeal.objects.all()
|
||
serializer_class = LendingSealSerializer
|
||
filterset_class = SealFilter
|
||
ordering = ["-create_time"]
|
||
data_filter = True
|
||
|
||
|
||
class VehicleRegViewSet(CustomModelViewSet):
|
||
"""list: 车辆
|
||
|
||
车辆
|
||
"""
|
||
queryset = VehicleReg.objects.all()
|
||
serializer_class = VehicleRecordSerializer
|
||
ordering = ["-create_time"]
|
||
|
||
class VehicleUseViewSet(CustomModelViewSet):
|
||
"""list: 车辆使用
|
||
|
||
车辆使用
|
||
"""
|
||
queryset = VehicleUse.objects.all()
|
||
serializer_class = VehicleUseSerializer
|
||
select_related_fields = ["create_by", "ticket", "belong_dept"]
|
||
filterset_class = VehicleFilterset
|
||
|
||
def add_info_for_list(self, data):
|
||
vehicle_ids = [d["id"] for d in data]
|
||
slots = VehicleSlot.objects.filter(vehicle_use__in=vehicle_ids).order_by("vehreg", "vehicle_use", "vdate", "slot")
|
||
vehicle_info = {}
|
||
for slot in slots:
|
||
vehicle_id = slot.vehicle_use.id
|
||
|
||
if vehicle_id not in vehicle_info:
|
||
vehicle_info[vehicle_id] = {
|
||
"vdate": slot.vdate.strftime("%Y-%m-%d"), # 格式化日期
|
||
"vehreg": slot.vehreg.id,
|
||
"vehreg_name": slot.vehreg.name, # 会议室名称
|
||
"time_ranges": [], # 存储时间段(如 ["8:00-9:00", "10:00-11:30"])
|
||
"current_slots": [], # 临时存储连续的slot(用于合并)
|
||
}
|
||
|
||
# 检查是否连续(当前slot是否紧接上一个slot)
|
||
current_slots = vehicle_info[vehicle_id]["current_slots"]
|
||
if not current_slots or slot.slot == current_slots[-1] + 1:
|
||
current_slots.append(slot.slot)
|
||
else:
|
||
# 如果不连续,先把当前连续的slot转换成时间段
|
||
if current_slots:
|
||
start_time = self._slot_to_time(current_slots[0])
|
||
end_time = self._slot_to_time(current_slots[-1] + 1)
|
||
vehicle_info[vehicle_id]["time_ranges"].append(f"{start_time}-{end_time}")
|
||
current_slots.clear()
|
||
current_slots.append(slot.slot)
|
||
|
||
# 处理最后剩余的连续slot
|
||
for info in vehicle_info.values():
|
||
if info["current_slots"]:
|
||
start_time = self._slot_to_time(info["current_slots"][0])
|
||
end_time = self._slot_to_time(info["current_slots"][-1] + 1)
|
||
info["time_ranges"].append(f"{start_time}-{end_time}")
|
||
info["slots"] = info.pop("current_slots") # 清理临时数据
|
||
|
||
for item in data:
|
||
item.update(vehicle_info.get(item["id"], {}))
|
||
return data
|
||
|
||
@staticmethod
|
||
def _slot_to_time(slot):
|
||
"""将slot (0-47) 转换为 HH:MM 格式的时间字符串"""
|
||
hours = slot // 2
|
||
minutes = (slot % 2) * 30
|
||
return f"{hours:02d}:{minutes:02d}"
|
||
|
||
def perform_update(self, serializer):
|
||
ins:VehicleUse = self.get_object()
|
||
ticket = ins.ticket
|
||
if ticket is None or ticket.state.type == 1:
|
||
pass
|
||
else:
|
||
raise ParseError("存在审批单,不允许修改")
|
||
if ins.create_by and ins.create_by != self.request.user:
|
||
raise ParseError("只允许创建者修改")
|
||
return super().perform_update(serializer)
|
||
|
||
def perform_destroy(self, instance):
|
||
if instance.create_by and instance.create_by != self.request.user:
|
||
raise ParseError("只允许创建者删除")
|
||
ticket = instance.ticket
|
||
if ticket is None or ticket.state.type == 1:
|
||
pass
|
||
else:
|
||
raise ParseError("存在审批单,不允许删除")
|
||
if ticket:
|
||
ticket.delete()
|
||
instance.delete()
|
||
|
||
|
||
class VehicleSlotViewSet(CustomListModelMixin, CustomGenericViewSet):
|
||
"""list:
|
||
|
||
会议室预订时段
|
||
"""
|
||
queryset = VehicleSlot.objects.all()
|
||
serializer_class = VehSlotSerializer
|
||
filterset_fields = ["vehreg", "vehicle_use", "vdate", "is_inuse"]
|
||
|
||
|
||
class FilerecordViewSet(CustomModelViewSet):
|
||
"""list: 文件
|
||
|
||
文件
|
||
"""
|
||
queryset = FileRecord.objects.all()
|
||
serializer_class = FileRecordSerializer
|
||
filterset_fields = [ "name", "number"]
|
||
ordering = ["-create_time", "number", "name"]
|
||
|
||
|
||
class FileborrowViewSet(CustomModelViewSet):
|
||
"""list: 文件借阅
|
||
|
||
文件借阅
|
||
"""
|
||
queryset = BorrowRecord.objects.all()
|
||
serializer_class = BorrowRecordSerializer
|
||
filterset_class = BorrowRecordFilter
|
||
ordering = ["-create_time"]
|
||
|
||
|
||
class PublicityViewSet(CustomModelViewSet):
|
||
"""list: 公告
|
||
|
||
公告
|
||
"""
|
||
queryset = Publicity.objects.all()
|
||
serializer_class = PublicitySerializer
|
||
filterset_fields = ["title","number"]
|
||
ordering = ["-create_time", "number"]
|
||
|
||
|