Skip to content

Commit dcfd0b3

Browse files
Allow runs with multiple prices to still be considered identical (#2563)
* improve handling for multiple prices * update python version of identical runs func, too * fix log typo
1 parent c804fda commit dcfd0b3

File tree

5 files changed

+110
-33
lines changed

5 files changed

+110
-33
lines changed

frontends/ol-utilities/src/learning-resources/learning-resources.test.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,84 @@ describe("allRunsAreIdentical", () => {
179179
expect(allRunsAreIdentical(resource)).toBe(true)
180180
})
181181

182+
test.each([
183+
{
184+
runPrices: [
185+
[
186+
{ amount: "0", currency: "USD" },
187+
{ amount: "50", currency: "USD" },
188+
{ amount: "100", currency: "USD" },
189+
],
190+
[
191+
{ amount: "0", currency: "USD" },
192+
{ amount: "50.00", currency: "USD" },
193+
{ amount: "100", currency: "USD" },
194+
],
195+
],
196+
case: "2 runs, 3 prices each, all the same",
197+
expected: true,
198+
},
199+
{
200+
runPrices: [
201+
[
202+
{ amount: "0", currency: "USD" },
203+
{ amount: "100", currency: "USD" },
204+
],
205+
[
206+
{ amount: "0", currency: "USD" },
207+
{ amount: "50.00", currency: "USD" },
208+
{ amount: "100", currency: "USD" },
209+
],
210+
],
211+
case: "2 runs, 2 vs 3 prices",
212+
expected: false,
213+
},
214+
{
215+
runPrices: [
216+
[
217+
{ amount: "0", currency: "USD" },
218+
{ amount: "50.00", currency: "USD" },
219+
{ amount: "150", currency: "USD" },
220+
],
221+
[
222+
{ amount: "0", currency: "USD" },
223+
{ amount: "50.00", currency: "USD" },
224+
{ amount: "100", currency: "USD" },
225+
],
226+
],
227+
case: "2 runs, 3 prices each, some not all same",
228+
expected: false,
229+
},
230+
])(
231+
"returns $expected if multiple runs ($case)",
232+
({ expected, runPrices: [prices1, prices2] }) => {
233+
const resource = factories.learningResources.resource({
234+
free: true,
235+
certification: true,
236+
})
237+
const delivery = [
238+
{
239+
code: CourseResourceDeliveryInnerCodeEnum.InPerson,
240+
name: "In person",
241+
},
242+
]
243+
const location = "New York"
244+
resource.runs = [
245+
makeRun({
246+
resource_prices: prices1,
247+
delivery: delivery,
248+
location: location,
249+
}),
250+
makeRun({
251+
resource_prices: prices2,
252+
delivery: delivery,
253+
location: location,
254+
}),
255+
]
256+
expect(allRunsAreIdentical(resource)).toBe(expected)
257+
},
258+
)
259+
182260
test("returns false if delivery methods differ", () => {
183261
const resource = factories.learningResources.resource()
184262
const prices = [{ amount: "100", currency: "USD" }]

frontends/ol-utilities/src/learning-resources/learning-resources.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -129,16 +129,15 @@ const allRunsAreIdentical = (resource: LearningResource) => {
129129
if (resource.runs.length <= 1) {
130130
return true
131131
}
132-
const amounts = new Set<number>()
133-
const currencies = new Set<string>()
132+
const prices = new Set<string>()
134133
const deliveryMethods = new Set<string>()
135134
const locations = new Set<string>()
136135
for (const run of resource.runs) {
137136
if (run.resource_prices) {
138-
run.resource_prices.forEach((price) => {
139-
amounts.add(Number(price.amount))
140-
currencies.add(price.currency)
141-
})
137+
const serialized = run.resource_prices
138+
.map((price) => `${Number(price.amount).toFixed(2)}-${price.currency}`)
139+
.join(":::")
140+
prices.add(serialized)
142141
}
143142
if (run.delivery) {
144143
for (const dm of run.delivery) {
@@ -149,13 +148,11 @@ const allRunsAreIdentical = (resource: LearningResource) => {
149148
locations.add(run.location)
150149
}
151150
}
152-
const expectedPrices = resource.free && resource.certification ? 2 : 1
153151
const hasInPerson = [...deliveryMethods].some(
154152
(dm) => dm === DeliveryEnum.InPerson,
155153
)
156154
return (
157-
amounts.size === expectedPrices &&
158-
currencies.size === 1 &&
155+
prices.size <= 1 &&
159156
deliveryMethods.size === 1 &&
160157
(hasInPerson ? locations.size === 1 : locations.size === 0)
161158
)

learning_resources/management/commands/backpopulate_mitxonline_data.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def handle(self, *args, **options): # noqa: ARG002
2828
"""Run Populate mitxonline courses"""
2929
if options["delete"]:
3030
self.stdout.write(
31-
"Deleting all existing xPro courses from database and opensearch"
31+
"Deleting all existing MITxOnline courses from database and opensearch"
3232
)
3333
for learning_resource in LearningResource.objects.filter(
3434
etl_source=ETLSource.mitxonline.value

learning_resources/serializers.py

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -492,35 +492,27 @@ class LearningResourceMetadataDisplaySerializer(serializers.Serializer):
492492

493493
def all_runs_are_identical(self, serialized_resource):
494494
"""Check if all runs are identical"""
495-
distinct_prices = set()
495+
distinct_resource_prices = set()
496496
distinct_delivery_methods = set()
497497
resource_delivery = [
498498
delivery["code"] for delivery in serialized_resource["delivery"]
499499
]
500500
has_in_person = (
501501
"in_person" in resource_delivery or "hybrid" in resource_delivery
502502
)
503-
distinct_currencies = {
504-
c["currency"] for c in serialized_resource["resource_prices"]
505-
}
506503

507504
distinct_locations = set()
508505
for run in serialized_resource.get("runs", []):
509-
prices = run.get("prices", [])
510-
if prices:
511-
distinct_prices.update(prices)
506+
resource_prices = run.get("resource_prices", [])
507+
distinct_resource_prices.add(
508+
tuple((price["currency"], price["amount"]) for price in resource_prices)
509+
)
512510
distinct_delivery_methods.update(
513511
[delivery["code"] for delivery in run.get("delivery", [])]
514512
)
515513
if run.get("location"):
516514
distinct_locations.add(run["location"])
517-
if (
518-
serialized_resource.get("free")
519-
and serialized_resource["certification"]
520-
and len(distinct_prices) != 2 # noqa: PLR2004
521-
):
522-
return False
523-
if len(distinct_currencies) != 1:
515+
if len(distinct_resource_prices) > 1:
524516
return False
525517
if len(distinct_delivery_methods) != 1:
526518
return False

learning_resources/serializers_test.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,7 @@ def _create_identical_runs_resource():
665665
delivery=["in_person"],
666666
)
667667
learning_resource.resource_prices.set(
668-
[LearningResourcePriceFactory.create(amount=Decimal("0.00"), currency="USD")]
668+
[LearningResourcePriceFactory.create(amount=Decimal("1.00"), currency="USD")]
669669
)
670670
start_date = datetime.datetime.now(tz=datetime.UTC)
671671
run = LearningResourceRunFactory.create(
@@ -692,7 +692,6 @@ def _create_identical_runs_resource():
692692
LearningResourcePriceFactory.create(amount=Decimal("1.00"), currency="USD")
693693
],
694694
)
695-
run.prices = [Decimal("1.00"), Decimal("2.00")]
696695
run.save()
697696
return learning_resource
698697

@@ -862,21 +861,32 @@ def test_metadata_display_serializer_all_runs_are_identical():
862861
assert (
863862
display_data_serializer.all_runs_are_identical(differing_runs_resource) is False
864863
)
865-
# Test that all_runs_are_identical will return False if there is more than 1 unique currency
864+
# Test that all_runs_are_identical will return False if not all runs have same prices
866865
differing_runs_resource = copy.deepcopy(identical_runs_resource)
867-
differing_runs_resource["resource_prices"] = [
868-
{"currency": "USD", "amount": Decimal("1.00")},
869-
{"currency": "BTC", "amount": Decimal("1.00")},
866+
differing_runs_resource["runs"][0]["resource_prices"] = [
867+
{"amount": "10.00", "currency": "USD"},
868+
{"amount": "20.00", "currency": "BTC"},
869+
]
870+
differing_runs_resource["runs"][1]["resource_prices"] = [
871+
{"amount": "10.00", "currency": "USD"},
872+
{"amount": "21.00", "currency": "BTC"},
870873
]
871874
assert (
872875
display_data_serializer.all_runs_are_identical(differing_runs_resource) is False
873876
)
874877

875-
# Test that all_runs_are_identical will return False if there is more than 1 unique price
878+
# Test that all_runs_are_identical will return True if all runs DO have same prices
876879
differing_runs_resource = copy.deepcopy(identical_runs_resource)
877-
differing_runs_resource["runs"][0]["prices"] = [Decimal(i) for i in range(5)]
880+
differing_runs_resource["runs"][0]["resource_prices"] = [
881+
{"amount": "10.00", "currency": "USD"},
882+
{"amount": "20.00", "currency": "BTC"},
883+
]
884+
differing_runs_resource["runs"][1]["resource_prices"] = [
885+
{"amount": "10.00", "currency": "USD"},
886+
{"amount": "20.00", "currency": "BTC"},
887+
]
878888
assert (
879-
display_data_serializer.all_runs_are_identical(differing_runs_resource) is False
889+
display_data_serializer.all_runs_are_identical(differing_runs_resource) is True
880890
)
881891
"""
882892
Test that all_runs_are_identical will return False if there is more than 1 unique location

0 commit comments

Comments
 (0)