first push
This commit is contained in:
0
ticket/__init__.py
Normal file
0
ticket/__init__.py
Normal file
3
ticket/admin.py
Normal file
3
ticket/admin.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
6
ticket/apps.py
Normal file
6
ticket/apps.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class TicketConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'ticket'
|
||||
97
ticket/bucket.py
Normal file
97
ticket/bucket.py
Normal file
@@ -0,0 +1,97 @@
|
||||
from botocore.exceptions import NoCredentialsError
|
||||
import boto3
|
||||
import logging
|
||||
from PIL import Image
|
||||
import io
|
||||
import base64
|
||||
|
||||
LIARA_ENDPOINT = 'https://storage.c2.liara.space'
|
||||
LIARA_BUCKET_NAME = 'ticket-rasadyar'
|
||||
LIARA_ACCESS_KEY = "gvqohestrakmqi6n"
|
||||
LIARA_SECRET_KEY = '7240fdd8-59bc-4f02-b5e6-4a124e37fa0e'
|
||||
|
||||
RASADYAR_ENDPOINT = 'https://s3.rasadyar.com'
|
||||
RASADYAR_BUCKET_NAME = 'rasadyar'
|
||||
RASADYAR_ACCESS_KEY = "zG3ewsbYsTqCmuws"
|
||||
RASADYAR_SECRET_KEY = 'RInUMB78zlQZp6CNf8+sRoSh2cNDHcGQhXrLnTJ1AuI='
|
||||
|
||||
|
||||
def upload_to_liara(image, name):
|
||||
s3 = boto3.client(
|
||||
's3',
|
||||
endpoint_url=RASADYAR_ENDPOINT,
|
||||
aws_access_key_id=RASADYAR_ACCESS_KEY,
|
||||
aws_secret_access_key=RASADYAR_SECRET_KEY
|
||||
)
|
||||
|
||||
s3.upload_fileobj(
|
||||
image,
|
||||
RASADYAR_BUCKET_NAME,
|
||||
name,
|
||||
ExtraArgs={'ACL': 'public-read'} # دسترسی عمومی
|
||||
)
|
||||
|
||||
return f"{RASADYAR_ENDPOINT}/{RASADYAR_BUCKET_NAME}/{name}"
|
||||
|
||||
def connect():
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
try:
|
||||
s3 = boto3.client(
|
||||
's3',
|
||||
endpoint_url=LIARA_ENDPOINT,
|
||||
aws_access_key_id=LIARA_ACCESS_KEY,
|
||||
aws_secret_access_key=LIARA_SECRET_KEY
|
||||
)
|
||||
except Exception as exc:
|
||||
logging.info(exc)
|
||||
return s3
|
||||
|
||||
|
||||
def upload_object_resize_to_liara(image_data, object_name):
|
||||
try:
|
||||
imgdata = base64.b64decode(image_data)
|
||||
img = Image.open(io.BytesIO(imgdata))
|
||||
|
||||
img.thumbnail((500, 500))
|
||||
|
||||
buffer = io.BytesIO()
|
||||
img.save(buffer, format="PNG")
|
||||
buffer.seek(0)
|
||||
|
||||
s3_resource = boto3.resource(
|
||||
's3',
|
||||
endpoint_url=LIARA_ENDPOINT,
|
||||
aws_access_key_id=LIARA_ACCESS_KEY,
|
||||
aws_secret_access_key=LIARA_SECRET_KEY
|
||||
)
|
||||
|
||||
bucket = s3_resource.Bucket(LIARA_BUCKET_NAME)
|
||||
bucket.put_object(
|
||||
ACL='public-read',
|
||||
Body=buffer,
|
||||
Key=object_name,
|
||||
ContentType='image/png'
|
||||
)
|
||||
|
||||
return f"{LIARA_ENDPOINT}/{LIARA_BUCKET_NAME}/{object_name}"
|
||||
|
||||
except Exception as e:
|
||||
raise Exception(f"خطا در آپلود فایل: {e}")
|
||||
|
||||
|
||||
def delete_file_from_liara(file_name):
|
||||
try:
|
||||
s3 = boto3.client(
|
||||
's3',
|
||||
endpoint_url=LIARA_ENDPOINT,
|
||||
aws_access_key_id=LIARA_ACCESS_KEY,
|
||||
aws_secret_access_key=LIARA_SECRET_KEY
|
||||
)
|
||||
|
||||
s3.delete_object(Bucket=LIARA_BUCKET_NAME, Key=file_name)
|
||||
|
||||
except NoCredentialsError:
|
||||
raise Exception("اعتبارنامههای AWS معتبر نیستند")
|
||||
except Exception as e:
|
||||
raise Exception(f"خطا در آپلود فایل: {e}")
|
||||
127
ticket/customer_views.py
Normal file
127
ticket/customer_views.py
Normal file
@@ -0,0 +1,127 @@
|
||||
import random
|
||||
|
||||
from rest_framework import viewsets
|
||||
from oauth2_provider.contrib.rest_framework import (
|
||||
TokenHasReadWriteScope,
|
||||
)
|
||||
from .models import (
|
||||
Ticket,
|
||||
TicketContent,
|
||||
Answer,
|
||||
Question,
|
||||
SupportUnit,
|
||||
Group,
|
||||
SystemUserProfile
|
||||
)
|
||||
from .serializers import (
|
||||
TicketSerializer,
|
||||
TicketContentSerializer,
|
||||
TicketAnswerSerializer,
|
||||
TicketQuestionSerializer,
|
||||
SupportUnitSerializer
|
||||
)
|
||||
from rest_framework.response import Response
|
||||
from .helper import upload_listed_image
|
||||
from rest_framework import status
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class CustomerTicketViewSet(viewsets.ModelViewSet):
|
||||
queryset = Ticket.objects.all()
|
||||
serializer_class = TicketSerializer
|
||||
permission_classes = [TokenHasReadWriteScope]
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
# get user object
|
||||
user = SystemUserProfile.objects.get(user=request.user)
|
||||
|
||||
# different style of ticket information
|
||||
if 'pending' in request.GET:
|
||||
ticket = self.queryset.filter(customer=user, state='pending')
|
||||
serializer = self.serializer_class(ticket, many=True)
|
||||
elif 'responded' in request.GET:
|
||||
ticket = self.queryset.filter(customer=user, state='responded')
|
||||
serializer = self.serializer_class(ticket, many=True)
|
||||
elif 'closed' in request.GET:
|
||||
ticket = self.queryset.filter(customer=user, state='closed')
|
||||
serializer = self.serializer_class(ticket, many=True)
|
||||
elif 'all' in request.GET:
|
||||
ticket = self.queryset.filter(customer=user)
|
||||
serializer = self.serializer_class(ticket, many=True)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
|
||||
def retrieve(self, request, *args, **kwargs):
|
||||
ticket = self.queryset.get(key=request.data['key'])
|
||||
serializer = self.serializer_class(ticket)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
|
||||
if 'ticket_key' in request.data.keys():
|
||||
ticket_key = request.data['ticket_key']
|
||||
request.data.pop('ticket_key')
|
||||
else:
|
||||
ticket_key = None
|
||||
|
||||
# get group unit information
|
||||
group = Group.objects.get(
|
||||
name__exact=request.data['support_unit']
|
||||
)
|
||||
request.data.pop('support_unit') # pop this block from body data
|
||||
|
||||
# get support unit object information
|
||||
support_unit = SupportUnit.objects.get(
|
||||
unit=group
|
||||
)
|
||||
|
||||
# ticket number
|
||||
ticket_id = random.randint(1000000, 9999999)
|
||||
|
||||
# process list of images
|
||||
req = upload_listed_image(req=request, field='image')
|
||||
|
||||
# create ticket content
|
||||
content_serializer = TicketContentSerializer(data=req.data)
|
||||
if content_serializer.is_valid():
|
||||
content_obj = content_serializer.create(validated_data=req.data)
|
||||
|
||||
# create question from customer
|
||||
question = Question(
|
||||
questioner=SystemUserProfile.objects.get(user=request.user),
|
||||
content=content_obj
|
||||
)
|
||||
question.save()
|
||||
|
||||
if ticket_key is not None:
|
||||
ticket = Ticket.objects.get(key=ticket_key)
|
||||
ticket.question.add(question)
|
||||
ticket.state = 'pending'
|
||||
ticket.save()
|
||||
else:
|
||||
# create final ticket
|
||||
ticket = Ticket(
|
||||
customer=SystemUserProfile.objects.get(user=request.user),
|
||||
support_unit=support_unit,
|
||||
state='pending',
|
||||
ticket_id=ticket_id
|
||||
)
|
||||
ticket.save()
|
||||
ticket.question.add(question)
|
||||
|
||||
serializer = self.serializer_class(ticket)
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||
|
||||
def update(self, request, *args, **kwargs):
|
||||
ticket = self.queryset.get(key=request.data['ticket_key']) # contains ticket object
|
||||
request.data.pop('ticket_key')
|
||||
|
||||
# send ticket object to serializer for update
|
||||
serializer = self.serializer_class(data=request.data)
|
||||
if serializer.is_valid():
|
||||
ticket_updated = serializer.update(validated_data=request.data, instance=ticket)
|
||||
serializer = self.serializer_class(ticket_updated)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
return Response(serializer.errors)
|
||||
|
||||
def destroy(self, request, *args, **kwargs):
|
||||
pass
|
||||
75
ticket/helper.py
Normal file
75
ticket/helper.py
Normal file
@@ -0,0 +1,75 @@
|
||||
import base64
|
||||
import io
|
||||
import os
|
||||
import random
|
||||
import string
|
||||
|
||||
import boto3
|
||||
from PIL import Image
|
||||
|
||||
from ticket.bucket import RASADYAR_ENDPOINT, RASADYAR_BUCKET_NAME, RASADYAR_ACCESS_KEY, RASADYAR_SECRET_KEY
|
||||
|
||||
ARVAN_TICKET_GALLERY = "https://profileimagedefault.s3.ir-thr-at1.arvanstorage.ir/"
|
||||
# ARVAN_TICKET_GALLERY = "https://ticketgallery.s3.ir-thr-at1.arvanstorage.com/"
|
||||
ARVAN_User_Image_URL = 'https://profileimagedefault.s3.ir-thr-at1.arvanstorage.ir/'
|
||||
|
||||
|
||||
def send_image_to_server(image):
|
||||
ran = ''.join(random.choices(string.ascii_uppercase + string.digits, k=15))
|
||||
imgdata = base64.b64decode(image)
|
||||
img = Image.open(io.BytesIO(imgdata))
|
||||
|
||||
img.thumbnail((500, 500))
|
||||
|
||||
buffer = io.BytesIO()
|
||||
img.save(buffer, format="PNG")
|
||||
buffer.seek(0)
|
||||
|
||||
s3_resource = boto3.resource(
|
||||
's3',
|
||||
endpoint_url=RASADYAR_ENDPOINT,
|
||||
aws_access_key_id=RASADYAR_ACCESS_KEY,
|
||||
aws_secret_access_key=RASADYAR_SECRET_KEY
|
||||
)
|
||||
|
||||
bucket = s3_resource.Bucket(RASADYAR_BUCKET_NAME)
|
||||
bucket.put_object(
|
||||
ACL='public-read',
|
||||
Body=buffer,
|
||||
Key=ran + '.jpg',
|
||||
ContentType='image/png'
|
||||
)
|
||||
|
||||
image_url = f"{RASADYAR_ENDPOINT}/{RASADYAR_BUCKET_NAME}/{ran + '.jpg'}"
|
||||
|
||||
return image_url
|
||||
|
||||
|
||||
def upload_listed_image(req=None, field=None):
|
||||
image_list = []
|
||||
if req.data[field] != []:
|
||||
for item in req.data[field]:
|
||||
image_list.append(send_image_to_server(item))
|
||||
req.data.pop(field)
|
||||
req.data[field] = image_list
|
||||
elif req.data[field] == "":
|
||||
req.data[field] = "empty"
|
||||
return req
|
||||
|
||||
|
||||
def send_image_to_server_for_poultry_science(image, name):
|
||||
s3 = boto3.client(
|
||||
's3',
|
||||
endpoint_url=RASADYAR_ENDPOINT,
|
||||
aws_access_key_id=RASADYAR_ACCESS_KEY,
|
||||
aws_secret_access_key=RASADYAR_SECRET_KEY
|
||||
)
|
||||
|
||||
s3.upload_fileobj(
|
||||
image,
|
||||
RASADYAR_BUCKET_NAME,
|
||||
name,
|
||||
ExtraArgs={'ACL': 'public-read'} # دسترسی عمومی
|
||||
)
|
||||
|
||||
return f"{RASADYAR_ENDPOINT}/{RASADYAR_BUCKET_NAME}/{name}"
|
||||
149
ticket/migrations/0001_initial.py
Normal file
149
ticket/migrations/0001_initial.py
Normal file
@@ -0,0 +1,149 @@
|
||||
# Generated by Django 3.2.13 on 2022-12-04 13:13
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('auth', '0012_alter_user_first_name_max_length'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('authentication', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Answer',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)),
|
||||
('create_date', models.DateTimeField(auto_now_add=True)),
|
||||
('modify_date', models.DateTimeField(auto_now=True)),
|
||||
('trash', models.BooleanField(default=False)),
|
||||
('state', models.CharField(max_length=100, null=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Question',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)),
|
||||
('create_date', models.DateTimeField(auto_now_add=True)),
|
||||
('modify_date', models.DateTimeField(auto_now=True)),
|
||||
('trash', models.BooleanField(default=False)),
|
||||
('state', models.CharField(max_length=100, null=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='SupportUnit',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)),
|
||||
('create_date', models.DateTimeField(auto_now_add=True)),
|
||||
('modify_date', models.DateTimeField(auto_now=True)),
|
||||
('trash', models.BooleanField(default=False)),
|
||||
('name', models.CharField(max_length=100, null=True)),
|
||||
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='supportunit_createdby', to=settings.AUTH_USER_MODEL)),
|
||||
('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='supportunit_modifiedby', to=settings.AUTH_USER_MODEL)),
|
||||
('unit', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='support_unit', to='auth.group')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TicketContent',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)),
|
||||
('create_date', models.DateTimeField(auto_now_add=True)),
|
||||
('modify_date', models.DateTimeField(auto_now=True)),
|
||||
('trash', models.BooleanField(default=False)),
|
||||
('title', models.CharField(max_length=200, null=True)),
|
||||
('content', models.TextField(max_length=2000, null=True)),
|
||||
('image', models.JSONField(default=dict)),
|
||||
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticketcontent_createdby', to=settings.AUTH_USER_MODEL)),
|
||||
('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticketcontent_modifiedby', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Ticket',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)),
|
||||
('create_date', models.DateTimeField(auto_now_add=True)),
|
||||
('modify_date', models.DateTimeField(auto_now=True)),
|
||||
('trash', models.BooleanField(default=False)),
|
||||
('state', models.CharField(max_length=100, null=True)),
|
||||
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticket_createdby', to=settings.AUTH_USER_MODEL)),
|
||||
('customer', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticket_customer', to='authentication.systemuserprofile')),
|
||||
('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticket_modifiedby', to=settings.AUTH_USER_MODEL)),
|
||||
('operator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticket_operator', to='authentication.systemuserprofile')),
|
||||
('question', models.ManyToManyField(related_name='ticket_question', to='ticket.Question')),
|
||||
('respond', models.ManyToManyField(related_name='ticket_respond', to='ticket.Answer')),
|
||||
('support_unit', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticket_unit', to='ticket.supportunit')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='question',
|
||||
name='content',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='questioner_content', to='ticket.ticketcontent'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='question',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='question_createdby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='question',
|
||||
name='modified_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='question_modifiedby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='question',
|
||||
name='questioner',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='questioner', to='authentication.systemuserprofile'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='answer',
|
||||
name='content',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='answer_content', to='ticket.ticketcontent'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='answer',
|
||||
name='created_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='answer_createdby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='answer',
|
||||
name='modified_by',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='answer_modifiedby', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='answer',
|
||||
name='question',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='answer_question', to='ticket.question'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='answer',
|
||||
name='responder',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='answer', to='authentication.systemuserprofile'),
|
||||
),
|
||||
]
|
||||
18
ticket/migrations/0002_ticket_ticket_id.py
Normal file
18
ticket/migrations/0002_ticket_ticket_id.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.2.13 on 2022-12-21 00:02
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('ticket', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='ticket',
|
||||
name='ticket_id',
|
||||
field=models.BigIntegerField(default=0),
|
||||
),
|
||||
]
|
||||
52
ticket/migrations/0003_messagesupport_ticketsupport.py
Normal file
52
ticket/migrations/0003_messagesupport_ticketsupport.py
Normal file
@@ -0,0 +1,52 @@
|
||||
# Generated by Django 3.2.13 on 2024-06-20 16:09
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0033_auto_20240620_1609'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('ticket', '0002_ticket_ticket_id'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='TicketSupport',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)),
|
||||
('create_date', models.DateTimeField(auto_now_add=True)),
|
||||
('modify_date', models.DateTimeField(auto_now=True)),
|
||||
('trash', models.BooleanField(default=False)),
|
||||
('title', models.CharField(max_length=100, null=True)),
|
||||
('ticket_id', models.BigIntegerField(default=1)),
|
||||
('status', models.CharField(default='open', max_length=100)),
|
||||
('type', models.CharField(max_length=100, null=True)),
|
||||
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticketsupport_createdby', to=settings.AUTH_USER_MODEL)),
|
||||
('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticketsupport_modifiedby', to=settings.AUTH_USER_MODEL)),
|
||||
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticket_support', to='authentication.systemuserprofile')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='MessageSupport',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('message', models.TextField()),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('sender', models.CharField(default='user', max_length=50)),
|
||||
('user_location', models.CharField(max_length=250, null=True)),
|
||||
('picture', models.CharField(max_length=250, null=True)),
|
||||
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='authentication.systemuserprofile')),
|
||||
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='replies', to='ticket.messagesupport')),
|
||||
('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='ticket.ticketsupport')),
|
||||
],
|
||||
),
|
||||
]
|
||||
108
ticket/migrations/0004_auto_20241227_1534.py
Normal file
108
ticket/migrations/0004_auto_20241227_1534.py
Normal file
@@ -0,0 +1,108 @@
|
||||
# Generated by Django 3.2.13 on 2024-12-27 15:34
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0043_auto_20241227_1534'),
|
||||
('auth', '0012_alter_user_first_name_max_length'),
|
||||
('ticket', '0003_messagesupport_ticketsupport'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='ticketsupport',
|
||||
old_name='type',
|
||||
new_name='last_message',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='messagesupport',
|
||||
name='user_location',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='ticketsupport',
|
||||
name='ticket_id',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='messagesupport',
|
||||
name='last_seen',
|
||||
field=models.DateTimeField(null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='messagesupport',
|
||||
name='send_message',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ticketsupport',
|
||||
name='parent',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='ticket.ticketsupport'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ticketsupport',
|
||||
name='read_only',
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ticketsupport',
|
||||
name='role',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ticketsupport',
|
||||
name='to_role',
|
||||
field=models.ManyToManyField(related_name='to_role_ticket', to='auth.Group'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ticketsupport',
|
||||
name='to_user',
|
||||
field=models.ManyToManyField(related_name='to_user_ticket', to='authentication.SystemUserProfile'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ticketsupport',
|
||||
name='type_ticket',
|
||||
field=models.CharField(default='single', max_length=100),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='answer',
|
||||
name='key',
|
||||
field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='question',
|
||||
name='key',
|
||||
field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='supportunit',
|
||||
name='key',
|
||||
field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticket',
|
||||
name='key',
|
||||
field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticketcontent',
|
||||
name='key',
|
||||
field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticketsupport',
|
||||
name='key',
|
||||
field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TicketPermission',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('role', models.CharField(max_length=200, null=True)),
|
||||
('roles', models.ManyToManyField(related_name='to_role', to='auth.Group')),
|
||||
],
|
||||
),
|
||||
]
|
||||
50
ticket/migrations/0005_auto_20241228_1050.py
Normal file
50
ticket/migrations/0005_auto_20241228_1050.py
Normal file
@@ -0,0 +1,50 @@
|
||||
# Generated by Django 3.2.13 on 2024-12-28 10:50
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('ticket', '0004_auto_20241227_1534'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='ticketpermission',
|
||||
name='roles',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='ticketsupport',
|
||||
name='created_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='ticketsupport',
|
||||
name='modified_by',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='ticketsupport',
|
||||
name='parent',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='ticketsupport',
|
||||
name='to_role',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='ticketsupport',
|
||||
name='to_user',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='ticketsupport',
|
||||
name='user',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='MessageSupport',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='TicketPermission',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='TicketSupport',
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,68 @@
|
||||
# Generated by Django 3.2.13 on 2024-12-28 10:54
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0044_auto_20241228_1054'),
|
||||
('auth', '0012_alter_user_first_name_max_length'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('ticket', '0005_auto_20241228_1050'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='TicketSupport',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)),
|
||||
('create_date', models.DateTimeField(auto_now_add=True)),
|
||||
('modify_date', models.DateTimeField(auto_now=True)),
|
||||
('trash', models.BooleanField(default=False)),
|
||||
('title', models.CharField(max_length=100, null=True)),
|
||||
('ticket_id', models.IntegerField(null=True, unique=True)),
|
||||
('status', models.CharField(default='open', max_length=100)),
|
||||
('last_message', models.CharField(max_length=100, null=True)),
|
||||
('type_ticket', models.CharField(default='single', max_length=100)),
|
||||
('read_only', models.BooleanField(default=True)),
|
||||
('role', models.CharField(max_length=100, null=True)),
|
||||
('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticketsupport_createdby', to=settings.AUTH_USER_MODEL)),
|
||||
('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticketsupport_modifiedby', to=settings.AUTH_USER_MODEL)),
|
||||
('parent', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='ticket.ticketsupport')),
|
||||
('to_role', models.ManyToManyField(related_name='to_role_ticket', to='auth.Group')),
|
||||
('to_user', models.ManyToManyField(related_name='to_user_ticket', to='authentication.SystemUserProfile')),
|
||||
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticket_support', to='authentication.systemuserprofile')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='TicketPermission',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('role', models.CharField(max_length=200, null=True)),
|
||||
('roles', models.ManyToManyField(related_name='to_role', to='auth.Group')),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='MessageSupport',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('message', models.TextField()),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('sender', models.CharField(default='user', max_length=50)),
|
||||
('picture', models.CharField(max_length=250, null=True)),
|
||||
('send_message', models.BooleanField(default=False)),
|
||||
('last_seen', models.DateTimeField(null=True)),
|
||||
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='authentication.systemuserprofile')),
|
||||
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='replies', to='ticket.messagesupport')),
|
||||
('ticket', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='ticket.ticketsupport')),
|
||||
],
|
||||
),
|
||||
]
|
||||
18
ticket/migrations/0007_messagesupport_file.py
Normal file
18
ticket/migrations/0007_messagesupport_file.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 3.2.13 on 2024-12-30 11:45
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('ticket', '0006_messagesupport_ticketpermission_ticketsupport'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='messagesupport',
|
||||
name='file',
|
||||
field=models.TextField(null=True),
|
||||
),
|
||||
]
|
||||
24
ticket/migrations/0008_auto_20250118_1751.py
Normal file
24
ticket/migrations/0008_auto_20250118_1751.py
Normal file
@@ -0,0 +1,24 @@
|
||||
# Generated by Django 3.2.13 on 2025-01-18 17:51
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0046_auto_20250118_1751'),
|
||||
('ticket', '0007_messagesupport_file'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='messagesupport',
|
||||
name='read_by',
|
||||
field=models.ManyToManyField(blank=True, related_name='read_messages', to='authentication.SystemUserProfile'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ticketsupport',
|
||||
name='unread_message',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
||||
35
ticket/migrations/0009_auto_20250201_1221.py
Normal file
35
ticket/migrations/0009_auto_20250201_1221.py
Normal file
@@ -0,0 +1,35 @@
|
||||
# Generated by Django 3.2.13 on 2025-02-01 12:21
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('authentication', '0048_auto_20250201_1221'),
|
||||
('ticket', '0008_auto_20250118_1751'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='ticketsupport',
|
||||
name='is_referred',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ticketsupport',
|
||||
name='referred_by',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='referred_by_me', to='authentication.systemuserprofile'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ticketsupport',
|
||||
name='referred_to',
|
||||
field=models.ManyToManyField(related_name='referred_tickets', to='authentication.SystemUserProfile'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='ticketsupport',
|
||||
name='user',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='ticket_support', to='authentication.systemuserprofile'),
|
||||
),
|
||||
]
|
||||
26
ticket/migrations/0010_auto_20250525_0951.py
Normal file
26
ticket/migrations/0010_auto_20250525_0951.py
Normal file
@@ -0,0 +1,26 @@
|
||||
# Generated by Django 3.2.13 on 2025-05-25 09:51
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('ticket', '0009_auto_20250201_1221'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='TicketClosePermission',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('active', models.BooleanField(default=False)),
|
||||
('day', models.SmallIntegerField(default=1)),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='ticketsupport',
|
||||
name='referred_date',
|
||||
field=models.DateTimeField(auto_now=True, null=True),
|
||||
),
|
||||
]
|
||||
0
ticket/migrations/__init__.py
Normal file
0
ticket/migrations/__init__.py
Normal file
190
ticket/models.py
Normal file
190
ticket/models.py
Normal file
@@ -0,0 +1,190 @@
|
||||
from django.db import models
|
||||
from authentication.models import (
|
||||
SystemUserProfile,
|
||||
BaseModel,
|
||||
Group
|
||||
)
|
||||
from panel.models import ProvinceOperator
|
||||
|
||||
|
||||
# Create your models here.
|
||||
|
||||
class Ticket(BaseModel):
|
||||
customer = models.ForeignKey(
|
||||
SystemUserProfile,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='ticket_customer',
|
||||
null=True
|
||||
)
|
||||
operator = models.ForeignKey(
|
||||
SystemUserProfile,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='ticket_operator',
|
||||
null=True
|
||||
)
|
||||
question = models.ManyToManyField(
|
||||
'Question',
|
||||
related_name="ticket_question",
|
||||
)
|
||||
respond = models.ManyToManyField(
|
||||
'Answer',
|
||||
related_name="ticket_respond"
|
||||
)
|
||||
support_unit = models.ForeignKey(
|
||||
'SupportUnit',
|
||||
on_delete=models.CASCADE,
|
||||
related_name="ticket_unit",
|
||||
null=True
|
||||
)
|
||||
ticket_id = models.BigIntegerField(default=0)
|
||||
state = models.CharField(max_length=100, null=True)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super(Ticket, self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class TicketContent(BaseModel):
|
||||
title = models.CharField(max_length=200, null=True)
|
||||
content = models.TextField(max_length=2000, null=True)
|
||||
image = models.JSONField(default=dict)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super(TicketContent, self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class Question(BaseModel):
|
||||
questioner = models.ForeignKey(
|
||||
SystemUserProfile,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="questioner",
|
||||
null=True
|
||||
)
|
||||
content = models.ForeignKey(
|
||||
TicketContent,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="questioner_content"
|
||||
)
|
||||
state = models.CharField(max_length=100, null=True)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super(Question, self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class Answer(BaseModel):
|
||||
responder = models.ForeignKey(
|
||||
SystemUserProfile,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="answer",
|
||||
null=True
|
||||
)
|
||||
question = models.ForeignKey(
|
||||
Question,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='answer_question',
|
||||
null=True
|
||||
)
|
||||
content = models.ForeignKey(
|
||||
TicketContent,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='answer_content',
|
||||
null=True
|
||||
)
|
||||
state = models.CharField(max_length=100, null=True)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super(Answer, self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class SupportUnit(BaseModel):
|
||||
name = models.CharField(max_length=100, null=True)
|
||||
unit = models.ForeignKey(
|
||||
Group,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="support_unit",
|
||||
null=True
|
||||
)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super(SupportUnit, self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class TicketSupport(BaseModel):
|
||||
user = models.ForeignKey(
|
||||
SystemUserProfile,
|
||||
on_delete=models.SET_NULL,
|
||||
related_name='ticket_support',
|
||||
null=True
|
||||
)
|
||||
referred_to = models.ManyToManyField(
|
||||
SystemUserProfile,
|
||||
related_name='referred_tickets',
|
||||
)
|
||||
referred_by = models.ForeignKey(
|
||||
SystemUserProfile,
|
||||
on_delete=models.SET_NULL,
|
||||
related_name='referred_by_me',
|
||||
null=True,
|
||||
)
|
||||
to_user=models.ManyToManyField(
|
||||
SystemUserProfile,
|
||||
related_name='to_user_ticket',
|
||||
)
|
||||
|
||||
to_role = models.ManyToManyField(
|
||||
Group,
|
||||
related_name='to_role_ticket',
|
||||
)
|
||||
|
||||
parent=models.ForeignKey('TicketSupport',on_delete=models.CASCADE,null=True)
|
||||
title = models.CharField(max_length=100, null=True)
|
||||
ticket_id = models.IntegerField(unique=True, null=True)
|
||||
status = models.CharField(max_length=100, default='open')
|
||||
last_message = models.CharField(max_length=100, null=True)
|
||||
type_ticket = models.CharField(default='single',max_length=100)
|
||||
read_only = models.BooleanField(default=True)
|
||||
role = models.CharField(max_length=100, null=True)
|
||||
unread_message=models.BooleanField(default=False)
|
||||
is_referred = models.BooleanField(default=False)
|
||||
referred_date = models.DateTimeField(auto_now=True,null=True)
|
||||
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.ticket_id:
|
||||
last_ticket = TicketSupport.objects.order_by('-ticket_id').first()
|
||||
self.ticket_id = last_ticket.ticket_id + 1 if last_ticket else 1
|
||||
super(TicketSupport, self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class MessageSupport(models.Model):
|
||||
ticket = models.ForeignKey(TicketSupport, related_name='messages', on_delete=models.CASCADE,null=True)
|
||||
created_by = models.ForeignKey(SystemUserProfile, on_delete=models.CASCADE)
|
||||
parent = models.ForeignKey('self', null=True, blank=True, related_name='replies', on_delete=models.CASCADE)
|
||||
message = models.TextField()
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
sender = models.CharField(max_length=50,default='user')
|
||||
picture = models.CharField(max_length=250, null=True)
|
||||
send_message = models.BooleanField(default=False)
|
||||
last_seen=models.DateTimeField(null=True)
|
||||
file=models.TextField( null=True)
|
||||
read_by = models.ManyToManyField(SystemUserProfile, related_name='read_messages', blank=True)
|
||||
|
||||
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super(MessageSupport,self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class TicketPermission(models.Model):
|
||||
role=models.CharField(max_length=200,null=True)
|
||||
roles=models.ManyToManyField(Group,related_name='to_role')
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super(TicketPermission,self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class TicketClosePermission(models.Model):
|
||||
active = models.BooleanField(default=False)
|
||||
day = models.SmallIntegerField(default=1)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super(TicketClosePermission, self).save(*args, **kwargs)
|
||||
117
ticket/operator_views.py
Normal file
117
ticket/operator_views.py
Normal file
@@ -0,0 +1,117 @@
|
||||
from rest_framework import viewsets
|
||||
from oauth2_provider.contrib.rest_framework import (
|
||||
TokenHasReadWriteScope,
|
||||
)
|
||||
from .models import (
|
||||
Ticket,
|
||||
TicketContent,
|
||||
Answer,
|
||||
Question,
|
||||
SupportUnit,
|
||||
Group,
|
||||
SystemUserProfile
|
||||
)
|
||||
from .serializers import (
|
||||
TicketSerializer,
|
||||
TicketContentSerializer,
|
||||
TicketAnswerSerializer,
|
||||
TicketQuestionSerializer,
|
||||
SupportUnitSerializer
|
||||
)
|
||||
from rest_framework.response import Response
|
||||
from .helper import upload_listed_image
|
||||
from rest_framework import status
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class OperatorTicketViewSet(viewsets.ModelViewSet):
|
||||
queryset = Ticket.objects.all()
|
||||
serializer_class = TicketSerializer
|
||||
permission_classes = [TokenHasReadWriteScope]
|
||||
|
||||
def ticket_by_flag(self, request, state):
|
||||
ticket_list = []
|
||||
roles = SystemUserProfile.objects.get(user=request.user).role.all()
|
||||
if state is not None:
|
||||
ticket = self.queryset.filter(state=state)
|
||||
else:
|
||||
ticket = self.queryset.all()
|
||||
for item in ticket:
|
||||
for role in roles:
|
||||
if item.support_unit.unit == role:
|
||||
ticket_list.append(item)
|
||||
return ticket_list
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
# get user object
|
||||
user = SystemUserProfile.objects.get(user=request.user)
|
||||
|
||||
# different style of ticket information
|
||||
if 'pending' in request.GET:
|
||||
ticket_list = self.ticket_by_flag(request=request, state='pending')
|
||||
serializer = self.serializer_class(ticket_list, many=True)
|
||||
elif 'responded' in request.GET:
|
||||
ticket = self.queryset.filter(operator=user, state='responded')
|
||||
serializer = self.serializer_class(ticket, many=True)
|
||||
elif 'closed' in request.GET:
|
||||
ticket = self.queryset.filter(operator=user, state='closed')
|
||||
serializer = self.serializer_class(ticket, many=True)
|
||||
elif 'all' in request.GET:
|
||||
ticket_list = self.ticket_by_flag(request=request, state=None)
|
||||
serializer = self.serializer_class(ticket_list, many=True)
|
||||
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
|
||||
def retrieve(self, request, *args, **kwargs):
|
||||
ticket = self.queryset.get(key=request.data['key'])
|
||||
serializer = self.serializer_class(ticket)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
ticket = self.queryset.get(key=request.data['ticket_key']) # contains ticket object
|
||||
request.data.pop('ticket_key')
|
||||
|
||||
# get question object
|
||||
# question = Question.objects.get(key=request.data['question_key'])
|
||||
# request.data.pop('question_key')
|
||||
question = ticket.question.all().last()
|
||||
|
||||
# create list of images
|
||||
req = upload_listed_image(req=request, field='image')
|
||||
|
||||
# create content object information
|
||||
content_serializer = TicketContentSerializer(data=req.data)
|
||||
if content_serializer.is_valid():
|
||||
content_obj = content_serializer.create(validated_data=req.data)
|
||||
|
||||
# create responder object information
|
||||
answer = Answer(
|
||||
responder=SystemUserProfile.objects.get(user=request.user),
|
||||
content=content_obj,
|
||||
question=question
|
||||
)
|
||||
answer.save()
|
||||
|
||||
# set respond for ticket questioner
|
||||
ticket.operator = SystemUserProfile.objects.get(user=request.user)
|
||||
ticket.state = 'responded'
|
||||
ticket.save()
|
||||
ticket.respond.add(answer)
|
||||
|
||||
serializer = self.serializer_class(ticket)
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||
|
||||
def update(self, request, *args, **kwargs):
|
||||
ticket = self.queryset.get(key=request.data['ticket_key']) # contains ticket object
|
||||
request.data.pop('ticket_key')
|
||||
|
||||
# send ticket object to serializer for update
|
||||
serializer = self.serializer_class(data=request.data)
|
||||
if serializer.is_valid():
|
||||
ticket_updated = serializer.update(validated_data=request.data, instance=ticket)
|
||||
serializer = self.serializer_class(ticket_updated)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
return Response(serializer.errors)
|
||||
|
||||
def destroy(self, request, *args, **kwargs):
|
||||
pass
|
||||
163
ticket/serializers.py
Normal file
163
ticket/serializers.py
Normal file
@@ -0,0 +1,163 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from authentication.models import SystemUserProfile
|
||||
from .models import (
|
||||
Ticket,
|
||||
TicketContent,
|
||||
Question,
|
||||
Answer,
|
||||
SupportUnit, TicketSupport, MessageSupport, TicketPermission, TicketClosePermission
|
||||
)
|
||||
from authentication.serializer.serializer import (
|
||||
SystemUserProfileSerializer,
|
||||
GroupSerializer, SystemUserProfileBaseInfoForTicketSerializer
|
||||
)
|
||||
|
||||
|
||||
class TicketContentSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = TicketContent
|
||||
exclude = (
|
||||
'id',
|
||||
'modify_date',
|
||||
'created_by',
|
||||
'modified_by',
|
||||
'trash',
|
||||
)
|
||||
|
||||
|
||||
class TicketQuestionSerializer(serializers.ModelSerializer):
|
||||
content = TicketContentSerializer(required=False)
|
||||
|
||||
class Meta:
|
||||
model = Question
|
||||
fields = (
|
||||
'key',
|
||||
'content'
|
||||
)
|
||||
|
||||
|
||||
class TicketAnswerSerializer(serializers.ModelSerializer):
|
||||
content = TicketContentSerializer(required=False)
|
||||
|
||||
# question = TicketQuestionSerializer(required=False)
|
||||
|
||||
class Meta:
|
||||
model = Answer
|
||||
fields = (
|
||||
'key',
|
||||
'content',
|
||||
# 'question'
|
||||
)
|
||||
|
||||
|
||||
class SupportUnitSerializer(serializers.ModelSerializer):
|
||||
unit = GroupSerializer(required=False)
|
||||
|
||||
class Meta:
|
||||
model = SupportUnit
|
||||
fields = (
|
||||
'unit',
|
||||
)
|
||||
|
||||
|
||||
class TicketSerializer(serializers.ModelSerializer):
|
||||
customer = SystemUserProfileSerializer(required=False)
|
||||
operator = SystemUserProfileSerializer(required=False)
|
||||
support_unit = SupportUnitSerializer(required=False)
|
||||
# question = TicketQuestionSerializer(required=False, many=True)
|
||||
# respond = TicketAnswerSerializer(required=False, many=True)
|
||||
title = serializers.SerializerMethodField('get_title')
|
||||
data = serializers.SerializerMethodField('get_responds')
|
||||
|
||||
class Meta:
|
||||
model = Ticket
|
||||
exclude = (
|
||||
'id',
|
||||
'created_by',
|
||||
'modified_by',
|
||||
'trash',
|
||||
'question',
|
||||
'respond',
|
||||
)
|
||||
|
||||
def get_title(self, instance):
|
||||
title = instance.question.all()
|
||||
title = title[0].content.title
|
||||
return title
|
||||
|
||||
def get_responds(self, instance):
|
||||
data = []
|
||||
for i in instance.question.all():
|
||||
question = TicketQuestionSerializer(i).data
|
||||
question['type'] = 'customer'
|
||||
data.append(question)
|
||||
for j in instance.respond.filter(question=i):
|
||||
answer = TicketAnswerSerializer(j).data
|
||||
answer['type'] = 'operator'
|
||||
data.append(answer)
|
||||
return data
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
instance.state = validated_data.get('state', instance.state)
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
|
||||
class SystemUserProfileForTicketPermissionSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = SystemUserProfile
|
||||
fields=['key','fullname','mobile']
|
||||
|
||||
|
||||
class TicketClosePermissionSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = TicketClosePermission
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class TicketSupportSerializer(serializers.ModelSerializer):
|
||||
user = SystemUserProfileForTicketPermissionSerializer(read_only=True)
|
||||
to_user = SystemUserProfileForTicketPermissionSerializer(read_only=True,many=True)
|
||||
referred_by = SystemUserProfileForTicketPermissionSerializer(read_only=True)
|
||||
referred_to = SystemUserProfileForTicketPermissionSerializer(read_only=True,many=True)
|
||||
to_role = GroupSerializer(read_only=True,many=True)
|
||||
|
||||
class Meta:
|
||||
model = TicketSupport
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class MessageSupportSerializer(serializers.ModelSerializer):
|
||||
created_by = SystemUserProfileForTicketPermissionSerializer(read_only=True)
|
||||
parent = SystemUserProfileForTicketPermissionSerializer(read_only=True)
|
||||
read_by = SystemUserProfileForTicketPermissionSerializer(read_only=True,many=True)
|
||||
ticket= TicketSupportSerializer(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = MessageSupport
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
class MessageSupportWithoutReadBySerializer(serializers.ModelSerializer):
|
||||
created_by = SystemUserProfileForTicketPermissionSerializer(read_only=True)
|
||||
parent = SystemUserProfileForTicketPermissionSerializer(read_only=True)
|
||||
# read_by = SystemUserProfileForTicketPermissionSerializer(read_only=True,many=True)
|
||||
|
||||
class Meta:
|
||||
model = MessageSupport
|
||||
exclude = ('read_by',)
|
||||
depth=1
|
||||
|
||||
class TicketPermissionSerializer(serializers.ModelSerializer):
|
||||
roles=serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = TicketPermission
|
||||
fields = ['id','role','roles']
|
||||
|
||||
def get_roles(self,obj):
|
||||
permissions = TicketPermission.objects.filter(role=obj.role).prefetch_related('roles')
|
||||
roles = [role.name for permission in permissions for role in permission.roles.all()]
|
||||
return roles
|
||||
|
||||
3
ticket/tests.py
Normal file
3
ticket/tests.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
22
ticket/urls.py
Normal file
22
ticket/urls.py
Normal file
@@ -0,0 +1,22 @@
|
||||
from django.urls import include, path
|
||||
from rest_framework.routers import DefaultRouter
|
||||
from . import customer_views, operator_views,views
|
||||
from .views import get_num_message, closed_unread_ticket, get_unread_ticket_for_dashboard
|
||||
|
||||
router = DefaultRouter()
|
||||
router.register('create_ticket', customer_views.CustomerTicketViewSet, basename='create_ticket')
|
||||
router.register('respond', operator_views.OperatorTicketViewSet, basename='respond')
|
||||
router.register(r'ticket', views.TicketSupportViewSet, basename='ticket')
|
||||
router.register(r'message', views.MessageSupportViewSet, basename='message')
|
||||
router.register(r'message-for-role', views.MessageForRoleViewSet, basename='message_for_role')
|
||||
router.register(r'ticket-permission', views.TicketPermissionViewSet, basename='ticket-permission')
|
||||
router.register(r'get-user-from-role', views.GetUserFromRoleViewSet, basename='get_user_from_role')
|
||||
router.register(r'ticket-close-permission', views.TicketClosePermissionViewSet, basename='ticket-close-permission')
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path('', include(router.urls)),
|
||||
path('get_num_message/', get_num_message),
|
||||
path('closed_unread_ticket/', closed_unread_ticket),
|
||||
path('get_unread_ticket_for_dashboard/', get_unread_ticket_for_dashboard),
|
||||
]
|
||||
512
ticket/views.py
Normal file
512
ticket/views.py
Normal file
@@ -0,0 +1,512 @@
|
||||
import datetime
|
||||
import random
|
||||
import string
|
||||
|
||||
import requests
|
||||
from django.db.models import Q, Count
|
||||
from django.http import HttpResponse
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope
|
||||
from rest_framework import status
|
||||
from rest_framework import viewsets
|
||||
from rest_framework.decorators import api_view, permission_classes
|
||||
from rest_framework.pagination import PageNumberPagination
|
||||
from rest_framework.permissions import AllowAny
|
||||
from rest_framework.response import Response
|
||||
|
||||
from authentication.models import SystemUserProfile, Group
|
||||
from authentication.sms_management import ticket_answered
|
||||
from helper_eata import token, chat_id
|
||||
from panel.filterset import TicketsFilterSet
|
||||
from panel.helper import build_query
|
||||
from ticket.models import TicketSupport, MessageSupport, TicketPermission, TicketClosePermission
|
||||
from ticket.serializers import TicketSupportSerializer, MessageSupportSerializer, TicketPermissionSerializer, \
|
||||
SystemUserProfileForTicketPermissionSerializer, MessageSupportWithoutReadBySerializer, \
|
||||
TicketClosePermissionSerializer
|
||||
from .bucket import upload_to_liara
|
||||
from .helper import send_image_to_server
|
||||
|
||||
|
||||
class CustomPagination(PageNumberPagination):
|
||||
page_size = 10
|
||||
|
||||
|
||||
def update_unread_ticket(tickets, user):
|
||||
user_roles = list(user.role.all())
|
||||
|
||||
unread_ticket_ids = MessageSupport.objects.filter(
|
||||
Q(ticket__user=user) |
|
||||
Q(ticket__to_user=user) |
|
||||
Q(ticket__to_role__in=user_roles) |
|
||||
Q(ticket__referred_by=user) |
|
||||
Q(ticket__referred_to=user.id),
|
||||
~Q(created_by=user),
|
||||
~Q(read_by=user.id),
|
||||
ticket__in=tickets
|
||||
).values_list('ticket_id', flat=True).distinct()
|
||||
|
||||
unread_set = set(unread_ticket_ids)
|
||||
|
||||
for ticket in tickets:
|
||||
ticket.unread_message = ticket.id in unread_set
|
||||
|
||||
TicketSupport.objects.bulk_update(tickets, ['unread_message'])
|
||||
|
||||
|
||||
class TicketSupportViewSet(viewsets.ModelViewSet):
|
||||
queryset = TicketSupport.objects.filter(trash=False).select_related(
|
||||
'user', 'referred_by'
|
||||
).prefetch_related(
|
||||
'to_role', 'referred_to', 'to_user').order_by('-unread_message', '-create_date')
|
||||
serializer_class = TicketSupportSerializer
|
||||
permission_classes = [TokenHasReadWriteScope]
|
||||
pagination_class = CustomPagination
|
||||
filterset_class = TicketsFilterSet
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
user = SystemUserProfile.objects.get(user=request.user)
|
||||
role_list = list(user.role.values_list('id', flat=True).distinct())
|
||||
role_check = any(role in ['AdminX', 'SuperAdmin'] for role in user.role.values_list('name', flat=True))
|
||||
type_param = request.GET.get('type', None)
|
||||
status = request.GET.get('status', 'open')
|
||||
base_filter = Q(user=user) | Q(to_user=user.id) | Q(to_role__in=role_list) | Q(referred_to=user.id) | Q(
|
||||
referred_by=user)
|
||||
|
||||
if role_check:
|
||||
if type_param:
|
||||
query = self.queryset.filter(type_ticket=type_param,
|
||||
status=status).distinct() if type_param else self.queryset
|
||||
else:
|
||||
query = self.queryset.filter(status=status).distinct()
|
||||
|
||||
else:
|
||||
if type_param:
|
||||
query = self.queryset.filter(base_filter, type_ticket=type_param, status=status).distinct()
|
||||
else:
|
||||
query = self.queryset.filter(base_filter, status=status)
|
||||
|
||||
value = request.GET.get('value')
|
||||
search = request.GET.get('search')
|
||||
if value and search == 'filter':
|
||||
if value != 'undefined' and value.strip():
|
||||
query = query.filter(
|
||||
build_query(self.filterset_class, value)
|
||||
)
|
||||
update_unread_ticket(query, user)
|
||||
query = query.order_by('-unread_message', '-create_date')
|
||||
page_size = request.query_params.get('page_size', None)
|
||||
if page_size:
|
||||
self.pagination_class.page_size = int(page_size)
|
||||
page = self.paginate_queryset(query)
|
||||
if page is not None:
|
||||
serializer = self.serializer_class(page, many=True)
|
||||
return self.get_paginated_response(serializer.data)
|
||||
ser_data = self.serializer_class(query, many=True)
|
||||
return Response(ser_data.data, status=status.HTTP_200_OK)
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
user = SystemUserProfile.objects.get(user=request.user)
|
||||
type_ticket = request.data.get('type_ticket')
|
||||
read_only = request.data.get('read_only')
|
||||
to_user_data = request.data.get('to_user')
|
||||
if request.data.get('image') is not None:
|
||||
image = send_image_to_server(request.data['image'])
|
||||
else:
|
||||
image = None
|
||||
if request.FILES.get('file'):
|
||||
file_obj = request.FILES.get('file')
|
||||
file_url = upload_to_liara(file_obj, file_obj.name)
|
||||
else:
|
||||
file_url = None
|
||||
if to_user_data:
|
||||
to_users = SystemUserProfile.objects.filter(key__in=request.data['to_user'])
|
||||
ticket = TicketSupport(
|
||||
user=user,
|
||||
title=request.data['title'],
|
||||
status='open',
|
||||
read_only=read_only,
|
||||
type_ticket=type_ticket,
|
||||
role=request.data.get('role'),
|
||||
)
|
||||
ticket.save()
|
||||
ticket.to_user.set(to_users)
|
||||
|
||||
else:
|
||||
to_role = Group.objects.filter(name__in=request.data.get('to_role'))
|
||||
if ((SystemUserProfile.objects.filter(trash=False, role__in=to_role).count() < 2)):
|
||||
return Response({'result': 'برای نقش انتخابی، لطفاً تیکت شخصی ثبت کنید!'},
|
||||
status=status.HTTP_403_FORBIDDEN)
|
||||
ticket = TicketSupport(
|
||||
user=user,
|
||||
title=request.data['title'],
|
||||
status='open',
|
||||
read_only=read_only,
|
||||
type_ticket=type_ticket,
|
||||
role=request.data.get('role'),
|
||||
)
|
||||
ticket.save()
|
||||
ticket.to_role.set(to_role)
|
||||
msg = MessageSupport(
|
||||
ticket=ticket,
|
||||
message=request.data['message'],
|
||||
created_by=user,
|
||||
sender=request.data.get('sender'),
|
||||
picture=image,
|
||||
file=file_url)
|
||||
msg.save()
|
||||
return Response({'msg': 'با موفقیت انجام شد.'}, status=status.HTTP_201_CREATED)
|
||||
|
||||
def update(self, request, *args, **kwargs):
|
||||
ticket_id = request.data.get('ticket')
|
||||
ticket = self.queryset.filter(ticket_id=int(ticket_id)).first()
|
||||
|
||||
if ticket:
|
||||
if 'referred_to' in request.data:
|
||||
referred_to = SystemUserProfile.objects.filter(key__in=request.data['referred_to'])
|
||||
ticket.referred_by = SystemUserProfile.objects.get(user=request.user)
|
||||
ticket.status = 'open'
|
||||
ticket.is_referred = True
|
||||
ticket.save()
|
||||
referrer_name = []
|
||||
for user in referred_to:
|
||||
if not ticket.referred_to.filter(id=user.id).exists():
|
||||
ticket.referred_to.add(user)
|
||||
referrer_name.append(user.fullname)
|
||||
if len(referrer_name) > 1:
|
||||
names = ' و '.join(referrer_name)
|
||||
else:
|
||||
names = referrer_name[0] if referrer_name else ''
|
||||
if referrer_name:
|
||||
MessageSupport.objects.create(
|
||||
ticket=ticket,
|
||||
message=f"تیکت شماره {ticket.ticket_id} به ({names}) ارجاع داده شد.",
|
||||
created_by=SystemUserProfile.objects.get(user=request.user),
|
||||
sender='Admin'
|
||||
)
|
||||
return Response({'message': 'تیکت با موفقیت ارجاع داده شد.'}, status=200)
|
||||
|
||||
else:
|
||||
ticket.status = 'closed'
|
||||
ticket.save()
|
||||
return Response({'result': 'تیکت با موفقیت پایان یافت.'}, status=status.HTTP_200_OK)
|
||||
return Response({'result': 'تیکت وجود ندارد!'}, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
class MessageSupportViewSet(viewsets.ModelViewSet):
|
||||
queryset = MessageSupport.objects.all().select_related('ticket').order_by('created_at')
|
||||
serializer_class = MessageSupportSerializer
|
||||
permission_classes = [TokenHasReadWriteScope]
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
user = SystemUserProfile.objects.get(user=request.user)
|
||||
ticket_id = request.GET.get('ticket')
|
||||
role_list = list(user.role.values_list('id', flat=True).distinct())
|
||||
role_check = any(
|
||||
role in ['AdminX', 'SuperAdmin', 'ProvinceOperator'] for role in user.role.values_list('name', flat=True))
|
||||
query = self.queryset.filter(ticket__ticket_id=int(ticket_id)).order_by('-created_at')
|
||||
if query.filter(Q(ticket__user=user) | Q(ticket__to_user=user.id) | Q(ticket__to_role__in=role_list) | Q(
|
||||
ticket__referred_by=user) | Q(ticket__referred_to=user.id)).exists():
|
||||
unseen_messages = query.filter(~Q(created_by=user), last_seen__isnull=True)
|
||||
unseen_messages.update(last_seen=datetime.datetime.now())
|
||||
|
||||
for message in query.filter(~Q(created_by=user)):
|
||||
if not message.read_by.filter(id=user.id).exists():
|
||||
message.read_by.add(user)
|
||||
|
||||
query = query.defer('message')
|
||||
if role_check:
|
||||
srz_data = self.serializer_class(query, many=True).data
|
||||
else:
|
||||
srz_data = MessageSupportWithoutReadBySerializer(query, many=True).data
|
||||
return Response(srz_data)
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
user = SystemUserProfile.objects.select_related('user').filter(user=request.user).first()
|
||||
ticket_id = request.data.get('ticket')
|
||||
ticket = TicketSupport.objects.get(ticket_id=int(ticket_id))
|
||||
|
||||
if ticket.status == 'closed':
|
||||
return Response({'result': 'این تیکت بسته شده است!'}, status=status.HTTP_403_FORBIDDEN)
|
||||
|
||||
if ticket.read_only == False and ticket.type_ticket == 'public' and ticket.parent is None \
|
||||
and ticket.user != user:
|
||||
new_ticket = TicketSupport(
|
||||
user=user,
|
||||
title=ticket.title,
|
||||
status='open',
|
||||
read_only=False,
|
||||
type_ticket='single',
|
||||
parent=ticket,
|
||||
last_message=request.data.get('sender'),
|
||||
role=request.data.get('role'),
|
||||
)
|
||||
new_ticket.save()
|
||||
new_ticket.to_user.add(ticket.user)
|
||||
|
||||
msg = MessageSupport(
|
||||
ticket=new_ticket,
|
||||
message=request.data.get('message'),
|
||||
created_by=user,
|
||||
sender=request.data.get('sender')
|
||||
)
|
||||
else:
|
||||
msg = MessageSupport(
|
||||
ticket=ticket,
|
||||
message=request.data.get('message'),
|
||||
created_by=user,
|
||||
sender=request.data.get('sender')
|
||||
)
|
||||
ticket.last_message = request.data.get('sender')
|
||||
ticket.save()
|
||||
if request.data['send_message'] == True:
|
||||
ticket_answered(ticket.user.mobile)
|
||||
msg.send_message = True
|
||||
if request.data.get('image') is not None:
|
||||
# ran = ''.join(random.choices(string.ascii_uppercase + string.digits, k=15))
|
||||
# upload_object_resize(image_data=request.data['image'], bucket_name="profileimagedefault",
|
||||
# object_name="{0}.jpg".format(str(ran)))
|
||||
msg.picture = send_image_to_server(request.data['image'])
|
||||
if request.FILES.get('file'):
|
||||
file_obj = request.FILES.get('file')
|
||||
file_url = upload_to_liara(file_obj, file_obj.name)
|
||||
msg.file = file_url
|
||||
msg.save()
|
||||
ser_data = self.serializer_class(msg)
|
||||
return Response(ser_data.data, status=status.HTTP_201_CREATED)
|
||||
|
||||
def update(self, request, *args, **kwargs):
|
||||
msg_id = request.data.get('message_id')
|
||||
instance = self.get_queryset().get(id=msg_id)
|
||||
request.data.pop('message_id')
|
||||
serializer = self.get_serializer(instance, data=request.data, partial=True)
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
return Response({'result': "با موفقیت انجام شد."}, status=status.HTTP_200_OK)
|
||||
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
class MessageForRoleViewSet(viewsets.ModelViewSet):
|
||||
queryset = MessageSupport.objects.all()
|
||||
serializer_class = MessageSupportSerializer
|
||||
permission_classes = [TokenHasReadWriteScope]
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
user_sender = SystemUserProfile.objects.get(user=request.user)
|
||||
if 'role' in request.data.keys():
|
||||
to_user = SystemUserProfile.objects.filter(trash=False, role__name__in=request.data['role'])
|
||||
relations = [
|
||||
TicketSupport(
|
||||
user=user_sender,
|
||||
title=request.data['title'],
|
||||
status='open',
|
||||
to_user=user
|
||||
)
|
||||
for user in to_user
|
||||
]
|
||||
TicketSupport.objects.bulk_create(relations)
|
||||
|
||||
return Response({'msg': 'با موفقیت ارسال شد'}, status=status.HTTP_201_CREATED)
|
||||
|
||||
|
||||
class TicketPermissionViewSet(viewsets.ModelViewSet):
|
||||
queryset = TicketPermission.objects.all()
|
||||
serializer_class = TicketPermissionSerializer
|
||||
permission_classes = [AllowAny]
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
role = request.data['role']
|
||||
group = request.data['roles']
|
||||
roles = Group.objects.filter(name__in=group)
|
||||
ticket = TicketPermission.objects.get(role=role)
|
||||
ticket.roles.set(roles)
|
||||
ser_data = self.serializer_class(ticket)
|
||||
return Response(ser_data.data, status=status.HTTP_201_CREATED)
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
if 'role' in request.GET:
|
||||
role = request.GET['role']
|
||||
query = self.queryset.get(role=role)
|
||||
ser_data = self.serializer_class(query).data
|
||||
return Response(ser_data, status=status.HTTP_200_OK)
|
||||
else:
|
||||
query = self.queryset
|
||||
ser_data = self.serializer_class(query, many=True).data
|
||||
return Response(ser_data, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class GetUserFromRoleViewSet(viewsets.ModelViewSet):
|
||||
queryset = SystemUserProfile.objects.all()
|
||||
serializer_class = SystemUserProfileForTicketPermissionSerializer
|
||||
permission_classes = [TokenHasReadWriteScope]
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
role = request.GET['role']
|
||||
user = SystemUserProfile.objects.filter(~Q(user=request.user), trash=False, role__name=role, )
|
||||
ser_data = self.serializer_class(user, many=True)
|
||||
return Response(ser_data.data, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class TicketClosePermissionViewSet(viewsets.ModelViewSet):
|
||||
queryset = TicketClosePermission.objects.all().first()
|
||||
serializer_class = TicketClosePermissionSerializer
|
||||
permission_classes = [TokenHasReadWriteScope]
|
||||
|
||||
|
||||
@api_view(["GET"])
|
||||
@csrf_exempt
|
||||
@permission_classes([TokenHasReadWriteScope])
|
||||
def get_num_message(request):
|
||||
user = SystemUserProfile.objects.get(user=request.user)
|
||||
message = MessageSupport.objects.filter(
|
||||
Q(ticket__user=user) | Q(ticket__to_user=user) | Q(ticket__to_role__in=user.role.all()) | Q(
|
||||
ticket__referred_by=user) | Q(ticket__referred_to=user.id)
|
||||
, ~Q(created_by=user)).exclude(read_by=user.id).values('ticket').annotate(
|
||||
ticket_count=Count('ticket', distinct=True)
|
||||
).distinct()
|
||||
state = True if message.count() > 0 else False
|
||||
return Response({
|
||||
'state': state,
|
||||
'num': message.count(),
|
||||
})
|
||||
|
||||
|
||||
# @api_view(["PUT"])
|
||||
# @csrf_exempt
|
||||
# @permission_classes([AllowAny])
|
||||
# def FileUploadView(request):
|
||||
# # queryset = TicketSupport.objects.all()
|
||||
# # permission_classes = [AllowAny]
|
||||
# # serializer_class = TicketSupportSerializer
|
||||
# #
|
||||
# # def create(self, request, *args, **kwargs):
|
||||
# file_obj = request.FILES.get('file')
|
||||
# if not file_obj:
|
||||
# return Response({"error": "فایلی ارسال نشده است"}, status=status.HTTP_400_BAD_REQUEST)
|
||||
#
|
||||
# try:
|
||||
# file_url = upload_to_liara(file_obj, file_obj.name)
|
||||
# return Response({"file_url": file_url}, status=status.HTTP_201_CREATED)
|
||||
# except Exception as e:
|
||||
# return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
|
||||
def bot_eitaa_for_bar():
|
||||
url = f'https://eitaayar.ir/api/{token}/sendMessage'
|
||||
data = {
|
||||
"cookie": "ASP.NET_SessionId=w1jadrzcqgznxugnjee1xrkj; .ASPXAUTH=4CC27FD1BAB0CA729584056577AA51209F731F22CDF4B95F9FEE33AD12F1DFFF960C77B0A237D5733E336195A2CA6DB1C1F2CA2EDCD079EC0B3C3092A2BF1BA8811D7C44263B1E5EB84430C0906024A55D51AF1FE5852F406C358A051715BB9270475D58228F44380D12FA075A4DF0E029220F0C809AEDDDF58FFE9568064DD9D397B038D19DC1757232A92EA63571EA7B47E1706F677528E539301417093B523B6C2BFD340AA33DC32D50E7853E3D14D93924313B9B1EB36320C90A2303BB852841EE0DE1D844B281B4CD6D7E95D593CF2E2F0C3816687C529B7702863F75CD6549F49D346C7C88F22F033C75C357BE9E91AD170A2502731BC03AE2DF09F594417646FE332B8BAB70673E584A23AD45CADC285C554B66FD29DD989F85962891A11C06FC84832DD8FB03933CF26E190601D493B0430A742544B8BC0A8639E4E5788432AA401FAFFD3A1C6793FB24909A992405D07E53B81DF546AB07ED90314735518C37E9291F10E2B723B795B8BB838C2810CE103A4EF893211BFDBB605ADBE0E3B9B35438A5FE3506937D020EC2EF061B6D1E3AAFB3A9A138CC219A4A556CEB6A2E44C18D53C85666A5C0C9663F8314EFD97FFF5C1844C0FEB4362A781E2138785D832EEFD1AEDAD1271C2513A6F4EC1174EF107AC2E9FEFF8A9A111CC6D6189CCC66E93224EE4D30813AAD9DCDE1CFC530B08CB67827C351DCE4C2AFD4E3FB12E85EA0CD6E2D3D4CC8753D74E863A37C5675D82C9977518A942786EF055F0DBFC809B9F9B6A45B269526FC9D8B5E888B1C6E40C6ACE8EB37ED7E1F9F266A018936F3228A3C8E20C1BD869CC657D1CE19FFEA8C8B979DE5077E17AE5FA1F085B3A424C91DA19D3743871A2A9440937B2C4E076EC99AE4DEE1A7AF601448F2F763FC2DF85ED8902287DDD0ED5B9E649A4490900B4BF64F639CDD761326AC08D1B540CBD853B42F556FFB8FD5BC33A54E68125CD20278B191A1896BF955FFA1B4CC5308E12A84003B64B0EE532079563DC334FB9AEB9B742803EBE35C82CA14E5D0D84CA736AB9A2E07EECFF98657561C029ECE3C1249DA843B4236E41BD745E54B1A86ED2CE4EA0FDDBB3B4B2B97A87548B23298283F6D09094F7BC709FAABE59CC84138F83B083EAB15BE0B032481; leggedOut=-"
|
||||
}
|
||||
r = requests.post(url='https://pay.rasadyar.net/transporting-chickens/', data=data)
|
||||
|
||||
data = {
|
||||
'chat_id': chat_id,
|
||||
'text': r.status_code,
|
||||
}
|
||||
response = requests.post(url, data=data, verify=False)
|
||||
|
||||
return HttpResponse(response.status_code)
|
||||
|
||||
|
||||
# def close_ticket_cron_job():
|
||||
# ticket=TicketSupport.objects.filter(Q(unread_message=False,read_only=True)|Q(unread_message=True,read_only=False),trash=False,status='open')
|
||||
# for t in ticket:
|
||||
# two_day_ago =datetime.datetime.now().date() - datetime.timedelta(days=2)
|
||||
# if (t.create_date.date() - datetime.datetime.now().date()).days > 2:
|
||||
# t.status='closed'
|
||||
# t.to_role=None
|
||||
# t.title=None
|
||||
# t.trash=False
|
||||
# t.create_date=datetime.datetime.now()
|
||||
# t.save()
|
||||
# else:
|
||||
# continue
|
||||
|
||||
@api_view(["GET"])
|
||||
@csrf_exempt
|
||||
@permission_classes([AllowAny])
|
||||
def closed_unread_ticket(request):
|
||||
user = SystemUserProfile.objects.filter(trash=False, role__name='AdminX').first()
|
||||
two_day_ago = datetime.datetime.now() - datetime.timedelta(days=2)
|
||||
ten_day_ago = datetime.datetime.now() - datetime.timedelta(days=10)
|
||||
tickets = TicketSupport.objects.filter(
|
||||
trash=False,
|
||||
status='open',
|
||||
type_ticket='single'
|
||||
)
|
||||
text_two_day_ago_message = 'به دلیل عدم دریافت پیام جدید در مدت 48 ساعت، این تیکت توسط سامانه به صورت خودکار بسته شد.'
|
||||
text_ten_day_ago_message = 'به دلیل خوانده نشدن پیام در مدت 10 روز، این تیکت توسط سامانه به صورت خودکار بسته شد.'
|
||||
for ticket in tickets:
|
||||
message = MessageSupport.objects.filter(ticket=ticket).last()
|
||||
if not message:
|
||||
continue
|
||||
if message.read_by.exists() and message.last_seen.date() <= two_day_ago.date():
|
||||
msg = MessageSupport(
|
||||
ticket=ticket,
|
||||
message=text_two_day_ago_message,
|
||||
created_by=user)
|
||||
msg.save()
|
||||
ticket.status = 'closed'
|
||||
ticket.save()
|
||||
|
||||
if not message.read_by.exists() and message.created_at.date() <= ten_day_ago.date():
|
||||
msg = MessageSupport(
|
||||
ticket=ticket,
|
||||
message=text_ten_day_ago_message,
|
||||
created_by=user)
|
||||
msg.save()
|
||||
ticket.status = 'closed'
|
||||
ticket.save()
|
||||
|
||||
return HttpResponse('ok')
|
||||
|
||||
|
||||
def closed_unread_ticket_cron():
|
||||
user = SystemUserProfile.objects.filter(trash=False, role__name='AdminX').first()
|
||||
two_day_ago = datetime.datetime.now() - datetime.timedelta(days=2)
|
||||
ten_day_ago = datetime.datetime.now() - datetime.timedelta(days=10)
|
||||
tickets = TicketSupport.objects.filter(
|
||||
trash=False,
|
||||
status='open',
|
||||
type_ticket='single'
|
||||
)
|
||||
text_two_day_ago_message = 'به دلیل عدم دریافت پیام جدید در مدت 48 ساعت، این تیکت توسط سامانه به صورت خودکار بسته شد.'
|
||||
# text_ten_day_ago_message = 'به دلیل خوانده نشدن پیام در مدت 10 روز، این تیکت توسط سامانه به صورت خودکار بسته شد.'
|
||||
for ticket in tickets:
|
||||
message = MessageSupport.objects.filter(ticket=ticket).last()
|
||||
if not message:
|
||||
continue
|
||||
if message.read_by.exists() and message.last_seen.date() <= two_day_ago.date():
|
||||
msg = MessageSupport(
|
||||
ticket=ticket,
|
||||
message=text_two_day_ago_message,
|
||||
created_by=user)
|
||||
msg.save()
|
||||
ticket.status = 'closed'
|
||||
ticket.save()
|
||||
|
||||
# if not message.read_by.exists() and message.created_at.date() <= ten_day_ago.date():
|
||||
# msg = MessageSupport(
|
||||
# ticket=ticket,
|
||||
# message=text_ten_day_ago_message,
|
||||
# created_by=user)
|
||||
# msg.save()
|
||||
# ticket.status = 'closed'
|
||||
# ticket.save()
|
||||
|
||||
|
||||
@api_view(["GET"])
|
||||
@csrf_exempt
|
||||
@permission_classes([TokenHasReadWriteScope])
|
||||
def get_unread_ticket_for_dashboard(request):
|
||||
user = SystemUserProfile.objects.get(user=request.user)
|
||||
role_list = list(user.role.values_list('id', flat=True).distinct())
|
||||
base_filter = Q(user=user) | Q(to_user=user.id) | Q(to_role__in=role_list) | Q(referred_to=user.id) | Q(
|
||||
referred_by=user)
|
||||
query = TicketSupport.objects.filter(base_filter, status='open',trash=False).select_related(
|
||||
'user', 'referred_by'
|
||||
).prefetch_related(
|
||||
'to_role', 'referred_to', 'to_user').order_by('-create_date')
|
||||
update_unread_ticket(query, user)
|
||||
query1 = query.filter(unread_message=True)
|
||||
ser_data = TicketSupportSerializer(query1, many=True)
|
||||
return Response(ser_data.data, status=status.HTTP_200_OK)
|
||||
Reference in New Issue
Block a user