2024-01-22 16:21:22 +00:00
|
|
|
from rest_framework import serializers
|
|
|
|
|
|
|
|
from authentication.models import ExtendedUser
|
2024-11-13 22:51:54 +00:00
|
|
|
from inventory.models import Event
|
2024-01-22 16:21:22 +00:00
|
|
|
from mail.api_v2 import AttachmentSerializer
|
2024-06-23 00:50:44 +00:00
|
|
|
from tickets.models import IssueThread, Comment, STATE_CHOICES, ShippingVoucher
|
2024-06-23 02:19:54 +00:00
|
|
|
from inventory.serializers import ItemSerializer
|
2024-01-22 16:21:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
class CommentSerializer(serializers.ModelSerializer):
|
|
|
|
|
|
|
|
def validate(self, attrs):
|
|
|
|
if 'comment' not in attrs or attrs['comment'] == '':
|
|
|
|
raise serializers.ValidationError('comment cannot be empty')
|
|
|
|
return attrs
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = Comment
|
|
|
|
fields = ('id', 'comment', 'timestamp', 'issue_thread')
|
|
|
|
|
|
|
|
|
|
|
|
class StateSerializer(serializers.Serializer):
|
|
|
|
text = serializers.SerializerMethodField()
|
|
|
|
value = serializers.SerializerMethodField()
|
|
|
|
|
|
|
|
def get_text(self, obj):
|
|
|
|
return obj['text']
|
|
|
|
|
|
|
|
def get_value(self, obj):
|
|
|
|
return obj['value']
|
|
|
|
|
|
|
|
|
2024-06-23 00:50:44 +00:00
|
|
|
class ShippingVoucherSerializer(serializers.ModelSerializer):
|
|
|
|
class Meta:
|
|
|
|
model = ShippingVoucher
|
|
|
|
fields = ('id', 'voucher', 'type', 'timestamp', 'issue_thread', 'used_at')
|
|
|
|
read_only_fields = ('id', 'timestamp', 'used_at')
|
|
|
|
|
|
|
|
|
2024-01-22 16:21:22 +00:00
|
|
|
class IssueSerializer(serializers.ModelSerializer):
|
|
|
|
timeline = serializers.SerializerMethodField()
|
|
|
|
last_activity = serializers.SerializerMethodField()
|
|
|
|
assigned_to = serializers.SlugRelatedField(slug_field='username', queryset=ExtendedUser.objects.all(),
|
|
|
|
allow_null=True, required=False)
|
2024-11-13 22:51:54 +00:00
|
|
|
event = serializers.SlugRelatedField(slug_field='slug', queryset=Event.objects.all(),
|
|
|
|
allow_null=True, required=False)
|
2024-06-23 02:19:54 +00:00
|
|
|
related_items = ItemSerializer(many=True, read_only=True)
|
2024-01-22 16:21:22 +00:00
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = IssueThread
|
2024-11-13 22:51:54 +00:00
|
|
|
fields = ('id', 'timeline', 'name', 'state', 'assigned_to', 'last_activity', 'uuid', 'related_items', 'event')
|
2024-06-23 02:19:54 +00:00
|
|
|
read_only_fields = ('id', 'timeline', 'last_activity', 'uuid', 'related_items')
|
2024-01-22 16:21:22 +00:00
|
|
|
|
|
|
|
def to_internal_value(self, data):
|
|
|
|
ret = super().to_internal_value(data)
|
|
|
|
if 'state' in data:
|
|
|
|
ret['state'] = data['state']
|
2024-06-26 16:42:56 +00:00
|
|
|
# if 'assigned_to' in data:
|
|
|
|
# ret['assigned_to'] = data['assigned_to']
|
2024-01-22 16:21:22 +00:00
|
|
|
return ret
|
|
|
|
|
|
|
|
def validate(self, attrs):
|
|
|
|
if 'state' in attrs:
|
|
|
|
if attrs['state'] not in [x[0] for x in STATE_CHOICES]:
|
|
|
|
raise serializers.ValidationError('invalid state')
|
|
|
|
return attrs
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def get_last_activity(self):
|
|
|
|
try:
|
|
|
|
last_state_change = self.state_changes.order_by('-timestamp').first().timestamp \
|
|
|
|
if self.state_changes.count() > 0 else None
|
|
|
|
last_comment = self.comments.order_by('-timestamp').first().timestamp if self.comments.count() > 0 else None
|
|
|
|
last_mail = self.emails.order_by('-timestamp').first().timestamp if self.emails.count() > 0 else None
|
2024-06-23 00:50:44 +00:00
|
|
|
last_assignment = self.assignments.order_by('-timestamp').first().timestamp if \
|
|
|
|
self.assignments.count() > 0 else None
|
2024-06-23 02:19:54 +00:00
|
|
|
last_relation = self.item_relations.order_by('-timestamp').first().timestamp if \
|
|
|
|
self.item_relations.count() > 0 else None
|
|
|
|
args = [x for x in [last_state_change, last_comment, last_mail, last_assignment, last_relation] if
|
2024-06-23 00:50:44 +00:00
|
|
|
x is not None]
|
2024-01-22 16:21:22 +00:00
|
|
|
return max(args)
|
|
|
|
except AttributeError:
|
|
|
|
return None
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def get_timeline(obj):
|
|
|
|
timeline = []
|
|
|
|
for comment in obj.comments.all():
|
|
|
|
timeline.append({
|
|
|
|
'type': 'comment',
|
|
|
|
'id': comment.id,
|
|
|
|
'timestamp': comment.timestamp,
|
|
|
|
'comment': comment.comment,
|
|
|
|
})
|
|
|
|
for state_change in obj.state_changes.all():
|
|
|
|
timeline.append({
|
|
|
|
'type': 'state',
|
|
|
|
'id': state_change.id,
|
|
|
|
'timestamp': state_change.timestamp,
|
|
|
|
'state': state_change.state,
|
|
|
|
})
|
|
|
|
for email in obj.emails.all():
|
|
|
|
timeline.append({
|
|
|
|
'type': 'mail',
|
|
|
|
'id': email.id,
|
|
|
|
'timestamp': email.timestamp,
|
|
|
|
'sender': email.sender,
|
|
|
|
'recipient': email.recipient,
|
|
|
|
'subject': email.subject,
|
|
|
|
'body': email.body,
|
|
|
|
'attachments': AttachmentSerializer(email.attachments.all(), many=True).data,
|
|
|
|
})
|
|
|
|
for assignment in obj.assignments.all():
|
|
|
|
timeline.append({
|
|
|
|
'type': 'assignment',
|
|
|
|
'id': assignment.id,
|
|
|
|
'timestamp': assignment.timestamp,
|
|
|
|
'assigned_to': assignment.assigned_to.username,
|
|
|
|
})
|
2024-06-23 02:19:54 +00:00
|
|
|
for relation in obj.item_relations.all():
|
|
|
|
timeline.append({
|
|
|
|
'type': 'item_relation',
|
|
|
|
'id': relation.id,
|
|
|
|
'status': relation.status,
|
|
|
|
'timestamp': relation.timestamp,
|
|
|
|
'item': ItemSerializer(relation.item).data,
|
|
|
|
})
|
2024-06-23 00:50:44 +00:00
|
|
|
for shipping_voucher in obj.shipping_vouchers.all():
|
|
|
|
timeline.append({
|
|
|
|
'type': 'shipping_voucher',
|
|
|
|
'id': shipping_voucher.id,
|
|
|
|
'timestamp': shipping_voucher.used_at,
|
|
|
|
'voucher': shipping_voucher.voucher,
|
|
|
|
'voucher_type': shipping_voucher.type,
|
|
|
|
})
|
2024-01-22 16:21:22 +00:00
|
|
|
return sorted(timeline, key=lambda x: x['timestamp'])
|
|
|
|
|
|
|
|
def get_queryset(self):
|
|
|
|
return IssueThread.objects.all().order_by('-last_activity')
|
2024-07-18 18:32:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
class SearchResultSerializer(serializers.Serializer):
|
|
|
|
search_score = serializers.IntegerField()
|
|
|
|
item = IssueSerializer()
|
|
|
|
|
|
|
|
def to_representation(self, instance):
|
|
|
|
return {**IssueSerializer(instance['item']).data, 'search_score': instance['search_score']}
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
model = IssueThread
|