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

furthemore / APIS / 18672757101

21 Oct 2025 04:20AM UTC coverage: 73.366%. Remained the same
18672757101

push

github

web-flow
Update frontend dependency versions (#395)

3446 of 4697 relevant lines covered (73.37%)

0.73 hits per line

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

62.18
/registration/views/common.py
1
import json
1✔
2
import logging
1✔
3
from datetime import datetime
1✔
4
from decimal import Decimal
1✔
5

6
from django.conf import settings
1✔
7
from django.contrib.admin.views.decorators import staff_member_required
1✔
8
from django.contrib.auth.decorators import user_passes_test
1✔
9
from django.core.serializers.json import DjangoJSONEncoder
1✔
10
from django.db.models import Q
1✔
11
from django.db.models.fields.files import FieldFile
1✔
12
from django.http import HttpResponse, JsonResponse
1✔
13
from django.shortcuts import get_object_or_404, render
1✔
14
from django.urls import reverse
1✔
15
from django.utils import timezone
1✔
16
from django.views.decorators.cache import cache_page
1✔
17
from idempotency_key.decorators import idempotency_key
1✔
18

19
import registration.emails
1✔
20
from registration.models import (
1✔
21
    Cart,
22
    Department,
23
    Discount,
24
    Event,
25
    Order,
26
    OrderItem,
27
    PriceLevel,
28
    PriceLevelOption,
29
    ShirtSizes,
30
    Staff,
31
    get_token,
32
)
33
from registration.payments import charge_payment
1✔
34
from registration.views import ordering
1✔
35
from registration.views.cart import saveCart
1✔
36
from registration.views.ordering import add_attendee_to_assistant
1✔
37

38
logger = logging.getLogger("django.request")
1✔
39

40

41
def flush(request):
1✔
42
    clear_session(request)
1✔
43
    return JsonResponse({"success": True})
1✔
44

45

46
def in_group(groupname):
1✔
47
    def inner(user):
1✔
48
        return user.groups.filter(name=groupname).exists()
×
49

50
    return inner
1✔
51

52

53
def clear_session(request):
1✔
54
    """
55
    Soft-clears session by removing any non-protected session values.
56
    (anything prefixed with '_'; keeps Django user logged-in)
57
    """
58
    for key in list(request.session.keys()):
1✔
59
        if key[0] != "_":
1✔
60
            del request.session[key]
1✔
61
            logger.debug(f"Delete session key {key}")
1✔
62
    request.session.save()
1✔
63

64

65
def get_client_ip(request):
1✔
66
    x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR")
1✔
67
    if x_forwarded_for:
1✔
68
        ip = x_forwarded_for.split(",")[0]
×
69
    else:
70
        ip = request.META.get("REMOTE_ADDR")
1✔
71
    return ip
1✔
72

73

74
def get_request_meta(request):
1✔
75
    values = {}
1✔
76
    values["HTTP_REFERER"] = request.META.get("HTTP_REFERER")
1✔
77
    values["HTTP_USER_AGENT"] = request.META.get("HTTP_USER_AGENT")
1✔
78
    values["IP"] = get_client_ip(request)
1✔
79
    return json.dumps(values)
1✔
80

81

82
def getOptionsDict(orderItems):
1✔
83
    orderDict = []
1✔
84
    for oi in orderItems:
1✔
85
        aos = oi.getOptions()
1✔
86
        for ao in aos:
1✔
87
            orderDict.append(
1✔
88
                {
89
                    "name": ao.option.optionName,
90
                    "type": ao.option.optionExtraType,
91
                    "value": ao.optionValue,
92
                    "id": ao.option.id,
93
                    "image": ao.option.getOptionImage(),
94
                }
95
            )
96

97
    return orderDict
1✔
98

99

100
@cache_page(60)
1✔
101
def get_events(request):
1✔
102
    events = Event.objects.all()
×
103
    data = [
×
104
        {
105
            "name": ev.name,
106
            "id": ev.id,
107
            "dealerStart": ev.dealerRegStart,
108
            "dealerEnd": ev.dealerRegEnd,
109
            "staffStart": ev.staffRegStart,
110
            "staffEnd": ev.staffRegEnd,
111
            "attendeeStart": ev.attendeeRegStart,
112
            "attendeeEnd": ev.attendeeRegEnd,
113
        }
114
        for ev in events
115
    ]
116
    return HttpResponse(
×
117
        json.dumps(data, cls=DjangoJSONEncoder), content_type="application/json"
118
    )
119

120

121
def abort(status=400, reason="Bad request"):
1✔
122
    """
123
    Returns a JSON response indicating an error to the client.
124

125
    status: A valid HTTP status code
126
    reason: Human-readable explanation
127
    """
128
    logger.info("JSON {0}: {1}".format(status, reason))
1✔
129
    return JsonResponse({"success": False, "reason": reason}, status=status)
1✔
130

131

132
def success(status=200, reason=None):
1✔
133
    """
134
    Returns a JSON response indicating success.
135

136
    status: A valid HTTP status code (2xx)
137
    reason: (Optional) human-readable explanation
138
    """
139
    if reason is None:
1✔
140
        logger.debug("JSON {0}".format(status))
1✔
141
        return JsonResponse({"success": True}, status=status)
1✔
142
    else:
143
        logger.debug("JSON {0}: {1}".format(status, reason))
×
144
        return JsonResponse(
×
145
            {
146
                "success": True,
147
                "reason": reason,
148
                "message": reason,  # Backwards compatibility
149
            },
150
            status=status,
151
        )
152

153

154
def get_confirmation_token():
1✔
155
    return get_token(6)
1✔
156

157

158
def get_unique_confirmation_token(model):
1✔
159
    reference = get_confirmation_token()
1✔
160
    while model.objects.filter(reference=reference).exists():
1✔
161
        reference = get_confirmation_token()
×
162
    return reference
1✔
163

164

165
def handler(obj):
1✔
166
    if hasattr(obj, "isoformat"):
1✔
167
        return obj.isoformat()
1✔
168
    elif isinstance(obj, Decimal):
1✔
169
        return str(obj)
1✔
170
    elif isinstance(obj, FieldFile):
×
171
        try:
×
172
            return obj.url
×
173
        except ValueError:
×
174
            return None
×
175
    else:
176
        raise TypeError(
×
177
            "Object of type %s with value of %s is not JSON serializable"
178
            % (
179
                type(obj),
180
                repr(obj),
181
            )
182
        )
183

184

185
def index(request):
1✔
186
    try:
1✔
187
        event = Event.objects.get(default=True)
1✔
188
    except Event.DoesNotExist:
1✔
189
        return render(request, "registration/docs/no-event.html")
1✔
190

191
    tz = timezone.get_current_timezone()
1✔
192
    today = tz.localize(datetime.now())
1✔
193
    discount = request.session.get("discount")
1✔
194
    if discount:
1✔
195
        discount = Discount.objects.filter(codeName=discount)
×
196
        if discount.count() > 0:
×
197
            discount = discount.first()
×
198

199
    context = {"event": event, "discount": discount, "form_type": "attendee"}
1✔
200

201
    if event.websiteUrl:
1✔
202
        context["homeRedirect"] = event.websiteUrl
1✔
203
    else:
204
        context["homeRedirect"] = reverse("registration:index")
1✔
205

206
    if event.attendeeRegStart <= today <= event.attendeeRegEnd:
1✔
207
        return render(request, "registration/registration-form.html", context)
1✔
208
    elif event.attendeeRegStart >= today:
1✔
209
        context["message"] = "is not yet open. Please stay tuned to our social media for updates!"
1✔
210
        return render(request, "registration/closed.html", context)
1✔
211
    elif event.attendeeRegEnd <= today:
1✔
212
        context["message"] = "has ended."
1✔
213
        return render(request, "registration/closed.html", context)
1✔
214

215

216
@staff_member_required
1✔
217
@user_passes_test(in_group("Manager"))
1✔
218
def manualDiscount(request):
1✔
219
    # FIXME stub
220
    raise NotImplementedError
×
221

222

223
@cache_page(60 * 5)
1✔
224
@staff_member_required
1✔
225
def basicBadges(request):
1✔
226
    event = Event.objects.get(default=True)
×
227

228
    staff = Staff.objects.filter(event=event)
×
229
    order_items = OrderItem.objects.filter(badge__event=event)
×
230

231
    bdata = [
×
232
        {
233
            "badgeName": oi.badge.badgeName,
234
            "level": oi.badge.effectiveLevel(),
235
            "assoc": oi.badge.abandoned,
236
            "firstName": oi.badge.attendee.firstName.lower(),
237
            "lastName": oi.badge.attendee.lastName.lower(),
238
            "printed": oi.badge.printed,
239
            "discount": oi.badge.getDiscount(),
240
            "orderItems": getOptionsDict(oi.badge.orderitem_set.all()),
241
        }
242
        for oi in order_items
243
    ]
244

245
    staffdata = [
×
246
        {
247
            "firstName": s.attendee.firstName.lower(),
248
            "lastName": s.attendee.lastName.lower(),
249
            "title": s.title,
250
            "id": s.id,
251
        }
252
        for s in staff
253
    ]
254

255
    for staff in staffdata:
×
256
        sbadge = Staff.objects.get(id=staff["id"]).getBadge()
×
257
        if sbadge:
×
258
            staff["badgeName"] = sbadge.badgeName
×
259
            if sbadge.effectiveLevel():
×
260
                staff["level"] = sbadge.effectiveLevel()
×
261
            else:
262
                staff["level"] = "none"
×
263
            staff["assoc"] = sbadge.abandoned
×
264
            staff["orderItems"] = getOptionsDict(sbadge.orderitem_set.all())
×
265

266
    sdata = sorted(bdata, key=lambda x: (str(x["level"]), x["lastName"]))
×
267
    ssdata = sorted(staffdata, key=lambda x: x["lastName"])
×
268

269
    dealers = [att for att in sdata if att["assoc"] == "Dealer"]
×
270
    staff = [att for att in ssdata]
×
271
    attendees = [att for att in sdata if att["assoc"] != "Staff"]
×
272
    return render(
×
273
        request,
274
        "registration/utility/badgelist.html",
275
        {"attendees": attendees, "dealers": dealers, "staff": staff},
276
    )
277

278

279
@cache_page(60 * 5)
1✔
280
@staff_member_required
1✔
281
def vipBadges(request):
1✔
282
    default_event = Event.objects.get(default=True)
×
283
    event_id = request.GET.get("event", default_event.id)
×
284
    event = get_object_or_404(Event, id=event_id)
×
285

286
    # Assumes VIP levels based on being marked as "vip" group, or EmailVIP set
287
    price_levels = PriceLevel.objects.filter(Q(emailVIP=True) | Q(group__iexact="vip"))
×
288
    shirt_sizes = {str(shirt.pk): shirt.name for shirt in ShirtSizes.objects.all()}
×
289

290
    vip_order_items = OrderItem.objects.filter(
×
291
        priceLevel__in=price_levels, badge__event=event
292
    )
293

294
    badges = [
×
295
        {
296
            "badge": oi.badge,
297
            "orderItems": getOptionsDict(oi.badge.orderitem_set.all()),
298
            "level": oi.badge.effectiveLevel(),
299
            "assoc": oi.badge.abandoned,
300
        }
301
        for oi in vip_order_items
302
        if oi.badge.abandoned != "Staff"
303
    ]
304

305
    context = {
×
306
        "badges": badges,
307
        "event": event,
308
        "shirt_sizes": shirt_sizes,
309
    }
310

311
    return render(
×
312
        request,
313
        "registration/utility/viplist.html",
314
        context,
315
    )
316

317

318
@cache_page(60)
1✔
319
def get_departments(request):
1✔
320
    depts = Department.objects.filter(volunteerListOk=True).order_by("name")
1✔
321
    data = [{"name": item.name, "id": item.id} for item in depts]
1✔
322
    return HttpResponse(json.dumps(data), content_type="application/json")
1✔
323

324

325
@cache_page(60)
1✔
326
def get_all_departments(request):
1✔
327
    depts = Department.objects.order_by("name")
×
328
    data = [{"name": item.name, "id": item.id} for item in depts]
×
329
    return HttpResponse(json.dumps(data), content_type="application/json")
×
330

331

332
@cache_page(60)
1✔
333
def get_shirt_sizes(request):
1✔
334
    sizes = ShirtSizes.objects.all()
1✔
335
    data = [{"name": size.name, "id": size.id} for size in sizes]
1✔
336
    return HttpResponse(json.dumps(data), content_type="application/json")
1✔
337

338

339
def get_session_addresses(request):
1✔
340
    event = Event.objects.get(default=True)
×
341
    sessionItems = request.session.get("cart_items", [])
×
342
    if not sessionItems:
×
343
        # might be from dealer workflow, which is order items in the session
344
        sessionItems = request.session.get("order_items", [])
×
345
        if not sessionItems:
×
346
            data = {}
×
347
        else:
348
            orderItems = OrderItem.objects.filter(id__in=sessionItems)
×
349
            data = [
×
350
                {
351
                    "id": oi.badge.attendee.id,
352
                    "fname": oi.badge.attendee.firstName,
353
                    "lname": oi.badge.attendee.lastName,
354
                    "email": oi.badge.attendee.email,
355
                    "address1": oi.badge.attendee.address1,
356
                    "address2": oi.badge.attendee.address2,
357
                    "city": oi.badge.attendee.city,
358
                    "state": oi.badge.attendee.state,
359
                    "country": oi.badge.attendee.country,
360
                    "postalCode": oi.badge.attendee.postalCode,
361
                }
362
                for oi in orderItems
363
            ]
364
    else:
365
        data = []
×
366
        cartItems = list(Cart.objects.filter(id__in=sessionItems))
×
367
        for cart in cartItems:
×
368
            cartJson = json.loads(cart.formData)
×
369
            pda = cartJson["attendee"]
×
370
            cartItem = {
×
371
                "fname": pda["firstName"],
372
                "lname": pda["lastName"],
373
                "email": pda["email"],
374
                "phone": pda["phone"],
375
            }
376
            if event.collectAddress:
×
377
                cartItem.update(
×
378
                    {
379
                        "address1": pda["address1"],
380
                        "address2": pda["address2"],
381
                        "city": pda["city"],
382
                        "state": pda["state"],
383
                        "postalCode": pda["postal"],
384
                        "country": pda["country"],
385
                    }
386
                )
387

388
            data.append(cartItem)
×
389
    return HttpResponse(json.dumps(data), content_type="application/json")
×
390

391

392
def get_registration_email(event=None):
1✔
393
    """
394
    Retrieves the email address to show on error messages in the attendee
395
    registration form for a specified event.  If no event specified, uses
396
    the first default event.  If no email is listed there, returns the
397
    default of APIS_DEFAULT_EMAIL in settings.py.
398
    """
399
    if event is None:
1✔
400
        try:
×
401
            event = Event.objects.get(default=True)
×
402
        except BaseException:
×
403
            return settings.APIS_DEFAULT_EMAIL
×
404
    if event.registrationEmail == "":
1✔
405
        return settings.APIS_DEFAULT_EMAIL
×
406
    return event.registrationEmail
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

© 2025 Coveralls, Inc