From 45ecb12ed625edee9a5d3cd1929df4e3f12092b3 Mon Sep 17 00:00:00 2001 From: Matthias Veit Date: Tue, 1 Oct 2024 17:30:49 +0200 Subject: [PATCH] [feat] user notification settings: add marketing column (#630) --- fixbackend/auth/schemas.py | 4 ++++ .../notification/user_notification_repo.py | 23 +++++++++++++------ .../2024-10-01T14:23:11Z_email_marketing.py | 23 +++++++++++++++++++ tests/fixbackend/auth/users_router_test.py | 4 ++-- .../user_notification_repo_test.py | 3 +++ 5 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 migrations/versions/2024-10-01T14:23:11Z_email_marketing.py diff --git a/fixbackend/auth/schemas.py b/fixbackend/auth/schemas.py index bcdd095f..9f14ee36 100644 --- a/fixbackend/auth/schemas.py +++ b/fixbackend/auth/schemas.py @@ -80,6 +80,7 @@ class UserNotificationSettingsRead(BaseModel): weekly_report: bool = Field(description="Whether to receive a weekly report") inactivity_reminder: bool = Field(description="Whether to receive a reminder for open incidents") tutorial: bool = Field(description="Whether to receive tutorial emails") + marketing: bool = Field(description="Whether to receive marketing emails") @staticmethod def from_model(model: UserNotificationSettings) -> "UserNotificationSettingsRead": @@ -87,6 +88,7 @@ def from_model(model: UserNotificationSettings) -> "UserNotificationSettingsRead weekly_report=model.weekly_report, inactivity_reminder=model.inactivity_reminder, tutorial=model.tutorial, + marketing=model.marketing, ) def to_model(self, user_id: UserId) -> UserNotificationSettings: @@ -95,6 +97,7 @@ def to_model(self, user_id: UserId) -> UserNotificationSettings: weekly_report=self.weekly_report, inactivity_reminder=self.inactivity_reminder, tutorial=self.tutorial, + marketing=self.marketing, ) @@ -104,6 +107,7 @@ class UserNotificationSettingsWrite(BaseModel): default=None, description="Whether to receive a reminder for open incidents" ) tutorial: Optional[bool] = Field(default=None, description="Whether to receive tutorial emails") + marketing: Optional[bool] = Field(default=None, description="Whether to receive marketing emails") class OTPConfig(BaseModel): diff --git a/fixbackend/notification/user_notification_repo.py b/fixbackend/notification/user_notification_repo.py index 50eac0f0..8667bf27 100644 --- a/fixbackend/notification/user_notification_repo.py +++ b/fixbackend/notification/user_notification_repo.py @@ -31,9 +31,10 @@ @frozen class UserNotificationSettings: user_id: UserId - weekly_report: bool - inactivity_reminder: bool - tutorial: bool + weekly_report: bool = True + inactivity_reminder: bool = True + tutorial: bool = True + marketing: bool = True class UserNotificationSettingsEntity(CreatedUpdatedMixin, Base): @@ -43,6 +44,7 @@ class UserNotificationSettingsEntity(CreatedUpdatedMixin, Base): weekly_report: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True) inactivity_reminder: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True) tutorial: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True) + marketing: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True) def to_model(self) -> UserNotificationSettings: return UserNotificationSettings( @@ -50,6 +52,7 @@ def to_model(self) -> UserNotificationSettings: weekly_report=self.weekly_report, inactivity_reminder=self.inactivity_reminder, tutorial=self.tutorial, + marketing=self.marketing, ) @staticmethod @@ -59,6 +62,7 @@ def from_model(settings: UserNotificationSettings) -> "UserNotificationSettingsE weekly_report=settings.weekly_report, inactivity_reminder=settings.inactivity_reminder, tutorial=settings.tutorial, + marketing=settings.marketing, ) @@ -72,9 +76,7 @@ async def get_notification_settings(self, user_id: UserId) -> UserNotificationSe if result := await session.get(UserNotificationSettingsEntity, user_id): return result.to_model() else: - return UserNotificationSettings( - user_id=user_id, weekly_report=True, inactivity_reminder=True, tutorial=True - ) + return UserNotificationSettings(user_id=user_id) async def update_notification_settings( self, @@ -83,6 +85,7 @@ async def update_notification_settings( weekly_report: Optional[bool] = None, inactivity_reminder: Optional[bool] = None, tutorial: Optional[bool] = None, + marketing: Optional[bool] = None, ) -> UserNotificationSettings: async with self.session_maker() as session: if isinstance(user_id_or_email, str): @@ -99,7 +102,11 @@ async def update_notification_settings( value = await session.get(UserNotificationSettingsEntity, user_id) if value is None: value = UserNotificationSettingsEntity( - user_id=user_id, weekly_report=True, inactivity_reminder=True, tutorial=True + user_id=user_id, + weekly_report=True, + inactivity_reminder=True, + tutorial=True, + marketing=True, ) session.add(value) if weekly_report is not None: @@ -108,6 +115,8 @@ async def update_notification_settings( value.inactivity_reminder = inactivity_reminder if tutorial is not None: value.tutorial = tutorial + if marketing is not None: + value.marketing = marketing settings = value.to_model() await session.commit() return settings diff --git a/migrations/versions/2024-10-01T14:23:11Z_email_marketing.py b/migrations/versions/2024-10-01T14:23:11Z_email_marketing.py new file mode 100644 index 00000000..cebc1860 --- /dev/null +++ b/migrations/versions/2024-10-01T14:23:11Z_email_marketing.py @@ -0,0 +1,23 @@ +""" +user_notification_settings: add marketing column +""" + +from typing import Union + +import sqlalchemy as sa +from alembic import op + +revision: str = "2c3086217445" +down_revision: Union[str, None] = "1e4ccaf4e087" + + +def upgrade() -> None: + op.add_column( + "user_notification_settings", + sa.Column( + "marketing", + sa.Boolean(), + nullable=False, + server_default="true", + ), + ) diff --git a/tests/fixbackend/auth/users_router_test.py b/tests/fixbackend/auth/users_router_test.py index 863e02db..36f2857d 100644 --- a/tests/fixbackend/auth/users_router_test.py +++ b/tests/fixbackend/auth/users_router_test.py @@ -43,8 +43,8 @@ async def client( async def test_user_notification_settings(client: AsyncClient) -> None: response = await client.get("/api/users/me/settings/notifications") assert response.status_code == 200 - assert response.json() == {"inactivity_reminder": True, "weekly_report": True, "tutorial": True} + assert response.json() == {"inactivity_reminder": True, "weekly_report": True, "tutorial": True, "marketing": True} response = await client.put("/api/users/me/settings/notifications", json={"weekly_report": False}) assert response.status_code == 200 - assert response.json() == {"inactivity_reminder": True, "weekly_report": False, "tutorial": True} + assert response.json() == {"inactivity_reminder": True, "weekly_report": False, "tutorial": True, "marketing": True} diff --git a/tests/fixbackend/notification/user_notification_repo_test.py b/tests/fixbackend/notification/user_notification_repo_test.py index 2adf2359..54e6e155 100644 --- a/tests/fixbackend/notification/user_notification_repo_test.py +++ b/tests/fixbackend/notification/user_notification_repo_test.py @@ -41,6 +41,7 @@ async def test_user_notification_settings_repo(async_session_maker: AsyncSession assert updated.weekly_report is False assert updated.inactivity_reminder is True assert updated.tutorial is False + assert updated.marketing is True # get updated settings settings = await repo.get_notification_settings(user.id) @@ -48,6 +49,7 @@ async def test_user_notification_settings_repo(async_session_maker: AsyncSession assert settings.weekly_report is False assert settings.inactivity_reminder is True assert settings.tutorial is False + assert settings.marketing is True # update via email settings updated = await repo.update_notification_settings( @@ -56,3 +58,4 @@ async def test_user_notification_settings_repo(async_session_maker: AsyncSession assert updated.weekly_report is True assert updated.inactivity_reminder is False assert updated.tutorial is True + assert updated.marketing is True