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

d120 / pyfeedback / 25237229969

01 May 2026 11:14PM UTC coverage: 88.833% (-0.8%) from 89.664%
25237229969

push

github

4-dash
minor fiexs

2991 of 3367 relevant lines covered (88.83%)

0.89 hits per line

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

63.86
/src/feedback/tools.py
1
# coding=utf-8
2

3
from django.template import TemplateSyntaxError, Template
1✔
4

5
from django.core.mail import send_mail
1✔
6
from django.utils.translation import gettext_lazy as _
1✔
7
from django.template.loader import render_to_string
1✔
8
from django.utils.safestring import mark_safe
1✔
9

10
from django.conf import settings
1✔
11

12
# ------------------------------ Durchschnittsberechnung für das Ranking ------------------------------ #
13

14
def get_average(ergebnis, fb_list, attr):
1✔
15
    """Berechnet das gewichtete Mittel über das Attribut attr für die Fragebogenliste fb_list."""
16

17
    # alle Ergebnisse, die in Mittelwert einfließen, zusammenstellen
18
    try:
1✔
19
        parts = getattr(ergebnis, attr + '_parts')
1✔
20
    except AttributeError:
1✔
21
        parts = [attr]
1✔
22

23
    # Gewichte einlesen, falls Bestandteile nicht zu gleichen Teilen in den Mittelwert eingehen sollen
24
    if attr in ergebnis.weight:
1✔
25
        weights = ergebnis.weight[attr]
1✔
26
    else:
27
        weights = [1] * len(parts)
1✔
28

29
    # Anzahl an Fragebögen, die ins Ergebnis eingehen
30
    fb_count = 0
1✔
31

32
    # gewichtete Zahl der Werte, die in das Ergebnis eingeht
33
    weighted_count = 0
1✔
34

35
    # gewichtete Werte, die in das Ergebnis eingehen
36
    weighted_sum = 0
1✔
37

38
    for fb in fb_list:
1✔
39
        contains_valid_field = False
1✔
40

41
        for part, weight in zip(parts, weights):
1✔
42
            value = getattr(fb, part)
1✔
43
            # Evasys gibt auch den Wert int(0) zurück
44
            # siehe: https://www.fachschaft.informatik.tu-darmstadt.de/trac/fs/ticket/1192
45
            if value is not None and value >= 1:
1✔
46
                contains_valid_field = True
1✔
47
                weighted_count += weight
1✔
48
                weighted_sum += value * weight
1✔
49

50
        if contains_valid_field:
1✔
51
            fb_count += 1
1✔
52

53
    if fb_count > 0:
1✔
54
        average = weighted_sum / float(weighted_count)
1✔
55
        return average, fb_count
1✔
56
    else:
57
        return None, 0
1✔
58

59

60
### Durchschnittsberechnung für das Ranking ###################################
61

62
def get_average_16(ergebnis, fb_list, erg_list, attr):
1✔
63
    """Berechnet das gewichtete Mittel über das Attribut attr für die Fragebogenliste fb_list."""
64

65
    # alle Ergebnisse, die in Mittelwert einfließen, zusammenstellen
66
    try:
×
67
        parts = getattr(ergebnis, attr + '_parts')
×
68
    except AttributeError:
×
69
        parts = [attr]
×
70

71
    # Gewichte einlesen, falls Bestandteile nicht zu gleichen Teilen in den Mittelwert eingehen sollen
72
    if attr in ergebnis.weight:
×
73
        weights = ergebnis.weight[attr]
×
74
    else:
75
        weights = [1] * len(parts)
×
76

77
    # Anzahl an Fragebögen, die ins Ergebnis eingehen
78
    fb_count = 0
×
79

80
    # gewichtete Zahl der Werte, die in das Ergebnis eingeht
81
    weighted_count = 0
×
82

83
    # gewichtete Werte, die in das Ergebnis eingehen
84
    weighted_sum = 0
×
85

86
    for fb in fb_list:
×
87
        contains_valid_field = False
×
88

89
        for part, weight in zip(parts, weights):
×
90
            value = getattr(fb, part)
×
91
            # Evasys gibt auch den Wert int(0) zurück
92
            # siehe: https://www.fachschaft.informatik.tu-darmstadt.de/trac/fs/ticket/1192
93
            if value is not None and value >= 1:
×
94
                contains_valid_field = True
×
95
                weighted_count += weight
×
96
                weighted_sum += value * weight
×
97

98
        if contains_valid_field:
×
99
            fb_count += 1
×
100

101
    if fb_count > 0:
×
102
        average = weighted_sum / float(weighted_count)
×
103
        return average, fb_count
×
104

105
    else:
106
        return None, 0
×
107
# ------------------------------ E-Mail-Handling ------------------------------ #
108

109
def render_email(template, context):
1✔
110
    try:
1✔
111
        return Template('{% autoescape off %}' + template + '{% endautoescape %}').render(context)
1✔
112
    except TemplateSyntaxError:
1✔
113
        return "!!! Syntaxfehler im Mailtext !!!"
1✔
114

115

116
def ean_checksum_calc(number):
1✔
117
    """ Berechne die Checksumme eines EAN Barcodes"""
118
    offset = 0
1✔
119

120
    # convert a int to a list of ints
121
    x = [int(i) for i in str(number)]
1✔
122
    length = len(x)
1✔
123
    if length == 8 or length == 13:
1✔
124
        offset = 1
1✔
125

126
    # nehme jedes 2 element beginned beim letzten element und gehe nach vorne zum ersten element,
127
    return (-(sum(x[-(1 + offset)::-2]) * 3 + sum(x[-(2 + offset)::-2]))) % 10
1✔
128

129

130
def ean_checksum_valid(x):
1✔
131
    """ Prüfe die Checksumme eines EAN Barcodes"""
132
    length = len(str(x))
1✔
133
    result = False
1✔
134
    if length == 8 or length == 13:
1✔
135
        if x % 10 == ean_checksum_calc(x):
1✔
136
            result = True
1✔
137
    return result
1✔
138

139
def send_change_email_link(to_email, link, minutes_to_expire) :
1✔
140
    """
141
    sends mail to given email with given link as a part of email change process
142
    """
143
    subject = "E-Mail-Änderungsanfrage / Email change request"
×
144

145
    message = render_to_string(
×
146
        "emails/email_change.txt",
147
        {"email": to_email, "link": mark_safe(link), "minutes_to_expire": minutes_to_expire,}
148
    )
149

150
    send_mail(
×
151
        subject=subject,
152
        message=message,
153
        from_email=settings.DEFAULT_FROM_EMAIL,
154
        recipient_list=[to_email],
155
        fail_silently=False,
156
    )
157

158
def send_change_email_otp(to_email, old_email, otp, minutes_to_expire) :
1✔
159
    """
160
    sends mail with otp
161
    """
162
    subject = "E-Mail-Änderung OTP / Email change OTP"
×
163

164
    message = render_to_string(
×
165
        "emails/email_change_otp.txt",
166
        {"email": to_email, "old_email": old_email, "otp": mark_safe(otp), "minutes_to_expire": minutes_to_expire,}
167
    )
168

169
    send_mail(
×
170
        subject=subject,
171
        message=message,
172
        from_email=settings.DEFAULT_FROM_EMAIL,
173
        recipient_list=[to_email],
174
        fail_silently=False,
175
    )
176

177

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