Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Envelope labels #173

Merged
merged 4 commits into from
Jan 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion registry/donor/forms.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
from flask import flash
from flask_wtf import FlaskForm
from wtforms import BooleanField, HiddenField, StringField, TextAreaField
from wtforms import (
BooleanField,
HiddenField,
IntegerField,
StringField,
TextAreaField,
)

from registry.donor.models import (
AwardedMedals,
Expand Down Expand Up @@ -103,3 +109,24 @@ def get_field_data(self):
field_data[field] = getattr(self, field).data or None

return field_data


class PrintEnvelopeLabelsForm(FlaskForm):
medal_id = HiddenField(validators=[DataRequired()])
skip = IntegerField(validators=[DataRequired()])

def validate(self):
self.medal = Medals.query.get(self.medal_id.data)

if self.medal is None:
flash("Odeslána nevalidní data.", "danger")
return False

if self.skip.data is None:
self.skip.data = 0

if not (0 <= self.skip.data < 16):
flash("Vynechat lze 0 až 15 štítků.", "danger")
return False
Comment on lines +128 to +130
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested this manually and the propper message does not seem to show itself. I see only an info message in English.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It works if you have disabled javascript. If you use JS, the browser doesn't allow you to send the request to the server.


return True
38 changes: 38 additions & 0 deletions registry/donor/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
from datetime import datetime
from itertools import chain

from flask import (
Blueprint,
Expand All @@ -23,6 +24,7 @@
DonorsOverrideForm,
IgnoreDonorForm,
NoteForm,
PrintEnvelopeLabelsForm,
RemoveFromIgnoredForm,
RemoveMedalForm,
)
Expand Down Expand Up @@ -214,6 +216,40 @@ def render_award_documents_for_award_prep(medal_slug):
)


@blueprint.post("/award_prep/envelope_labels")
@login_required
def render_envelope_labels():
print_envelope_labels_form = PrintEnvelopeLabelsForm()
if print_envelope_labels_form.validate_on_submit():
medal = print_envelope_labels_form.medal
donors = DonorsOverview.query.filter(
and_(
DonorsOverview.donation_count_total >= medal.minimum_donations,
getattr(DonorsOverview, "awarded_medal_" + medal.slug).is_(False),
)
).all()

# To skip already used labels, we prepend some
# empty donors to the list.
empty_donor = {
k: "" for k in ("first_name", "last_name", "address", "city", "postal_code")
}
all_donors = chain([empty_donor] * print_envelope_labels_form.skip.data, donors)
pages = []

for index, donor in enumerate(all_donors):
if index % 16 == 0:
pages.append([])
pages[-1].append(donor)

return render_template(
"donor/envelope_labels.html",
pages=pages,
)

return redirect(request.referrer)


@blueprint.post("/remove_medal")
@login_required
def remove_medal():
Expand All @@ -240,12 +276,14 @@ def award_prep(medal_slug):
).all()
award_medal_form = AwardMedalForm()
award_medal_form.add_checkboxes([d.rodne_cislo for d in donors])
print_envelope_labels_form = PrintEnvelopeLabelsForm()
return render_template(
"donor/award_prep.html",
medal=medal,
donors=donors,
award_medal_form=award_medal_form,
override_column_names=json.dumps(DonorsOverview.basic_fields),
print_envelope_labels_form=print_envelope_labels_form,
)


Expand Down
15 changes: 11 additions & 4 deletions registry/templates/donor/award_prep.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,19 @@

<h1>Přehled dárců k ocenění: {{ medal.title }}</h1>

{% with form=award_medal_form %}

<a class="btn btn-primary" role="button" href="{{ url_for('donor.render_award_documents_for_award_prep', medal_slug=medal.slug) }}" target="_blank">Potvrzení k medailím pro všechny</a>
{% with form=print_envelope_labels_form %}
<form id="printEnvelopeLabelsForm" action="{{ url_for('donor.render_envelope_labels') }}" method="POST" class="form-inline" role="form" target="_blank">
{{ form.csrf_token }}
{{ form.medal_id(value=medal.id) }}
<input type="submit" class="btn btn-primary" value="Štítky na obálky">
<div>Vynechat prvních {{ form.skip(value=0, size=2, min=0, max=15) }} štítků.</div>
</form>
{% endwith %}
{% with form=award_medal_form %}
<form id="awardMedalForm" action="{{ url_for('donor.award_medal') }}" method="POST" class="form-inline" role="form">
{{ form.csrf_token }}
{{ form.medal_id(value=medal.id) }}
{{ form.csrf_token }}
{{ form.medal_id(value=medal.id) }}
<input type="submit" class="btn btn-success" value="Udělit medaili označeným dárcům">

<!-- Updating the table? Don't forget to check the print (pre)view. -->
Expand Down
80 changes: 80 additions & 0 deletions registry/templates/donor/envelope_labels.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<!--

This page is prepared for 16 labels 105×37 mm each.
For example: https://obalyostrava.cz/samolepici-etikety/428-etikety-a4-105x37mm-100stranek.html

-->
<!DOCTYPE html>
<html lang="cs">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Štítky na obálky</title>
<!-- <link rel="stylesheet" href="{{ url_for('static', filename='css/award_document.css') }}"> -->
<style>
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
background-color: grey; /* #FAFAFA */
font-family: Arial, Helvetica, sans-serif;
font-size: 16pt;
}

.page {
width: 210mm;
height: 297mm;
margin: 10mm auto;
background: white;
}

.label {
width: 105mm;
height: 37mm;
float: left;
}

p {
margin: 4mm auto auto 5mm;
}

@page {
size: A4;
margin: 0;
}

@media print {
html, body {
width: 210mm;
height: 297mm;
}
.page {
margin: 0;
border: initial;
border-radius: initial;
width: initial;
min-height: initial;
box-shadow: initial;
background: initial;
page-break-after: always;
}
}

</style>
</head>
<body>
{% for page in pages %}
<div class="page">
{% for donor in page %}
<div class="label">
<p>{{ donor.first_name}} {{ donor.last_name }}</p>
<p>{{ donor.address }}</p>
<p>{{ donor.postal_code }} {{donor.city}}</p>
</div>
{% endfor %}
</div>
{% endfor %}
</body>
</html>
3 changes: 3 additions & 0 deletions tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ def test_dynamic_urls_404(self, user, testapp, case_name):
("donor.awarded", {}),
("donor.show_ignored", {}),
("donor.award_prep", {"medal_slug": "br"}),
("donor.render_award_document", {"medal_slug": "br", "rc": "0000000000"}),
("donor.render_award_documents_for_award_prep", {"medal_slug": "br"}),
("donor.render_envelope_labels", {}),
]

@pytest.mark.parametrize(("endpoint, kwargs"), testcases_401)
Expand Down
112 changes: 112 additions & 0 deletions tests/test_detail.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import re
from datetime import datetime
from math import ceil

import pytest
from flask import url_for
from sqlalchemy import and_

from registry.donor.models import (
AwardedMedals,
Expand Down Expand Up @@ -187,3 +189,113 @@ def test_award_prep_documents(self, user, testapp, medal_id):

assert rows == documents.text.count('<div class="page">')
assert rows == documents.text.count(f"Ve Frýdku-Místku, dne {today}")


class TestEnvelopeLabels:
@pytest.mark.parametrize("medal_id", range(1, 8))
def test_envelope_labels(self, user, testapp, medal_id):
medal = Medals.query.get(medal_id)
login(user, testapp)
page = testapp.get(url_for("donor.award_prep", medal_slug=medal.slug))
labels = page.forms["printEnvelopeLabelsForm"].submit()
eligible_donors = DonorsOverview.query.filter(
and_(
DonorsOverview.donation_count_total >= medal.minimum_donations,
getattr(DonorsOverview, "awarded_medal_" + medal.slug).is_(False),
)
).count()

pages_count = labels.text.count('<div class="page">')
assert ceil(eligible_donors / 16) == pages_count

labels_count = labels.text.count('<div class="label">')
assert labels_count == eligible_donors

def test_envelope_labels_detail(self, user, testapp):
medal = Medals.query.get(1)
login(user, testapp)
page = testapp.get(url_for("donor.award_prep", medal_slug=medal.slug))
labels = page.forms["printEnvelopeLabelsForm"].submit()
eligible_donors = DonorsOverview.query.filter(
and_(
DonorsOverview.donation_count_total >= medal.minimum_donations,
getattr(DonorsOverview, "awarded_medal_" + medal.slug).is_(False),
)
).all()

for donor in eligible_donors:
assert f"<p>{donor.first_name} {donor.last_name}</p>" in labels.text
assert f"<p>{donor.address}</p>" in labels.text
assert f"<p>{donor.postal_code} {donor.city}</p>" in labels.text

@pytest.mark.parametrize("skip", (1, 3, 9, 13))
@pytest.mark.parametrize("medal_id", range(1, 8))
def test_envelope_labels_skip(self, user, testapp, medal_id, skip):
medal = Medals.query.get(medal_id)
login(user, testapp)
page = testapp.get(url_for("donor.award_prep", medal_slug=medal.slug))
page.forms["printEnvelopeLabelsForm"].fields["skip"][0].value = skip
labels = page.forms["printEnvelopeLabelsForm"].submit()
eligible_donors = DonorsOverview.query.filter(
and_(
DonorsOverview.donation_count_total >= medal.minimum_donations,
getattr(DonorsOverview, "awarded_medal_" + medal.slug).is_(False),
)
).count()

labels_count = labels.text.count('<div class="label">')
assert labels_count == eligible_donors + skip

pages_count = labels.text.count('<div class="page">')
assert ceil((eligible_donors + skip) / 16) == pages_count

empty_p = labels.text.count("<p></p>") # for address
space_p = labels.text.count("<p> </p>") # for name and city

assert empty_p == skip
assert space_p == skip * 2

@pytest.mark.parametrize("skip", (-1, -33, 99, 16))
def test_envelope_labels_invalid_skip(self, user, testapp, skip):
medal = Medals.query.get(1)
login(user, testapp)
page = testapp.get(url_for("donor.award_prep", medal_slug=medal.slug))
page.forms["printEnvelopeLabelsForm"].fields["skip"][0].value = skip
labels = page.forms["printEnvelopeLabelsForm"].submit().follow()

assert "Vynechat lze 0 až 15 štítků." in labels.text

def test_envelope_labels_empty_skip(self, user, testapp):
medal = Medals.query.get(1)
login(user, testapp)
page = testapp.get(url_for("donor.award_prep", medal_slug=medal.slug))
page.forms["printEnvelopeLabelsForm"].fields["skip"][0].value = ""
labels = page.forms["printEnvelopeLabelsForm"].submit()
eligible_donors = DonorsOverview.query.filter(
and_(
DonorsOverview.donation_count_total >= medal.minimum_donations,
getattr(DonorsOverview, "awarded_medal_" + medal.slug).is_(False),
)
).count()

labels_count = labels.text.count('<div class="label">')
assert labels_count == eligible_donors

pages_count = labels.text.count('<div class="page">')
assert ceil(eligible_donors / 16) == pages_count

empty_p = labels.text.count("<p></p>") # for address
space_p = labels.text.count("<p> </p>") # for name and city

assert empty_p == 0
assert space_p == 0

@pytest.mark.parametrize("medal_id", (-1, -33, 99, 16))
def test_envelope_labels_invalid_medal(self, user, testapp, medal_id):
medal = Medals.query.get(1)
login(user, testapp)
page = testapp.get(url_for("donor.award_prep", medal_slug=medal.slug))
page.forms["printEnvelopeLabelsForm"].fields["medal_id"][0].value = medal_id
labels = page.forms["printEnvelopeLabelsForm"].submit().follow()

assert "Odeslána nevalidní data." in labels.text
Loading