from collections.abc import Iterable, Sequence from fansifter_common.email import EmailType from email_campaigns.adapters.db import Repository from email_campaigns.emails.models import BaseEmail, EmailAnalyticsV3Dbt from email_campaigns.emails.types import ( EmailAnalytics, EmailAnalyticsList, EmailLinkAnalytics, EmailLinkAnalyticsList, EmailReportingAnalytics, EmailReportingAnalyticsAdapter, EmailReportingLinkAnalytics, EmailReportingLinkAnalyticsList, ) class EmailAnalyticsRepository(Repository[EmailAnalyticsV3Dbt]): def find_analytics_by_ids( self, email_ids: Iterable[str], *, email_type: EmailType ) -> list[EmailAnalytics]: if not email_ids: return [] query = self.db.query_from_template( "email-analytics/find-by-email-ids.sql", context={ "email_ids": email_ids, "email_type": email_type, }, ) result = self.db.session.execute(query) return EmailAnalyticsList.validate_python(result.mappings().all()) def find_link_analytics_by_id( self, email_id: str, *, email_type: EmailType ) -> list[EmailLinkAnalytics]: if not email_id: return [] query = self.db.query_from_template( "email-analytics/find-links-by-email-id.sql", context={ "email_id": email_id, "email_type": email_type, }, ) result = self.db.session.execute(query).mappings() return EmailLinkAnalyticsList.validate_python(result) def prefetch_analytics[T: BaseEmail]( self, emails: Sequence[T], *, email_type: EmailType ) -> Sequence[T]: email_ids = [email.id for email in emails] analytics = { analytics.campaign_id: analytics for analytics in self.find_analytics_by_ids( email_ids, email_type=email_type ) } for email in emails: email.analytics = analytics.get(email.id) return emails def find_reporting_analytics_by_email_ids( self, email_ids: Iterable[str], *, email_type: EmailType ) -> EmailReportingAnalytics: if not email_ids: return EmailReportingAnalyticsAdapter.validate_python( { "sends": 0, "delivered": 0, "opens": 0, "clicks": 0, "bounces": 0, "spam_complaints": 0, "unsubscribes": 0, "open_rate": 0.0, "delivered_rate": 0.0, "click_through_rate": 0.0, "click_to_open_rate": 0.0, "bounce_rate": 0.0, "spam_complaints_rate": 0.0, "unsubscribe_rate": 0.0, } ) query = self.db.query_from_template( "email-analytics/find-reporting-analytics-by-email-ids.sql", context={"email_ids": email_ids, "email_type": email_type}, ) row = self.db.session.execute(query).mappings().one() return EmailReportingAnalyticsAdapter.validate_python(dict(row)) def find_reporting_link_analytics_by_email_ids( self, email_ids: Iterable[str], *, email_type: EmailType ) -> list[EmailReportingLinkAnalytics]: if not email_ids: return [] query = self.db.query_from_template( "email-analytics/find-reporting-link-analytics-by-email-ids.sql", context={"email_ids": email_ids, "email_type": email_type}, ) result = self.db.session.execute(query).mappings() return EmailReportingLinkAnalyticsList.validate_python(result)