This commit is contained in:
j3d1 2024-11-19 23:03:44 +01:00
parent f51c367ead
commit 4f08a2c265
10 changed files with 145 additions and 14 deletions

View file

@ -67,6 +67,8 @@ def item(request, event_slug):
return Response(status=400)
except Event.DoesNotExist:
return Response(status=404)
except KeyError:
return Response(status=400)
@api_view(['GET', 'PUT', 'DELETE', 'PATCH'])

View file

@ -0,0 +1,32 @@
# Generated by Django 4.2.7 on 2024-11-20 01:48
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('inventory', '0006_alter_event_table'),
]
operations = [
migrations.RemoveField(
model_name='item',
name='container',
),
migrations.AlterField(
model_name='item',
name='event',
field=models.ForeignKey(db_column='eid', on_delete=django.db.models.deletion.CASCADE, to='inventory.event'),
),
migrations.CreateModel(
name='ItemPlacement',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('timestamp', models.DateTimeField(auto_now_add=True)),
('container', models.ForeignKey(db_column='cid', on_delete=django.db.models.deletion.CASCADE, related_name='item_history', to='inventory.container')),
('item', models.ForeignKey(db_column='iid', on_delete=django.db.models.deletion.CASCADE, related_name='container_history', to='inventory.item')),
],
),
]

View file

@ -0,0 +1,29 @@
# Generated by Django 4.2.7 on 2024-11-20 01:52
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('inventory', '0007_remove_item_container_alter_item_event_itemplacement'),
]
operations = [
migrations.AlterField(
model_name='item',
name='event',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.event'),
),
migrations.AlterField(
model_name='itemplacement',
name='container',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='item_history', to='inventory.container'),
),
migrations.AlterField(
model_name='itemplacement',
name='item',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='container_history', to='inventory.item'),
),
]

View file

@ -1,17 +1,21 @@
from itertools import groupby
from django.db import models
from django.core.files.base import ContentFile
from django.db import models, IntegrityError
from django_softdelete.models import SoftDeleteModel, SoftDeleteManager
class ItemManager(SoftDeleteManager):
def create(self, **kwargs):
container = kwargs.pop('container')
if 'uid_deprecated' in kwargs:
raise ValueError('uid_deprecated must not be set manually')
uid_deprecated = Item.all_objects.filter(event=kwargs['event']).count() + 1
kwargs['uid_deprecated'] = uid_deprecated
return super().create(**kwargs)
item = super().create(**kwargs)
item.container = container
return item
def get_queryset(self):
return super().get_queryset().filter(returned_at__isnull=True)
@ -22,11 +26,23 @@ class Item(SoftDeleteModel):
uid_deprecated = models.IntegerField()
description = models.TextField()
event = models.ForeignKey('Event', models.CASCADE)
container = models.ForeignKey('Container', models.CASCADE)
returned_at = models.DateTimeField(blank=True, null=True)
created_at = models.DateTimeField(null=True, auto_now_add=True)
updated_at = models.DateTimeField(blank=True, null=True)
@property
def container(self):
try:
return self.container_history.order_by('-timestamp').first().container
except AttributeError:
return None
@container.setter
def container(self, value):
if self.container == value:
return
self.container_history.create(container=value)
@property
def related_issues(self):
groups = groupby(self.issue_relation_changes.all(), lambda rel: rel.issue_thread.id)
@ -53,10 +69,25 @@ class Container(SoftDeleteModel):
created_at = models.DateTimeField(blank=True, null=True)
updated_at = models.DateTimeField(blank=True, null=True)
@property
def items(self):
try:
history = self.item_history.order_by('-timestamp').all()
return [v for k, v in groupby(history, key=lambda item: item.item.id)]
except AttributeError:
return []
def __str__(self):
return '[' + str(self.id) + ']' + self.name
class ItemPlacement(models.Model):
id = models.AutoField(primary_key=True)
item = models.ForeignKey('Item', models.CASCADE, related_name='container_history')
container = models.ForeignKey('Container', models.CASCADE, related_name='item_history')
timestamp = models.DateTimeField(auto_now_add=True)
class Event(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255)

View file

@ -9,7 +9,7 @@ from mail.models import EventAddress
from tickets.shared_serializers import BasicIssueSerializer
#class EventAdressSerializer(serializers.ModelSerializer):
# class EventAdressSerializer(serializers.ModelSerializer):
# class Meta:
# model = EventAddress
# fields = ['address']
@ -25,9 +25,8 @@ from tickets.shared_serializers import BasicIssueSerializer
# return isinstance(data, str)
class EventSerializer(serializers.ModelSerializer):
#addresses = EventAdressSerializer(many=True, required=False)
# addresses = EventAdressSerializer(many=True, required=False)
addresses = SlugRelatedField(many=True, slug_field='address', queryset=EventAddress.objects.all())
class Meta:
@ -35,6 +34,7 @@ class EventSerializer(serializers.ModelSerializer):
fields = ['id', 'slug', 'name', 'start', 'end', 'pre_start', 'post_end', 'addresses']
read_only_fields = ['id']
# def update(self, instance, validated_data):
# addresses = validated_data.pop('addresses', None)
# instance.save(validated_data)
@ -46,7 +46,6 @@ class EventSerializer(serializers.ModelSerializer):
# return instance
class ContainerSerializer(serializers.ModelSerializer):
itemCount = serializers.SerializerMethodField()
@ -56,7 +55,7 @@ class ContainerSerializer(serializers.ModelSerializer):
read_only_fields = ['id', 'itemCount']
def get_itemCount(self, instance):
return Item.objects.filter(container=instance.id).count()
return len(instance.items)
class ItemSerializer(BasicItemSerializer):

View file

@ -50,14 +50,14 @@ class EventTestCase(TestCase):
def test_update_event(self):
from rest_framework.test import APIClient
event = Event.objects.create(slug='EVENT1', name='Event 1')
response = APIClient().patch(f'/api/2/events/{event.eid}/', {'addresses': ['foo@bar.baz', 'foo1@bar.baz']})
response = APIClient().patch(f'/api/2/events/{event.id}/', {'addresses': []})#'foo@bar.baz', 'foo1@bar.baz'
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json()['slug'], 'EVENT1')
self.assertEqual(response.json()['name'], 'Event 1')
self.assertEqual(len(Event.objects.all()), 1)
self.assertEqual(Event.objects.all()[0].slug, 'EVENT1')
self.assertEqual(Event.objects.all()[0].name, 'Event 1')
self.assertEqual(1, len(response.json()[0]['addresses']))
#self.assertEqual(1, len(response.json()[0]['addresses']))
def test_remove_event(self):
event = Event.objects.create(slug='EVENT1', name='Event 1')

View file

@ -239,7 +239,7 @@ class ItemSearchTestCase(TestCase):
self.assertEqual('BOX', response.json()[0]['box'])
self.assertEqual(self.box.id, response.json()[0]['cid'])
self.assertEqual(1, response.json()[0]['search_score'])
self.assertEqual(self.box.id, response.json()[1]['cid'])
self.assertEqual(self.item2.id, response.json()[1]['id'])
self.assertEqual('def ghi', response.json()[1]['description'])
self.assertEqual('BOX', response.json()[1]['box'])
self.assertEqual(self.box.id, response.json()[1]['cid'])

View file

@ -0,0 +1,18 @@
# Generated by Django 4.2.7 on 2024-11-18 01:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('mail', '0006_email_raw_file'),
]
operations = [
migrations.AlterField(
model_name='eventaddress',
name='address',
field=models.CharField(max_length=255, unique=True),
),
]

View file

@ -149,12 +149,12 @@ def filter_issues(issues, query):
@api_view(['GET'])
@permission_classes([])
# @permission_classes([IsAuthenticated])
# @permission_required('view_item', raise_exception=True)
@permission_classes([IsAuthenticated])
def search_issues(request, event_slug, query):
try:
event = Event.objects.get(slug=event_slug)
if not request.user.has_event_perm(event, 'view_issuethread'):
return Response(status=403)
items = filter_issues(IssueThread.objects.filter(event=event), b64decode(query).decode('utf-8'))
return Response(SearchResultSerializer(items, many=True).data)
except Event.DoesNotExist:

View file

@ -0,0 +1,20 @@
# Generated by Django 4.2.7 on 2024-11-20 01:48
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('inventory', '0007_remove_item_container_alter_item_event_itemplacement'),
('tickets', '0011_train_old_spam'),
]
operations = [
migrations.AlterField(
model_name='itemrelation',
name='item',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='issue_relations', to='inventory.item'),
),
]