127 lines
No EOL
5.1 KiB
Python
127 lines
No EOL
5.1 KiB
Python
from rest_framework.serializers import ModelSerializer, SerializerMethodField, IntegerField, UUIDField
|
|
from rest_framework.exceptions import ValidationError
|
|
from apps.orgs.models import Organization, OrganizationMembership, OrganizationInvitation, Role, RoleMembership, TrainingFile
|
|
from apps.users.serializers import UserSerializer
|
|
|
|
class OrganizationSerializer(ModelSerializer):
|
|
owner = UserSerializer(read_only = True)
|
|
member_count = SerializerMethodField()
|
|
role_count = SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = Organization
|
|
fields = ['id', 'uuid', 'name', 'description', 'owner', 'created_at', 'updated_at', 'member_count', 'role_count']
|
|
read_only_fields = ['uuid', 'owner', 'created_at', 'updated_at']
|
|
|
|
def get_member_count(self, obj):
|
|
return obj.memberships.count()
|
|
|
|
def get_role_count(self, obj):
|
|
return obj.roles.count()
|
|
|
|
class OrganizationMembershipSerializer(ModelSerializer):
|
|
user = UserSerializer(read_only = True)
|
|
user_id = IntegerField(write_only = True, required = False)
|
|
|
|
class Meta:
|
|
model = OrganizationMembership
|
|
fields = ['id', 'user', 'user_id', 'organization', 'created_at', 'updated_at']
|
|
read_only_fields = ['organization', 'created_at', 'updated_at']
|
|
|
|
def create(self, validated_data):
|
|
user_id = validated_data.pop('user_id', None)
|
|
if user_id:
|
|
validated_data['user_id'] = user_id
|
|
return super().create(validated_data)
|
|
|
|
class OrganizationInvitationSerializer(ModelSerializer):
|
|
created_by = UserSerializer(read_only = True)
|
|
invite_url = SerializerMethodField()
|
|
is_valid = SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = OrganizationInvitation
|
|
fields = ['id', 'token', 'organization', 'created_by', 'expires_at', 'max_uses', 'is_active', 'invite_url', 'is_valid', 'created_at', 'updated_at', 'uses']
|
|
read_only_fields = ['token', 'organization', 'created_by', 'max_uses', 'created_at', 'updated_at', 'uses']
|
|
|
|
def get_invite_url(self, obj):
|
|
request = self.context.get('request')
|
|
if request:
|
|
return request.build_absolute_uri(f'/invite/{obj.token}')
|
|
return f'/invite/{obj.token}'
|
|
|
|
def get_is_valid(self, obj):
|
|
return obj.is_valid()
|
|
|
|
class RoleMembershipSerializer(ModelSerializer):
|
|
user = UserSerializer(read_only = True)
|
|
|
|
class Meta:
|
|
model = RoleMembership
|
|
fields = ['id', 'user', 'role', 'created_at']
|
|
read_only_fields = ['created_at']
|
|
|
|
class RoleSerializer(ModelSerializer):
|
|
organization = OrganizationSerializer(read_only = True)
|
|
member_count = SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = Role
|
|
fields = ['id', 'uuid', 'name', 'organization', 'member_count', 'description', 'created_at', 'updated_at']
|
|
read_only_fields = ['uuid', 'organization', 'created_at', 'updated_at']
|
|
|
|
def get_member_count(self, obj):
|
|
return obj.memberships.count()
|
|
|
|
class TrainingFileSerializer(ModelSerializer):
|
|
uploaded_by = UserSerializer(read_only = True)
|
|
file_url = SerializerMethodField()
|
|
role = RoleSerializer(read_only = True)
|
|
role_uuid = UUIDField(write_only = True, required = True)
|
|
|
|
class Meta:
|
|
model = TrainingFile
|
|
fields = ['id', 'uuid', 'role', 'role_uuid', 'uploaded_by', 'file', 'file_name', 'file_size', 'file_type', 'description', 'status', 'is_processed', 'file_url', 'created_at', 'updated_at']
|
|
read_only_fields = ['uuid', 'uploaded_by', 'file_size', 'file_type', 'status', 'is_processed', 'created_at', 'updated_at', 'role']
|
|
|
|
def get_file_url(self, obj):
|
|
request = self.context.get('request')
|
|
if request and obj.file:
|
|
return request.build_absolute_uri(obj.file.url)
|
|
return None
|
|
|
|
def validate_file(self, value):
|
|
if not value:
|
|
raise ValueError('File is required')
|
|
|
|
import os
|
|
file_extension = os.path.splitext(value.name)[1][1:].lower()
|
|
|
|
if file_extension not in TrainingFile.ALLOWED_EXTENSIONS:
|
|
raise ValueError(
|
|
f'File type ".{file_extension}" is not allowed. '
|
|
f'Allowed types: {", ".join(TrainingFile.ALLOWED_EXTENSIONS)}'
|
|
)
|
|
|
|
max_size = 50 * 1024 * 1024
|
|
if value.size > max_size:
|
|
raise ValueError(f'File size must not exceed 50MB. Current size: {value.size / 1024 / 1024:.2f}MB')
|
|
|
|
return value
|
|
|
|
def create(self, validated_data):
|
|
role_uuid = validated_data.pop('role_uuid', None)
|
|
file_obj = validated_data.get('file')
|
|
if file_obj:
|
|
validated_data['file_size'] = file_obj.size
|
|
import os
|
|
file_extension = os.path.splitext(file_obj.name)[1][1:].lower()
|
|
validated_data['file_type'] = file_extension
|
|
if not role_uuid:
|
|
raise ValidationError({'role_uuid': 'Role is required'})
|
|
try:
|
|
role = Role.objects.get(uuid = role_uuid)
|
|
except Role.DoesNotExist:
|
|
raise ValidationError({'role_uuid': 'Role not found'})
|
|
validated_data['role'] = role
|
|
return super().create(validated_data) |