codeforamerica/intake

View on GitHub
formation/forms.py

Summary

Maintainability
F
5 days
Test Coverage
from formation.combinable_base import CombinableFormSpec, FormSpecSelector
from formation.form_base import Form
from formation.display_form_base import DisplayForm
from formation import fields as F
from formation.validators import (
    gave_preferred_contact_methods, at_least_email_or_phone
)


class CombinableCountyFormSpec(CombinableFormSpec):

    def is_correct_spec(self, *args, **kwargs):
        counties = kwargs.get('counties', [])
        return self.county in counties


class CombinableOrganizationFormSpec(CombinableFormSpec):

    def is_correct_spec(self, *args, **kwargs):
        organizations = kwargs.get('organizations', [])
        return self.organization in organizations


class SupplementaryDisplayForm(CombinableCountyFormSpec):

    def is_correct_spec(self, *args, **kwargs):
        return True

    fields = {
        F.DateReceived,
        F.Counties,
    }


class NotListedFormSpec(CombinableCountyFormSpec):
    """This could be used by Code for America to send applicants
    information on clean slate services in other counties or states.
    """
    county = 'not_listed'
    fields = {
        F.UnlistedCountyNote,
        F.UnlistedCounties,
        F.FirstName,
        F.LastName,
        F.PhoneNumberField,
        F.EmailField,
        F.HowDidYouHear,
        F.AdditionalInformation,
    }
    required_fields = {
        F.UnlistedCounties,
        F.FirstName
    }
    optional_fields = {
        F.HowDidYouHear,
        F.AdditionalInformation
    }
    validators = [
        at_least_email_or_phone
    ]


class SanFranciscoCountyFormSpec(CombinableCountyFormSpec):
    county = 'sanfrancisco'
    fields = {
        F.ContactPreferences,
        F.FirstName,
        F.MiddleName,
        F.LastName,
        F.PhoneNumberField,
        F.EmailField,
        F.AddressField,
        F.DateOfBirthField,
        F.SocialSecurityNumberField,
        F.CitizenshipStatus,
        F.ServingSentence,
        F.OnProbationParole,
        F.WhereProbationParole,
        F.WhenProbationParole,
        F.BeingCharged,
        F.OtherCountyArrestsOrConvictions,
        F.WhenWhereOtherCounties,
        F.FinancialScreeningNote,
        F.CurrentlyEmployed,
        F.MonthlyIncome,
        F.MonthlyExpenses,
        F.HowDidYouHear,
        F.AdditionalInformation,
        F.UnderstandsLimits,
        F.ConsentToRepresent,
    }
    required_fields = {
        F.FirstName,
        F.LastName,
        F.PhoneNumberField,
        F.DateOfBirthField,
        F.CitizenshipStatus,
        F.AddressField,
        F.OnProbationParole,
        F.ServingSentence,
        F.BeingCharged,
        F.OtherCountyArrestsOrConvictions,
        F.CurrentlyEmployed,
        F.MonthlyIncome,
        F.MonthlyExpenses,
        F.UnderstandsLimits,
        F.ConsentToRepresent,
    }
    recommended_fields = {
        F.SocialSecurityNumberField,
    }
    optional_fields = {
        F.HowDidYouHear,
        F.MiddleName,
        F.AdditionalInformation,
    }
    validators = [
        gave_preferred_contact_methods
    ]


class ContraCostaFormSpec(CombinableCountyFormSpec):
    county = 'contracosta'
    fields = {
        F.ContactPreferences,
        F.FirstName,
        F.MiddleName,
        F.LastName,
        F.PhoneNumberField,
        F.EmailField,
        F.AddressField,
        F.DateOfBirthField,
        F.CitizenshipStatus,
        F.ServingSentence,
        F.OnProbationParole,
        F.WhereProbationParole,
        F.WhenProbationParole,
        F.FinancialScreeningNote,
        F.CurrentlyEmployed,
        F.MonthlyIncome,
        F.IncomeSource,
        F.MonthlyExpenses,
        F.HowDidYouHear,
        F.UnderstandsLimits,
        F.ConsentToRepresent,
        F.AdditionalInformation
    }
    required_fields = {
        F.FirstName,
        F.LastName,
        F.AddressField,
        F.CitizenshipStatus,
        F.CurrentlyEmployed,
        F.DateOfBirthField,
        F.MonthlyIncome,
        F.IncomeSource,
        F.MonthlyExpenses,
        F.ServingSentence,
        F.OnProbationParole,
        F.UnderstandsLimits,
        F.ConsentToRepresent,
    }
    optional_fields = {
        F.HowDidYouHear,
        F.AdditionalInformation
    }
    validators = [
        gave_preferred_contact_methods
    ]


class AlamedaCountyFormSpec(CombinableCountyFormSpec):
    county = 'alameda'
    fields = {
        F.ContactPreferences,
        F.FirstName,
        F.MiddleName,
        F.LastName,
        F.PreferredPronouns,
        F.PhoneNumberField,
        F.AlternatePhoneNumberField,
        F.EmailField,
        F.AddressField,
        F.FinancialScreeningNote,
        F.MonthlyIncome,
        F.OnPublicBenefits,
        F.OwnsHome,
        F.HouseholdSize,
        F.ReasonsForApplying,
        F.DateOfBirthField,
        F.CitizenshipStatus,
        F.OnProbationParole,
        F.FinishedHalfProbation,
        F.ReducedProbation,
        F.ServingSentence,
        F.BeingCharged,
        F.HasSuspendedLicense,
        F.OwesCourtFees,
        F.OtherCountyArrestsOrConvictions,
        F.WhenWhereOtherCounties,
        F.HowDidYouHear,
        F.AdditionalInformation,
        F.UnderstandsLimits,
        F.ConsentToRepresent,
        F.HasBeenDeniedHousingOrEmployment,
        F.WhoWhenDeniedHousingOrEmployment,
        F.SeekingEmploymentThatRequiresLiveScan,
        F.IsRegisteredUnderPc290,
    }
    required_fields = {
        F.FirstName,
        F.LastName,
        F.AddressField,
        F.DateOfBirthField,
        F.MonthlyIncome,
        F.OnPublicBenefits,
        F.OwnsHome,
        F.HouseholdSize,
        F.OnProbationParole,
        F.FinishedHalfProbation,
        F.ReducedProbation,
        F.ServingSentence,
        F.BeingCharged,
        F.UnderstandsLimits,
        F.ConsentToRepresent,
    }
    optional_fields = {
        F.AlternatePhoneNumberField,
        F.HowDidYouHear,
        F.AdditionalInformation,
    }
    validators = [
        gave_preferred_contact_methods
    ]


class MontereyCountyFormSpec(CombinableCountyFormSpec):
    county = 'monterey'
    fields = {
        F.ContactPreferences,
        F.FirstName,
        F.MiddleName,
        F.LastName,
        F.PhoneNumberField,
        F.EmailField,
        F.AddressField,
        F.FinancialScreeningNote,
        F.MonthlyIncome,
        F.OnPublicBenefits,
        F.HouseholdSize,
        F.DateOfBirthField,
        F.CitizenshipStatus,
        F.IsVeteran,
        F.IsStudent,
        F.OnProbationParole,
        F.WhereProbationParole,
        F.WhenProbationParole,
        F.ServingSentence,
        F.BeingCharged,
        F.OtherCountyArrestsOrConvictions,
        F.WhenWhereOtherCounties,
        F.HowDidYouHear,
        F.AdditionalInformation,
        F.UnderstandsLimits,
        F.ConsentToRepresent,
    }
    required_fields = {
        F.FirstName,
        F.LastName,
        F.AddressField,
        F.DateOfBirthField,
        F.MonthlyIncome,
        F.OnPublicBenefits,
        F.HouseholdSize,
        F.OnProbationParole,
        F.ServingSentence,
        F.BeingCharged,
        F.UnderstandsLimits,
        F.ConsentToRepresent,
    }
    optional_fields = {
        F.HowDidYouHear,
        F.AdditionalInformation,
    }
    validators = [
        gave_preferred_contact_methods
    ]


class SolanoCountyFormSpec(CombinableCountyFormSpec):
    county = 'solano'
    fields = {
        F.ContactPreferences,
        F.FirstName,
        F.MiddleName,
        F.LastName,
        F.PhoneNumberField,
        F.AlternatePhoneNumberField,
        F.EmailField,
        F.AddressField,
        F.DateOfBirthField,
        F.CitizenshipStatus,
        F.OnProbationParole,
        F.WhereProbationParole,
        F.WhenProbationParole,
        F.OwesCourtFees,
        F.ServingSentence,
        F.BeingCharged,
        F.OtherCountyArrestsOrConvictions,
        F.WhenWhereOtherCounties,
        F.HowDidYouHear,
        F.AdditionalInformation,
        F.UnderstandsLimits,
        F.ConsentToRepresent,
    }
    required_fields = {
        F.FirstName,
        F.LastName,
        F.DateOfBirthField,
        F.OnProbationParole,
        F.OwesCourtFees,
        F.ServingSentence,
        F.BeingCharged,
        F.UnderstandsLimits,
        F.ConsentToRepresent,
    }
    optional_fields = {
        F.MiddleName,
        F.AlternatePhoneNumberField,
        F.HowDidYouHear,
        F.AdditionalInformation
    }
    validators = [
        gave_preferred_contact_methods,
        at_least_email_or_phone
    ]


class SanDiegoCountyFormSpec(SolanoCountyFormSpec):
    county = 'san_diego'
    fields = (SolanoCountyFormSpec.fields | {
        F.CaseNumber,
        F.IdentityConfirmation,
        F.SocialSecurityNumberField,
        F.DriverLicenseOrIDNumber
    }) - {
        F.CitizenshipStatus,
    }
    required_fields = SolanoCountyFormSpec.required_fields | {
        F.IdentityConfirmation
    }
    optional_fields = SolanoCountyFormSpec.optional_fields | {
        F.CaseNumber
    }
    recommended_fields = {
        F.SocialSecurityNumberField,
        F.DriverLicenseOrIDNumber
    }
    validators = [
        gave_preferred_contact_methods,
        at_least_email_or_phone
    ]


class SanJoaquinCountyFormSpec(SolanoCountyFormSpec):
    county = 'san_joaquin'
    validators = [
        gave_preferred_contact_methods
    ]


class FresnoCountyFormSpec(SolanoCountyFormSpec):
    county = 'fresno'
    fields = {
        F.ContactPreferences,
        F.FirstName,
        F.MiddleName,
        F.LastName,
        F.PhoneNumberField,
        F.AlternatePhoneNumberField,
        F.EmailField,
        F.AddressField,
        F.DateOfBirthField,
        F.CitizenshipStatus,
        F.OnProbationParole,
        F.WhereProbationParole,
        F.WhenProbationParole,
        F.ServingSentence,
        F.BeingCharged,
        F.HowDidYouHear,
        F.AdditionalInformation,
        F.UnderstandsLimits,
        F.ConsentSelfRepresent,
        F.Aliases,
        F.CaseNumber,
        F.ReasonsForApplying,
        F.FinancialScreeningNote,
        F.MonthlyIncome,
        F.HowManyDependents,
        F.LastFourOfSocial,
        F.DriverLicenseOrIDNumber,
        F.CurrentlyEmployed,
        F.IncomeSource,
        F.HowMuchSavings,
        F.OnPublicBenefits,
        F.MonthlyExpenses,
        F.OwnsHome,
        F.IsMarried
    }
    optional_fields = {
        F.MiddleName,
        F.AlternatePhoneNumberField,
        F.HowDidYouHear,
        F.AdditionalInformation,
        F.Aliases
    }
    required_fields = {
        F.FirstName,
        F.LastName,
        F.DateOfBirthField,
        F.OnProbationParole,
        F.ServingSentence,
        F.BeingCharged,
        F.UnderstandsLimits,
        F.ConsentSelfRepresent,
        F.MonthlyIncome,
        F.HowManyDependents,
        F.CurrentlyEmployed,
        F.IncomeSource,
        F.HowMuchSavings,
        F.OnPublicBenefits,
        F.MonthlyExpenses,
        F.OwnsHome,
        F.IsMarried
    }
    validators = [
        gave_preferred_contact_methods
    ]


class SantaClaraCountyFormSpec(SolanoCountyFormSpec):
    county = 'santa_clara'
    fields = (SolanoCountyFormSpec.fields | {
        F.FinancialScreeningNote,
        F.CurrentlyEmployed,
        F.MonthlyIncome,
        F.IncomeSource,
        F.MonthlyExpenses,
        F.OnPublicBenefits,
        F.HouseholdSize,
        F.IsMarried,
        F.HasChildren,
        F.IsVeteran,
        F.ReducedProbation,
        F.ReasonsForApplying,
        F.PFNNumber,
        F.PreferredPronouns,
    }) - {
        F.CitizenshipStatus,
    }
    required_fields = (SolanoCountyFormSpec.required_fields | {
        F.CurrentlyEmployed,
        F.MonthlyIncome,
        F.IncomeSource,
        F.MonthlyExpenses,
        F.OnPublicBenefits,
        F.HouseholdSize,
    }) - {F.PhoneNumberField}
    validators = [
        gave_preferred_contact_methods
    ]


class SantaCruzCountyFormSpec(SolanoCountyFormSpec):
    county = 'santa_cruz'
    fields = (SolanoCountyFormSpec.fields | {
        F.FinancialScreeningNote,
        F.MonthlyIncome,
        F.ReasonsForApplying
    }) - {
        F.OwesCourtFees,
        F.OtherCountyArrestsOrConvictions,
        F.WhenWhereOtherCounties
    }
    required_fields = SolanoCountyFormSpec.required_fields - {
        F.OwesCourtFees,
    }


class SonomaCountyFormSpec(SolanoCountyFormSpec):
    county = 'sonoma'
    validators = [
        gave_preferred_contact_methods
    ]


class TulareCountyFormSpec(SolanoCountyFormSpec):
    county = 'tulare'
    validators = [
        gave_preferred_contact_methods
    ]


class VenturaCountyFormSpec(CombinableCountyFormSpec):
    county = 'ventura'
    fields = {
        F.ContactPreferences,
        F.FirstName,
        F.MiddleName,
        F.LastName,
        F.PhoneNumberField,
        F.AlternatePhoneNumberField,
        F.EmailField,
        F.AddressField,
        F.IsCaliforniaResident,
        F.HowLongCaliforniaResident,
        F.OwnsHome,
        F.FinancialScreeningNote,
        F.CurrentlyEmployed,
        F.MonthlyIncome,
        F.IncomeSource,
        F.OnPublicBenefits,
        F.MonthlyExpenses,
        F.OwnsHome,
        F.HowManyDependents,
        F.IsVeteran,
        F.DateOfBirthField,
        F.OnProbationParole,
        F.WhereProbationParole,
        F.OwesCourtFees,
        F.ServingSentence,
        F.BeingCharged,
        F.OtherCountyArrestsOrConvictions,
        F.WhenWhereOtherCounties,
        F.CaseNumber,
        F.HowDidYouHear,
        F.AdditionalInformation,
        F.UnderstandsLimits,
        F.ConsentToRepresent,
    }
    required_fields = {
        F.CurrentlyEmployed,
        F.MonthlyIncome,
        F.IncomeSource,
        F.MonthlyExpenses,
        F.OwnsHome,
        F.HowManyDependents,
        F.OnPublicBenefits,
        F.HouseholdSize,
        F.DateOfBirthField,
        F.OnProbationParole,
        F.OwesCourtFees,
        F.ServingSentence,
        F.BeingCharged,
        F.UnderstandsLimits,
        F.ConsentToRepresent,
    }
    validators = [
        gave_preferred_contact_methods,
        at_least_email_or_phone
    ]


class SantaBarbaraCountyFormSpec(VenturaCountyFormSpec):
    county = 'santa_barbara'
    fields = (VenturaCountyFormSpec.fields | {
        F.Aliases,
        F.ReasonsForApplying,
        F.IsMarried,
        F.HowMuchSavings,
        F.DriverLicenseOrIDNumber,
        F.WhenProbationParole}) - {
        F.IsCaliforniaResident,
        F.HowLongCaliforniaResident,
        F.IsVeteran,
    }
    required_fields = (
        VenturaCountyFormSpec.required_fields | {F.HowMuchSavings})


class YoloCountyFormSpec(SonomaCountyFormSpec):
    county = 'yolo'
    fields = (SonomaCountyFormSpec.fields | {
        F.Aliases,
        F.CaseNumber,
        F.CurrentlyEmployed,
        F.MonthlyIncome,
        F.IncomeSource,
        F.HowMuchSavings,
        F.OnPublicBenefits,
        F.MonthlyExpenses,
        F.OwnsHome,
        F.HasChildren,
        F.HowManyDependents,
        F.IsMarried,
        F.UnderstandsMaybeFee
    }) - {
        F.AlternatePhoneNumberField,
        F.OwesCourtFees,
        F.ServingSentence,
        F.CitizenshipStatus
    }
    required_fields = (SonomaCountyFormSpec.required_fields | {
        F.CurrentlyEmployed,
        F.MonthlyIncome,
        F.IncomeSource,
        F.HowMuchSavings,
        F.MonthlyExpenses,
        F.OwnsHome,
        F.HowManyDependents,
        F.IsMarried,
        F.ReasonsForApplying,
        F.UnderstandsMaybeFee
        }) - {
        F.OwesCourtFees,
    }


class StanislausCountyFormSpec(FresnoCountyFormSpec):
    county = 'stanislaus'
    fields = (FresnoCountyFormSpec.fields | {
        F.BeenToPrison,
        F.OtherCountyArrestsOrConvictions,
        F.WhenWhereOtherCounties,
        F.OwesCourtFees,
    }) - {
        F.DriverLicenseOrIDNumber,
        F.LastFourOfSocial,
        F.CaseNumber,
        F.CitizenshipStatus,
        F.MonthlyIncome,
        F.IncomeSource,
        F.HowMuchSavings,
        F.HowManyDependents
    }
    required_fields = FresnoCountyFormSpec.required_fields


class MarinCountyFormSpec(CombinableCountyFormSpec):
    county = 'marin'
    fields = {
        F.ContactPreferences,
        F.FirstName,
        F.MiddleName,
        F.LastName,
        F.Aliases,
        F.PhoneNumberField,
        F.AlternatePhoneNumberField,
        F.EmailField,
        F.AddressField,
        F.DateOfBirthField,
        F.DriverLicenseOrIDNumber,
        F.SocialSecurityNumberField,
        F.CaseNumber,
        F.BeingCharged,
        F.ServingSentence,
        F.OnProbationParole,
        F.WhereProbationParole,
        F.WhenProbationParole,
        F.OtherCountyArrestsOrConvictions,
        F.WhenWhereOtherCounties,
        F.OwesCourtFees,
        F.CurrentlyEmployed,
        F.MonthlyIncome,
        F.IncomeSource,
        F.HowMuchSavings,
        F.OtherIncome,
        F.OnPublicBenefits,
        F.MonthlyExpenses,
        F.OwnsHome,
        F.HasChildren,
        F.HowManyDependents,
        F.IsMarried,
        F.ReasonsForApplying,
        F.HowDidYouHear,
        F.AdditionalInformation,
        F.UnderstandsLimits,
        F.ConsentToRepresent
    }
    required_fields = {
        F.ContactPreferences,
        F.FirstName,
        F.LastName,
        F.PhoneNumberField,
        F.AddressField,
        F.DateOfBirthField,
        F.BeingCharged,
        F.ServingSentence,
        F.OnProbationParole,
        F.OwesCourtFees,
        F.CurrentlyEmployed,
        F.MonthlyIncome,
        F.IncomeSource,
        F.HowMuchSavings,
        F.OnPublicBenefits,
        F.MonthlyExpenses,
        F.OwnsHome,
        F.HasChildren,
        F.HowManyDependents,
        F.IsMarried,
        F.UnderstandsLimits,
        F.ConsentToRepresent
    }
    validators = [
        gave_preferred_contact_methods
    ]


class SiskiyouCountyFormSpec(AlamedaCountyFormSpec):
    county = 'siskiyou'
    fields = (AlamedaCountyFormSpec.fields | {
        F.LastFourOfSocial,
        F.DriverLicenseOrIDNumber,
        F.IsCaliforniaResident,
        F.HowLongCaliforniaResident,
        F.IsVeteran,
        F.CaseNumber,
        F.CurrentlyEmployed
    })

    required_fields = AlamedaCountyFormSpec.required_fields
    optional_fields = AlamedaCountyFormSpec.optional_fields

    validators = [
        gave_preferred_contact_methods
    ]


class DeclarationLetterFormSpec(CombinableFormSpec):
    fields = {
        F.DeclarationLetterNote,
        F.DeclarationLetterIntro,
        F.DeclarationLetterLifeChanges,
        F.DeclarationLetterActivities,
        F.DeclarationLetterGoals,
        F.DeclarationLetterWhy,
    }
    required_fields = {
        F.DeclarationLetterIntro,
        F.DeclarationLetterLifeChanges,
        F.DeclarationLetterActivities,
        F.DeclarationLetterGoals,
        F.DeclarationLetterWhy,
    }


class DeclarationLetterDisplay(DisplayForm):
    display_template_name = "forms/declaration_letter_display.jinja"
    fields = [
        F.DateReceived,
        F.DeclarationLetterIntro,
        F.DeclarationLetterLifeChanges,
        F.DeclarationLetterActivities,
        F.DeclarationLetterGoals,
        F.DeclarationLetterWhy,
        F.FirstName,
        F.MiddleName,
        F.LastName,
    ]


class ApplicationReviewForm(Form):
    fields = [F.ApplicationReviewActions]
    required_fields = [F.ApplicationReviewActions]


class DeclarationLetterReviewForm(Form):
    fields = [F.DeclarationLetterReviewActions]
    required_fields = [F.DeclarationLetterReviewActions]


class SelectCountyForm(Form):
    fields = [F.Counties]
    required_fields = [F.Counties]


INPUT_FORM_SPECS = [
    NotListedFormSpec(),
    SanFranciscoCountyFormSpec(),
    ContraCostaFormSpec(),
    AlamedaCountyFormSpec(),
    MontereyCountyFormSpec(),
    SolanoCountyFormSpec(),
    SanDiegoCountyFormSpec(),
    SanJoaquinCountyFormSpec(),
    SantaClaraCountyFormSpec(),
    SantaCruzCountyFormSpec(),
    FresnoCountyFormSpec(),
    SonomaCountyFormSpec(),
    TulareCountyFormSpec(),
    VenturaCountyFormSpec(),
    SantaBarbaraCountyFormSpec(),
    YoloCountyFormSpec(),
    StanislausCountyFormSpec(),
    MarinCountyFormSpec(),
    SiskiyouCountyFormSpec()
]

DISPLAY_FORM_SPECS = INPUT_FORM_SPECS + [
    SupplementaryDisplayForm(),
]

display_form_selector = FormSpecSelector(DISPLAY_FORM_SPECS, DisplayForm)
county_display_form_selector = FormSpecSelector(INPUT_FORM_SPECS, DisplayForm)
county_form_selector = FormSpecSelector(INPUT_FORM_SPECS, Form)


def print_all_fields_for_county(county_slug):
    form_class = county_form_selector.get_combined_form_class(
        counties=[county_slug])
    for field in form_class.fields:
        output = '\t{}'.format(field.context_key)
        if field in form_class.required_fields:
            output += ' (R)'
        print(output)


def print_all_forms():
    from user_accounts.models import Organization
    for org in Organization.objects.all():
        print('\n{}'.format(org.name))
        print_all_fields_for_county(org.county.slug)