add /shipping_vouchers endpoint

This commit is contained in:
j3d1 2024-06-23 02:50:44 +02:00
parent 2f354130da
commit f11758607e
6 changed files with 123 additions and 5 deletions

View file

@ -1,6 +1,6 @@
from django.contrib import admin from django.contrib import admin
from tickets.models import IssueThread, Comment, StateChange from tickets.models import IssueThread, Comment, StateChange, Assignment, ShippingVoucher
class IssueThreadAdmin(admin.ModelAdmin): class IssueThreadAdmin(admin.ModelAdmin):
@ -15,6 +15,16 @@ class StateChangeAdmin(admin.ModelAdmin):
pass pass
class AssignmentAdmin(admin.ModelAdmin):
pass
class ShippingVouchersAdmin(admin.ModelAdmin):
pass
admin.site.register(IssueThread, IssueThreadAdmin) admin.site.register(IssueThread, IssueThreadAdmin)
admin.site.register(Comment, CommentAdmin) admin.site.register(Comment, CommentAdmin)
admin.site.register(StateChange, StateChangeAdmin) admin.site.register(StateChange, StateChangeAdmin)
admin.site.register(Assignment, AssignmentAdmin)
admin.site.register(ShippingVoucher, ShippingVouchersAdmin)

View file

@ -13,8 +13,8 @@ from core.settings import MAIL_DOMAIN
from mail.models import Email from mail.models import Email
from mail.protocol import send_smtp, make_reply, collect_references from mail.protocol import send_smtp, make_reply, collect_references
from notify_sessions.models import SystemEvent from notify_sessions.models import SystemEvent
from tickets.models import IssueThread, Comment, STATE_CHOICES from tickets.models import IssueThread, Comment, STATE_CHOICES, ShippingVoucher
from tickets.serializers import IssueSerializer, CommentSerializer from tickets.serializers import IssueSerializer, CommentSerializer, ShippingVoucherSerializer
class IssueViewSet(viewsets.ModelViewSet): class IssueViewSet(viewsets.ModelViewSet):
@ -22,6 +22,11 @@ class IssueViewSet(viewsets.ModelViewSet):
queryset = IssueThread.objects.all() queryset = IssueThread.objects.all()
class ShippingVoucherViewSet(viewsets.ModelViewSet):
serializer_class = ShippingVoucherSerializer
queryset = ShippingVoucher.objects.all()
@api_view(['POST']) @api_view(['POST'])
@permission_classes([IsAuthenticated]) @permission_classes([IsAuthenticated])
@permission_required('tickets.add_issuethread', raise_exception=True) @permission_required('tickets.add_issuethread', raise_exception=True)
@ -113,6 +118,7 @@ def add_comment(request, pk):
router = routers.SimpleRouter() router = routers.SimpleRouter()
router.register(r'tickets', IssueViewSet, basename='issues') router.register(r'tickets', IssueViewSet, basename='issues')
router.register(r'shipping_vouchers', ShippingVoucherViewSet, basename='shipping_vouchers')
urlpatterns = ([ urlpatterns = ([
re_path(r'^tickets/(?P<pk>\d+)/reply/$', reply, name='reply'), re_path(r'^tickets/(?P<pk>\d+)/reply/$', reply, name='reply'),

View file

@ -0,0 +1,25 @@
# Generated by Django 4.2.7 on 2024-06-23 00:47
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('tickets', '0008_alter_issuethread_options_and_more'),
]
operations = [
migrations.CreateModel(
name='ShippingVoucher',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('voucher', models.CharField(max_length=255)),
('type', models.CharField(max_length=255)),
('timestamp', models.DateTimeField(auto_now_add=True)),
('used_at', models.DateTimeField(null=True)),
('issue_thread', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='shipping_vouchers', to='tickets.issuethread')),
],
),
]

View file

@ -1,4 +1,5 @@
from django.db import models from django.db import models
from django.utils import timezone
from django_softdelete.models import SoftDeleteModel from django_softdelete.models import SoftDeleteModel
from authentication.models import ExtendedUser from authentication.models import ExtendedUser
@ -116,3 +117,20 @@ class Assignment(models.Model):
def __str__(self): def __str__(self):
return str(self.issue_thread) + ' assigned to ' + self.assigned_to.username return str(self.issue_thread) + ' assigned to ' + self.assigned_to.username
class ShippingVoucher(models.Model):
id = models.AutoField(primary_key=True)
issue_thread = models.ForeignKey(IssueThread, on_delete=models.CASCADE, related_name='shipping_vouchers', null=True)
voucher = models.CharField(max_length=255)
type = models.CharField(max_length=255)
timestamp = models.DateTimeField(auto_now_add=True)
used_at = models.DateTimeField(null=True)
def __str__(self):
return self.voucher + ' (' + self.type + ')'
def save(self, *args, **kwargs):
if self.used_at is None and self.issue_thread is not None:
self.used_at = timezone.now()
super().save(*args, **kwargs)

View file

@ -2,7 +2,7 @@ from rest_framework import serializers
from authentication.models import ExtendedUser from authentication.models import ExtendedUser
from mail.api_v2 import AttachmentSerializer from mail.api_v2 import AttachmentSerializer
from tickets.models import IssueThread, Comment, STATE_CHOICES from tickets.models import IssueThread, Comment, STATE_CHOICES, ShippingVoucher
class CommentSerializer(serializers.ModelSerializer): class CommentSerializer(serializers.ModelSerializer):
@ -28,6 +28,13 @@ class StateSerializer(serializers.Serializer):
return obj['value'] return obj['value']
class ShippingVoucherSerializer(serializers.ModelSerializer):
class Meta:
model = ShippingVoucher
fields = ('id', 'voucher', 'type', 'timestamp', 'issue_thread', 'used_at')
read_only_fields = ('id', 'timestamp', 'used_at')
class IssueSerializer(serializers.ModelSerializer): class IssueSerializer(serializers.ModelSerializer):
timeline = serializers.SerializerMethodField() timeline = serializers.SerializerMethodField()
last_activity = serializers.SerializerMethodField() last_activity = serializers.SerializerMethodField()
@ -60,7 +67,10 @@ class IssueSerializer(serializers.ModelSerializer):
if self.state_changes.count() > 0 else None 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_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 last_mail = self.emails.order_by('-timestamp').first().timestamp if self.emails.count() > 0 else None
args = [x for x in [last_state_change, last_comment, last_mail] if x is not None] last_assignment = self.assignments.order_by('-timestamp').first().timestamp if \
self.assignments.count() > 0 else None
args = [x for x in [last_state_change, last_comment, last_mail, last_assignment] if
x is not None]
return max(args) return max(args)
except AttributeError: except AttributeError:
return None return None
@ -100,6 +110,14 @@ class IssueSerializer(serializers.ModelSerializer):
'timestamp': assignment.timestamp, 'timestamp': assignment.timestamp,
'assigned_to': assignment.assigned_to.username, 'assigned_to': assignment.assigned_to.username,
}) })
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,
})
return sorted(timeline, key=lambda x: x['timestamp']) return sorted(timeline, key=lambda x: x['timestamp'])
def get_queryset(self): def get_queryset(self):

View file

@ -0,0 +1,41 @@
from datetime import datetime, timedelta
from django.test import TestCase, Client
from authentication.models import ExtendedUser
from mail.models import Email, EmailAttachment
from tickets.models import IssueThread, StateChange, Comment, ShippingVoucher
from django.contrib.auth.models import Permission
from knox.models import AuthToken
class ShippingVoucherApiTest(TestCase):
def setUp(self):
super().setUp()
self.user = ExtendedUser.objects.create_user('testuser', 'test', 'test')
self.user.user_permissions.add(*Permission.objects.all())
self.user.save()
self.token = AuthToken.objects.create(user=self.user)
self.client = Client(headers={'Authorization': 'Token ' + self.token[1]})
def test_issues_empty(self):
response = self.client.get('/api/2/shipping_vouchers/')
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json(), [])
def test_issues_list(self):
ShippingVoucher.objects.create(voucher='1234', type='2kg-eu')
response = self.client.get('/api/2/shipping_vouchers/')
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json()[0]['voucher'], '1234')
self.assertEqual(response.json()[0]['used_at'], None)
self.assertEqual(response.json()[0]['issue_thread'], None)
self.assertEqual(response.json()[0]['type'], '2kg-eu')
def test_issues_create(self):
response = self.client.post('/api/2/shipping_vouchers/', {'voucher': '1234', 'type': '2kg-eu'})
self.assertEqual(response.status_code, 201)
self.assertEqual(response.json()['voucher'], '1234')
self.assertEqual(response.json()['used_at'], None)
self.assertEqual(response.json()['issue_thread'], None)