Commit 468d703b by Brian Wilson

Update CDD export to output only changed records.

parent cc8e8ba6
import csv
import uuid
from collections import defaultdict, OrderedDict
from collections import OrderedDict
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 os.path import isdir
from fs.path import pathjoin
class Command(BaseCommand):
CSV_TO_MODEL_FIELDS = OrderedDict([
# Skipping optional field CandidateID
("ClientCandidateID", "client_candidate_id"),
("FirstName", "first_name"),
("LastName", "last_name"),
......@@ -44,9 +47,36 @@ class Command(BaseCommand):
print Command.help
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,
Command.CSV_TO_MODEL_FIELDS,
delimiter="\t",
......@@ -54,11 +84,15 @@ class Command(BaseCommand):
extrasaction='ignore')
writer.writeheader()
for tcu in TestCenterUser.objects.order_by('id'):
record = dict((csv_field, getattr(tcu, model_field))
for csv_field, model_field
in Command.CSV_TO_MODEL_FIELDS.items())
record["LastUpdate"] = record["LastUpdate"].strftime("%Y/%m/%d %H:%M:%S")
writer.writerow(record)
if dump_all or tcu.needs_uploading:
record = dict((csv_field, ensure_encoding(getattr(tcu, model_field)))
for csv_field, model_field
in Command.CSV_TO_MODEL_FIELDS.items())
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 make_sample(**kwargs):
......
import uuid
from datetime import datetime
from optparse import make_option
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):
option_list = BaseCommand.option_list + (
make_option(
'--client_candidate_id',
action='store',
dest='client_candidate_id',
help='ID we assign a user to identify them to Pearson'
),
# demographics:
make_option(
'--first_name',
action='store',
......@@ -64,6 +57,25 @@ class Command(BaseCommand):
dest='phone_country_code',
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>"
help = "Create a TestCenterUser entry for a given Student"
......@@ -79,7 +91,41 @@ class Command(BaseCommand):
print username
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.test_center_user = TestCenterUser(**our_options)
student.test_center_user.save()
try:
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):
candidate_id = models.IntegerField(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
def user_provided_fields():
......@@ -223,7 +226,7 @@ class TestCenterUser(models.Model):
# needs_updating = any([__getattribute__(fieldname) != dict[fieldname]
# 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 False
......@@ -231,7 +234,7 @@ class TestCenterUser(models.Model):
@staticmethod
def _generate_candidate_id():
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
def create(user):
......@@ -266,7 +269,7 @@ class TestCenterUserForm(ModelForm):
def update_and_save(self):
new_user = self.save(commit=False)
# create additional values here:
new_user.user_updated_at = datetime.now()
new_user.user_updated_at = datetime.utcnow()
new_user.save()
# add validation:
......@@ -505,7 +508,7 @@ class TestCenterRegistrationForm(ModelForm):
def update_and_save(self):
registration = self.save(commit=False)
# create additional values here:
registration.user_updated_at = datetime.now()
registration.user_updated_at = datetime.utcnow()
registration.save()
# 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