Skip to content

Commit

Permalink
Send avvik til Teams når de opprettes, litt UI/UX tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
sondregronas committed Sep 19, 2023
1 parent 526a259 commit aca9ae9
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 76 deletions.
11 changes: 9 additions & 2 deletions BookingSystem/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,15 @@
LABEL_SERVER = os.getenv('LABEL_SERVER')
KIOSK_FQDN = os.getenv('KIOSK_FQDN')
API_TOKEN = os.getenv('API_TOKEN')
TEAMS_WEBHOOKS = os.getenv('TEAMS_WEBHOOKS', '').split(',')
TEAMS_WEBHOOKS_DEVIATIONS = os.getenv('TEAMS_WEBHOOKS_DEVIATIONS', '').split(',')

# Teams webhooks
TEAMS_WEBHOOKS = os.getenv('TEAMS_WEBHOOKS')
TEAMS_WEBHOOKS_DEVIATIONS = os.getenv('TEAMS_WEBHOOKS_DEVIATIONS')
if TEAMS_WEBHOOKS:
TEAMS_WEBHOOKS = TEAMS_WEBHOOKS.split(',')
if TEAMS_WEBHOOKS_DEVIATIONS:
TEAMS_WEBHOOKS_DEVIATIONS = TEAMS_WEBHOOKS_DEVIATIONS.split(',')

REGEX_ID = r'^(?:(?![\s])[a-zA-Z0-9_\s\-]*[a-zA-Z0-9_\-]+)$'
REGEX_ITEM = r'^(?:(?![\s])[ÆØÅæøåa-zA-Z0-9_\s\-]*[ÆØÅæøåa-zA-Z0-9_\-]+)$'

Expand Down
3 changes: 2 additions & 1 deletion BookingSystem/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,8 @@ def registrer_avvik() -> flask.Response:
txt = f'Generelt avvik: {log_text}'

audits.audit('AVVIK', markupsafe.escape(txt))
return flask.Response(f'Avvik registrert: {markupsafe.escape(txt)}', status=200)
teams.send_deviation(txt)
return flask.Response(f'Avvik ble sendt til videre oppfølging', status=200)


@api.route('/send_report', methods=['POST'])
Expand Down
11 changes: 10 additions & 1 deletion BookingSystem/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,16 @@ def booking() -> str:
@app.route('/innlevering')
@login_required(admin_only=True)
def innlevering() -> str:
return flask.render_template('innlevering.html')
"""
Renders the innlevering page.
Parameters:
warn (str): Whether to show the warning or not. Defaults to '1'.
"""

return flask.render_template('innlevering.html',
show_popup=flask.request.args.get('show_popup', '1') == '1')


@app.route('/varetelling')
Expand Down
56 changes: 38 additions & 18 deletions BookingSystem/teams.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import markupsafe
import pymsteams

import audits
import inventory
from __init__ import TEAMS_WEBHOOKS, TEAMS_WEBHOOKS_DEVIATIONS
from db import Settings
Expand Down Expand Up @@ -41,14 +40,14 @@ def formatted_overdue_items(items: list) -> str:
'\n<small><i>Dersom du kjenner igjen utlåneren, vennligst få dem til å levere utstyret tilbake ASAP.</i></small>'


def formatted_new_deviations(deviations: list) -> str:
def formatted_deviation(deviation: str) -> str:
"""Return formatted HTML string of new deviations."""
if not deviations:
return ''
if not deviation:
raise APIException('Ingen avvik å rapportere.', 400)
return '<blockquote style="border-color: #FF0000;">' + \
'<br>'.join([f'{markupsafe.escape(deviation)}' for deviation in deviations]) + \
str(markupsafe.escape(deviation)) + \
'</blockquote>' + \
'<small><i><b>NB:</b> Avvik må registreres manuelt i notatblokken (inntil videre), jeg kan kun varsle om nye avvik.</i></small>'
'<small><i><b>NB:</b> Avvik må oppfølges manuelt av dere mennesker, jeg kan kun varsle om nye avvik.</i></small>'


def generate_card(title, text, color, webhook=None) -> pymsteams.connectorcard:
Expand Down Expand Up @@ -76,10 +75,11 @@ def get_overdue_card(overdue_items: list) -> pymsteams.connectorcard:
color='FFA500')


def get_deviation_card(new_deviations: list) -> pymsteams.connectorcard:
def get_deviation_card(deviation: str) -> pymsteams.connectorcard:
"""Return a card with new deviations."""
return generate_card(title='Nye avvik som krever oppfølging',
text=formatted_new_deviations(new_deviations),
title, text = deviation.split(':', 1)
return generate_card(title=title,
text=formatted_deviation(f'Melding: {text}'),
color='FFA500')


Expand All @@ -90,25 +90,45 @@ def send_card_to_hooks(card: pymsteams.connectorcard, webhooks: list[str]) -> No
Process(target=card.send).start()


def send_deviation(deviation: str) -> flask.Response: # pragma: no cover
"""
Send a deviation to all webhooks in TEAMS_WEBHOOKS_DEVIATIONS.
Args:
deviation: The formatted deviation string.
Returns:
None (sends a card asynchronously).
"""
deviation_webhooks = TEAMS_WEBHOOKS_DEVIATIONS if TEAMS_WEBHOOKS_DEVIATIONS else TEAMS_WEBHOOKS
print(deviation_webhooks)

if not deviation_webhooks:
raise APIException('Avvik ikke sendt: webhooks er ikke konfigurert', 400)

if not deviation:
raise APIException('Avvik ikke sendt: avviket er tomt', 400)

card = get_deviation_card(deviation)
send_card_to_hooks(card, deviation_webhooks)
return flask.Response('Avvik sendt til alle konfigurerte teamskanaler!', 200)


def send_report() -> flask.Response: # pragma: no cover
"""Send a report card to all webhooks in TEAMS_WEBHOOKS."""
last_sent = last_sent_within_hour_treshold()
# Throw exception if last report was sent less than an hour ago
last_sent_within_hour_treshold()

if TEAMS_WEBHOOKS == ['']:
if not TEAMS_WEBHOOKS:
raise APIException('Rapport ikke sendt: webhooks er ikke konfigurert', 400)
deviation_webhooks = TEAMS_WEBHOOKS_DEVIATIONS if TEAMS_WEBHOOKS_DEVIATIONS != [''] else TEAMS_WEBHOOKS

overdue_items = inventory.get_all_overdue()
new_deviations = audits.get_new_deviations(since=last_sent)

if not overdue_items and not new_deviations:
raise APIException('Rapport ikke sendt: ingen nye avvik eller utlån på overtid', 400)
if not overdue_items:
raise APIException('Rapport ikke sendt, ingen utlån på overtid', 400)

if overdue_items:
send_card_to_hooks(get_overdue_card(overdue_items), TEAMS_WEBHOOKS)

if new_deviations:
send_card_to_hooks(get_deviation_card(new_deviations), deviation_webhooks)

# Return 200 OK, even if some webhooks failed (the process is async, so we can't catch exceptions)
return flask.Response('Rapport ble sendt til alle konfigurerte teamskanaler!', 200)
26 changes: 14 additions & 12 deletions BookingSystem/templates/forms/return.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,26 @@

<script>
$(document).ready(function () {
$.confirm({
title: 'Gå gjennom utstyret før innlevering!',
content: '<li>Se gjennom vesker/etui - bekreft at alt er på plass<br>' +
{% if show_popup %}
$.confirm({
title: 'Gå gjennom utstyret før innlevering!',
content: '<li>Se gjennom vesker/etui - bekreft at alt er på plass<br>' +
'<li>Sjekk minnekort og annet medfølgende tilbehør<br>' +
'<li>Sett eventuelle batterier til lading<br>' +
'<br>' +
'<b>Eventuelle avvik skal registreres.</b>',
type: 'orange',
icon: 'fa fa-exclamation-triangle',
buttons: {
ok: {
text: 'Den er grei!',
btnClass: 'btn-blue',
action: function () {
type: 'orange',
icon: 'fa fa-exclamation-triangle',
buttons: {
ok: {
text: 'Den er grei!',
btnClass: 'btn-blue',
action: function () {
}
}
}
}
})
})
{% endif %}
$('#id').focus();
$('form').submit(function (event) {
event.preventDefault();
Expand Down
17 changes: 12 additions & 5 deletions BookingSystem/templates/index_admin.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,23 @@ <h3>Velkommen! Her kan du <a href="{{ url_for('app.innlevering') }}">levere inn<
<br>

<a href="{{ url_for('app.booking') }}">
<button>Låne ut utstyr</button>
<button>
Låne ut utstyr
</button>
</a>
<a href="{{ url_for('app.innlevering') }}">
<button>Levere inn utstyr</button>
</a>
<a href="{{ url_for('app.inventar') }}">
<button>Administrere utstyr</button>
<button>
Levere inn utstyr
</button>
</a>
<center>
<a href="{{ url_for('app.inventar') }}">
Administrere utstyr
</a>
</center>

{% if overdue_items %}
<br>
<div id="overdue_items">
<br><br>
<center>
Expand Down
12 changes: 8 additions & 4 deletions BookingSystem/templates/partials/header_admin.html
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
<nav>
<li><a href="{{ url_for('app.index') }}">Utstyrbase</a></li>
<ul>
<li><a href="{{ url_for('app.innlevering') }}">Innlevering</a></li>
<li><a href="{{ url_for('app.booking') }}">Booking</a></li>
<li><a href="{{ url_for('app.inventar') }}">Inventar</a></li>
<li><a href="{{ url_for('app.booking') }}">
Utlån
</a></li>
<li><a href="{{ url_for('app.innlevering') }}">
Innlevering
</a></li>
<div class="dropdown">
<li><a class="dropbtn" href="{{ url_for('app.admin_settings') }}">
<li><a class="dropbtn" href="{{ url_for('app.inventar') }}">
<i class="fa fa-cogs" aria-hidden="true"></i>
</a></li>
<div class="dropdown-content">
<a href="{{ url_for('app.inventar') }}">Inventar</a>
<a href="{{ url_for('app.admin_settings') }}">Adminpanel</a>
<a href="{{ url_for('app.labelserver') }}">Etikettserver</a>
<a href="{{ url_for('app.audits') }}">Audits</a>
Expand Down
2 changes: 1 addition & 1 deletion BookingSystem/templates/registrer_avvik.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ <h3>Alle avvik skal loggføres, både små og store.</h3>
data: $('form').serialize(),
success: function (response) {
cueAlert('Suksess!', response, 'success');
window.location.href = '{{ url_for("app.innlevering") }}';
window.location.href = '{{ url_for("app.innlevering") }}?show_popup=0';
},
error: function (response) {
iziToast.error({
Expand Down
33 changes: 1 addition & 32 deletions tests/test_teams.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import uuid
from datetime import datetime

import audits
import db
from conftest import *
from sanitizer import APIException
from teams import get_overdue_card, get_deviation_card, last_sent_within_hour_treshold, formatted_new_deviations, \
formatted_overdue_items
from teams import get_overdue_card, last_sent_within_hour_treshold, formatted_overdue_items
from test_items import generate_item


Expand All @@ -16,35 +13,7 @@ def test_generate_overdue_card():
assert item.html_repr() in c.payload['text']


def test_generate_deviations_card(admin_client):
noid_data = {
'id': None,
'text': f'Testavvik uten ID ({str(uuid.uuid4())})',
}
noid_expected = f'Generelt avvik: {noid_data["text"]}'

id_data = {
'id': str(uuid.uuid4()),
'text': 'Testavvik med ID',
}
id_expected = f'Avvik på utstyr {id_data["id"]}: {id_data["text"]}'

last_sent = db.Settings.get('report_last_sent') or 0

c = get_deviation_card(audits.get_new_deviations(since=last_sent))
assert noid_expected not in c.payload['text']
assert id_expected not in c.payload['text']

admin_client.post(url_for(admin_client, 'api.registrer_avvik'), data=noid_data)
admin_client.post(url_for(admin_client, 'api.registrer_avvik'), data=id_data)

c = get_deviation_card(audits.get_new_deviations(since=last_sent))
assert noid_expected in c.payload['text']
assert id_expected in c.payload['text']


def test_empty_formatted_cards():
assert not formatted_new_deviations([])
assert not formatted_overdue_items([])


Expand Down

0 comments on commit aca9ae9

Please sign in to comment.