File size: 4,413 Bytes
061507f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
"""
API-specific validation for ChurnRequest
"""
from typing import List, Tuple
from src.serving.schema import ChurnRequest


def validate_churn_request(request: ChurnRequest) -> Tuple[bool, List[str]]:
    """
    Validate a ChurnRequest object against business rules.
    
    Returns:
        Tuple[bool, List[str]]: (is_valid, list_of_errors)
    """
    errors = []
    
    allowed_gender = ["Male", "Female"]
    if request.gender not in allowed_gender:
        errors.append(f"Invalid gender: '{request.gender}'. Must be one of: {allowed_gender}")
    
    if request.SeniorCitizen not in [0, 1]:
        errors.append(f"Invalid SeniorCitizen: {request.SeniorCitizen}. Must be 0 or 1")
    
    if not (0 <= request.tenure <= 72):
        errors.append(f"Invalid tenure: {request.tenure}. Must be between 0 and 72")
    
    binary_fields = {
        "Partner": request.Partner,
        "Dependents": request.Dependents,
        "PhoneService": request.PhoneService,
        "PaperlessBilling": request.PaperlessBilling
    }
    
    for field_name, field_value in binary_fields.items():
        if field_value not in ["Yes", "No"]:
            errors.append(f"Invalid {field_name}: '{field_value}'. Must be 'Yes' or 'No'")
    
    optional_binary_fields = {
        "MultipleLines": request.MultipleLines,
        "OnlineSecurity": request.OnlineSecurity,
        "OnlineBackup": request.OnlineBackup,
        "DeviceProtection": request.DeviceProtection,
        "TechSupport": request.TechSupport,
        "StreamingTV": request.StreamingTV,
        "StreamingMovies": request.StreamingMovies
    }
    
    for field_name, field_value in optional_binary_fields.items():
        if field_value is not None and field_value not in ["Yes", "No", "No phone service", "No internet service"]:
            errors.append(
                f"Invalid {field_name}: '{field_value}'. "
                f"Must be 'Yes', 'No', 'No phone service', or 'No internet service'"
            )
    
    allowed_internet = ["DSL", "Fiber optic", "No"]
    if request.InternetService not in allowed_internet:
        errors.append(
            f"Invalid InternetService: '{request.InternetService}'. "
            f"Must be one of: {allowed_internet}"
        )
    
    allowed_contract = ["Month-to-month", "One year", "Two year"]
    if request.Contract not in allowed_contract:
        errors.append(
            f"Invalid Contract: '{request.Contract}'. "
            f"Must be one of: {allowed_contract}"
        )
    
    allowed_payment = [
        "Electronic check",
        "Mailed check",
        "Bank transfer (automatic)",
        "Credit card (automatic)"
    ]
    if request.PaymentMethod not in allowed_payment:
        errors.append(
            f"Invalid PaymentMethod: '{request.PaymentMethod}'. "
            f"Must be one of: {allowed_payment}"
        )
    
    if request.MonthlyCharges < 0:
        errors.append(f"MonthlyCharges cannot be negative: {request.MonthlyCharges}")
    
    if request.TotalCharges < 0:
        errors.append(f"TotalCharges cannot be negative: {request.TotalCharges}")
    
    if request.TotalCharges < request.MonthlyCharges:
        errors.append(
            f"TotalCharges ({request.TotalCharges}) must be >= MonthlyCharges ({request.MonthlyCharges})"
        )
    
    if request.InternetService == "No":
        internet_dependent_fields = {
            "OnlineSecurity": request.OnlineSecurity,
            "OnlineBackup": request.OnlineBackup,
            "DeviceProtection": request.DeviceProtection,
            "TechSupport": request.TechSupport,
            "StreamingTV": request.StreamingTV,
            "StreamingMovies": request.StreamingMovies
        }
        
        for field_name, field_value in internet_dependent_fields.items():
            if field_value not in [None, "No internet service"]:
                errors.append(
                    f"Cannot have InternetService='No' and {field_name}='{field_value}'. "
                    f"{field_name} must be None or 'No internet service'"
                )
    
    if request.PhoneService == "No" and request.MultipleLines not in [None, "No phone service"]:
        errors.append(
            f"Cannot have PhoneService='No' and MultipleLines='{request.MultipleLines}'. "
            f"MultipleLines must be None or 'No phone service'"
        )
    
    return len(errors) == 0, errors