* Update question instance scores from a CSV file. * * @param {number} assessment_id - The assessment to update. * @param {csvFile} csvFile - An object with keys {originalname, size, buffer}. * @param {number} user_id - The current user performing the update. * @param {numbe
(assessment_id, csvFile, user_id, authn_user_id, callback)
| 24 | * @param {function} callback - A callback(err, job_sequence_id) function. |
| 25 | */ |
| 26 | uploadInstanceQuestionScores(assessment_id, csvFile, user_id, authn_user_id, callback) { |
| 27 | debug('uploadInstanceQuestionScores()'); |
| 28 | if (csvFile == null) { |
| 29 | return callback(new Error('No CSV file uploaded')); |
| 30 | } |
| 31 | const params = {assessment_id}; |
| 32 | sqldb.queryOneRow(sql.select_assessment_info, params, function(err, result) { |
| 33 | if (ERR(err, callback)) return; |
| 34 | const assessment_label = result.rows[0].assessment_label; |
| 35 | const course_instance_id = result.rows[0].course_instance_id; |
| 36 | const course_id = result.rows[0].course_id; |
| 37 | |
| 38 | const options = { |
| 39 | course_id: course_id, |
| 40 | course_instance_id: course_instance_id, |
| 41 | assessment_id: assessment_id, |
| 42 | user_id: user_id, |
| 43 | authn_user_id: authn_user_id, |
| 44 | type: 'upload_instance_question_scores', |
| 45 | description: 'Upload question scores for ' + assessment_label, |
| 46 | }; |
| 47 | serverJobs.createJobSequence(options, function(err, job_sequence_id) { |
| 48 | if (ERR(err, callback)) return; |
| 49 | callback(null, job_sequence_id); |
| 50 | |
| 51 | // We've now triggered the callback to our caller, but we |
| 52 | // continue executing below to launch the jobs themselves. |
| 53 | |
| 54 | const jobOptions = { |
| 55 | course_id: course_id, |
| 56 | course_instance_id: course_instance_id, |
| 57 | assessment_id: assessment_id, |
| 58 | user_id: user_id, |
| 59 | authn_user_id: authn_user_id, |
| 60 | type: 'upload_instance_question_scores', |
| 61 | description: 'Upload question scores for ' + assessment_label, |
| 62 | job_sequence_id: job_sequence_id, |
| 63 | last_in_sequence: true, |
| 64 | }; |
| 65 | serverJobs.createJob(jobOptions, function(err, job) { |
| 66 | if (err) { |
| 67 | logger.error('Error in createJob()', err); |
| 68 | serverJobs.failJobSequence(job_sequence_id); |
| 69 | return; |
| 70 | } |
| 71 | job.verbose('Uploading question scores for ' + assessment_label); |
| 72 | |
| 73 | // acculumate output lines in the "output" variable and actually |
| 74 | // output put them in blocks, to avoid spamming the updates |
| 75 | let output = null; |
| 76 | let outputCount = 0; |
| 77 | let outputThreshold = 100; |
| 78 | |
| 79 | job.verbose(`Parsing uploaded CSV file "${csvFile.originalname}" (${csvFile.size} bytes)`); |
| 80 | job.verbose(`----------------------------------------`); |
| 81 | const csvStream = streamifier.createReadStream(csvFile.buffer, {encoding: 'utf8'}); |
| 82 | const csvConverter = csvtojson({ |
| 83 | colParser:{ |