You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
195 lines
6.7 KiB
Python
195 lines
6.7 KiB
Python
from rest_framework import serializers
|
|
from django.contrib.auth.password_validation import validate_password
|
|
from .models import ComPortReading, User
|
|
from vehicles.models import Vehicle, VehicleExtra
|
|
from nomenclatures.models import Nomenclature, NomenclatureField
|
|
|
|
|
|
class UserSerializer(serializers.ModelSerializer):
|
|
password = serializers.CharField(write_only=True, required=False)
|
|
|
|
class Meta:
|
|
model = User
|
|
fields = ['id', 'username', 'email', 'first_name', 'last_name',
|
|
'role', 'is_admin', 'is_active', 'date_joined', 'password']
|
|
read_only_fields = ['id', 'date_joined']
|
|
extra_kwargs = {
|
|
'password': {'write_only': True}
|
|
}
|
|
|
|
def create(self, validated_data):
|
|
password = validated_data.pop('password', None)
|
|
user = User(**validated_data)
|
|
if password:
|
|
user.set_password(password)
|
|
user.save()
|
|
return user
|
|
|
|
def update(self, instance, validated_data):
|
|
password = validated_data.pop('password', None)
|
|
for attr, value in validated_data.items():
|
|
setattr(instance, attr, value)
|
|
if password:
|
|
instance.set_password(password)
|
|
instance.save()
|
|
return instance
|
|
|
|
|
|
class UserDetailSerializer(serializers.ModelSerializer):
|
|
"""Serializer for current user details (excludes password)"""
|
|
class Meta:
|
|
model = User
|
|
fields = ['id', 'username', 'email', 'first_name', 'last_name',
|
|
'role', 'is_admin', 'is_active', 'date_joined']
|
|
read_only_fields = ['id', 'date_joined']
|
|
|
|
|
|
class ChangePasswordSerializer(serializers.Serializer):
|
|
"""Serializer for password change endpoint"""
|
|
old_password = serializers.CharField(required=True, write_only=True)
|
|
new_password = serializers.CharField(required=True, write_only=True)
|
|
|
|
def validate_old_password(self, value):
|
|
user = self.context['request'].user
|
|
if not user.check_password(value):
|
|
raise serializers.ValidationError("Old password is incorrect")
|
|
return value
|
|
|
|
def validate_new_password(self, value):
|
|
# Use Django's password validators
|
|
validate_password(value, self.context['request'].user)
|
|
return value
|
|
|
|
def save(self, **kwargs):
|
|
user = self.context['request'].user
|
|
user.set_password(self.validated_data['new_password'])
|
|
user.save()
|
|
return user
|
|
|
|
|
|
class ComPortReadingSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = ComPortReading
|
|
fields = ['id', 'port', 'data', 'timestamp', 'source_ip']
|
|
read_only_fields = ['id', 'timestamp']
|
|
|
|
|
|
class VehicleExtraSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = VehicleExtra
|
|
fields = ['id', 'data']
|
|
read_only_fields = ['id']
|
|
|
|
|
|
class VehicleSerializer(serializers.ModelSerializer):
|
|
extra = VehicleExtraSerializer(required=False, allow_null=True)
|
|
|
|
class Meta:
|
|
model = Vehicle
|
|
fields = ['id', 'vehicle_number', 'extra']
|
|
read_only_fields = ['id']
|
|
|
|
def create(self, validated_data):
|
|
extra_data = validated_data.pop('extra', None)
|
|
vehicle = Vehicle.objects.create(**validated_data)
|
|
|
|
if extra_data:
|
|
VehicleExtra.objects.create(vehicle=vehicle, **extra_data)
|
|
|
|
return vehicle
|
|
|
|
def update(self, instance, validated_data):
|
|
extra_data = validated_data.pop('extra', None)
|
|
|
|
# Update Vehicle fields
|
|
instance.vehicle_number = validated_data.get('vehicle_number', instance.vehicle_number)
|
|
instance.save()
|
|
|
|
# Handle VehicleExtra update/creation
|
|
if extra_data is not None:
|
|
if hasattr(instance, 'extra'):
|
|
# Update existing VehicleExtra
|
|
for attr, value in extra_data.items():
|
|
setattr(instance.extra, attr, value)
|
|
instance.extra.save()
|
|
else:
|
|
# Create new VehicleExtra
|
|
VehicleExtra.objects.create(vehicle=instance, **extra_data)
|
|
|
|
return instance
|
|
|
|
def validate_vehicle_number(self, value):
|
|
if not value or not value.strip():
|
|
raise serializers.ValidationError("Vehicle number cannot be empty")
|
|
return value.strip()
|
|
|
|
|
|
class NomenclatureFieldSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = NomenclatureField
|
|
fields = ['id', 'key', 'field_type']
|
|
read_only_fields = ['id']
|
|
|
|
def validate_key(self, value):
|
|
if not value or not value.strip():
|
|
raise serializers.ValidationError("Field key cannot be empty")
|
|
return value.strip()
|
|
|
|
def validate_field_type(self, value):
|
|
valid_types = [choice[0] for choice in NomenclatureField.FIELD_TYPES]
|
|
if value not in valid_types:
|
|
raise serializers.ValidationError(
|
|
f"Invalid field type. Must be one of: {', '.join(valid_types)}"
|
|
)
|
|
return value
|
|
|
|
|
|
class NomenclatureSerializer(serializers.ModelSerializer):
|
|
fields = NomenclatureFieldSerializer(many=True, required=False, source='nomenclaturefield_set')
|
|
|
|
class Meta:
|
|
model = Nomenclature
|
|
fields = ['id', 'code', 'name', 'applies_to', 'fields']
|
|
read_only_fields = ['id']
|
|
|
|
def create(self, validated_data):
|
|
fields_data = validated_data.pop('nomenclaturefield_set', [])
|
|
nomenclature = Nomenclature.objects.create(**validated_data)
|
|
|
|
for field_data in fields_data:
|
|
NomenclatureField.objects.create(nomenclature=nomenclature, **field_data)
|
|
|
|
return nomenclature
|
|
|
|
def update(self, instance, validated_data):
|
|
fields_data = validated_data.pop('nomenclaturefield_set', None)
|
|
|
|
# Update Nomenclature fields
|
|
instance.code = validated_data.get('code', instance.code)
|
|
instance.name = validated_data.get('name', instance.name)
|
|
instance.applies_to = validated_data.get('applies_to', instance.applies_to)
|
|
instance.save()
|
|
|
|
# Handle fields update - replace all fields
|
|
if fields_data is not None:
|
|
# Delete existing fields
|
|
instance.nomenclaturefield_set.all().delete()
|
|
# Create new fields
|
|
for field_data in fields_data:
|
|
NomenclatureField.objects.create(nomenclature=instance, **field_data)
|
|
|
|
return instance
|
|
|
|
def validate_code(self, value):
|
|
if not value or not value.strip():
|
|
raise serializers.ValidationError("Code cannot be empty")
|
|
return value.strip()
|
|
|
|
def validate_applies_to(self, value):
|
|
valid_choices = ['vehicle', 'container']
|
|
if value not in valid_choices:
|
|
raise serializers.ValidationError(
|
|
f"Invalid applies_to value. Must be one of: {', '.join(valid_choices)}"
|
|
)
|
|
return value
|