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
9 changes: 6 additions & 3 deletions fixtures/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,12 @@ def offeror_featured_lists(): # noqa: PT004
is_course=True,
)
if offered_by == OfferedBy.ocw.name:
LearningResourceRun.objects.filter(
learning_resource=resource.id
).update(prices=[])
for run in LearningResourceRun.objects.filter(
learning_resource__id=resource.id
):
run.resource_prices.set([])
run.prices = []
run.save()
featured_path.resources.add(
resource,
through_defaults={
Expand Down
86 changes: 86 additions & 0 deletions frontends/api/src/generated/v1/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,12 @@ export interface CourseResource {
* @memberof CourseResource
*/
prices: Array<string>
/**
*
* @type {Array<LearningResourcePrice>}
* @memberof CourseResource
*/
resource_prices: Array<LearningResourcePrice>
/**
*
* @type {Array<LearningResourceRun>}
Expand Down Expand Up @@ -1432,6 +1438,12 @@ export interface LearningPathResource {
* @memberof LearningPathResource
*/
prices: Array<string>
/**
*
* @type {Array<LearningResourcePrice>}
* @memberof LearningPathResource
*/
resource_prices: Array<LearningResourcePrice>
/**
*
* @type {Array<LearningResourceRun>}
Expand Down Expand Up @@ -2147,6 +2159,44 @@ export interface LearningResourcePlatformRequest {
*/
name?: string
}
/**
* Serializer for LearningResourcePrice model
* @export
* @interface LearningResourcePrice
*/
export interface LearningResourcePrice {
/**
*
* @type {string}
* @memberof LearningResourcePrice
*/
amount: string
/**
*
* @type {string}
* @memberof LearningResourcePrice
*/
currency: string
}
/**
* Serializer for LearningResourcePrice model
* @export
* @interface LearningResourcePriceRequest
*/
export interface LearningResourcePriceRequest {
/**
*
* @type {string}
* @memberof LearningResourcePriceRequest
*/
amount: string
/**
*
* @type {string}
* @memberof LearningResourcePriceRequest
*/
currency: string
}
/**
* CRUD serializer for LearningResourceRelationship
* @export
Expand Down Expand Up @@ -2252,6 +2302,12 @@ export interface LearningResourceRun {
* @memberof LearningResourceRun
*/
pace: Array<CourseResourcePaceInner>
/**
*
* @type {Array<LearningResourcePrice>}
* @memberof LearningResourceRun
*/
resource_prices: Array<LearningResourcePrice>
/**
*
* @type {string}
Expand Down Expand Up @@ -4201,6 +4257,12 @@ export interface PodcastEpisodeResource {
* @memberof PodcastEpisodeResource
*/
prices: Array<string>
/**
*
* @type {Array<LearningResourcePrice>}
* @memberof PodcastEpisodeResource
*/
resource_prices: Array<LearningResourcePrice>
/**
*
* @type {Array<LearningResourceRun>}
Expand Down Expand Up @@ -4589,6 +4651,12 @@ export interface PodcastResource {
* @memberof PodcastResource
*/
prices: Array<string>
/**
*
* @type {Array<LearningResourcePrice>}
* @memberof PodcastResource
*/
resource_prices: Array<LearningResourcePrice>
/**
*
* @type {Array<LearningResourceRun>}
Expand Down Expand Up @@ -5209,6 +5277,12 @@ export interface ProgramResource {
* @memberof ProgramResource
*/
prices: Array<string>
/**
*
* @type {Array<LearningResourcePrice>}
* @memberof ProgramResource
*/
resource_prices: Array<LearningResourcePrice>
/**
*
* @type {Array<LearningResourceRun>}
Expand Down Expand Up @@ -6076,6 +6150,12 @@ export interface VideoPlaylistResource {
* @memberof VideoPlaylistResource
*/
prices: Array<string>
/**
*
* @type {Array<LearningResourcePrice>}
* @memberof VideoPlaylistResource
*/
resource_prices: Array<LearningResourcePrice>
/**
*
* @type {Array<LearningResourceRun>}
Expand Down Expand Up @@ -6452,6 +6532,12 @@ export interface VideoResource {
* @memberof VideoResource
*/
prices: Array<string>
/**
*
* @type {Array<LearningResourcePrice>}
* @memberof VideoResource
*/
resource_prices: Array<LearningResourcePrice>
/**
*
* @type {Array<LearningResourceRun>}
Expand Down
21 changes: 21 additions & 0 deletions frontends/api/src/test-utils/factories/learningResources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type {
LearningResourceInstructor,
LearningResourceOfferorDetail,
LearningResourcePlatform,
LearningResourcePrice,
LearningResourceRun,
LearningResourceSchool,
LearningResourceTopic,
Expand Down Expand Up @@ -84,6 +85,17 @@ const learningResourceInstructor: Factory<LearningResourceInstructor> = (
return instructor
}

const learningResourcePrice: Factory<LearningResourcePrice> = (
overrides = {},
) => {
const resourcePrice: LearningResourcePrice = {
amount: faker.finance.amount({ min: 0, max: 200 }),
currency: "USD",
...overrides,
}
return resourcePrice
}

const learningResourceBaseSchool: Factory<LearningResourceBaseSchool> = (
overrides = {},
) => {
Expand Down Expand Up @@ -212,6 +224,7 @@ const learningResourceRun: Factory<LearningResourceRun> = (overrides = {}) => {
name: uniqueEnforcerWords.enforce(() => faker.lorem.words()),
},
],
resource_prices: repeat(learningResourcePrice, { min: 0, max: 5 }),
...overrides,
}
return run
Expand Down Expand Up @@ -264,6 +277,14 @@ const _learningResourceShared = (): Partial<
platform: maybe(learningResourcePlatform) ?? null,
free,
prices: free ? ["0"] : [faker.finance.amount({ min: 0, max: 100 })],
resource_prices: free
? [{ amount: "0", currency: "USD" }]
: [
{
amount: faker.finance.amount({ min: 0, max: 100 }).toString(),
currency: "USD",
},
],
readable_id: faker.lorem.slug(),
course_feature: repeat(faker.lorem.word),
runs: [],
Expand Down
3 changes: 3 additions & 0 deletions learning_resources/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,3 +301,6 @@ class Format(ExtendedEnum):

synchronous = "Synchronous"
asynchronous = "Asynchronous"


CURRENCY_USD = "USD"
2 changes: 2 additions & 0 deletions learning_resources/etl/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from named_enum import ExtendedEnum

from learning_resources.constants import LearningResourceDelivery
from learning_resources.models import LearningResourcePrice

# A custom UA so that operators of OpenEdx will know who is pinging their service
COMMON_HEADERS = {
Expand Down Expand Up @@ -115,5 +116,6 @@ class ContentTagCategory(ExtendedEnum):
class ResourceNextRunConfig:
next_start_date: datetime = None
prices: list[Decimal] = field(default_factory=list)
resource_prices: list[LearningResourcePrice] = field(default_factory=list)
availability: str = None
location: str = None
34 changes: 29 additions & 5 deletions learning_resources/etl/loaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
LearningResourceInstructor,
LearningResourceOfferor,
LearningResourcePlatform,
LearningResourcePrice,
LearningResourceRelationship,
LearningResourceRun,
LearningResourceTopic,
Expand Down Expand Up @@ -145,11 +146,17 @@ def load_run_dependent_values(
if resource.certification and best_run and best_run.prices
else []
)
resource.resource_prices.set(
best_run.resource_prices.all()
if resource.certification and best_run and best_run.resource_prices
else []
)
resource.location = best_run.location
resource.save()
return ResourceNextRunConfig(
next_start_date=resource.next_start_date,
prices=resource.prices,
resource_prices=resource.resource_prices.all(),
availability=resource.availability,
location=resource.location,
)
Expand Down Expand Up @@ -182,6 +189,23 @@ def load_instructors(
return instructors


def load_prices(
run: LearningResourceRun, prices_data: list[dict]
) -> list[LearningResourcePrice]:
"""Load the prices for a resource run into the database"""
prices = []
for price in prices_data:
lr_price, _ = LearningResourcePrice.objects.get_or_create(
amount=price["amount"],
currency=price["currency"],
)
prices.append(lr_price)

run.resource_prices.set(prices)
run.save()
return prices


def load_image(resource: LearningResource, image_data: dict) -> LearningResourceImage:
"""Load the image for a resource into the database"""
if image_data:
Expand Down Expand Up @@ -253,14 +277,13 @@ def load_run(
status = run_data.pop("status", None)
instructors_data = run_data.pop("instructors", [])

resource_prices = run_data.get("prices", [])
run_data["prices"] = sorted({price["amount"] for price in resource_prices})

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:
# Make sure any prices are unique and sorted in ascending order
run_data["prices"] = sorted(
set(run_data.get("prices", [])), key=lambda x: float(x)
)
resource_prices = []

with transaction.atomic():
(
Expand All @@ -273,6 +296,7 @@ def load_run(
)

load_instructors(learning_resource_run, instructors_data)
load_prices(learning_resource_run, resource_prices)
load_image(learning_resource_run, image_data)
return learning_resource_run

Expand Down
Loading
Loading