Handle duplicate references #89

This commit is contained in:
Daniel Grams 2021-01-25 11:07:49 +01:00
parent 9ba18a6f63
commit 0cffc7ec7e
9 changed files with 141 additions and 13 deletions

View File

@ -0,0 +1,46 @@
"""empty message
Revision ID: 35a6577b6af8
Revises: a0a248667cd8
Create Date: 2021-01-25 10:37:41.116909
"""
from alembic import op
import sqlalchemy as sa
import sqlalchemy_utils
from project import dbtypes
# revision identifiers, used by Alembic.
revision = "35a6577b6af8"
down_revision = "a0a248667cd8"
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_unique_constraint(
"eventreference_event_id_admin_unit_id",
"eventreference",
["event_id", "admin_unit_id"],
)
op.create_unique_constraint(
"eventreferencerequest_event_id_admin_unit_id",
"eventreferencerequest",
["event_id", "admin_unit_id"],
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(
"eventreferencerequest_event_id_admin_unit_id",
"eventreferencerequest",
type_="unique",
)
op.drop_constraint(
"eventreference_event_id_admin_unit_id", "eventreference", type_="unique"
)
# ### end Alembic commands ###

View File

@ -373,6 +373,11 @@ def purge_event_organizer(mapper, connect, self):
class EventReference(db.Model, TrackableMixin):
__tablename__ = "eventreference"
__table_args__ = (
UniqueConstraint(
"event_id", "admin_unit_id", name="eventreference_event_id_admin_unit_id"
),
)
id = Column(Integer(), primary_key=True)
event_id = db.Column(db.Integer, db.ForeignKey("event.id"), nullable=False)
admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=False)
@ -384,6 +389,13 @@ class EventReference(db.Model, TrackableMixin):
class EventReferenceRequest(db.Model, TrackableMixin):
__tablename__ = "eventreferencerequest"
__table_args__ = (
UniqueConstraint(
"event_id",
"admin_unit_id",
name="eventreferencerequest_event_id_admin_unit_id",
),
)
id = Column(Integer(), primary_key=True)
event_id = db.Column(db.Integer, db.ForeignKey("event.id"), nullable=False)
admin_unit_id = db.Column(db.Integer, db.ForeignKey("adminunit.id"), nullable=False)
@ -431,7 +443,9 @@ class EventMixin(object):
class EventSuggestion(db.Model, TrackableMixin, EventMixin):
__tablename__ = "eventsuggestion"
__table_args__ = (
CheckConstraint("NOT(event_place_id IS NULL AND event_place_text IS NULL)"),
CheckConstraint(
"NOT(event_place_id IS NULL AND event_place_text IS NULL)",
),
CheckConstraint("NOT(organizer_id IS NULL AND organizer_text IS NULL)"),
)
id = Column(Integer(), primary_key=True)

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2021-01-25 09:17+0100\n"
"POT-Creation-Date: 2021-01-25 10:17+0100\n"
"PO-Revision-Date: 2020-06-07 18:51+0200\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: de\n"
@ -1634,12 +1634,18 @@ msgstr "Empfehlung erfolgreich erstellt"
msgid "Request successfully updated"
msgstr "Empfehlungsanfrage erfolgreich aktualisiert"
#: project/views/utils.py:53
#: project/views/utils.py:30
msgid ""
"An entry with the entered values already exists. Duplicate entries are "
"not allowed."
msgstr "Ein Eintrag mit den eingegebenen Werten existiert bereits. Doppelte Einträge sind nicht erlaubt."
#: project/views/utils.py:61
#, python-format
msgid "Error in the %s field - %s"
msgstr "Fehler im Feld %s: %s"
#: project/views/utils.py:61
#: project/views/utils.py:69
msgid "Show"
msgstr "Anzeigen"

View File

@ -4,6 +4,7 @@ from flask_babelex import gettext
from flask import request, url_for, render_template, flash, redirect, Markup
from flask_mail import Message
from sqlalchemy.exc import SQLAlchemyError
from psycopg2.errorcodes import UNIQUE_VIOLATION
def track_analytics(key, value1, value2):
@ -19,12 +20,21 @@ def track_analytics(key, value1, value2):
def handleSqlError(e: SQLAlchemyError) -> str:
if e.orig:
message = str(e.orig)
else:
message = str(e)
print(message)
return message
if not e.orig:
return str(e)
prefix = None
message = str(e.orig)
if e.orig.pgcode == UNIQUE_VIOLATION:
prefix = gettext(
"An entry with the entered values already exists. Duplicate entries are not allowed."
)
if not prefix:
return message
return "%s (%s)" % (prefix, message)
def get_pagination_urls(pagination, **kwargs):

View File

@ -86,10 +86,10 @@ class UtilActions(object):
assert response.content_type == "application/json"
return response.json
def mock_db_commit(self, mocker):
def mock_db_commit(self, mocker, orig=None):
mocked_commit = mocker.patch("project.db.session.commit")
mocked_commit.side_effect = IntegrityError(
"MockException", "MockException", None
"MockException", "MockException", orig
)
def mock_send_mails(self, mocker):

View File

@ -1,4 +1,5 @@
import pytest
from psycopg2.errors import UniqueViolation
def test_read(client, seeder, utils):
@ -19,7 +20,7 @@ def test_create(client, app, utils, seeder, mocker, db_error):
response = utils.get_ok(url)
if db_error:
utils.mock_db_commit(mocker)
utils.mock_db_commit(mocker, UniqueViolation("MockException", "MockException"))
response = utils.post_form(
url,

View File

@ -49,6 +49,27 @@ def test_create(client, app, utils, seeder, mocker, db_error):
assert reference is not None
def test_create_duplicateNotAllowed(client, seeder, utils, app):
user_id, admin_unit_id = seeder.setup_base()
(
other_user_id,
other_admin_unit_id,
event_id,
reference_id,
) = seeder.create_any_reference(admin_unit_id)
url = utils.get_url("event_reference_create", event_id=event_id)
response = utils.get_ok(url)
response = utils.post_form(
url,
response,
{"admin_unit_id": admin_unit_id},
)
utils.assert_response_ok(response)
assert b"duplicate key" in response.data
def test_create_401(client, app, utils, seeder, mocker):
seeder.create_user()
seeder._utils.login()

View File

@ -50,6 +50,36 @@ def test_create(client, app, utils, seeder, mocker, db_error):
)
def test_create_duplicateNotAllowed(client, app, utils, seeder):
user_id, admin_unit_id = seeder.setup_base()
event_id = seeder.create_event(admin_unit_id)
other_user_id = seeder.create_user("other@test.de")
other_admin_unit_id = seeder.create_admin_unit(other_user_id, "Other Crew")
# First
url = utils.get_url("event_reference_request_create", event_id=event_id)
response = utils.get_ok(url)
response = utils.post_form(
url,
response,
{"admin_unit_id": other_admin_unit_id},
)
utils.assert_response_redirect(
response, "manage_admin_unit_reference_requests_outgoing", id=admin_unit_id
)
# Second
url = utils.get_url("event_reference_request_create", event_id=event_id)
response = utils.get_ok(url)
response = utils.post_form(
url,
response,
{"admin_unit_id": other_admin_unit_id},
)
utils.assert_response_ok(response)
assert b"duplicate key" in response.data
def test_admin_unit_reference_requests_incoming(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_base()
seeder.create_incoming_reference_request(admin_unit_id)