Commit 468d703b by Brian Wilson

Update CDD export to output only changed records.

parent cc8e8ba6
import csv import csv
import uuid import uuid
from collections import defaultdict, OrderedDict from collections import OrderedDict
from datetime import datetime from datetime import datetime
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand
from student.models import TestCenterUser from student.models import TestCenterUser
from os.path import isdir
from fs.path import pathjoin
class Command(BaseCommand): class Command(BaseCommand):
CSV_TO_MODEL_FIELDS = OrderedDict([ CSV_TO_MODEL_FIELDS = OrderedDict([
# Skipping optional field CandidateID
("ClientCandidateID", "client_candidate_id"), ("ClientCandidateID", "client_candidate_id"),
("FirstName", "first_name"), ("FirstName", "first_name"),
("LastName", "last_name"), ("LastName", "last_name"),
...@@ -44,9 +47,36 @@ class Command(BaseCommand): ...@@ -44,9 +47,36 @@ class Command(BaseCommand):
print Command.help print Command.help
return return
self.reset_sample_data() # use options to set these:
dump_all = False
# self.reset_sample_data()
with open(args[0], "wb") as outfile: # update time should use UTC in order to be comparable to the user_updated_at
# field
uploaded_at = datetime.utcnow()
# if specified destination is an existing directory, then
# create a filename for it automatically. If it doesn't exist,
# or exists as a file, then we will just write to it.
# Name will use timestamp -- this is UTC, so it will look funny,
# but it should at least be consistent with the other timestamps
# used in the system.
dest = args[0]
if isdir(dest):
destfile = pathjoin(dest, uploaded_at.strftime("cdd-%Y%m%d-%H%M%S.dat"))
else:
destfile = dest
# strings must be in latin-1 format. CSV parser will
# otherwise convert unicode objects to ascii.
def ensure_encoding(value):
if isinstance(value, unicode):
return value.encode('iso-8859-1');
else:
return value;
with open(destfile, "wb") as outfile:
writer = csv.DictWriter(outfile, writer = csv.DictWriter(outfile,
Command.CSV_TO_MODEL_FIELDS, Command.CSV_TO_MODEL_FIELDS,
delimiter="\t", delimiter="\t",
...@@ -54,11 +84,15 @@ class Command(BaseCommand): ...@@ -54,11 +84,15 @@ class Command(BaseCommand):
extrasaction='ignore') extrasaction='ignore')
writer.writeheader() writer.writeheader()
for tcu in TestCenterUser.objects.order_by('id'): for tcu in TestCenterUser.objects.order_by('id'):
record = dict((csv_field, getattr(tcu, model_field)) if dump_all or tcu.needs_uploading:
for csv_field, model_field record = dict((csv_field, ensure_encoding(getattr(tcu, model_field)))
in Command.CSV_TO_MODEL_FIELDS.items()) for csv_field, model_field
record["LastUpdate"] = record["LastUpdate"].strftime("%Y/%m/%d %H:%M:%S") in Command.CSV_TO_MODEL_FIELDS.items())
writer.writerow(record) record["LastUpdate"] = record["LastUpdate"].strftime("%Y/%m/%d %H:%M:%S")
writer.writerow(record)
tcu.uploaded_at = uploaded_at
tcu.save()
def reset_sample_data(self): def reset_sample_data(self):
def make_sample(**kwargs): def make_sample(**kwargs):
......
import uuid
from datetime import datetime
from optparse import make_option from optparse import make_option
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand
from student.models import TestCenterUser from student.models import TestCenterUser, TestCenterUserForm
class Command(BaseCommand): class Command(BaseCommand):
option_list = BaseCommand.option_list + ( option_list = BaseCommand.option_list + (
make_option( # demographics:
'--client_candidate_id',
action='store',
dest='client_candidate_id',
help='ID we assign a user to identify them to Pearson'
),
make_option( make_option(
'--first_name', '--first_name',
action='store', action='store',
...@@ -64,6 +57,25 @@ class Command(BaseCommand): ...@@ -64,6 +57,25 @@ class Command(BaseCommand):
dest='phone_country_code', dest='phone_country_code',
help='Phone country code, just "1" for the USA' help='Phone country code, just "1" for the USA'
), ),
# internal values:
make_option(
'--client_candidate_id',
action='store',
dest='client_candidate_id',
help='ID we assign a user to identify them to Pearson'
),
make_option(
'--upload_status',
action='store',
dest='upload_status',
help='status value assigned by Pearson'
),
make_option(
'--upload_error_message',
action='store',
dest='upload_error_message',
help='error message provided by Pearson on a failure.'
),
) )
args = "<student_username>" args = "<student_username>"
help = "Create a TestCenterUser entry for a given Student" help = "Create a TestCenterUser entry for a given Student"
...@@ -79,7 +91,41 @@ class Command(BaseCommand): ...@@ -79,7 +91,41 @@ class Command(BaseCommand):
print username print username
our_options = dict((k, v) for k, v in options.items() our_options = dict((k, v) for k, v in options.items()
if Command.is_valid_option(k)) if Command.is_valid_option(k) and v is not None)
student = User.objects.get(username=username) student = User.objects.get(username=username)
student.test_center_user = TestCenterUser(**our_options) try:
student.test_center_user.save() testcenter_user = TestCenterUser.objects.get(user=student)
needs_updating = testcenter_user.needs_update(our_options)
except TestCenterUser.DoesNotExist:
# do additional initialization here:
testcenter_user = TestCenterUser.create(student)
needs_updating = True
if needs_updating:
form = TestCenterUserForm(instance=testcenter_user, data=our_options)
if form.is_valid():
form.update_and_save()
else:
if (len(form.errors) > 0):
print "Field Form errors encountered:"
for fielderror in form.errors:
print "Field Form Error: %s" % fielderror
if (len(form.non_field_errors()) > 0):
print "Non-field Form errors encountered:"
for nonfielderror in form.non_field_errors:
print "Non-field Form Error: %s" % nonfielderror
else:
print "No changes necessary to make to existing user's demographics."
# override internal values:
change_internal = False
testcenter_user = TestCenterUser.objects.get(user=student)
for internal_field in [ 'upload_error_message', 'upload_status', 'client_candidate_id']:
if internal_field in our_options:
testcenter_user = our_options[internal_field]
change_internal = True
if change_internal:
testcenter_user.save()
...@@ -208,6 +208,9 @@ class TestCenterUser(models.Model): ...@@ -208,6 +208,9 @@ class TestCenterUser(models.Model):
candidate_id = models.IntegerField(null=True, db_index=True) candidate_id = models.IntegerField(null=True, db_index=True)
confirmed_at = models.DateTimeField(null=True, db_index=True) confirmed_at = models.DateTimeField(null=True, db_index=True)
@property
def needs_uploading(self):
return self.uploaded_at is None or self.uploaded_at < self.user_updated_at
@staticmethod @staticmethod
def user_provided_fields(): def user_provided_fields():
...@@ -223,7 +226,7 @@ class TestCenterUser(models.Model): ...@@ -223,7 +226,7 @@ class TestCenterUser(models.Model):
# needs_updating = any([__getattribute__(fieldname) != dict[fieldname] # needs_updating = any([__getattribute__(fieldname) != dict[fieldname]
# for fieldname in TestCenterUser.user_provided_fields()]) # for fieldname in TestCenterUser.user_provided_fields()])
for fieldname in TestCenterUser.user_provided_fields(): for fieldname in TestCenterUser.user_provided_fields():
if self.__getattribute__(fieldname) != dict[fieldname]: if fieldname in dict and self.__getattribute__(fieldname) != dict[fieldname]:
return True return True
return False return False
...@@ -231,7 +234,7 @@ class TestCenterUser(models.Model): ...@@ -231,7 +234,7 @@ class TestCenterUser(models.Model):
@staticmethod @staticmethod
def _generate_candidate_id(): def _generate_candidate_id():
NUM_DIGITS = 12 NUM_DIGITS = 12
return u"edX%0d" % randint(1, 10**NUM_DIGITS-1) # binascii.hexlify(os.urandom(8)) return u"edX%0d" % randint(1, 10**NUM_DIGITS-1)
@staticmethod @staticmethod
def create(user): def create(user):
...@@ -266,7 +269,7 @@ class TestCenterUserForm(ModelForm): ...@@ -266,7 +269,7 @@ class TestCenterUserForm(ModelForm):
def update_and_save(self): def update_and_save(self):
new_user = self.save(commit=False) new_user = self.save(commit=False)
# create additional values here: # create additional values here:
new_user.user_updated_at = datetime.now() new_user.user_updated_at = datetime.utcnow()
new_user.save() new_user.save()
# add validation: # add validation:
...@@ -505,7 +508,7 @@ class TestCenterRegistrationForm(ModelForm): ...@@ -505,7 +508,7 @@ class TestCenterRegistrationForm(ModelForm):
def update_and_save(self): def update_and_save(self):
registration = self.save(commit=False) registration = self.save(commit=False)
# create additional values here: # create additional values here:
registration.user_updated_at = datetime.now() registration.user_updated_at = datetime.utcnow()
registration.save() registration.save()
# TODO: add validation code for values added to accommodation_code field. # TODO: add validation code for values added to accommodation_code field.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment