Added html view of serial numbers. Refactored code.
This commit is contained in:
@@ -9,15 +9,18 @@ from xmodule.modulestore.django import modulestore
|
||||
|
||||
from licenses.models import CourseSoftware, UserLicense
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = """Imports serial numbers for software used in a course.
|
||||
|
||||
Usage: import_serial_numbers <course_id> <software_name> <filename>
|
||||
Usage: import_serial_numbers <course_id> <software_name> <file>
|
||||
|
||||
serial_file is a text file that list one available serial number per line.
|
||||
<file> is a text file that list one available serial number per line.
|
||||
|
||||
Example:
|
||||
django-admin.py import_serial_numbers MITx/6.002x/2012_Fall matlab /tmp/matlab-serials.txt
|
||||
|
||||
import_serial_numbers MITx/6.002x/2012_Fall matlab serials.txt
|
||||
|
||||
"""
|
||||
args = "course_id software_id serial_file"
|
||||
|
||||
@@ -49,7 +52,6 @@ class Command(BaseCommand):
|
||||
|
||||
return course_id, software_name, filename
|
||||
|
||||
|
||||
def _import_serials(self, software, filename):
|
||||
print "Importing serial numbers for {0}.".format(software)
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
"""
|
||||
"""
|
||||
from django.db import models
|
||||
import logging
|
||||
|
||||
from django.db import models, transaction
|
||||
|
||||
from student.models import User
|
||||
|
||||
log = logging.getLogger("mitx.licenses")
|
||||
|
||||
|
||||
class CourseSoftware(models.Model):
|
||||
name = models.CharField(max_length=255)
|
||||
@@ -18,3 +21,58 @@ class UserLicense(models.Model):
|
||||
software = models.ForeignKey(CourseSoftware, db_index=True)
|
||||
user = models.ForeignKey(User, null=True)
|
||||
serial = models.CharField(max_length=255)
|
||||
|
||||
|
||||
def get_courses_licenses(user, courses):
|
||||
course_ids = set(course.id for course in courses)
|
||||
all_software = CourseSoftware.objects.filter(course_id__in=course_ids)
|
||||
|
||||
assigned_licenses = UserLicense.objects.filter(software__in=all_software,
|
||||
user=user)
|
||||
|
||||
licenses = dict.fromkeys(all_software, None)
|
||||
for license in assigned_licenses:
|
||||
licenses[license.software] = license
|
||||
|
||||
log.info(assigned_licenses)
|
||||
log.info(licenses)
|
||||
|
||||
return licenses
|
||||
|
||||
|
||||
def get_license(user, software):
|
||||
try:
|
||||
license = UserLicense.objects.get(user=user, software=software)
|
||||
except UserLicense.DoesNotExist:
|
||||
license = None
|
||||
|
||||
return license
|
||||
|
||||
|
||||
def get_or_create_license(user, software):
|
||||
license = get_license(user, software)
|
||||
if license is None:
|
||||
license = _create_license(user, software)
|
||||
|
||||
return license
|
||||
|
||||
|
||||
def _create_license(user, software):
|
||||
license = None
|
||||
|
||||
try:
|
||||
# find one license that has not been assigned, locking the
|
||||
# table/rows with select_for_update to prevent race conditions
|
||||
with transaction.commit_on_success():
|
||||
selected = UserLicense.objects.select_for_update()
|
||||
license = selected.filter(user__isnull=True)[0]
|
||||
license.user = user
|
||||
license.save()
|
||||
except IndexError:
|
||||
# there are no free licenses
|
||||
log.error('No serial numbers available for {0}', software)
|
||||
license = None
|
||||
# TODO [rocha]look if someone has unenrolled from the class
|
||||
# and already has a serial number
|
||||
|
||||
return license
|
||||
|
||||
@@ -1,60 +1,35 @@
|
||||
import logging
|
||||
from itertools import groupby
|
||||
from collections import Iterable
|
||||
from collections import namedtuple, defaultdict
|
||||
|
||||
from django.db.models import Q
|
||||
from mitxmako.shortcuts import render_to_string
|
||||
|
||||
from models import get_courses_licenses, get_or_create_license
|
||||
|
||||
from models import CourseSoftware, UserLicense
|
||||
|
||||
log = logging.getLogger("mitx.licenses")
|
||||
|
||||
|
||||
def get_or_create_courses_licenses(user, courses):
|
||||
user_licenses = get_courses_licenses(user, courses)
|
||||
License = namedtuple('License', 'software serial')
|
||||
|
||||
for software, license in user_licenses.iteritems():
|
||||
|
||||
def get_licenses_by_course(user, courses):
|
||||
licenses = get_courses_licenses(user, courses)
|
||||
licenses_by_course = defaultdict(list)
|
||||
|
||||
# create missing licenses and group by course_id
|
||||
for software, license in licenses.iteritems():
|
||||
if license is None:
|
||||
user_licenses[software] = get_or_create_user_license(user, software)
|
||||
licenses[software] = get_or_create_license(user, software)
|
||||
|
||||
log.info(user_licenses)
|
||||
course_id = software.course_id
|
||||
serial = license.serial if license else None
|
||||
licenses_by_course[course_id].append(License(software, serial))
|
||||
|
||||
return user_licenses
|
||||
# render elements
|
||||
data_by_course = {}
|
||||
for course_id, licenses in licenses_by_course.iteritems():
|
||||
context = {'licenses': licenses}
|
||||
template = 'licenses/serial_numbers.html'
|
||||
data_by_course[course_id] = render_to_string(template, context)
|
||||
|
||||
|
||||
def get_courses_licenses(user, courses):
|
||||
course_ids = set(course.id for course in courses)
|
||||
all_software = CourseSoftware.objects.filter(course_id__in=course_ids)
|
||||
|
||||
user_licenses = dict.fromkeys(all_software, None)
|
||||
|
||||
assigned_licenses = UserLicense.objects.filter(software__in=all_software, user=user)
|
||||
assigned_by_software = {lic.software:lic for lic in assigned_licenses}
|
||||
|
||||
for software, license in assigned_by_software.iteritems():
|
||||
user_licenses[software] = license
|
||||
|
||||
return user_licenses
|
||||
|
||||
|
||||
def get_or_create_user_license(user, software):
|
||||
license = None
|
||||
try:
|
||||
# Find a licenses associated with the user or with no user
|
||||
# associated.
|
||||
query = (Q(user__isnull=True) | Q(user=user)) & Q(software=software)
|
||||
|
||||
# TODO fix a race condition in this code when more than one
|
||||
# user is getting a license assigned
|
||||
|
||||
license = UserLicense.objects.filter(query)[0]
|
||||
|
||||
if license.user is not user:
|
||||
license.user = user
|
||||
license.save()
|
||||
|
||||
except IndexError:
|
||||
# TODO look if someone has unenrolled from the class and already has a serial number
|
||||
log.error('No serial numbers available for {0}', software)
|
||||
|
||||
|
||||
return license
|
||||
return data_by_course
|
||||
|
||||
10
lms/templates/licenses/serial_numbers.html
Normal file
10
lms/templates/licenses/serial_numbers.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<dl>
|
||||
% for license in licenses:
|
||||
<dt> ${license.software.name}: </dt>
|
||||
% if license.serial:
|
||||
<dd> ${license.serial} </dd>
|
||||
% else:
|
||||
<dd> None Available </dd>
|
||||
% endif
|
||||
% endfor
|
||||
</dl>
|
||||
Reference in New Issue
Block a user