diff --git a/learning_resources_search/models.py b/learning_resources_search/models.py index 8b10a69981..d6a35667ba 100644 --- a/learning_resources_search/models.py +++ b/learning_resources_search/models.py @@ -45,14 +45,17 @@ def source_description(self): channel = self.source_channel() if self.display_label: return self.display_label - if channel: + if channel and self.source_type == self.CHANNEL_SUBSCRIPTION_TYPE: return channel.title return self.original_url_params() def source_channel(self): original_query_params = self.original_url_params() channels_filtered = Channel.objects.filter(search_filter=original_query_params) - if channels_filtered.exists(): + if ( + channels_filtered.exists() + and self.source_type == self.CHANNEL_SUBSCRIPTION_TYPE + ): return channels_filtered.first() return None diff --git a/learning_resources_search/models_test.py b/learning_resources_search/models_test.py index 3a6058e2ea..ddf1f5fab3 100644 --- a/learning_resources_search/models_test.py +++ b/learning_resources_search/models_test.py @@ -12,6 +12,7 @@ from learning_resources_search.indexing_api import ( get_reindexing_alias_name, ) +from learning_resources_search.models import PercolateQuery pytestmark = [pytest.mark.django_db, pytest.mark.usefixtures("mocked_es")] @@ -63,7 +64,9 @@ def test_percolate_query_unit_labels(mocker, mocked_es): "yearly_decay_percent": None, } query = PercolateQueryFactory.create( - original_query=original_query, query=original_query + original_query=original_query, + query=original_query, + source_type=PercolateQuery.CHANNEL_SUBSCRIPTION_TYPE, ) assert query.original_url_params() == "offered_by=mitx" assert query.source_label() == "unit" @@ -91,7 +94,9 @@ def test_percolate_query_topic_labels(mocker, mocked_es): "yearly_decay_percent": None, } query = PercolateQueryFactory.create( - original_query=original_query, query=original_query + original_query=original_query, + query=original_query, + source_type=PercolateQuery.CHANNEL_SUBSCRIPTION_TYPE, ) assert query.original_url_params() == "topic=Math" assert query.source_label() == "topic" @@ -118,7 +123,9 @@ def test_percolate_query_department_labels(mocker, mocked_es): "yearly_decay_percent": None, } query = PercolateQueryFactory.create( - original_query=original_query, query=original_query + original_query=original_query, + query=original_query, + source_type=PercolateQuery.CHANNEL_SUBSCRIPTION_TYPE, ) assert query.original_url_params() == "department=physics" assert query.source_label() == "department" @@ -196,6 +203,9 @@ def encode_params(oparams): original_query=original_query, query=original_query, display_label=test_label, + source_type=PercolateQuery.CHANNEL_SUBSCRIPTION_TYPE + if is_channel_query + else PercolateQuery.SEARCH_SUBSCRIPTION_TYPE, ) assert query.original_url_params() == encode_params(original_query) if not is_channel_query: diff --git a/learning_resources_search/tasks.py b/learning_resources_search/tasks.py index b3a07cf71c..6585e8172a 100644 --- a/learning_resources_search/tasks.py +++ b/learning_resources_search/tasks.py @@ -18,6 +18,7 @@ from opensearchpy.exceptions import NotFoundError, RequestError from requests.models import PreparedRequest +from learning_resources.constants import LearningResourceType from learning_resources.etl.constants import RESOURCE_FILE_ETL_SOURCES from learning_resources.models import ( ContentFile, @@ -167,7 +168,7 @@ def _infer_percolate_group(percolate_query): elif key == "offered_by": return LearningResourceOfferor.objects.get(code=val[0]).name return val[0] - return None + return percolate_query.original_url_params() def _infer_percolate_group_url(percolate_query): @@ -181,6 +182,8 @@ def _infer_percolate_group_url(percolate_query): query_string_params = {k: v for k, v in original_query.items() if v} if "endpoint" in query_string_params: query_string_params.pop("endpoint") + if "sortby" not in query_string_params: + query_string_params["sortby"] = "new" query_string = urlencode(query_string_params, doseq=True) return frontend_absolute_url(f"/search?{query_string}") @@ -232,7 +235,9 @@ def _get_percolated_rows(resources, subscription_type): "resource_image_url": resource.image.url if resource.image else "", - "resource_type": resource.resource_type, + "resource_type": LearningResourceType[ + resource.resource_type + ].value, "user_id": user, "source_label": query.source_label(), "source_channel_type": source_channel.channel_type @@ -881,23 +886,35 @@ def finish_recreate_index(results, backing_indices): def _generate_subscription_digest_subject( sample_course, source_name, unique_resource_types, total_count, shortform ): - prefix = "" if shortform else "MIT Learn: " + """ + Generate the subject line and/or content header for subscription emails + Args: + sample_course (a learning resource): A sample resource to reference + source_name (string): the subscription type (saved_search etc) + unique_resource_types (list): set of unique resource types in the email + total_count (int): total number of resources in the email + shortform (bool): if False return the (longer) email subject + otherwise short content header + """ + prefix = "" if shortform else "MIT Learn: " + resource_type = unique_resource_types.pop() if sample_course["source_channel_type"] == "saved_search": + if shortform: + return f"New {resource_type}{pluralize(total_count)} from MIT Learn" return ( f"{prefix}New" - f' "{source_name}" ' - f"{unique_resource_types.pop().capitalize()}{pluralize(total_count)}" + f" {resource_type}{pluralize(total_count)}: " + f"{sample_course['resource_title']}" ) preposition = "from" if sample_course["source_channel_type"] == "topic": preposition = "in" suffix = "" if shortform else f": {sample_course['resource_title']}" - return ( f"{prefix}New" - f" {unique_resource_types.pop().capitalize()}{pluralize(total_count)} " + f" {resource_type}{pluralize(total_count)} " f"{preposition} {source_name}{suffix}" ) diff --git a/learning_resources_search/tasks_test.py b/learning_resources_search/tasks_test.py index b3b8bb0174..a285f40f24 100644 --- a/learning_resources_search/tasks_test.py +++ b/learning_resources_search/tasks_test.py @@ -951,7 +951,7 @@ def test_subscription_digest_subject(): total_count=1, shortform=False, ) - assert subject_line == "MIT Learn: New Program in electronics: robotics" + assert subject_line == "MIT Learn: New program in electronics: robotics" sample_course = {"source_channel_type": "podcast", "resource_title": "robotics"} resource_types = {"program"} @@ -963,7 +963,7 @@ def test_subscription_digest_subject(): total_count=9, shortform=False, ) - assert subject_line == "MIT Learn: New Programs from xpro: robotics" + assert subject_line == "MIT Learn: New programs from xpro: robotics" resource_types = {"podcast"} subject_line = _generate_subscription_digest_subject( @@ -973,13 +973,13 @@ def test_subscription_digest_subject(): total_count=19, shortform=False, ) - assert subject_line == "MIT Learn: New Podcasts from engineering: robotics" + assert subject_line == "MIT Learn: New podcasts from engineering: robotics" resource_types = {"course"} subject_line = _generate_subscription_digest_subject( sample_course, "management", resource_types, 19, shortform=True ) - assert subject_line == "New Courses from management" + assert subject_line == "New courses from management" def test_update_featured_rank(mocker, offeror_featured_lists): diff --git a/main/settings_celery.py b/main/settings_celery.py index 7fc24e41d4..8209830a9a 100644 --- a/main/settings_celery.py +++ b/main/settings_celery.py @@ -130,6 +130,11 @@ "schedule": crontab(minute=30, hour=18), # 2:30pm EST "kwargs": {"period": "daily", "subscription_type": "channel_subscription_type"}, }, + "send-search-subscription-emails-every-1-days": { + "task": "learning_resources_search.tasks.send_subscription_emails", + "schedule": crontab(minute=0, hour=19), # 3:00pm EST + "kwargs": {"period": "daily", "subscription_type": "search_subscription_type"}, + }, "update-search-featured-ranks-1-days": { "task": "learning_resources_search.tasks.update_featured_rank", "schedule": crontab(minute=30, hour=7), # 3:30am EST