from django.utils import timezone from rest_framework import serializers from rest_framework.relations import SlugRelatedField from files.models import File from inventory.models import Event, Container, Item from inventory.shared_serializers import BasicItemSerializer from mail.models import EventAddress from tickets.shared_serializers import BasicIssueSerializer class EventSerializer(serializers.ModelSerializer): addresses = SlugRelatedField(many=True, slug_field='address', queryset=EventAddress.objects.all()) class Meta: model = Event fields = ['id', 'slug', 'name', 'start', 'end', 'pre_start', 'post_end', 'addresses'] read_only_fields = ['id'] def to_internal_value(self, data): data = data.copy() addresses = data.pop('addresses', None) dict = super().to_internal_value(data) if addresses: dict['addresses'] = [EventAddress.objects.get_or_create(address=x)[0] for x in addresses] return dict class ContainerSerializer(serializers.ModelSerializer): itemCount = serializers.SerializerMethodField() class Meta: model = Container fields = ['id', 'name', 'itemCount'] read_only_fields = ['id', 'itemCount'] def get_itemCount(self, instance): return len(instance.items) class ItemSerializer(BasicItemSerializer): timeline = serializers.SerializerMethodField() dataImage = serializers.CharField(write_only=True, required=False) related_issues = BasicIssueSerializer(many=True, read_only=True) class Meta: model = Item fields = ['cid', 'box', 'id', 'description', 'file', 'dataImage', 'returned', 'event', 'related_issues', 'timeline'] read_only_fields = ['id'] def to_internal_value(self, data): container = None returned = False if 'cid' in data: container = Container.objects.get(id=data['cid']) if 'returned' in data: returned = data['returned'] internal = super().to_internal_value(data) if container: internal['container'] = container if returned: internal['returned_at'] = timezone.now() return internal def validate(self, attrs): if not 'container' in attrs and not self.partial: raise serializers.ValidationError("This field cannot be empty.") return super().validate(attrs) def create(self, validated_data): if 'dataImage' in validated_data: file = File.objects.create(data=validated_data['dataImage']) validated_data.pop('dataImage') item = Item.objects.create(**validated_data) item.files.set([file]) return item return Item.objects.create(**validated_data) def update(self, instance, validated_data): if 'returned' in validated_data: if validated_data['returned']: validated_data['returned_at'] = timezone.now() validated_data.pop('returned') if 'dataImage' in validated_data: file = File.objects.create(data=validated_data['dataImage']) validated_data.pop('dataImage') instance.files.add(file) return super().update(instance, validated_data) @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 relation in (obj.issue_relation_changes.all()): timeline.append({ 'type': 'issue_relation', 'id': relation.id, 'status': relation.status, 'timestamp': relation.timestamp, 'issue_thread': BasicIssueSerializer(relation.issue_thread).data, }) for placement in (obj.container_history.all()): timeline.append({ 'type': 'placement', 'id': placement.id, 'timestamp': placement.timestamp, 'cid': placement.container.id, 'box': placement.container.name }) return sorted(timeline, key=lambda x: x['timestamp']) class SearchResultSerializer(serializers.Serializer): search_score = serializers.IntegerField() item = ItemSerializer() def to_representation(self, instance): return {**ItemSerializer(instance['item']).data, 'search_score': instance['search_score']} class Meta: model = Item