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

Group send mail bug #678

Merged
merged 3 commits into from
Oct 24, 2023
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
28 changes: 20 additions & 8 deletions pycroft/lib/user.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2015 The Pycroft Authors. See the AUTHORS file.

Check warning on line 1 in pycroft/lib/user.py

View workflow job for this annotation

GitHub Actions / python-lint

Warning

docstring of pycroft.lib.user.edit_email:8: Field list ends without a blank line; unexpected unindent.

Check warning on line 1 in pycroft/lib/user.py

View workflow job for this annotation

GitHub Actions / python-lint

Warning

docstring of pycroft.lib.user.edit_birthdate:5: Field list ends without a blank line; unexpected unindent.
# This file is part of the Pycroft project and licensed under the terms of
# the Apache License, Version 2.0. See the LICENSE file for details.
"""
Expand All @@ -17,7 +17,8 @@
from difflib import SequenceMatcher
from typing import Iterable

from sqlalchemy import func, select, Boolean, String, ColumnElement
from sqlalchemy import func, select, Boolean, String, ColumnElement, ScalarResult
from sqlalchemy.orm import Session

from pycroft import config, property
from pycroft.helpers import user as user_helper, utc
Expand Down Expand Up @@ -53,9 +54,15 @@
UserMoveInParams
from pycroft.model.traffic import TrafficHistoryEntry
from pycroft.model.traffic import traffic_history as func_traffic_history
from pycroft.model.user import User, UnixAccount, PreMember, BaseUser, \
RoomHistoryEntry, \
PropertyGroup
from pycroft.model.user import (
User,
UnixAccount,
PreMember,
BaseUser,
RoomHistoryEntry,
PropertyGroup,
Membership,
)
from pycroft.model.webstorage import WebStorage
from pycroft.task import send_mails_async

Expand Down Expand Up @@ -1087,12 +1094,17 @@
user_send_mails([user], template, soft_fail, use_internal, **kwargs)


def group_send_mail(group: PropertyGroup, subject: str, body_plain: str) -> None:
active_memberships = User.active_memberships()
def get_active_users(session: Session, group: PropertyGroup) -> ScalarResult[User]:
return session.scalars(
select(User)
.join(User.current_memberships)
.where(Membership.group == group)
.distinct()
)

users = User.q.join(active_memberships)\
.filter(active_memberships.c.group_id == group.id).distinct().all()

def group_send_mail(group: PropertyGroup, subject: str, body_plain: str) -> None:
users = get_active_users(session=session.session, group=group)
user_send_mails(users, soft_fail=True, body_plain=body_plain, subject=subject)


Expand Down
52 changes: 52 additions & 0 deletions tests/lib/user/test_active_members.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import pytest
from datetime import datetime, timedelta

from pycroft.helpers.interval import closedopen
from pycroft.lib.user import get_active_users
from pycroft.model.user import PropertyGroup, User
from tests import factories as f


@pytest.fixture(scope="session")
def yesterday() -> datetime:
return datetime.now() - timedelta(days=1)


@pytest.fixture(scope="session")
def next_year() -> datetime:
return datetime.now() + timedelta(days=365)


@pytest.fixture(scope="module")
def g(module_session) -> PropertyGroup:
return f.PropertyGroupFactory.create(name="cool group")


@pytest.fixture(scope="module")
def users_with_mem(module_session, yesterday, next_year, g) -> tuple[User, User]:
u1 = f.UserFactory.create(
with_membership=True,
membership__group=g,
membership__active_during=closedopen(yesterday, next_year),
)
u2 = f.UserFactory.create(
with_membership=True,
membership__group=g,
membership__active_during=closedopen(yesterday, None),
)
return u1, u2


@pytest.fixture(scope="module")
def users_without_mem(module_session, yesterday, g) -> tuple[User, User]:
u3 = f.UserFactory.create(
with_membership=True,
membership__group=g,
membership__active_during=closedopen(None, yesterday),
)
u4 = f.UserFactory.create()
return u3, u4


def test_get_active_members(session, g, users_with_mem):
assert set(get_active_users(session, g)) == set(users_with_mem)
Loading