• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

gcivil-nyu-org / INET-Wednesday-Spring2024-Team-2 / 610

24 Apr 2024 12:36AM UTC coverage: 88.975% (+2.2%) from 86.788%
610

cron

travis-pro

web-flow
Merge pull request #163 from gcivil-nyu-org/develop

Merging into master from DEV

199 of 235 new or added lines in 7 files covered. (84.68%)

58 existing lines in 3 files now uncovered.

1033 of 1161 relevant lines covered (88.98%)

0.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.32
/users/forms.py
1
import re
1✔
2
from datetime import date, timedelta
1✔
3
from crispy_forms.helper import FormHelper
1✔
4
from crispy_forms.layout import Layout, Submit, Row, Column, Field, HTML
1✔
5
from django import forms
1✔
6
from django.contrib.auth.forms import UserCreationForm
1✔
7
from django.contrib.auth import get_user_model
1✔
8
from .models import CustomUser, Rental_Listings
1✔
9
from django.contrib.auth.forms import AuthenticationForm
1✔
10
from django.core.exceptions import ValidationError
1✔
11
from django.contrib.auth.forms import UserChangeForm
1✔
12
from django.utils import timezone
1✔
13

14
User = get_user_model()
1✔
15

16

17
class UserSignUpForm(UserCreationForm):
1✔
18
    full_name = forms.CharField(max_length=255, required=True)
1✔
19
    phone_number = forms.CharField(max_length=15, required=True)
1✔
20
    city = forms.CharField(max_length=100, required=True)
1✔
21
    email = forms.EmailField(required=True)
1✔
22

23
    class Meta:
1✔
24
        model = User
1✔
25
        fields = (
1✔
26
            "email",
27
            "full_name",
28
            "phone_number",
29
            "city",
30
            "password1",
31
            "password2",
32
        )
33

34
    def clean_email(self):
1✔
35
        email = self.cleaned_data["email"]
1✔
36
        if not email.endswith("@nyu.edu"):
1✔
37
            raise ValidationError("Oops! Only NYU email addresses are supported.")
1✔
38
        if User.objects.filter(username=self.cleaned_data["email"]).exists():
1✔
39
            raise ValidationError("Email already exists. Please use a different one.")
×
40
        return email
1✔
41
    def clean_phone_number(self):
42
        phone_number = self.cleaned_data.get('phone_number')
1✔
43
        if len(phone_number) != 10 or not phone_number.isdigit():
1✔
44
            raise ValidationError("Phone number must be 10 digits.")
1✔
NEW
45
        return phone_number
×
46

1✔
47
class LandlordSignupForm(UserCreationForm):
48
    pdf_file = forms.FileField(required=False, label="OwnerShip Document")  #
49

1✔
50
    class Meta:
1✔
51
        model = CustomUser
52
        fields = (
1✔
53
            "username",
1✔
54
            "email",
1✔
55
            "full_name",
56
            "phone_number",
57
            "city",
58
            "password1",
59
            "password2",
60
            # "user_type",
61
            "pdf_file",
62
        )
63

64
    # def _init_(self, *args, **kwargs):
65
    #     super(LandlordSignupForm, self)._init_(*args, **kwargs)
66
    #     self.fields["user_type"].initial = CustomUser.LANDLORD
67
    #     self.fields[
68
    #         "user_type"
69
    #     ].widget = forms.HiddenInput()  # Hide the user_type field
70

71
    def _init_(self, *args, **kwargs):
72
        super(LandlordSignupForm, self)._init_(*args, **kwargs)
73
        # No need to set user_type initial value here, as it will be set in save.
1✔
UNCOV
74

×
75
    def save(self, commit=True):
76
        user = super(LandlordSignupForm, self).save(commit=False)
77
        user.user_type = CustomUser.LANDLORD  # Set user_type to LANDLORD
1✔
78

1✔
79
        if commit:
1✔
80
            user.save()
81
            self.save_m2m()
1✔
82

1✔
83
        return user
1✔
84

85

1✔
86
class RentalListingForm(forms.ModelForm):
87
    ROOMS_CHOICES = [(i, str(i)) for i in range(1, 11)]
88
    BATHS_CHOICES = [(i * 0.5, str(i * 0.5)) for i in range(2, 21)]
1✔
89
   
1✔
90

1✔
91
    UNIT_TYPE_CHOICES = [("Apartment", "Apartment"), ("House", "House"),("Multi-family", "Multi-family"), 
92
                         ("Condo","Condo"),("Rental Unit","Rental Unit"),("Building","Building"),
1✔
93
                           ("Townhouse","Townhouse"),("Co-op","Co-op")]
94
    NEIGHBORHOOD_CHOICES = [
95
        ("Manhattan", "Manhattan"),
96
        ("Brooklyn", "Brooklyn"),
97
        ("Upper East Side", "Upper East Side"),
98
        ("Upper West Side", "Upper West Side"),
99
        ("Midtown", "Midtown"),
100
        ("Harlem", "Harlem"),
101
        ("Chelsea", "Chelsea"),
102
        ("Greenwich Village", "Greenwich Village"),
1✔
103
        ("Soho", "Soho"),
104
        ("East Village", "East Village"),
105
        ("Lower East Side", "Lower East Side"),
106
        ("Williamsburg", "Williamsburg"),
107
        ("Bushwick", "Bushwick"),
108
        ("Park Slope", "Park Slope"),
109
        ("Brooklyn Heights", "Brooklyn Heights"),
110
        ("Red Hook", "Red Hook"),
111
        ("Astoria", "Astoria"),
112
        ("Long Island City", "Long Island City"),
113
        ("Flushing", "Flushing"),
114
        ("Jamaica", "Jamaica"),
115
        ("Forest Hills", "Forest Hills"),
116
        ("Riverdale", "Riverdale"),
117
        ("Fordham", "Fordham"),
118
        ("Concourse", "Concourse"),
119
        ("Throgs Neck", "Throgs Neck"),
120
        ("St. George", "St. George"),
121
        ("Tottenville", "Tottenville"),
122
        ("Stapleton", "Stapleton"),
123
    ]
124

125
    BOROUGH_CHOICES = [
126
        ("Manhattan", "Manhattan"),
127
        ("Brooklyn", "Brooklyn"),
128
        ("Queens", "Queens"),
129
        ("Bronx", "Bronx"),
130
        ("Staten Island", "Staten Island"),
131
    ]
132
    address = forms.CharField(
133
        widget=forms.TextInput(attrs={'id': 'id_address', 'placeholder': 'Enter your address', 'autocomplete': 'off'})
1✔
134
    )
135
    rooms = forms.ChoiceField(choices=ROOMS_CHOICES)
136
    beds = forms.ChoiceField(choices=ROOMS_CHOICES)
137
    baths = forms.ChoiceField(choices=BATHS_CHOICES)
138
    unit_type = forms.ChoiceField(choices=UNIT_TYPE_CHOICES)
139
    neighborhood = forms.CharField(required=True,widget=forms.TextInput(attrs={'id': 'id_neighborhood'}))
140
    borough = forms.ChoiceField(choices=BOROUGH_CHOICES, widget=forms.Select(attrs={'id': 'id_borough'}))
1✔
141
    photo = forms.ImageField(required=False, label= 'Images',widget=forms.ClearableFileInput(attrs={'multiple': True}))
142
    latitude = forms.FloatField( widget=forms.HiddenInput(attrs={'readonly': 'readonly'}))
143
    longitude = forms.FloatField(widget=forms.HiddenInput(attrs={'readonly': 'readonly'}))
144
    zipcode = forms.CharField(required=True, label= 'Zip', widget=forms.TextInput(attrs={'id': 'id_zipcode' ,'placeholder': ''}))
145
    sq_ft = forms.IntegerField(required=True, label= 'Area(sqft)')
146
    Availability_Date = forms.DateField(required=True, widget=forms.DateInput(attrs={"type": "date"}))
147
    apt_no = forms.CharField(required=False, label= 'Apt#', widget=forms.TextInput(attrs={'id': 'id_aptNo' ,'placeholder': ''}) )
148

149
    def __init__(self, *args, **kwargs):
1✔
150
        super(RentalListingForm, self).__init__(*args, **kwargs)
1✔
151
        self.helper = FormHelper(self)
1✔
152
        self.helper.form_method = 'post'
1✔
153
        self.helper.form_enctype = 'multipart/form-data'
1✔
154
        self.helper.layout = Layout(
155
            Row(
156
                Column('address', css_class='form-group col-md-8 mb-0'),
1✔
157
                Column('zipcode', css_class='form-group col-md-2 mb-0'),
158
                Column('apt_no', css_class='form-group col-md-2 mb-0'),
159
                css_class='form-row',
1✔
160
            ),
161
             Row(
162
                Column('price', css_class='form-group col-md-4 mb-0'),
163
                Column('sq_ft', css_class='form-group col-md-4 mb-0'),
164
                Column('broker_fee', css_class='form-group col-md-4 mb-0'),
1✔
165
                css_class='form-row',
166
            ),
167
            Row(
1✔
168
                Column('rooms', css_class='form-group col-md-4 mb-0'),
169
                Column('beds', css_class='form-group col-md-4 mb-0'),
170
                Column('baths', css_class='form-group col-md-4 mb-0'),
1✔
171
                css_class='form-row',
172
            ),
173

174
            Row(
175
                Column('neighborhood', css_class='form-group col-md-4 mb-0'),
1✔
176
                Column('borough', css_class='form-group col-md-4 mb-0'),
1✔
177
                Column('unit_type', css_class='form-group col-md-4 mb-0'),
178
                css_class='form-row',
179
            ),
1✔
180
            Row(
181
                Column('dishwasher', css_class='form-group col-md-6 mb-0'),
182
                Column('doorman', css_class='form-group col-md-6 mb-0'),
183
                css_class='form-row',
184
            ),
185
            Row(
1✔
186
                Column('central_air_conditioning', css_class='form-group col-md-6 mb-0'),
1✔
187
                Column('furnished', css_class='form-group col-md-6 mb-0'),
1✔
188
                css_class='form-row',
1✔
189
            ),
1✔
190
           
1✔
191
            Row(
192
                Column('parking_available', css_class='form-group col-md-6 mb-0'),
193
                Column('washer_dryer_in_unit', css_class='form-group col-md-6 mb-0'),
194
                css_class='form-row',
195
            ),
196
            Column('elevator', css_class='form-group col-md-4 mb-0'),
197

198

199
             "Availability_Date",
200
           Row(
201
                Column('latitude', css_class='form-group col-md-4 mb-0 align-self-end'),  # Add 'align-self-end' class
202
                Column('longitude', css_class='form-group col-md-4 mb-0 align-self-end'),  # Add 'align-self-end' class
203
                css_class='form-row location-row',
204
            ),
205

206
            Field("photo", multiple=True),
207
            Submit("submit", "Submit", css_class="btn btn-primary form-button1"),
208
            
209
        )
210
    class Meta:
211
        model = Rental_Listings
212
        fields = [
213
            "address",
214
            "zipcode",
215
            "price",
216
            "sq_ft",
217
            "rooms",
218
            "beds",
219
            "baths",
220
            "unit_type",
221
            "neighborhood",
222
            "borough",
223
            "broker_fee",
224
            "central_air_conditioning",
225
            "dishwasher",
226
            "doorman",
227
            "elevator",
228
            "furnished",
229
            "parking_available",
230
            "washer_dryer_in_unit",
231
            "Availability_Date",
232
            "photo",
233
            "latitude",
234
            "longitude",
235
        ]
236
        widgets = {
237
            "Availability_Date": forms.DateInput(attrs={"type": "date"})
238
        }
239

240
    def clean_price(self):
241
        price = self.cleaned_data["price"]
242
        if price < 0:
243
            raise ValidationError("Price cannot be negative.")
244
        return price
245
    def clean_brokerfee(self):
246
        broker_fee = self.cleaned_data["broker_fee"]
247
        if broker_fee < 0:
1✔
248
            raise ValidationError("Broker Fee cannot be negative.")
1✔
249
        return broker_fee
1✔
250

251
    def clean_Availability_Date(self):
252
        availability_date = self.cleaned_data.get("Availability_Date")
253
        if availability_date and availability_date < date.today():
254
            raise ValidationError("The availability date cannot be in the past.")
255
        if availability_date and availability_date > date.today() + timedelta(days=365):
256
            raise ValidationError("The availability date is too far in the future.")
257
        return availability_date
258

259
    def clean_rooms_beds(self):
260
        rooms = self.cleaned_data.get("rooms")
261
        beds = self.cleaned_data.get("beds")
262

263
        if rooms is not None and beds is not None and rooms < beds:
264
            raise ValidationError(
265
                "Total number of rooms cannot be less than the number of bedrooms."
266
            )
267

268
    def clean_zipcode(self):
269
        zipcode = self.cleaned_data["zipcode"]
270
        if not zipcode.isdigit() or len(zipcode) != 5:
271
            raise forms.ValidationError("Please enter a valid 5-digit zip code.")
272
        return zipcode
273

1✔
274
    def clean_sq_ft(self):
275
        sq_ft = self.cleaned_data["sq_ft"]
1✔
276
        if sq_ft < 100:
1✔
277
            raise forms.ValidationError(
1✔
278
                "Please enter a valid square footage (100 sq ft minimum)."
1✔
279
            )
1✔
280
        return sq_ft
281

1✔
NEW
282
    def clean_address(self):
×
NEW
283
        address = self.cleaned_data["address"]
×
NEW
284
        if len(address) > 255:
×
NEW
285
            raise forms.ValidationError("Address is too long.")
×
286
        return address
287

1✔
288

1✔
289
class CustomLoginForm(AuthenticationForm):
1✔
290
    def __init__(self, *args, **kwargs):
1✔
291
        super().__init__(*args, **kwargs)
1✔
UNCOV
292

×
293

1✔
294
class CustomUserEditForm(forms.ModelForm):
295
    class Meta:
1✔
UNCOV
296
        model = CustomUser
×
UNCOV
297
        fields = ("full_name", "phone_number", "city")
×
298
        widgets = {
UNCOV
299
            "full_name": forms.TextInput(attrs={"class": "form-control"}),
×
UNCOV
300
            "phone_number": forms.TextInput(attrs={"class": "form-control"}),
×
301
            "city": forms.TextInput(attrs={"class": "form-control"}),
302
        }
303

304
    def clean_full_name(self):
1✔
305
        full_name = self.cleaned_data["full_name"]
1✔
306
        if not re.match("^[a-zA-Z\\s]*$", full_name):  # noqa: W605
1✔
307
            raise ValidationError("Name should only contain letters and spaces.")
1✔
308
        return full_name
1✔
309

310
    def clean_phone_number(self):
1✔
311
        phone_number = self.cleaned_data["phone_number"]
1✔
312
        if not phone_number.isdigit() or len(phone_number) != 10:
1✔
313
            raise ValidationError("Phone number must contain exactly 10 digits.")
×
314
        return phone_number
315

316
    def clean_city(self):
1✔
317
        city = self.cleaned_data["city"]
318
        if not re.match("^[a-zA-Z\\s]*$", city):  # noqa: W605
1✔
319
            raise ValidationError("City should only contain letters and spaces.")
1✔
320
        return city
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc