Skip to content

Commit

Permalink
Merge pull request #243 from r-xyz/out-of-schedule-area-email
Browse files Browse the repository at this point in the history
Out of schedule email for areas.
  • Loading branch information
rptmat57 authored Jun 19, 2024
2 parents e9840fb + 41b9d73 commit 340f661
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 30 deletions.
61 changes: 34 additions & 27 deletions NEMO/views/timed_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ def email_out_of_time_reservation_notification(request):

def send_email_out_of_time_reservation_notification(request=None):
"""
Out of time reservation notification for areas is when a user is still logged in an area but his reservation expired.
Out of time reservation notification for areas is when a user is still logged in an area but either their reservation expired or they are outside of their permitted access hours.
"""
# Exit early if the out of time reservation email template has not been customized for the organization yet.
# This feature only sends emails, so if the template is not defined there nothing to do.
Expand All @@ -394,7 +394,8 @@ def send_email_out_of_time_reservation_notification(request=None):
"The out of time reservation email template has not been customized for your organization yet. Please visit the customization page to upload a template, then out of time email notifications can be sent."
)

out_of_time_user_area = []
out_of_time_user_reservations = []
trigger_time = timezone.now().replace(second=0, microsecond=0) # Round down to the nearest minute.

# Find all logged users
access_records: List[AreaAccessRecord] = (
Expand All @@ -409,31 +410,36 @@ def send_email_out_of_time_reservation_notification(request=None):
if customer.is_staff or customer.is_service_personnel:
continue

if area.requires_reservation:
# Calculate the timestamp of how late a user can be logged in after a reservation ended.
threshold = (
timezone.now()
if not area.logout_grace_period
else timezone.now() - timedelta(minutes=area.logout_grace_period)
)
threshold = datetime.replace(threshold, second=0, microsecond=0) # Round down to the nearest minute.
ending_reservations = Reservation.objects.filter(
cancelled=False,
missed=False,
shortened=False,
area=area,
user=customer,
start__lte=timezone.now(),
end=threshold,
)
# find out if a reservation is starting right at the same time (in case of back to back reservations, in which case customer is good)
starting_reservations = Reservation.objects.filter(
cancelled=False, missed=False, shortened=False, area=area, user=customer, start=threshold
)
if ending_reservations.exists() and not starting_reservations.exists():
out_of_time_user_area.append(ending_reservations[0])
threshold = (
trigger_time if not area.logout_grace_period else trigger_time - timedelta(minutes=area.logout_grace_period)
)
physical_access = PhysicalAccessLevel.objects.filter(user=customer, area=area).first()
# Check first if allowed schedule has just expired
if (
physical_access
and physical_access.accessible_at(threshold - timedelta(minutes=1))
and not physical_access.accessible_at(threshold)
):
out_of_time_user_reservations.append(Reservation(user=customer, area=area, end=threshold))
else:
if area.requires_reservation:
ending_reservations = Reservation.objects.filter(
cancelled=False,
missed=False,
shortened=False,
area=area,
user=customer,
start__lte=timezone.now(),
end=threshold,
)
# find out if a reservation is starting right at the same time (in case of back to back reservations, in which case customer is good)
starting_reservations = Reservation.objects.filter(
cancelled=False, missed=False, shortened=False, area=area, user=customer, start=threshold
)
if ending_reservations.exists() and not starting_reservations.exists():
out_of_time_user_reservations.append(ending_reservations[0])

for reservation in out_of_time_user_area:
for reservation in out_of_time_user_reservations:
send_out_of_time_reservation_notification(reservation, request)

return HttpResponse()
Expand All @@ -443,7 +449,8 @@ def send_out_of_time_reservation_notification(reservation: Reservation, request=
message = get_media_file_contents("out_of_time_reservation_email.html")
user_office_email = EmailsCustomization.get("user_office_email_address")
if message and user_office_email:
subject = "Out of time in the " + str(reservation.area.name)
name = str(reservation.area.name)
subject = "Out of time for the " + name if reservation.start else "Out of allowed schedule for the " + name
message = render_email_template(message, {"reservation": reservation}, request)
recipients = reservation.user.get_emails(
reservation.user.get_preferences().email_send_reservation_ending_reminders
Expand Down
26 changes: 23 additions & 3 deletions resources/emails/out_of_time_reservation_email.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,38 @@
font-family: 'Avenir Next', 'Helvetica Neue', 'Helvetica', 'Arial', 'sans-serif'">
<tr>
<td align="center" style="color: white; background: #d9534f; padding: 50px 0;" bgcolor="#d9534f">
<h1 style="max-width: 90%; margin: 0 auto; padding: 0;">OUT OF TIME IN THE {{ reservation.area }}</h1>
<h1 style="max-width: 90%; margin: 0 auto; padding: 0;">
OUT OF
{% if reservation.start %}
TIME
{% else %}
ALLOWED SCHEDULE
{% endif %}
IN THE {{ reservation.area }}
</h1>
</td>
</tr>
<tr>
<td style="padding: 10px;">
<p>Dear {{ reservation.user.first_name }},</p>
<p>Your reservation of the {{ reservation.area }} in the facility ended at {{ reservation.end }}.</p>
<p>
Your
{% if reservation.start %}
reservation of the
{% else %}
allowed schedule for the
{% endif %}
{{ reservation.area }} in the {{ facility_name }} ended at {{ reservation.end }}.
</p>
<p>However, our records show that you are still logged in the {{ reservation.area }}.</p>
<p>If you simply forgot to log out, please contact a staff member</p>
<br>
<p>
Please remember that the facility is a shared resource, and overstaying a reservation may inhibit the productivity of other facility users.
{% if reservation.start %}
Please remember that the {{ facility_name }} is a shared resource, and overstaying a reservation may inhibit the productivity of other facility users.
{% else %}
Please remember that users are not allowed to overstay in areas outside their allowed schedule.
{% endif %}
</p>
</td>
</tr>
Expand Down

0 comments on commit 340f661

Please sign in to comment.