Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
course-discovery
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
course-discovery
Commits
6659595d
Commit
6659595d
authored
Jun 26, 2018
by
Sanford Student
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
start undoing changes to get rid of model
parent
dc233f8b
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
33 additions
and
48 deletions
+33
-48
course_discovery/apps/publisher/api/v1/views.py
+10
-18
course_discovery/apps/publisher/dataloader/create_courses.py
+1
-7
course_discovery/apps/publisher/forms.py
+3
-3
course_discovery/apps/publisher/models.py
+3
-1
course_discovery/apps/publisher/signals.py
+2
-3
course_discovery/apps/publisher/studio_api_utils.py
+12
-16
course_discovery/apps/publisher/tests/factories.py
+2
-0
No files found.
course_discovery/apps/publisher/api/v1/views.py
View file @
6659595d
import
logging
from
collections
import
OrderedDict
from
datetime
import
date
import
pytz
from
edx_rest_api_client.client
import
EdxRestApiClient
from
edx_rest_framework_extensions.authentication
import
JwtAuthentication
...
...
@@ -21,7 +20,6 @@ from course_discovery.apps.publisher.api.utils import (
)
from
course_discovery.apps.publisher.models
import
CourseRun
,
Seat
from
course_discovery.apps.publisher.studio_api_utils
import
StudioAPI
from
course_discovery.apps.publisher.utils
import
parse_datetime_field
logger
=
logging
.
getLogger
(
__name__
)
...
...
@@ -43,17 +41,12 @@ class CourseRunViewSet(viewsets.GenericViewSet):
def
publish
(
self
,
request
,
pk
=
None
):
course_run
=
self
.
get_object
()
partner
=
request
.
site
.
partner
start
=
None
end
=
None
if
'start'
in
request
.
data
:
start
=
pytz
.
utc
.
localize
(
parse_datetime_field
(
request
.
data
[
'start'
]))
if
'end'
in
request
.
data
:
end
=
pytz
.
utc
.
localize
(
parse_datetime_field
(
request
.
data
[
'end'
]))
publication_status
=
{}
try
:
publication_status
[
'studio'
]
=
self
.
publish_to_studio
(
partner
,
course_run
,
start
,
end
)
publication_status
[
'discovery'
]
=
self
.
publish_to_discovery
(
partner
,
course_run
,
start
,
end
)
publication_status
[
'studio'
]
=
self
.
publish_to_studio
(
partner
,
course_run
)
publication_status
[
'discovery'
]
=
self
.
publish_to_discovery
(
partner
,
course_run
)
# Publish to ecommerce last because it needs the just-created UUID from discovery
publication_status
[
'ecommerce'
]
=
self
.
publish_to_ecommerce
(
partner
,
course_run
)
except
SlumberBaseException
as
ex
:
...
...
@@ -78,11 +71,11 @@ class CourseRunViewSet(viewsets.GenericViewSet):
)
return
Response
(
publication_status
,
status
=
status_code
)
def
publish_to_studio
(
self
,
partner
,
course_run
,
start
,
end
):
def
publish_to_studio
(
self
,
partner
,
course_run
):
api
=
StudioAPI
(
partner
.
studio_api_client
)
try
:
api
.
update_course_run_details_in_studio
(
course_run
,
start
,
end
)
api
.
update_course_run_details_in_studio
(
course_run
)
api
.
update_course_run_image_in_studio
(
course_run
)
return
self
.
PUBLICATION_SUCCESS_STATUS
except
SlumberBaseException
as
ex
:
...
...
@@ -102,7 +95,7 @@ class CourseRunViewSet(viewsets.GenericViewSet):
'id'
:
course_run
.
lms_course_id
,
'uuid'
:
str
(
discovery_course
.
uuid
),
'name'
:
course_run
.
title_override
or
course_run
.
course
.
title
,
'verification_deadline'
:
serialize_datetime
(
course_run
.
lms_
end
),
'verification_deadline'
:
serialize_datetime
(
course_run
.
end
),
}
# NOTE: We only order here to aid testing. The E-Commerce API does NOT care about ordering.
...
...
@@ -120,7 +113,7 @@ class CourseRunViewSet(viewsets.GenericViewSet):
logger
.
exception
(
'Failed to publish course run [
%
d] to E-Commerce! Error was: [
%
s]'
,
course_run
.
pk
,
content
)
return
'FAILED: '
+
content
def
publish_to_discovery
(
self
,
partner
,
course_run
,
start
,
end
):
def
publish_to_discovery
(
self
,
partner
,
course_run
):
publisher_course
=
course_run
.
course
course_key
=
self
.
get_course_key
(
publisher_course
)
...
...
@@ -150,7 +143,10 @@ class CourseRunViewSet(viewsets.GenericViewSet):
subjects
=
list
(
OrderedDict
.
fromkeys
(
subjects
))
discovery_course
.
subjects
.
clear
()
discovery_course
.
subjects
.
add
(
*
subjects
)
defaults
=
{
'start'
:
course_run
.
start
,
'end'
:
course_run
.
end
,
'pacing_type'
:
course_run
.
pacing_type
,
'title_override'
:
course_run
.
title_override
,
'min_effort'
:
course_run
.
min_effort
,
...
...
@@ -159,10 +155,6 @@ class CourseRunViewSet(viewsets.GenericViewSet):
'weeks_to_complete'
:
course_run
.
length
,
'learner_testimonials'
:
publisher_course
.
learner_testimonial
,
}
if
start
or
end
:
defaults
[
'start'
]
=
start
defaults
[
'end'
]
=
end
discovery_course_run
,
__
=
DiscoveryCourseRun
.
objects
.
update_or_create
(
course
=
discovery_course
,
key
=
course_run
.
lms_course_id
,
...
...
course_discovery/apps/publisher/dataloader/create_courses.py
View file @
6659595d
...
...
@@ -6,7 +6,6 @@ from django.core.files import File
from
course_discovery.apps.publisher.choices
import
CourseRunStateChoices
,
CourseStateChoices
,
PublisherUserRole
from
course_discovery.apps.publisher.models
import
Course
,
CourseRun
,
CourseRunState
,
CourseState
,
Seat
from
course_discovery.apps.publisher.signals
import
PUBLISHER_COURSE_RUN_CREATED
logger
=
logging
.
getLogger
(
__name__
)
...
...
@@ -124,6 +123,7 @@ def create_course_runs(meta_data_course, publisher_course):
if
canonical_course_run
and
canonical_course_run
.
key
:
defaults
=
{
'course'
:
publisher_course
,
'start'
:
canonical_course_run
.
start
,
'end'
:
canonical_course_run
.
end
,
'min_effort'
:
canonical_course_run
.
min_effort
,
'max_effort'
:
canonical_course_run
.
max_effort
,
'language'
:
canonical_course_run
.
language
,
'pacing_type'
:
canonical_course_run
.
pacing_type
,
'length'
:
canonical_course_run
.
weeks_to_complete
,
...
...
@@ -136,12 +136,6 @@ def create_course_runs(meta_data_course, publisher_course):
lms_course_id
=
canonical_course_run
.
key
,
defaults
=
defaults
)
PUBLISHER_COURSE_RUN_CREATED
.
send
(
model
=
publisher_course_run
,
start
=
canonical_course_run
.
start
,
end
=
canonical_course_run
.
end
)
# add many to many fields.
publisher_course_run
.
transcript_languages
.
add
(
*
canonical_course_run
.
transcript_languages
.
all
())
publisher_course_run
.
staff
.
add
(
*
canonical_course_run
.
staff
.
all
())
...
...
course_discovery/apps/publisher/forms.py
View file @
6659595d
...
...
@@ -230,8 +230,8 @@ class CourseSearchForm(forms.Form):
class
CourseRunForm
(
BaseForm
):
start
=
forms
.
DateTimeField
(
label
=
_
(
'Course Start Date'
),
required
=
Fals
e
)
end
=
forms
.
DateTimeField
(
label
=
_
(
'Course End Date'
),
required
=
Fals
e
)
start
=
forms
.
DateTimeField
(
label
=
_
(
'Course Start Date'
),
required
=
Tru
e
)
end
=
forms
.
DateTimeField
(
label
=
_
(
'Course End Date'
),
required
=
Tru
e
)
staff
=
forms
.
ModelMultipleChoiceField
(
label
=
_
(
'Instructor'
),
queryset
=
Person
.
objects
.
all
(),
...
...
@@ -292,7 +292,7 @@ class CourseRunForm(BaseForm):
model
=
CourseRun
fields
=
(
'length'
,
'transcript_languages'
,
'language'
,
'min_effort'
,
'max_effort'
,
'target_content'
,
'pacing_type'
,
'video_language'
,
'staff'
,
'is_xseries'
,
'xseries_name'
,
'is_professional_certificate'
,
'video_language'
,
'staff'
,
'
start'
,
'end'
,
'
is_xseries'
,
'xseries_name'
,
'is_professional_certificate'
,
'professional_certificate_name'
,
'is_micromasters'
,
'micromasters_name'
,
'lms_course_id'
,
)
...
...
course_discovery/apps/publisher/models.py
View file @
6659595d
...
...
@@ -279,6 +279,8 @@ class CourseRun(TimeStampedModel, ChangedByMixin):
course
=
models
.
ForeignKey
(
Course
,
related_name
=
'publisher_course_runs'
)
lms_course_id
=
models
.
CharField
(
max_length
=
255
,
unique
=
True
,
null
=
True
,
blank
=
True
)
start
=
models
.
DateTimeField
(
null
=
True
,
blank
=
True
)
end
=
models
.
DateTimeField
(
null
=
True
,
blank
=
True
)
certificate_generation
=
models
.
DateTimeField
(
null
=
True
,
blank
=
True
)
pacing_type
=
models
.
CharField
(
max_length
=
255
,
db_index
=
True
,
null
=
True
,
blank
=
True
,
choices
=
CourseRunPacing
.
choices
,
...
...
@@ -356,7 +358,7 @@ class CourseRun(TimeStampedModel, ChangedByMixin):
history
=
HistoricalRecords
()
def
__str__
(
self
):
return
'{course}: {
lms_course_id}'
.
format
(
course
=
self
.
course
.
title
,
lms_course_id
=
self
.
lms_course_id
)
return
'{course}: {
start_date}'
.
format
(
course
=
self
.
course
.
title
,
start_date
=
self
.
start
)
@property
def
post_back_url
(
self
):
...
...
course_discovery/apps/publisher/signals.py
View file @
6659595d
...
...
@@ -4,7 +4,7 @@ import waffle
from
django.contrib.auth.models
import
Permission
from
django.core.exceptions
import
ObjectDoesNotExist
from
django.db.models.signals
import
post_save
from
django.dispatch
import
receiver
,
Signal
from
django.dispatch
import
receiver
from
slumber.exceptions
import
SlumberBaseException
from
course_discovery.apps.publisher.models
import
CourseRun
,
OrganizationExtension
...
...
@@ -12,7 +12,6 @@ from course_discovery.apps.publisher.studio_api_utils import StudioAPI
logger
=
logging
.
getLogger
(
__name__
)
PUBLISHER_COURSE_RUN_CREATED
=
Signal
(
providing_args
=
[
'model'
,
'start'
,
'end'
])
def
get_related_discovery_course_run
(
publisher_course_run
):
try
:
...
...
@@ -22,7 +21,7 @@ def get_related_discovery_course_run(publisher_course_run):
return
@receiver
(
PUBLISHER_COURSE_RUN_CREATED
,
sender
=
CourseRun
)
@receiver
(
post_save
,
sender
=
CourseRun
)
def
create_course_run_in_studio_receiver
(
sender
,
instance
,
created
,
**
kwargs
):
# pylint: disable=unused-argument
if
created
and
waffle
.
switch_is_active
(
'enable_publisher_create_course_run_in_studio'
):
course
=
instance
.
course
...
...
course_discovery/apps/publisher/studio_api_utils.py
View file @
6659595d
...
...
@@ -25,7 +25,8 @@ class StudioAPI:
return
candidate
@classmethod
def
calculate_course_run_key_run_value
(
cls
,
course_run
,
start
):
def
calculate_course_run_key_run_value
(
cls
,
course_run
):
start
=
course_run
.
start
trimester
=
math
.
ceil
(
start
.
month
/
4.
)
run
=
'{trimester}T{year}'
.
format
(
trimester
=
trimester
,
year
=
start
.
year
)
...
...
@@ -40,7 +41,7 @@ class StudioAPI:
return
cls
.
_get_next_run
(
run
,
''
,
related_course_runs
)
@classmethod
def
generate_data_for_studio_api
(
cls
,
publisher_course_run
,
start
=
None
,
end
=
Non
e
):
def
generate_data_for_studio_api
(
cls
,
publisher_course_run
,
include_schedule
=
Fals
e
):
course
=
publisher_course_run
.
course
course_team_admin
=
course
.
course_team_admin
team
=
[]
...
...
@@ -60,28 +61,23 @@ class StudioAPI:
'title'
:
publisher_course_run
.
title_override
or
course
.
title
,
'org'
:
course
.
organizations
.
first
()
.
key
,
'number'
:
course
.
number
,
# this should raise an error if no start is provided and no lms course run exists
'run'
:
cls
.
calculate_course_run_key_run_value
(
publisher_course_run
,
start
if
start
else
publisher_course_run
.
lms_start
),
'run'
:
cls
.
calculate_course_run_key_run_value
(
publisher_course_run
),
'team'
:
team
,
'pacing_type'
:
publisher_course_run
.
pacing_type
,
}
if
start
or
end
:
if
include_schedule
:
data
[
'schedule'
]
=
{
'start'
:
serialize_datetime
(
start
),
'end'
:
serialize_datetime
(
end
),
}
'start'
:
serialize_datetime
(
publisher_course_run
.
start
),
'end'
:
serialize_datetime
(
publisher_course_run
.
end
),
}
,
return
data
def
create_course_rerun_in_studio
(
self
,
publisher_course_run
,
discovery_course_run
,
start
,
end
):
data
=
self
.
generate_data_for_studio_api
(
publisher_course_run
,
start
,
end
)
def
create_course_rerun_in_studio
(
self
,
publisher_course_run
,
discovery_course_run
):
data
=
self
.
generate_data_for_studio_api
(
publisher_course_run
,
include_schedule
=
True
)
return
self
.
_api
.
course_runs
(
discovery_course_run
.
key
)
.
rerun
.
post
(
data
)
def
create_course_run_in_studio
(
self
,
publisher_course_run
,
start
,
end
):
data
=
self
.
generate_data_for_studio_api
(
publisher_course_run
,
start
,
end
)
def
create_course_run_in_studio
(
self
,
publisher_course_run
):
data
=
self
.
generate_data_for_studio_api
(
publisher_course_run
,
include_schedule
=
True
)
return
self
.
_api
.
course_runs
.
post
(
data
)
def
update_course_run_image_in_studio
(
self
,
publisher_course_run
):
...
...
course_discovery/apps/publisher/tests/factories.py
View file @
6659595d
...
...
@@ -48,6 +48,8 @@ class CourseFactory(factory.DjangoModelFactory):
class
CourseRunFactory
(
factory
.
DjangoModelFactory
):
course
=
factory
.
SubFactory
(
CourseFactory
)
start
=
FuzzyDateTime
(
datetime
(
2014
,
1
,
1
,
tzinfo
=
UTC
))
end
=
FuzzyDateTime
(
datetime
(
2014
,
1
,
1
,
tzinfo
=
UTC
))
.
end_dt
certificate_generation
=
FuzzyDateTime
(
datetime
(
2014
,
1
,
1
,
tzinfo
=
UTC
))
min_effort
=
FuzzyInteger
(
1
,
10
)
max_effort
=
FuzzyInteger
(
10
,
20
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment