Skip to content
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
20 changes: 20 additions & 0 deletions frontends/api/src/generated/v1/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2170,6 +2170,12 @@ export interface LearningResourceRun {
* @memberof LearningResourceRun
*/
level: Array<LearningResourceRunLevelInner>
/**
*
* @type {Array<CourseResourceDeliveryInner>}
* @memberof LearningResourceRun
*/
delivery: Array<CourseResourceDeliveryInner>
/**
*
* @type {string}
Expand Down Expand Up @@ -2272,7 +2278,14 @@ export interface LearningResourceRun {
* @memberof LearningResourceRun
*/
checksum?: string | null
/**
*
* @type {AvailabilityEnum}
* @memberof LearningResourceRun
*/
availability?: AvailabilityEnum | null
}

/**
*
* @export
Expand Down Expand Up @@ -2420,7 +2433,14 @@ export interface LearningResourceRunRequest {
* @memberof LearningResourceRunRequest
*/
checksum?: string | null
/**
*
* @type {AvailabilityEnum}
* @memberof LearningResourceRunRequest
*/
availability?: AvailabilityEnum | null
}

/**
* Serializer for LearningResourceSchool model, including list of departments
* @export
Expand Down
9 changes: 9 additions & 0 deletions frontends/api/src/test-utils/factories/learningResources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import type {
VideoResource,
} from "api"
import {
AvailabilityEnum,
DeliveryEnum,
ResourceTypeEnum,
LearningResourceRunLevelInnerCodeEnum,
PlatformEnum,
Expand Down Expand Up @@ -177,6 +179,13 @@ const learningResourceRun: Factory<LearningResourceRun> = (overrides = {}) => {
languages: maybe(() => repeat(language, { min: 0, max: 3 })),
start_date: start.toISOString(),
end_date: end.toISOString(),
availability: faker.helpers.arrayElement(Object.values(AvailabilityEnum)),
delivery: [
{
code: faker.helpers.arrayElement(Object.values(DeliveryEnum)),
name: uniqueEnforcerWords.enforce(() => faker.lorem.words()),
},
],
level: [
{
code: faker.helpers.arrayElement(
Expand Down
6 changes: 3 additions & 3 deletions learning_resources/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
FAVORITES_TITLE = "Favorites"


class RunAvailability(ExtendedEnum):
class RunStatus(ExtendedEnum):
"""
Enum for Course availability options dictated by edX API values.
Enum for run status options dictated by edX API values.
"""

current = "Current"
Expand Down Expand Up @@ -270,7 +270,7 @@ class LevelType(ExtendedEnum):


class LearningResourceFormat(ExtendedEnum):
"""Enum for resource learning_format"""
"""Enum for resource learning format"""

online = "Online"
hybrid = "Hybrid"
Expand Down
10 changes: 10 additions & 0 deletions learning_resources/etl/constants.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
"""Constants for learning_resources ETL processes"""

from collections import namedtuple
from dataclasses import dataclass, field
from datetime import datetime
from decimal import Decimal
from enum import Enum

from django.conf import settings
Expand Down Expand Up @@ -106,3 +109,10 @@ class ContentTagCategory(ExtendedEnum):
"Assignments": ContentTagCategory.problem_sets.value,
# Can add more here if ever needed, in format tag_name:category
}


@dataclass
class ResourceNextRunConfig:
next_start_date: datetime = None
prices: list[Decimal] = field(default_factory=list)
availability: str = None
42 changes: 0 additions & 42 deletions learning_resources/etl/deduplication.py

This file was deleted.

61 changes: 0 additions & 61 deletions learning_resources/etl/deduplication_test.py

This file was deleted.

35 changes: 23 additions & 12 deletions learning_resources/etl/loaders.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
"""learning_resources data loaders"""

import datetime
import logging
from decimal import Decimal

from django.contrib.auth import get_user_model
from django.db import transaction
Expand All @@ -12,14 +10,15 @@
LearningResourceRelationTypes,
LearningResourceType,
PlatformType,
RunAvailability,
RunStatus,
)
from learning_resources.etl.constants import (
CONTENT_TAG_CATEGORIES,
READABLE_ID_FIELD,
ContentTagCategory,
CourseLoaderConfig,
ProgramLoaderConfig,
ResourceNextRunConfig,
)
from learning_resources.etl.exceptions import ExtractException
from learning_resources.etl.utils import most_common_topics
Expand Down Expand Up @@ -118,9 +117,18 @@ def load_departments(
return resource.departments.all()


def load_next_start_date_and_prices(
def load_run_dependent_values(
resource: LearningResource,
) -> tuple[datetime.time | None, list[Decimal]]:
) -> ResourceNextRunConfig:
"""
Assign prices, availability, and next_start_date to a resource based on its runs

Args:
resource (LearningResource): the resource to update

Returns:
tuple[datetime.time | None, list[Decimal], str]: date, prices, and availability
"""
next_upcoming_run = resource.next_run
if next_upcoming_run:
resource.next_start_date = next_upcoming_run.start_date
Expand All @@ -130,13 +138,18 @@ def load_next_start_date_and_prices(
next_upcoming_run
or resource.runs.filter(published=True).order_by("-start_date").first()
)
resource.availability = best_run.availability if best_run else resource.availability
resource.prices = (
best_run.prices
if resource.certification and best_run and best_run.prices
else []
)
resource.save()
return resource.next_start_date, resource.prices
return ResourceNextRunConfig(
next_start_date=resource.next_start_date,
prices=resource.prices,
availability=resource.availability,
)


def load_instructors(
Expand Down Expand Up @@ -234,12 +247,10 @@ def load_run(
"""
run_id = run_data.pop("run_id")
image_data = run_data.pop("image", None)
status = run_data.pop("status", None)
instructors_data = run_data.pop("instructors", [])

if (
run_data.get("availability") == RunAvailability.archived.value
or learning_resource.certification is False
):
if status == RunStatus.archived.value or learning_resource.certification is False:
# Archived runs or runs of resources w/out certificates should not have prices
run_data["prices"] = []
else:
Expand Down Expand Up @@ -430,7 +441,7 @@ def load_course(
run.save()
resource_run_unpublished_actions(run)

load_next_start_date_and_prices(learning_resource)
load_run_dependent_values(learning_resource)
load_topics(learning_resource, topics_data)
load_offered_by(learning_resource, offered_bys_data)
load_image(learning_resource, image_data)
Expand Down Expand Up @@ -544,7 +555,7 @@ def load_program(
run.published = False
run.save()

load_next_start_date_and_prices(learning_resource)
load_run_dependent_values(learning_resource)

for course_data in courses_data:
# skip courses that don't define a readable_id
Expand Down
Loading