mirror of
https://github.com/lucaspalomodevelop/eventcally.git
synced 2026-03-13 08:09:37 +00:00
Send reference mail only when event changed significantly #161
This commit is contained in:
parent
85e818ef01
commit
023aca094f
6
.vscode/launch.json
vendored
6
.vscode/launch.json
vendored
@ -47,6 +47,12 @@
|
||||
"request": "launch",
|
||||
"program": "${file}",
|
||||
"console": "integratedTerminal"
|
||||
},
|
||||
{
|
||||
"name": "Debug Unit Test",
|
||||
"type": "python",
|
||||
"request": "test",
|
||||
"justMyCode": false,
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -25,6 +25,7 @@ from project.oauth2 import require_oauth
|
||||
from project.services.event import (
|
||||
get_event_with_details_or_404,
|
||||
get_events_query,
|
||||
get_significant_event_changes,
|
||||
update_event,
|
||||
)
|
||||
from project.services.event_search import EventSearchParams
|
||||
@ -59,8 +60,11 @@ class EventResource(BaseResource):
|
||||
|
||||
event = self.update_instance(EventPostRequestSchema, instance=event)
|
||||
update_event(event)
|
||||
changes = get_significant_event_changes(event)
|
||||
db.session.commit()
|
||||
send_referenced_event_changed_mails(event)
|
||||
|
||||
if changes:
|
||||
send_referenced_event_changed_mails(event)
|
||||
|
||||
return make_response("", 204)
|
||||
|
||||
@ -75,8 +79,11 @@ class EventResource(BaseResource):
|
||||
|
||||
event = self.update_instance(EventPatchRequestSchema, instance=event)
|
||||
update_event(event)
|
||||
changes = get_significant_event_changes(event)
|
||||
db.session.commit()
|
||||
send_referenced_event_changed_mails(event)
|
||||
|
||||
if changes:
|
||||
send_referenced_event_changed_mails(event)
|
||||
|
||||
return make_response("", 204)
|
||||
|
||||
|
||||
@ -37,12 +37,13 @@ class BaseResource(MethodResource):
|
||||
return instance
|
||||
|
||||
def update_instance(self, schema_cls, instance):
|
||||
instance = schema_cls().load(
|
||||
request.json, session=db.session, instance=instance
|
||||
)
|
||||
with db.session.no_autoflush:
|
||||
instance = schema_cls().load(
|
||||
request.json, session=db.session, instance=instance
|
||||
)
|
||||
|
||||
validate = getattr(instance, "validate", None)
|
||||
if callable(validate):
|
||||
validate()
|
||||
validate = getattr(instance, "validate", None)
|
||||
if callable(validate):
|
||||
validate()
|
||||
|
||||
return instance
|
||||
|
||||
@ -353,6 +353,10 @@ class UpdateEventForm(BaseEventForm):
|
||||
obj.photo = Image()
|
||||
field.populate_obj(obj, name)
|
||||
|
||||
if obj.photo and obj.photo.is_empty():
|
||||
obj.photo = None
|
||||
obj.photo_id = None
|
||||
|
||||
|
||||
class DeleteEventForm(FlaskForm):
|
||||
submit = SubmitField(lazy_gettext("Delete event"))
|
||||
|
||||
@ -15,9 +15,11 @@ from project.models import (
|
||||
EventOrganizer,
|
||||
EventPlace,
|
||||
EventReference,
|
||||
EventStatus,
|
||||
Image,
|
||||
Location,
|
||||
)
|
||||
from project.utils import get_pending_changes
|
||||
|
||||
|
||||
def get_event_category(category_name):
|
||||
@ -278,12 +280,15 @@ def update_event_dates_with_recurrence_rule(event):
|
||||
|
||||
|
||||
def insert_event(event):
|
||||
if not event.status:
|
||||
event.status = EventStatus.scheduled
|
||||
update_event_dates_with_recurrence_rule(event)
|
||||
db.session.add(event)
|
||||
|
||||
|
||||
def update_event(event):
|
||||
update_event_dates_with_recurrence_rule(event)
|
||||
with db.session.no_autoflush:
|
||||
update_event_dates_with_recurrence_rule(event)
|
||||
|
||||
|
||||
def get_upcoming_event_dates(event_id):
|
||||
@ -294,3 +299,17 @@ def get_upcoming_event_dates(event_id):
|
||||
.order_by(EventDate.start)
|
||||
.all()
|
||||
)
|
||||
|
||||
|
||||
def get_significant_event_changes(event) -> dict:
|
||||
keys = [
|
||||
"name",
|
||||
"start",
|
||||
"recurrence_rule",
|
||||
"status",
|
||||
"attendance_mode",
|
||||
"booked_up",
|
||||
"event_place_id",
|
||||
"organizer_id",
|
||||
]
|
||||
return get_pending_changes(event, include_collections=False, include_keys=keys)
|
||||
|
||||
@ -4,6 +4,7 @@ import pathlib
|
||||
from flask_babelex import lazy_gettext
|
||||
from psycopg2.errorcodes import CHECK_VIOLATION, UNIQUE_VIOLATION
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.orm.base import NO_CHANGE, object_state
|
||||
|
||||
|
||||
def get_event_category_name(category):
|
||||
@ -56,3 +57,35 @@ def make_check_violation(message: str = None, statement: str = "") -> IntegrityE
|
||||
|
||||
def make_unique_violation(message: str = None, statement: str = "") -> IntegrityError:
|
||||
return make_integrity_error(UNIQUE_VIOLATION, message, statement)
|
||||
|
||||
|
||||
def get_pending_changes(
|
||||
instance, include_collections=True, passive=None, include_keys=None
|
||||
) -> dict:
|
||||
result = {}
|
||||
|
||||
state = object_state(instance)
|
||||
|
||||
if not state.modified: # pragma: no cover
|
||||
return result
|
||||
|
||||
dict_ = state.dict
|
||||
|
||||
for attr in state.manager.attributes:
|
||||
if (
|
||||
(include_keys and attr.key not in include_keys)
|
||||
or (not include_collections and hasattr(attr.impl, "get_collection"))
|
||||
or not hasattr(attr.impl, "get_history")
|
||||
): # pragma: no cover
|
||||
continue
|
||||
|
||||
(added, unchanged, deleted) = attr.impl.get_history(
|
||||
state, dict_, passive=NO_CHANGE
|
||||
)
|
||||
|
||||
if added or deleted:
|
||||
old_value = deleted[0] if deleted else None
|
||||
new_value = added[0] if added else None
|
||||
result[attr.key] = [new_value, old_value]
|
||||
|
||||
return result
|
||||
|
||||
@ -30,6 +30,7 @@ from project.models import (
|
||||
)
|
||||
from project.services.event import (
|
||||
get_event_with_details_or_404,
|
||||
get_significant_event_changes,
|
||||
get_upcoming_event_dates,
|
||||
insert_event,
|
||||
update_event,
|
||||
@ -179,8 +180,11 @@ def event_update(event_id):
|
||||
|
||||
try:
|
||||
update_event(event)
|
||||
changes = get_significant_event_changes(event)
|
||||
db.session.commit()
|
||||
send_referenced_event_changed_mails(event)
|
||||
|
||||
if changes:
|
||||
send_referenced_event_changed_mails(event)
|
||||
flash_message(
|
||||
gettext("Event successfully updated"),
|
||||
url_for("event", event_id=event.id),
|
||||
@ -304,10 +308,11 @@ def prepare_event_form_for_suggestion(form, event_suggestion):
|
||||
|
||||
|
||||
def update_event_with_form(event, form, event_suggestion=None):
|
||||
form.populate_obj(event)
|
||||
event.categories = EventCategory.query.filter(
|
||||
EventCategory.id.in_(form.category_ids.data)
|
||||
).all()
|
||||
with db.session.no_autoflush:
|
||||
form.populate_obj(event)
|
||||
event.categories = EventCategory.query.filter(
|
||||
EventCategory.id.in_(form.category_ids.data)
|
||||
).all()
|
||||
|
||||
|
||||
def get_user_rights(event):
|
||||
|
||||
@ -314,6 +314,48 @@ def test_put_dateWithoutTimezone(client, seeder, utils, app):
|
||||
assert event.start == expected
|
||||
|
||||
|
||||
def test_put_referencedEventUpdate_sendsMail(client, seeder, utils, app, mocker):
|
||||
user_id, admin_unit_id = seeder.setup_api_access()
|
||||
event_id = seeder.create_event_via_api(admin_unit_id)
|
||||
place_id = seeder.upsert_default_event_place(admin_unit_id)
|
||||
organizer_id = seeder.upsert_default_event_organizer(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")
|
||||
seeder.create_reference(event_id, other_admin_unit_id)
|
||||
|
||||
mail_mock = utils.mock_send_mails(mocker)
|
||||
url = utils.get_url("api_v1_event", id=event_id)
|
||||
put = create_put(place_id, organizer_id)
|
||||
put["name"] = "Changed name"
|
||||
response = utils.put_json(url, put)
|
||||
|
||||
utils.assert_response_no_content(response)
|
||||
utils.assert_send_mail_called(mail_mock, "other@test.de")
|
||||
|
||||
|
||||
def test_put_referencedEventNonDirtyUpdate_doesNotSendMail(
|
||||
client, seeder, utils, app, mocker
|
||||
):
|
||||
user_id, admin_unit_id = seeder.setup_api_access()
|
||||
event_id = seeder.create_event_via_api(admin_unit_id)
|
||||
place_id = seeder.upsert_default_event_place(admin_unit_id)
|
||||
organizer_id = seeder.upsert_default_event_organizer(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")
|
||||
seeder.create_reference(event_id, other_admin_unit_id)
|
||||
|
||||
mail_mock = utils.mock_send_mails(mocker)
|
||||
url = utils.get_url("api_v1_event", id=event_id)
|
||||
put = create_put(place_id, organizer_id)
|
||||
put["name"] = "Name"
|
||||
response = utils.put_json(url, put)
|
||||
|
||||
utils.assert_response_no_content(response)
|
||||
mail_mock.assert_not_called()
|
||||
|
||||
|
||||
def test_patch(client, seeder, utils, app):
|
||||
user_id, admin_unit_id = seeder.setup_api_access()
|
||||
event_id = seeder.create_event(admin_unit_id)
|
||||
@ -342,6 +384,22 @@ def test_patch_startAfterEnd(client, seeder, utils, app):
|
||||
utils.assert_response_bad_request(response)
|
||||
|
||||
|
||||
def test_patch_referencedEventUpdate_sendsMail(client, seeder, utils, app, mocker):
|
||||
user_id, admin_unit_id = seeder.setup_api_access()
|
||||
event_id = seeder.create_event_via_api(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")
|
||||
seeder.create_reference(event_id, other_admin_unit_id)
|
||||
|
||||
mail_mock = utils.mock_send_mails(mocker)
|
||||
url = utils.get_url("api_v1_event", id=event_id)
|
||||
response = utils.patch_json(url, {"name": "Changed name"})
|
||||
|
||||
utils.assert_response_no_content(response)
|
||||
utils.assert_send_mail_called(mail_mock, "other@test.de")
|
||||
|
||||
|
||||
def test_delete(client, seeder, utils, app):
|
||||
user_id, admin_unit_id = seeder.setup_api_access()
|
||||
event_id = seeder.create_event(admin_unit_id)
|
||||
|
||||
@ -176,8 +176,7 @@ class Seeder(object):
|
||||
category = get_event_category(category_name)
|
||||
return category.id
|
||||
|
||||
def create_event(self, admin_unit_id, recurrence_rule=None, external_link=None):
|
||||
from project.dateutils import get_now
|
||||
def create_event(self, admin_unit_id, recurrence_rule="", external_link=""):
|
||||
from project.models import Event
|
||||
from project.services.event import insert_event, upsert_event_category
|
||||
|
||||
@ -187,16 +186,65 @@ class Seeder(object):
|
||||
event.categories = [upsert_event_category("Other")]
|
||||
event.name = "Name"
|
||||
event.description = "Beschreibung"
|
||||
event.start = get_now()
|
||||
event.start = self.get_now_by_minute()
|
||||
event.event_place_id = self.upsert_default_event_place(admin_unit_id)
|
||||
event.organizer_id = self.upsert_default_event_organizer(admin_unit_id)
|
||||
event.recurrence_rule = recurrence_rule
|
||||
event.external_link = external_link
|
||||
event.ticket_link = ""
|
||||
event.tags = ""
|
||||
event.price_info = ""
|
||||
insert_event(event)
|
||||
self._db.session.commit()
|
||||
event_id = event.id
|
||||
return event_id
|
||||
|
||||
def create_event_via_form(self, admin_unit_id: int) -> str:
|
||||
place_id = self.upsert_default_event_place(admin_unit_id)
|
||||
organizer_id = self.upsert_default_event_organizer(admin_unit_id)
|
||||
url = self._utils.get_url("event_create_for_admin_unit_id", id=admin_unit_id)
|
||||
response = self._utils.get_ok(url)
|
||||
response = self._utils.post_form(
|
||||
url,
|
||||
response,
|
||||
{
|
||||
"name": "Name",
|
||||
"description": "Beschreibung",
|
||||
"start": ["2030-12-31", "23", "59"],
|
||||
"event_place_id": place_id,
|
||||
"organizer_id": organizer_id,
|
||||
"photo-image_base64": self.get_default_image_upload_base64(),
|
||||
},
|
||||
)
|
||||
|
||||
with self._app.app_context():
|
||||
from project.models import Event
|
||||
|
||||
event = (
|
||||
Event.query.filter(Event.admin_unit_id == admin_unit_id)
|
||||
.filter(Event.name == "Name")
|
||||
.first()
|
||||
)
|
||||
return event.id
|
||||
|
||||
def create_event_via_api(self, admin_unit_id: int) -> int:
|
||||
place_id = self.upsert_default_event_place(admin_unit_id)
|
||||
organizer_id = self.upsert_default_event_organizer(admin_unit_id)
|
||||
|
||||
url = self._utils.get_url("api_v1_organization_event_list", id=admin_unit_id)
|
||||
response = self._utils.post_json(
|
||||
url,
|
||||
{
|
||||
"name": "Name",
|
||||
"start": "2021-02-07T11:00:00.000Z",
|
||||
"place": {"id": place_id},
|
||||
"organizer": {"id": organizer_id},
|
||||
},
|
||||
)
|
||||
self._utils.assert_response_created(response)
|
||||
assert "id" in response.json
|
||||
return response.json["id"]
|
||||
|
||||
def get_default_image_base64(self):
|
||||
return """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"""
|
||||
|
||||
@ -217,7 +265,6 @@ class Seeder(object):
|
||||
return image_id
|
||||
|
||||
def create_event_suggestion(self, admin_unit_id, free_text=False):
|
||||
from project.dateutils import get_now
|
||||
from project.models import EventSuggestion
|
||||
from project.services.event import upsert_event_category
|
||||
from project.services.event_suggestion import insert_event_suggestion
|
||||
@ -230,7 +277,7 @@ class Seeder(object):
|
||||
suggestion.contact_email_notice = True
|
||||
suggestion.name = "Vorschlag"
|
||||
suggestion.description = "Beschreibung"
|
||||
suggestion.start = get_now()
|
||||
suggestion.start = self.get_now_by_minute()
|
||||
suggestion.photo_id = self.upsert_default_image()
|
||||
suggestion.categories = [upsert_event_category("Other")]
|
||||
|
||||
@ -290,3 +337,13 @@ class Seeder(object):
|
||||
event_id = self.create_event(other_admin_unit_id)
|
||||
reference_request_id = self.create_reference_request(event_id, admin_unit_id)
|
||||
return (other_user_id, other_admin_unit_id, event_id, reference_request_id)
|
||||
|
||||
def get_now_by_minute(self):
|
||||
from datetime import datetime
|
||||
|
||||
from project.dateutils import get_now
|
||||
|
||||
now = get_now()
|
||||
return datetime(
|
||||
now.year, now.month, now.day, now.hour, now.minute, tzinfo=now.tzinfo
|
||||
)
|
||||
|
||||
@ -199,15 +199,16 @@ def test_admin_unit_references_outgoing(client, seeder, utils):
|
||||
|
||||
def test_referencedEventUpdate_sendsMail(client, seeder, utils, app, mocker):
|
||||
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)
|
||||
other_user_id = seeder.create_user("other@test.de")
|
||||
other_admin_unit_id = seeder.create_admin_unit(other_user_id, "Other Crew")
|
||||
|
||||
utils.logout()
|
||||
utils.login("other@test.de")
|
||||
|
||||
# Event per Form anlegen, um dieselben Default-Werte wie im Update zu haben
|
||||
event_id = seeder.create_event_via_form(other_admin_unit_id)
|
||||
seeder.create_reference(event_id, admin_unit_id)
|
||||
|
||||
url = utils.get_url("event_update", event_id=event_id)
|
||||
response = utils.get_ok(url)
|
||||
|
||||
@ -221,3 +222,30 @@ def test_referencedEventUpdate_sendsMail(client, seeder, utils, app, mocker):
|
||||
)
|
||||
|
||||
utils.assert_send_mail_called(mail_mock, "test@test.de")
|
||||
|
||||
|
||||
def test_referencedEventNonDirtyUpdate_doesNotSendMail(
|
||||
client, seeder, utils, app, mocker
|
||||
):
|
||||
user_id, admin_unit_id = seeder.setup_base()
|
||||
other_user_id = seeder.create_user("other@test.de")
|
||||
other_admin_unit_id = seeder.create_admin_unit(other_user_id, "Other Crew")
|
||||
|
||||
utils.logout()
|
||||
utils.login("other@test.de")
|
||||
|
||||
# Event per Form anlegen, um dieselben Default-Werte wie im Update zu haben
|
||||
event_id = seeder.create_event_via_form(other_admin_unit_id)
|
||||
seeder.create_reference(event_id, admin_unit_id)
|
||||
|
||||
url = utils.get_url("event_update", event_id=event_id)
|
||||
response = utils.get_ok(url)
|
||||
|
||||
mail_mock = utils.mock_send_mails(mocker)
|
||||
response = utils.post_form(
|
||||
url,
|
||||
response,
|
||||
{},
|
||||
)
|
||||
|
||||
mail_mock.assert_not_called()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user