HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux spn-python 5.15.0-89-generic #99-Ubuntu SMP Mon Oct 30 20:42:41 UTC 2023 x86_64
User: arjun (1000)
PHP: 8.1.2-1ubuntu2.20
Disabled: NONE
Upload Files
File: //home/arjun/projects/unlimited-leads/Unlimited-Leads-Be/user/serializers.py
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from authorization.models import UnlimitedLeadUser
from payment.models import Transaction
from user.models import EmailOrPhoneVerifyProcessedFile,EmailOrPhoneVerifyFileUpload,UserLeadSearch,ScrappingSearchTask,SrcappingSearchResult

from Admin.models import Lead
from utils.validators import validate_password_strength, validate_phone_number, validate_name


class UserProfileSerializer(serializers.ModelSerializer):
    phone_number = serializers.CharField(validators=[validate_phone_number],required=False)
    profile_image = serializers.FileField(required=False, allow_null=True)  
    class Meta:
        model = UnlimitedLeadUser
        fields = ['profile_image', 'first_name', 'last_name', 'phone_number', 'email','credit_limit']
        read_only_fields = ['email','credit_limit']


class ChangePasswordSerializer(serializers.Serializer):
    old_password = serializers.CharField(write_only=True, required=True)
    new_password = serializers.CharField(write_only=True, required=True, validators=[validate_password_strength])
    confirm_password = serializers.CharField(write_only=True, required=True)

    def validate(self, data):
        if data['new_password'] != data['confirm_password']:
            raise serializers.ValidationError({"password_mismatch": "Passwords do not match."})
        return data


class MyPlanSerializer(serializers.ModelSerializer):
    plan_name = serializers.CharField(source='product.plan_name', read_only=True)
    pricing = serializers.DecimalField(max_digits=10, decimal_places=2, read_only=True)
    is_free = serializers.CharField(source='product.is_free', read_only=True)
    amount = serializers.CharField(source='product.amount', read_only=True)
    currency = serializers.CharField(source='product.currency', read_only=True)
    credit_limit = serializers.IntegerField(source='customer.credit_limit', read_only=True) 

    class Meta:
        model = Transaction
        fields = ['plan_name', 'pricing', 'subscription_start', 'subscription_end', 'is_free', 'is_cancelled', 'amount', 'currency', 'credit_limit']

class uploadEmailOrPhoneSeriaizer(serializers.Serializer):
    data = serializers.CharField(required=False, allow_blank=True)
    files = serializers.ListField(
        child=serializers.FileField(),
        required=False
    )
    data_type = serializers.CharField(required=True, allow_blank=True)
    notification_type = serializers.CharField(required=True, allow_blank=True)

    def validate(self, data):
        # Ensure at least one of email or file is provided
        if not data.get('data') and not data.get('files'):
            raise serializers.ValidationError("Either 'email' or 'file' must be provided.")
        if not data.get('data_type') or not data.get('notification_type'):
            raise serializers.ValidationError("data_type and notification_type is required.")

        return data


class EmailOrPhoneVerifyProcessedFileSerializer(serializers.ModelSerializer):
    class Meta:
        model = EmailOrPhoneVerifyProcessedFile
        fields = ['id', 'file_key', 'user', 'total_deliverable_emails', 'total_valid_phone_numbers', 'processed_at','total_email_count','total_phone_num_count',
                  'type','uploaded_file_name','amount_paid','notification_type']


class EmailOrPhoneVerifyFileUploadSerializer(serializers.ModelSerializer):
    class Meta:
        model = EmailOrPhoneVerifyFileUpload
        fields = [
            'id', 'user', 'payment_status', 'file_key', 'status', 'uploaded_at',
            'processed_at', 'transactionID', 'type', 'email_count', 'phone_num_count', 
            'uploaded_file_name', 'amount_paid','notification_type','payment_mode','credit_used'
        ]


class UserLeadSearchParamSerializer(serializers.Serializer):
    ordering_fields = ["created_on", "first_name", "last_name", "city", "state"]
    LEAD_TYPE_CHOICES = [
        ("Business", "Business"),
        ("Consumer", "Consumer"),
    ]

    search = serializers.CharField(required=False)
    email_present = serializers.BooleanField(required=False)
    phone_present = serializers.BooleanField(required=False)
    lead_type = serializers.ChoiceField(required=False, choices=LEAD_TYPE_CHOICES)
    location = serializers.CharField(required=False)
    city = serializers.CharField(required=False)
    state = serializers.CharField(required=False)
    country = serializers.CharField(required=False)
    sic_code = serializers.IntegerField(required=False)
    ordering = serializers.CharField(required=False, default="-created_on")

    def validate_ordering(self, value):
        if value == "":
            raise ValidationError(f"Provide a valid ordering field")

        ordering = [order.strip() for order in value.split(",")]
        for order in ordering:
            if order.lstrip("-") not in self.ordering_fields:
                raise ValidationError(f"{order} not a valid ordering field")

        return ",".join(ordering)


class UserLeadSavedSearchCreateSerializer(serializers.ModelSerializer):
    lead_search = serializers.UUIDField()

    class Meta:
        model = UserLeadSearch
        fields = ("title", "receive_notification", "lead_search","scrapped_search_id")
        extra_kwargs = {
            "title": {"validators": [validate_name]},
        }

    def validate_title(self, value):
        request = self.context["request"]

        if UserLeadSearch.objects.filter(title=value, user=request.user).exists():
            raise ValidationError("It has already been taken")

        return value

    def validate_lead_search(self, value):
        request = self.context["request"]

        try:
            lead_search = UserLeadSearch.objects.get(
                id=value, is_deleted=False, user=request.user
            )
        except UserLeadSearch.DoesNotExist:
            raise ValidationError("Search not found")

        return lead_search


class UserLeadSavedSearchSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserLeadSearch
        fields = (
            "id",
            "new_records_found",
            "title",
            "receive_notification",
            "search_filter_parameter",
            "scrapped_search_id"
        )

class UserLeadDownloadCreateSerializer(serializers.ModelSerializer):
    id = serializers.UUIDField()
    scrapped_search_id = serializers.IntegerField(required=False, allow_null=True)

    class Meta:
        model = Lead
        fields = (
            "id",
            "scrapped_search_id",
        )

    def validate(self, attrs):
        request = self.context.get("request")

        # Validate the `id` field only
        try:
            attrs["id"] = UserLeadSearch.objects.get(id=attrs.get("id"), user=request.user, is_deleted=False)
        except UserLeadSearch.DoesNotExist:
            raise ValidationError("Search not found")

        return attrs


class UserLeadDownloadSerializer(serializers.ModelSerializer):
    is_email_verified = serializers.SerializerMethodField()
    
    class Meta:
        model = Lead
        fields = (
            "lead_type",
            "business_name",
            "first_name",
            "last_name",
            "street_address",
            "city",
            "state",
            "country",
            "zipcode",
            "phone",
            "phone_type",
            "email",
            "is_email_verified",
            "sic_code",
        )
    
    def get_is_email_verified(self, obj):
        return "Yes" if obj.is_email_verified else "No"
    

class ScrappingSearchTaskSerializer(serializers.ModelSerializer):
    LEAD_TYPE_CHOICES = [
        ("Business", "Business"),
        ("Consumer", "Consumer"),
    ]

    lead_type = serializers.ChoiceField(choices=LEAD_TYPE_CHOICES, required=False)
    search_keyword = serializers.CharField(required=False)
    location = serializers.CharField(required=False)
    notification_type = serializers.CharField(required=True)

    class Meta:
        model = ScrappingSearchTask
        fields = ['search_keyword', 'lead_type', 'location','notification_type']

    def validate(self, data):
        # Ensure at least one of search_keyword, lead_type, or location is provided
        if not any(data.get(field) for field in ['search_keyword', 'lead_type', 'location']):
            raise serializers.ValidationError("At least one of 'search_keyword', 'lead_type', or 'location' must be provided.")
        return data
    
class ScrappingSearchTaskGetSerializer(serializers.ModelSerializer):
    class Meta:
        model = ScrappingSearchTask
        fields = ['id', 'search_keyword', 'lead_type', 'location', 'task_status', 'created_at']

class SrcappingSearchResultSerializer(serializers.ModelSerializer):
    class Meta:
        model = SrcappingSearchResult
        fields = ['id', 'website_name', 'website_link', 'phone_number', 'email']