diff --git a/backend/ticket/migrations/0016_alter_ticket_status.py b/backend/ticket/migrations/0016_alter_ticket_status.py new file mode 100644 index 0000000..1890399 --- /dev/null +++ b/backend/ticket/migrations/0016_alter_ticket_status.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.2 on 2025-02-28 15:24 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0015_remove_ticket_attachments_remove_ticket_content'), + ] + + operations = [ + migrations.AlterField( + model_name='ticket', + name='status', + field=models.CharField(choices=[('in_progress', 'در حال پردازش'), ('resolved', 'حل شده'), ('closed', 'بسته')], default='in_progress', max_length=20, verbose_name='وضعیت تیکت'), + ), + ] diff --git a/backend/ticket/migrations/0017_alter_ticket_status.py b/backend/ticket/migrations/0017_alter_ticket_status.py new file mode 100644 index 0000000..71e1ade --- /dev/null +++ b/backend/ticket/migrations/0017_alter_ticket_status.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.2 on 2025-02-28 16:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0016_alter_ticket_status'), + ] + + operations = [ + migrations.AlterField( + model_name='ticket', + name='status', + field=models.CharField(choices=[('in_progress', 'در انتظار پاسخ'), ('resolved', 'پاسخ داده شده'), ('closed', 'بسته شده')], default='in_progress', max_length=20, verbose_name='وضعیت تیکت'), + ), + ] diff --git a/backend/ticket/migrations/0018_alter_ticket_created_at_alter_ticket_updated_at.py b/backend/ticket/migrations/0018_alter_ticket_created_at_alter_ticket_updated_at.py new file mode 100644 index 0000000..b5d35f1 --- /dev/null +++ b/backend/ticket/migrations/0018_alter_ticket_created_at_alter_ticket_updated_at.py @@ -0,0 +1,23 @@ +# Generated by Django 5.1.2 on 2025-02-28 19:19 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0017_alter_ticket_status'), + ] + + operations = [ + migrations.AlterField( + model_name='ticket', + name='created_at', + field=models.DateTimeField(auto_now_add=True, verbose_name='ساخته شده در'), + ), + migrations.AlterField( + model_name='ticket', + name='updated_at', + field=models.DateTimeField(auto_now=True, verbose_name='اپدیت شده در'), + ), + ] diff --git a/backend/ticket/models.py b/backend/ticket/models.py index 6a40c05..76933b7 100644 --- a/backend/ticket/models.py +++ b/backend/ticket/models.py @@ -21,11 +21,11 @@ class Attachment(models.Model): super(Attachment, self).save(*args, **kwargs) class Ticket(models.Model): - objects = jmodels.jManager() + # objects = jmodels.jManager() STATUS_CHOICES = [ - ('in_progress', 'در حال پردازش'), - ('resolved', 'حل شده'), - ('closed', 'بسته'), + ('in_progress', 'در انتظار پاسخ'), + ('resolved', 'پاسخ داده شده'), + ('closed', 'بسته شده'), ] CATEGORY_CHOICES = [ ('finance_and_accounting', 'مالی و حسابداری'), @@ -40,9 +40,11 @@ class Ticket(models.Model): ticket_category = models.CharField(max_length=30, verbose_name='دسته بندی تیکت', choices=CATEGORY_CHOICES) customer = models.ForeignKey(User, on_delete=models.CASCADE, related_name="tickets", verbose_name='کاربر') admin = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name="assigned_tickets", verbose_name='ادمین') - status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='open', verbose_name='وضعیت تیکت') - created_at = jmodels.jDateTimeField(auto_now_add=True, verbose_name='ساخته شده در') - updated_at = jmodels.jDateTimeField(auto_now=True, verbose_name='اپدیت شده در') + status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='in_progress', verbose_name='وضعیت تیکت') + # created_at = jmodels.jDateTimeField(auto_now_add=True, verbose_name='ساخته شده در') + # updated_at = jmodels.jDateTimeField(auto_now=True, verbose_name='اپدیت شده در') + created_at = models.DateTimeField(auto_now_add=True, verbose_name='ساخته شده در') + updated_at = models.DateTimeField(auto_now=True, verbose_name='اپدیت شده در') order = models.ForeignKey(OrderModel ,blank=True, null=True, on_delete=models.SET_NULL) def __str__(self): diff --git a/backend/ticket/serializers.py b/backend/ticket/serializers.py index ba2cc9c..7dc19d4 100644 --- a/backend/ticket/serializers.py +++ b/backend/ticket/serializers.py @@ -2,6 +2,8 @@ from rest_framework import serializers from .models import Ticket, Message, Attachment from django.utils.timezone import localtime from account.serializers import ProfileSerializer +from order.serializers import OrderSerializer +from order.serializers import OrderModel class AttachmentSerializer(serializers.ModelSerializer): file = serializers.FileField(write_only=True) @@ -19,18 +21,37 @@ class AttachmentSerializer(serializers.ModelSerializer): return obj.file.url class MessageSerializer(serializers.ModelSerializer): + is_user = serializers.SerializerMethodField(read_only=True) class Meta: model = Message exclude = ('sender', ) extra_kwargs = {'ticket': {'write_only': True}} + def get_is_user(self, obj): + user = self.context['request'].user + return user == obj.sender + +class MessageAttachmentSerializer(serializers.ModelSerializer): + is_user = serializers.SerializerMethodField(read_only=True) + attachments = AttachmentSerializer(many=True, read_only=True) + class Meta: + model = Message + exclude = ('sender', ) + extra_kwargs = {'ticket': {'write_only': True}} + def get_is_user(self, obj): + user = self.context['request'].user + return user == obj.sender class MessageForTicketSerializer(serializers.ModelSerializer): class Meta: model = Message exclude = ('sender', 'ticket') class TicketSerializer(serializers.ModelSerializer): - messages = MessageSerializer(many=True, read_only=True) + status = serializers.SerializerMethodField() + ticket_category = serializers.SerializerMethodField() + messages = MessageAttachmentSerializer(many=True, read_only=True) message = MessageForTicketSerializer(write_only=True) + order_id = serializers.PrimaryKeyRelatedField(queryset=OrderModel.objects.all(), write_only=True, source='order') + order = OrderSerializer(read_only=True) class Meta: model = Ticket exclude = ('customer', 'admin') @@ -38,20 +59,34 @@ class TicketSerializer(serializers.ModelSerializer): def create(self, validated_data): message = validated_data.pop('message', None) - ticket = super().create(validated_data) - print(f'fck this shit{ticket.pk}') - message['ticket'] = ticket.pk - message_obj = MessageSerializer(data=message) - if message_obj.is_valid(): - message_obj.save(sender=ticket.customer) - return ticket - else: - raise Exception('bullshit data for message') + ticket = super().create(validated_data) + if message: + message['ticket'] = ticket.pk + if 'attachments' in message: + message['attachments'] = [attachment.pk for attachment in message['attachments']] + message_obj = MessageSerializer(data=message) + if message_obj.is_valid(): + message_obj.save(sender=ticket.customer) + else: + raise Exception(f'error in create failed: {message_obj.errors}') + return ticket + + def get_status(self, obj): + return obj.get_status_display() + + def get_ticket_category(self, obj): + return obj.get_ticket_category_display() class TicketListSerializer(serializers.ModelSerializer): + status = serializers.SerializerMethodField() + ticket_category = serializers.SerializerMethodField() + order = OrderSerializer() class Meta: model = Ticket exclude = ('customer', 'admin', ) read_only_fields = ('status',) + def get_status(self, obj): + return obj.get_status_display() - + def get_ticket_category(self, obj): + return obj.get_ticket_category_display() \ No newline at end of file diff --git a/backend/ticket/views.py b/backend/ticket/views.py index 556d6b8..ac6fdae 100644 --- a/backend/ticket/views.py +++ b/backend/ticket/views.py @@ -55,15 +55,13 @@ class TicketCreateView(APIView): serializer_class = TicketSerializer permission_classes = [permissions.IsAuthenticated] def post(self, request): - new_ticket_ser = self.serializer_class(data=request.data) + new_ticket_ser = self.serializer_class(data=request.data, context={'request': request}) message = request.data.get('message', None) - print(message) if new_ticket_ser.is_valid(): new_ticket_ser.save(customer=request.user) return Response(new_ticket_ser.data, status=status.HTTP_201_CREATED) else: - print(new_ticket_ser.error_messages) - return Response(new_ticket_ser.errors) + return Response(new_ticket_ser.errors, status=status.HTTP_400_BAD_REQUEST) class TicketListView(APIView): serializer_class = TicketListSerializer permission_classes = [permissions.IsAuthenticated]