4242from course_discovery .apps .core .tests .mixins import ElasticsearchTestMixin , LMSAPIClientMixin
4343from course_discovery .apps .core .utils import serialize_datetime
4444from course_discovery .apps .course_metadata .choices import CourseRunStatus , ProgramStatus
45- from course_discovery .apps .course_metadata .models import AbstractLocationRestrictionModel , CourseReview
45+ from course_discovery .apps .course_metadata .models import AbstractLocationRestrictionModel , CourseReview , CourseType
4646from course_discovery .apps .course_metadata .search_indexes .documents import (
4747 CourseDocument , CourseRunDocument , LearnerPathwayDocument , PersonDocument , ProgramDocument
4848)
5555from course_discovery .apps .course_metadata .tests .factories import (
5656 AdditionalMetadataFactory , AdditionalPromoAreaFactory , CertificateInfoFactory , CollaboratorFactory ,
5757 CorporateEndorsementFactory , CourseEditorFactory , CourseEntitlementFactory , CourseFactory ,
58- CourseLocationRestrictionFactory , CourseRunFactory , CourseSkillsFactory , CurriculumCourseMembershipFactory ,
59- CurriculumFactory , CurriculumProgramMembershipFactory , DegreeAdditionalMetadataFactory , DegreeCostFactory ,
60- DegreeDeadlineFactory , DegreeFactory , EndorsementFactory , ExpectedLearningItemFactory , FactFactory ,
61- IconTextPairingFactory , ImageFactory , JobOutlookItemFactory , OrganizationFactory , PathwayFactory ,
62- PersonAreaOfExpertiseFactory , PersonFactory , PersonSocialNetworkFactory , PositionFactory , PrerequisiteFactory ,
63- ProgramFactory , ProgramLocationRestrictionFactory , ProgramSkillFactory , ProgramSubscriptionFactory ,
64- ProgramSubscriptionPriceFactory , ProgramTypeFactory , RankingFactory , SeatFactory , SeatTypeFactory ,
65- SpecializationFactory , SubjectFactory , TopicFactory , VideoFactory
58+ CourseLocationRestrictionFactory , CourseRunFactory , CourseSkillsFactory , CourseTypeFactory ,
59+ CurriculumCourseMembershipFactory , CurriculumFactory , CurriculumProgramMembershipFactory ,
60+ DegreeAdditionalMetadataFactory , DegreeCostFactory , DegreeDeadlineFactory , DegreeFactory , EndorsementFactory ,
61+ ExpectedLearningItemFactory , FactFactory , IconTextPairingFactory , ImageFactory , JobOutlookItemFactory ,
62+ OrganizationFactory , PathwayFactory , PersonAreaOfExpertiseFactory , PersonFactory , PersonSocialNetworkFactory ,
63+ PositionFactory , PrerequisiteFactory , ProgramFactory , ProgramLocationRestrictionFactory , ProgramSkillFactory ,
64+ ProgramSubscriptionFactory , ProgramSubscriptionPriceFactory , ProgramTypeFactory , RankingFactory , SeatFactory ,
65+ SeatTypeFactory , SpecializationFactory , SubjectFactory , TopicFactory , VideoFactory
6666)
6767from course_discovery .apps .course_metadata .utils import get_course_run_estimated_hours
6868from course_discovery .apps .ietf_language_tags .models import LanguageTag
@@ -636,6 +636,7 @@ def get_expected_data(cls, course_run, request):
636636 'external_key' : course_run .external_key ,
637637 'is_enrollable' : course_run .is_enrollable ,
638638 'is_marketable' : course_run .is_marketable ,
639+ 'is_marketable_external' : course_run .is_marketable_external ,
639640 'availability' : course_run .availability ,
640641 'variant_id' : str (course_run .variant_id ),
641642 'fixed_price_usd' : str (course_run .fixed_price_usd ),
@@ -647,6 +648,7 @@ def get_expected_data(cls, course_run, request):
647648 }
648649
649650
651+ @ddt .ddt
650652class MinimalCourseRunSerializerTests (MinimalCourseRunBaseTestSerializer ):
651653
652654 def test_data (self ):
@@ -656,6 +658,73 @@ def test_data(self):
656658 expected = self .get_expected_data (course_run , request )
657659 assert serializer .data == expected
658660
661+ @ddt .data (
662+ {
663+ 'course_type' : CourseType .EXECUTIVE_EDUCATION_2U ,
664+ 'status' : CourseRunStatus .Reviewed ,
665+ 'is_marketable' : False ,
666+ 'has_future_start_date' : True ,
667+ 'expected_is_marketable_external' : True
668+ },
669+ {
670+ 'course_type' : CourseType .EXECUTIVE_EDUCATION_2U ,
671+ 'status' : CourseRunStatus .InternalReview ,
672+ 'is_marketable' : False ,
673+ 'has_future_start_date' : True ,
674+ 'expected_is_marketable_external' : False
675+ },
676+ {
677+ 'course_type' : CourseType .EXECUTIVE_EDUCATION_2U ,
678+ 'status' : CourseRunStatus .LegalReview ,
679+ 'is_marketable' : False ,
680+ 'has_future_start_date' : True ,
681+ 'expected_is_marketable_external' : False
682+ },
683+ {
684+ 'course_type' : CourseType .EXECUTIVE_EDUCATION_2U ,
685+ 'status' : CourseRunStatus .Unpublished ,
686+ 'is_marketable' : False ,
687+ 'has_future_start_date' : True ,
688+ 'expected_is_marketable_external' : False
689+ },
690+ {
691+ 'course_type' : CourseType .PROFESSIONAL ,
692+ 'status' : CourseRunStatus .InternalReview ,
693+ 'is_marketable' : False ,
694+ 'has_future_start_date' : True ,
695+ 'expected_is_marketable_external' : False
696+ },
697+ {
698+ 'course_type' : CourseType .VERIFIED_AUDIT ,
699+ 'status' : CourseRunStatus .Published ,
700+ 'is_marketable' : True ,
701+ 'has_future_start_date' : False ,
702+ 'expected_is_marketable_external' : True
703+ },
704+ )
705+ @ddt .unpack
706+ def test_is_marketable_external (
707+ self , course_type , status , is_marketable ,
708+ has_future_start_date , expected_is_marketable_external
709+ ):
710+ course_type_instance = CourseTypeFactory (slug = course_type )
711+ current_time = datetime .datetime .now (tz = UTC )
712+ start_date = current_time + datetime .timedelta (
713+ days = 10 ) if has_future_start_date else current_time - datetime .timedelta (days = 10 )
714+ go_live_date = current_time + datetime .timedelta (days = 5 ) # Assuming go_live_date is 5 days in the future
715+
716+ course_run = CourseRunFactory (
717+ course = CourseFactory (type = course_type_instance ),
718+ status = status ,
719+ start = start_date ,
720+ go_live_date = go_live_date
721+ )
722+ seat = SeatFactory (course_run = course_run , type = SeatTypeFactory .verified ())
723+ course_run .seats .set ([seat ])
724+
725+ assert course_run .is_marketable == is_marketable
726+ assert course_run .is_marketable_external == expected_is_marketable_external
727+
659728 def test_get_lms_course_url (self ):
660729 partner = PartnerFactory ()
661730 course_key = 'course-v1:testX+test1.23+2018T1'
0 commit comments