From bdd686f50b2b248d9f8851a9d4a4dd6bdf8313e6 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Sun, 28 Sep 2025 10:24:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=9A=E8=AE=AE=E5=AE=A4=E9=A2=84?= =?UTF-8?q?=E5=AE=9A=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ofm/migrations/0014_auto_20250928_1023.py | 33 +++++++++++++++++++ apps/ofm/models.py | 7 ++-- apps/ofm/serializers.py | 8 ++--- apps/ofm/services.py | 12 ++++--- apps/ofm/views.py | 18 ++++++++-- 5 files changed, 64 insertions(+), 14 deletions(-) create mode 100644 apps/ofm/migrations/0014_auto_20250928_1023.py diff --git a/apps/ofm/migrations/0014_auto_20250928_1023.py b/apps/ofm/migrations/0014_auto_20250928_1023.py new file mode 100644 index 00000000..76e7a782 --- /dev/null +++ b/apps/ofm/migrations/0014_auto_20250928_1023.py @@ -0,0 +1,33 @@ +# Generated by Django 3.2.12 on 2025-09-28 02:23 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('wf', '0003_workflow_view_path'), + ('ofm', '0013_mroomslot_ticket'), + ] + + operations = [ + migrations.AddField( + model_name='mroombooking', + name='ticket', + field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='mrooms_ticket', to='wf.ticket', verbose_name='关联会议室'), + ), + migrations.AddField( + model_name='mroomslot', + name='is_inuse', + field=models.BooleanField(default=True, verbose_name='是否占用'), + ), + migrations.AlterUniqueTogether( + name='mroomslot', + unique_together={('mroom', 'mdate', 'slot', 'is_inuse')}, + ), + migrations.RemoveField( + model_name='mroomslot', + name='ticket', + ), + ] diff --git a/apps/ofm/models.py b/apps/ofm/models.py index 3ce5f27a..7bf1c4dd 100644 --- a/apps/ofm/models.py +++ b/apps/ofm/models.py @@ -28,6 +28,8 @@ class Mroom(CommonADModel): class MroomBooking(CommonADModel): """TN: 会议室预定信息""" title = models.CharField('会议主题', max_length=100) + ticket = models.ForeignKey('wf.ticket', verbose_name='关联会议室', + on_delete=models.SET_NULL, related_name='mrooms_ticket', null=True, blank=True, db_constraint=False) class MroomSlot(BaseModel): @@ -36,11 +38,10 @@ class MroomSlot(BaseModel): booking = models.ForeignKey(MroomBooking, on_delete=models.CASCADE, related_name="slot_b") mdate = models.DateField('会议日期', db_index=True) slot = models.PositiveIntegerField('时段', help_text='0-47') - ticket = models.ForeignKey('wf.ticket', verbose_name='关联会议室', - on_delete=models.SET_NULL, related_name='mrooms_ticket', null=True, blank=True, db_constraint=False) + is_inuse = models.BooleanField('是否占用', default=True) class Meta: - unique_together = ('mroom', 'mdate', 'slot') + unique_together = ('mroom', 'mdate', 'slot', 'is_inuse') # class Seal(BaseModel): diff --git a/apps/ofm/serializers.py b/apps/ofm/serializers.py index 46a3c9d4..37aba45b 100644 --- a/apps/ofm/serializers.py +++ b/apps/ofm/serializers.py @@ -5,6 +5,7 @@ from rest_framework import serializers from django.db import transaction from rest_framework.exceptions import ParseError from apps.utils.constants import EXCLUDE_FIELDS +from apps.wf.serializers import TicketSimpleSerializer class MroomSerializer(CustomModelSerializer): @@ -18,12 +19,12 @@ class MroomBookingSerializer(CustomModelSerializer): mdate = serializers.DateField(write_only=True, label="预订日期") slots = serializers.ListField(child=serializers.IntegerField(), write_only=True, label="时段索引") create_by_name = serializers.CharField(source='create_by.username', read_only=True) + ticket_ = TicketSimpleSerializer(source='ticket', read_only=True) class Meta: model = MroomBooking fields = '__all__' read_only_fields = EXCLUDE_FIELDS - @transaction.atomic def create(self, validated_data): mroom = validated_data.pop('mroom') slots = validated_data.pop('slots') @@ -34,12 +35,11 @@ class MroomBookingSerializer(CustomModelSerializer): if slot < 0 or slot > 47: raise ParseError("时段索引超出范围") try: - MroomSlot.objects.create(booking=booking, slot=slot, mdate=mdate, mroom=mroom) + MroomSlot.objects.create(booking=booking, slot=slot, mdate=mdate, mroom=mroom, is_inuse=True) except Exception as e: raise ParseError(f"时段已预订,请刷新重选-{e}") return booking - @transaction.atomic def update(self, instance, validated_data): mroom = validated_data.pop('mroom') slots = validated_data.pop('slots') @@ -50,7 +50,7 @@ class MroomBookingSerializer(CustomModelSerializer): if slot < 0 or slot > 47: raise ParseError("时段索引超出范围") try: - MroomSlot.objects.create(booking=booking, slot=slot, mdate=mdate, mroom=mroom) + MroomSlot.objects.create(booking=booking, slot=slot, mdate=mdate, mroom=mroom, is_inuse=True) except Exception as e: raise ParseError(f"时段已预订,请刷新重选-{e}") return booking diff --git a/apps/ofm/services.py b/apps/ofm/services.py index a781592b..b9093569 100644 --- a/apps/ofm/services.py +++ b/apps/ofm/services.py @@ -1,7 +1,7 @@ from apps.wf.models import Ticket # TicketFlow, Transition, Workflow, CustomField, State, -from apps.ofm.models import LendingSeal, Vehicle, BorrowRecord, Publicity, MroomSlot +from apps.ofm.models import LendingSeal, Vehicle, BorrowRecord, Publicity, MroomBooking, MroomSlot from rest_framework.exceptions import ParseError @@ -11,11 +11,11 @@ def seal_submit_validate(ins: LendingSeal): if ins.mtask and ins.mtask.state == LendingSeal.MTASK_STOP: raise ParseError('该任务已停止!') -def bind_mslot(ticket: Ticket, transition, new_ticket_data: dict): - ins = MroomSlot.objects.get(id=new_ticket_data['t_id']) +def bind_mroombooking(ticket: Ticket, transition, new_ticket_data: dict): + ins = MroomBooking.objects.get(id=new_ticket_data['t_id']) ticket_data = ticket.ticket_data ticket_data.update({ - 't_model': 'mroomslot', + 't_model': 'mroombooking', 't_id': ins.id, }) ticket.ticket_data = ticket_data @@ -24,6 +24,10 @@ def bind_mslot(ticket: Ticket, transition, new_ticket_data: dict): if ins.ticket is None: ins.ticket = ticket ins.save() + +def mroombooking_reject(ticket: Ticket, transition, new_ticket_data: dict): + ins = MroomBooking.objects.get(id=new_ticket_data['t_id']) + MroomSlot.objects.filter(booking=ins).update(is_inuse=False) def bind_lendingseal(ticket: Ticket, transition, new_ticket_data: dict): ins = LendingSeal.objects.get(id=new_ticket_data['t_id']) diff --git a/apps/ofm/views.py b/apps/ofm/views.py index 39443791..f137b634 100644 --- a/apps/ofm/views.py +++ b/apps/ofm/views.py @@ -28,7 +28,7 @@ class MroomBookingViewSet(CustomModelViewSet): """ queryset = MroomBooking.objects.all() serializer_class = MroomBookingSerializer - select_related_fields = ["create_by"] + select_related_fields = ["create_by", "ticket"] filterset_class = MroomBookingFilterset def add_info_for_list(self, data): @@ -81,6 +81,11 @@ class MroomBookingViewSet(CustomModelViewSet): 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) @@ -88,7 +93,14 @@ class MroomBookingViewSet(CustomModelViewSet): def perform_destroy(self, instance): if instance.create_by and instance.create_by != self.request.user: raise ParseError("只允许创建者删除") - return super().perform_destroy(instance) + 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): @@ -98,7 +110,7 @@ class MroomSlotViewSet(CustomListModelMixin, CustomGenericViewSet): """ queryset = MroomSlot.objects.all() serializer_class = MroomSlotSerializer - filterset_fields = ["mroom", "mdate", "booking"] + filterset_fields = ["mroom", "mdate", "booking", "is_inuse"] class LendingSealViewSet(CustomModelViewSet):