Skip to content

Commit

Permalink
Merge branch 'next' into Enheder-til-rangliste
Browse files Browse the repository at this point in the history
  • Loading branch information
krestenlaust authored Sep 24, 2024
2 parents 7215124 + 7d2089e commit 5b42c8c
Show file tree
Hide file tree
Showing 26 changed files with 477 additions and 28 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/black.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ jobs:
- name: Black Code Formatter
uses: lgeiger/[email protected]
with:
args: --check --target-version py311 --line-length 120 --skip-string-normalization --exclude '(migrations|urls\.py)' stregsystem stregreport kiosk
args: --check --target-version py311 --line-length 120 --skip-string-normalization --exclude '(migrations|urls\.py)' stregsystem stregreport kiosk razzia
Empty file added razzia/__init__.py
Empty file.
5 changes: 5 additions & 0 deletions razzia/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.contrib import admin

from razzia.models import Razzia

admin.site.register(Razzia)
6 changes: 6 additions & 0 deletions razzia/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class RazziaConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "razzia"
78 changes: 78 additions & 0 deletions razzia/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Generated by Django 4.1.13 on 2024-09-14 13:35

import datetime
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

initial = True

dependencies = [
(
"stregsystem",
"0018_member_signup_due_paid_alter_mobilepayment_status_and_more",
),
]

operations = [
migrations.CreateModel(
name="Razzia",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=20)),
("turns_per_member", models.IntegerField(default=0)),
("turn_interval", models.DurationField(default=datetime.timedelta(0))),
("start_date", models.DateTimeField(auto_now_add=True)),
],
options={
"permissions": (
("host_razzia", "Can host a foobar, fnugfald or bread razzia"),
),
},
),
migrations.CreateModel(
name="RazziaEntry",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("time", models.DateTimeField(auto_now_add=True, null=True)),
(
"member",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="stregsystem.member",
),
),
(
"razzia",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE, to="razzia.razzia"
),
),
],
),
migrations.AddField(
model_name="razzia",
name="members",
field=models.ManyToManyField(
through="razzia.RazziaEntry", to="stregsystem.member"
),
),
]
Empty file added razzia/migrations/__init__.py
Empty file.
25 changes: 25 additions & 0 deletions razzia/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from django.db import models

from stregsystem.models import Member
from datetime import timedelta


class Razzia(models.Model):
class Meta:
permissions = (("host_razzia", "Can host a foobar, fnugfald or bread razzia"),)

name = models.CharField(max_length=20)
turns_per_member = models.IntegerField(default=0)
turn_interval = models.DurationField(default=timedelta(0))
# required_products = models.ManyToManyField(Product)
# purchase_start_date = models.DateTimeField(null=True, blank=True)
# purchase_end_date = models.DateTimeField(null=True, blank=True)

members = models.ManyToManyField(Member, through='RazziaEntry')
start_date = models.DateTimeField(auto_now_add=True)


class RazziaEntry(models.Model):
member = models.ForeignKey(Member, on_delete=models.CASCADE)
razzia = models.ForeignKey(Razzia, on_delete=models.CASCADE)
time = models.DateTimeField(null=True, blank=True, auto_now_add=True)
14 changes: 14 additions & 0 deletions razzia/templates/members.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{% extends "admin/stregsystem/razzia/razzia.html" %}

{% block title %}{{title|default:"Razzia"}}{% endblock %}
{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../../">Hjem</a>&nbsp;&rsaquo;&nbsp;<a href="../../../">Stregsystem</a>&nbsp;&rsaquo;&nbsp;<a href="../">{{title|default:"Razzia"}}</a><a href=".">&nbsp;&rsaquo;&nbsp;Members</a></div>{% endblock %}

{% block razzia_content %}
<p><a href="../{{razzia.pk}}">Back to razzia</a></p>
<h2>Registered members at razzia {{ razzia.start_date | date:"D d M Y" }} - {{ razzia.members.all | length }} fember(s)</h2>
{% for entry in razzia.razziaentry_set.all %}
<ul>
<li>{{ entry.member.firstname }} {{ entry.member.lastname }} ({{ entry.member.username }}) at {{entry.time}}</li>
</ul>
{% endfor %}
{% endblock %}
27 changes: 27 additions & 0 deletions razzia/templates/menu.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{% extends "razzia_base.html" %}

{% block title %}{{title|default:"Razzia"}}{% endblock %}

{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../">Hjem</a>&nbsp;&rsaquo;&nbsp;<a href="../">Stregsystem</a>&nbsp;&rsaquo;&nbsp;{{title|default:"Razzia"}}</div>{% endblock %}

{% block razzia_content %}
<a href="./new">
<div class="searcher rounded">
<div class="titlebar">
<h1>{{new_text|default:"New razzia"}}</h1>
</div>
</div>
</a>
{% if razzias %}
<h2>Previous razzias</h2>
{% endif %}
{% for razzia in razzias %}
<a href="./{{ razzia.pk }}">
<div class="searcher top rounded">
<div class="titlebar">
<h1>{{ razzia.start_date | date:"D d M Y" }} - {{razzia.members.all | length}} fember(s)</h1>
</div>
</div>
</a>
{% endfor %}
{% endblock %}
35 changes: 35 additions & 0 deletions razzia/templates/razzia.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{% extends "razzia_search.html" %}

{% block breadcrumbs %}<div class="breadcrumbs"><a href="../../../">Hjem</a>&nbsp;&rsaquo;&nbsp;<a href="../../">Stregsystem</a>&nbsp;&rsaquo;&nbsp;<a href="../">Razzia</a></div>{% endblock %}

{% block member_present %}
<div class="result">
<div class="status">
{% if drunkard %}
<script>
// fade/flash background color to more easily notify foobar crew
let ofs = 0;
let el = document.body;
window.setInterval(function(){
el.style.background = 'rgba(255,255,0,'+Math.abs(Math.sin(ofs))+')';
ofs += 0.02;
}, 10);
</script>
<div class="fa fa-exclamation-triangle failure" aria-hidden="true"></div>
{% else %}
<div class="fa {% if already_used %} fa-exclamation-circle sucess {% else %} fa-check-circle sucess {% endif %}" aria-hidden="true"></div>
{% endif %}
</div>
{% if drunkard %}
{{member.firstname}} {{member.lastname}} ({{member.username}}) <b>wait {{ remaining_time_mins }}m {{ remaining_time_secs }}s </b> before next free beer
{% else %}
{{member.firstname}} {{member.lastname}} ({{member.username}}) {% if already_checked_in %} last checked in at {{last_entry.time}} {% endif %}
{% endif %}
</div>
{% endblock %}

{% block drunkard_present %}
fa-exclamation-triangle
{% if drunkard %} checked in within the previous hour, wait {{ remaining_time }}{% endif %}
{% endblock %}

16 changes: 16 additions & 0 deletions razzia/templates/razzia_base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{% extends "admin/base_site.html" %}

{% block title %}{{title|default:"Razzia"}}{% endblock %}

{% block content %}
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static '/stregsystem/razzia.css' %}" />

<script src="https://use.fontawesome.com/fd7e4e00a3.js"></script>

<div id="content-main">
<div class="grouped-vertical">
{% block razzia_content %}{% endblock %}
</div>
</div>
{% endblock %}
31 changes: 31 additions & 0 deletions razzia/templates/razzia_search.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{% extends "razzia_base.html" %}

{% block razzia_content %}
<div class="searcher">
<div class="titlebar">
<h1>{{title|default:"Razzia"}}!</h1>
</div>
<form action="./" method="post" class="content">{% csrf_token %}
<div class="grouped">
<span class="group-label fa fa-search">
</span>
<input id="usernamesearcher" type="text" autofocus name="username" maxlength="40" value="{{username}}" autocomplete="off" placeholder="Brugernavn" />
<input type="submit" class="" value="Search">
</div>
</form>
<a class="fember-link" href="./members">View registered fembers</a>
</div>
{% if queryname %}
{% if member %}
{% block member_present %}{% endblock %}
{% else %}
{% block member_not_present %}
<div class="result">
<div class="status">
<div class="fa fa-times-circle failure" aria-hidden="true"></div></div>
{{queryname}} is not a fember!!!
</div>
{% endblock %}
{% endif %}
{% endif %}
{% endblock %}
77 changes: 77 additions & 0 deletions razzia/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from django.test import TestCase
from django.urls import reverse
from freezegun import freeze_time

from razzia.models import Razzia

import datetime


class RazziaTests(TestCase):
fixtures = ["initial_data"]

def test_razzia_can_create_new(self):
previous_number_razzias = Razzia.objects.count()

self.client.login(username="tester", password="treotreo")
response = self.client.get(reverse("razzia_new"), follow=True)
last_url, status_code = response.redirect_chain[-1]

current_number_razzias = Razzia.objects.count()

self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, "razzia.html")
self.assertEqual(current_number_razzias, previous_number_razzias + 1)

def test_razzia_member_can_only_register_once(self):
self.client.login(username="tester", password="treotreo")
response = self.client.get(reverse("razzia_new"), follow=True)
razzia_url, _ = response.redirect_chain[-1]

response_add_1 = self.client.post(razzia_url, {"username": "jokke"}, follow=True)

response_add_2 = self.client.post(razzia_url, {"username": "jokke"}, follow=True)

self.assertEqual(response_add_1.status_code, 200)
self.assertEqual(response_add_2.status_code, 200)
self.assertTemplateUsed(response, "razzia.html")
# Note: Different interface, should be fixed later.
# self.assertNotContains(response_add_1, "already checked in", status_code=200)
# self.assertContains(response_add_2, "already checked in", status_code=200)

def test_razzia_member_can_register_multiple_times(self):
with freeze_time() as frozen_datetime:
self.client.login(username="tester", password="treotreo")
response = self.client.get(reverse("razzia_new"), follow=True)
razzia_url, _ = response.redirect_chain[-1]

response_members_0 = self.client.get(razzia_url + "members", follow=True)

response_add_1 = self.client.post(razzia_url, {"username": "jokke"}, follow=True)
frozen_datetime.tick(delta=datetime.timedelta(hours=1, minutes=1))
response_add_2 = self.client.post(razzia_url, {"username": "jokke"}, follow=True)

response_members_2 = self.client.get(razzia_url + "members", follow=True)

self.assertEqual(response_add_1.status_code, 200)
self.assertEqual(response_add_2.status_code, 200)
self.assertTemplateUsed(response_add_1, "razzia.html")
self.assertTemplateUsed(response_add_2, "razzia.html")
# Note: Different interface, should be fixed later.
# self.assertNotContains(response_add_1, "last checked in at", status_code=200)
# self.assertContains(response_add_2, "last checked in at", status_code=200)
self.assertContains(response_members_0, "0 fember(s)", status_code=200)
self.assertContains(response_members_2, "2 fember(s)", status_code=200)

def test_razzia_registered_member_is_in_member_list(self):
self.client.login(username="tester", password="treotreo")
response = self.client.get(reverse("razzia_new"), follow=True)
razzia_url, _ = response.redirect_chain[-1]

response_add = self.client.post(razzia_url, {"username": "jokke"}, follow=True)

response_members = self.client.get(razzia_url + "members", follow=True)

self.assertEqual(response_add.status_code, 200)
self.assertTemplateUsed(response_members, "members.html")
self.assertContains(response_members, "jokke", status_code=200)
9 changes: 9 additions & 0 deletions razzia/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from django.urls import re_path
from . import views

urlpatterns = [
re_path(r'^admin/razzia/(?P<razzia_id>\d+)/$', views.razzia, name="razzia_view"),
re_path(r'^admin/razzia/(?P<razzia_id>\d+)/members$', views.razzia_members, name="razzia_members_view"),
re_path(r'^admin/razzia/$', views.razzia_menu, name="razzia_menu"),
re_path(r'^admin/razzia/new$', views.new_razzia, name="razzia_new"),
]
Loading

0 comments on commit 5b42c8c

Please sign in to comment.