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

gcivil-nyu-org / team4-wed-spring25 / 637

23 Apr 2025 01:06AM UTC coverage: 92.93% (-0.01%) from 92.942%
637

cron

travis-pro

web-flow
Merge pull request #297 from gcivil-nyu-org/resolve_settings_conflict

Resolve settings conflict

148 of 158 new or added lines in 8 files covered. (93.67%)

1 existing line in 1 file now uncovered.

1459 of 1570 relevant lines covered (92.93%)

0.93 hits per line

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

98.17
/parks/models.py
1
from django.db import models
1✔
2
from cloudinary.models import CloudinaryField
1✔
3
from django.contrib.auth.models import User
1✔
4
from django.utils import timezone
1✔
5
from django.utils.text import slugify
1✔
6
from django.urls import reverse
1✔
7

8

9
class DogRun(models.Model):
1✔
10
    id = models.CharField(max_length=255)
1✔
11
    prop_id = models.CharField(max_length=255, primary_key=True)
1✔
12
    name = models.CharField(max_length=255)
1✔
13
    address = models.CharField(max_length=255)
1✔
14
    dogruns_type = models.CharField(max_length=100)
1✔
15
    accessible = models.CharField(max_length=50)
1✔
16
    notes = models.TextField(max_length=255)
1✔
17
    image = models.ImageField(upload_to="dogruns/", null=True, blank=True)
1✔
18

19
    class Meta:
1✔
20
        db_table = "dog_runs"
1✔
21

22
    def __str__(self):
23
        return self.name
24

25

26
class DogRunNew(models.Model):
1✔
27
    id = models.CharField(max_length=255, primary_key=True)
1✔
28
    prop_id = models.CharField(max_length=255)
1✔
29
    name = models.CharField(max_length=255)
1✔
30
    address = models.CharField(max_length=255)
1✔
31
    dogruns_type = models.CharField(max_length=100)
1✔
32
    accessible = models.CharField(max_length=50)
1✔
33
    notes = models.TextField(max_length=255)
1✔
34
    google_name = models.TextField(null=True, blank=True)
1✔
35
    borough = models.TextField(null=True, blank=True)
1✔
36
    zip_code = models.TextField(null=True, blank=True)
1✔
37
    formatted_address = models.TextField(null=True, blank=True)
1✔
38
    latitude = models.FloatField(null=True, blank=True)
1✔
39
    longitude = models.FloatField(null=True, blank=True)
1✔
40
    additional = models.JSONField(null=True, blank=True)  # PostgreSQL JSONB
1✔
41
    display_name = models.TextField(null=False, blank=False)
1✔
42
    slug = models.SlugField(null=False, blank=False)
1✔
43

44
    class Meta:
1✔
45
        db_table = "dog_runs_new"
1✔
46

47
    def __str__(self):
48
        return self.name
49

50
    def save(self, *args, **kwargs):
1✔
51
        combined = f"{self.display_name}-{self.prop_id}"
1✔
52
        self.slug = slugify(combined)
1✔
53
        super().save(*args, **kwargs)
1✔
54

55
    # function to easily get url of park_detail
56
    def detail_page_url(self):
1✔
57
        return reverse("park_detail", kwargs={"slug": self.slug, "id": self.id})
1✔
58

59

60
class Review(models.Model):
1✔
61
    park = models.ForeignKey(
1✔
62
        DogRunNew, on_delete=models.CASCADE, related_name="reviews"
63
    )
64
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="reviews")
1✔
65
    text = models.TextField()
1✔
66
    rating = models.IntegerField()
1✔
67
    created_at = models.DateTimeField(auto_now_add=True)
1✔
68

69
    # Soft Delete fields
70
    is_removed = models.BooleanField(default=False)
1✔
71
    removed_at = models.DateTimeField(null=True, blank=True)
1✔
72
    removed_by = models.ForeignKey(
1✔
73
        User,
74
        null=True,
75
        blank=True,
76
        on_delete=models.SET_NULL,
77
        related_name="removed_reviews",
78
    )
79
    is_deleted = models.BooleanField(default=False)
1✔
80

81
    def has_active_replies(self):
1✔
NEW
82
        return self.replies.filter(is_deleted=False).exists()
×
83

84
    class Meta:
1✔
85
        db_table = "park_reviews"
1✔
86
        ordering = ["-created_at"]
1✔
87

88
    def __str__(self):
89
        return f"Review for {self.park.name} ({self.rating} stars)"
90

91

92
class ParkImage(models.Model):
1✔
93
    park = models.ForeignKey(
1✔
94
        DogRunNew,
95
        on_delete=models.CASCADE,
96
        related_name="images",
97
        to_field="id",
98
        db_column="park_id",
99
    )
100
    user = models.ForeignKey(
1✔
101
        User, on_delete=models.CASCADE, related_name="images", null=True, blank=True
102
    )
103
    review = models.ForeignKey(
1✔
104
        "Review", on_delete=models.CASCADE, null=True, blank=True, related_name="images"
105
    )
106
    image = CloudinaryField("image")
1✔
107

108
    # Soft deletion fields:
109
    is_removed = models.BooleanField(default=False)
1✔
110
    removed_at = models.DateTimeField(null=True, blank=True)
1✔
111
    removed_by = models.ForeignKey(
1✔
112
        User,
113
        on_delete=models.SET_NULL,
114
        null=True,
115
        blank=True,
116
        related_name="removed_images",
117
        help_text="Admin who removed the image",
118
    )
119

120
    def __str__(self):
121
        return f"Image for {self.park.name}"
122

123

124
class ReviewReport(models.Model):
1✔
125
    review = models.ForeignKey(
1✔
126
        "Review", on_delete=models.CASCADE, related_name="reports"
127
    )
128
    reported_by = models.ForeignKey(User, on_delete=models.CASCADE)
1✔
129
    reason = models.TextField()
1✔
130
    reported_at = models.DateTimeField(default=timezone.now)
1✔
131

132
    def __str__(self):
133
        return f"Reported by {self.reported_by.username} on {self.review.id}"
134

135

136
class ImageReport(models.Model):
1✔
137
    user = models.ForeignKey(
1✔
138
        User, on_delete=models.CASCADE, related_name="image_reports"
139
    )
140
    image = models.ForeignKey(
1✔
141
        ParkImage, on_delete=models.CASCADE, related_name="reports"
142
    )
143
    reason = models.TextField()
1✔
144
    created_at = models.DateTimeField(auto_now_add=True)
1✔
145

146
    def __str__(self):
147
        return f"Report by {self.user.username} on Image {self.image.id}"
148

149

150
class Reply(models.Model):
1✔
151
    review = models.ForeignKey(Review, on_delete=models.CASCADE, related_name="replies")
1✔
152
    user = models.ForeignKey(User, on_delete=models.CASCADE)
1✔
153
    parent_reply = models.ForeignKey(
1✔
154
        "self", on_delete=models.CASCADE, null=True, blank=True, related_name="children"
155
    )
156
    text = models.TextField()
1✔
157
    created_at = models.DateTimeField(auto_now_add=True)
1✔
158

159
    is_deleted = models.BooleanField(default=False)
1✔
160

161
    def has_active_children(self):
1✔
NEW
162
        return self.children.filter(is_deleted=False).exists()
×
163

164
    class Meta:
1✔
165
        ordering = ["created_at"]
1✔
166

167
    def __str__(self):
168
        return f"Reply by {self.user.username} on review {self.review.id}"
169

170

171
class ReplyReport(models.Model):
1✔
172
    reply = models.ForeignKey(Reply, on_delete=models.CASCADE, related_name="reports")
1✔
173
    user = models.ForeignKey(User, on_delete=models.CASCADE)
1✔
174
    reason = models.TextField()
1✔
175
    created_at = models.DateTimeField(auto_now_add=True)
1✔
176

177

178
class ParkPresence(models.Model):
1✔
179
    STATUS_CHOICES = [
1✔
180
        ("Current", "Current"),
181
        ("On their way", "On their way"),
182
    ]
183

184
    user = models.ForeignKey(
1✔
185
        User, on_delete=models.CASCADE, related_name="park_presences"
186
    )
187
    park = models.ForeignKey(
1✔
188
        DogRunNew, on_delete=models.CASCADE, related_name="presences"
189
    )
190
    status = models.CharField(max_length=20, choices=STATUS_CHOICES)
1✔
191

192
    # This is now the proper datetime for scheduled arrival
193
    time = models.DateTimeField(null=True, blank=True)
1✔
194

195
    checked_in_at = models.DateTimeField(auto_now_add=True)
1✔
196

197
    class Meta:
1✔
198
        db_table = "park_presence"
1✔
199
        unique_together = ("user", "park")
1✔
200
        ordering = ["-checked_in_at"]
1✔
201

202
    def __str__(self):
203
        return f"{self.user.username} - {self.park.display_name} ({self.status})"
204

205

206
class Message(models.Model):
1✔
207
    sender = models.ForeignKey(
1✔
208
        User, on_delete=models.CASCADE, related_name="sent_messages"
209
    )
210
    recipient = models.ForeignKey(
1✔
211
        User, on_delete=models.CASCADE, related_name="received_messages"
212
    )
213
    content = models.TextField()
1✔
214
    timestamp = models.DateTimeField(auto_now_add=True)
1✔
215

216
    class Meta:
1✔
217
        ordering = ["timestamp"]
1✔
218

219
    def __str__(self):
220
        return f"From {self.sender} to {self.recipient} at {self.timestamp}"
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