Update CDD export to output only changed records.
This commit is contained in:
@@ -1,14 +1,17 @@
|
||||
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):
|
||||
|
||||
@@ -1,20 +1,13 @@
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user