diff --git a/app/models/form.server.model.js b/app/models/form.server.model.js index 7521549e..888f8714 100644 --- a/app/models/form.server.model.js +++ b/app/models/form.server.model.js @@ -9,6 +9,7 @@ var mongoose = require('mongoose'), _ = require('lodash'), config = require('../../config/config'), path = require('path'), + mUtilities = require('mongoose-utilities'), fs = require('fs-extra'), async = require('async'), util = require('util'); @@ -44,13 +45,13 @@ var ButtonSchema = new Schema({ * Form Schema */ var FormSchema = new Schema({ - created: { - type: Date, - default: Date.now - }, - lastModified: { - type: Date, - }, + // created: { + // type: Date, + // default: Date.now + // }, + // lastModified: { + // type: Date, + // }, title: { type: String, trim: true, @@ -66,9 +67,9 @@ var FormSchema = new Schema({ type: String, default: '', }, - form_fields: [{ - type: Schema.Types.Mixed - }], + form_fields: { + type: [FieldSchema], + }, submissions: [{ type: Schema.Types.ObjectId, @@ -173,6 +174,12 @@ var FormSchema = new Schema({ } }); +FormSchema.plugin(mUtilities.timestamp, { + createdPath: 'created', + modifiedPath: 'lastModified', + useVirtual: false +}); + //Delete template PDF of current Form FormSchema.pre('remove', function (next) { if(this.pdf && process.env.NODE_ENV === 'development'){ @@ -203,16 +210,6 @@ FormSchema.pre('save', function (next) { }); }); -//Update lastModified and created everytime we save -FormSchema.pre('save', function (next) { - var now = new Date(); - this.lastModified = now; - if( !this.created ){ - this.created = now; - } - next(); -}); - function getDeletedIndexes(needle, haystack){ var deletedIndexes = []; @@ -298,7 +295,7 @@ FormSchema.pre('save', function (next) { field.fieldType = _typeConvMap[ field.fieldType+'' ]; } - field = new Field(field); + // field = new Field(field); field.required = false; _form_fields[i] = field; } @@ -343,8 +340,8 @@ FormSchema.pre('save', function (next) { // var _original = this._original; // console.log('_original\n------------'); // console.log(_original); - // console.log('field has been deleted: '); - // console.log(this.isModified('form_fields') && !!this.form_fields && !!_original); + //console.log('field has been deleted: '); + //console.log(this.isModified('form_fields') && !!this.form_fields && !!_original); if(this.isModified('form_fields') && this.form_fields.length >= 0 && _original){ @@ -354,12 +351,12 @@ FormSchema.pre('save', function (next) { deletedIds = getDeletedIndexes(old_ids, new_ids), that = this; - // console.log('deletedId Indexes\n--------'); - // console.log(deletedIds); - // console.log('old_ids\n--------'); - // console.log(old_ids); - // console.log('new_ids\n--------'); - // console.log(new_ids); + console.log('deletedId Indexes\n--------'); + console.log(deletedIds); + console.log('old_ids\n--------'); + console.log(old_ids); + console.log('new_ids\n--------'); + console.log(new_ids); //Preserve fields that have at least one submission if( deletedIds.length > 0 ){ @@ -387,25 +384,26 @@ FormSchema.pre('save', function (next) { // callback(null, modifiedSubmissions); // } else{ + + //Find FormSubmissions that contain field with _id equal to 'deleted_id' FormSubmission. - find({ form: that._id, admin: that.admin, form_fields: {$elemMatch: {_id: deleted_id} } }). + find({ form: that._id, admin: that.admin, form_fields: {$elemMatch: {_id: deleted_id} } }). exec(function(err, submissions){ if(err){ console.error(err); return callback(err); } - // console.log(submissions); - - //Delete field if there are no submission(s) found - if(submissions.length) { - //Push old form_field to start of array - // that.form_fields.unshift(old_form_fields[deletedIdIndex]); - modifiedSubmissions.push.apply(modifiedSubmissions, submissions); - } + //Delete field if there are no submission(s) found + if(submissions.length) { + console.log('adding submissions'); + console.log(submissions); + //Add submissions + modifiedSubmissions.push.apply(modifiedSubmissions, submissions); + } - callback(null); - }); + callback(null); + }); // } }, function (err) { @@ -417,34 +415,32 @@ FormSchema.pre('save', function (next) { // console.log('modifiedSubmissions\n---------\n\n'); // console.log(modifiedSubmissions); - // console.log('preserved deleted fields'); - // console.log(submissions); - + //Iterate through all submissions with modified form_fields async.forEachOfSeries(modifiedSubmissions, function (submission, key, callback) { + //Iterate through ids of deleted fields for(var i = 0; i < deletedIds.length; i++){ + //Get index of deleted field var index = _.findIndex(submission.form_fields, function(field) { var tmp_id = field._id+''; - // console.log(tmp_id === old_ids[ deletedIds[i] ]); return tmp_id === old_ids[ deletedIds[i] ]; }); - // console.log('index: '+index); + var deletedField = submission.form_fields[index]; - var tmpField = submission.form_fields[index]; - - if(tmpField){ - // console.log('tmpField\n-------\n\n'); - // console.log(tmpField); + //Hide field if it exists + if(deletedField){ + console.log('deletedField\n-------\n\n'); + console.log(deletedField); //Delete old form_field submission.form_fields.splice(index, 1); - tmpField.deletePreserved = true; - //Move old form_field to start - submission.form_fields.unshift(tmpField); + deletedField.deletePreserved = true; - that.form_fields.unshift(tmpField); + //Move deleted form_field to start + submission.form_fields.unshift(deletedField); + that.form_fields.unshift(deletedField); // console.log('form.form_fields\n--------\n\n'); // console.log(that.form_fields); } diff --git a/app/models/form_field.server.model.js b/app/models/form_field.server.model.js index d6531b8a..b5f2ae34 100644 --- a/app/models/form_field.server.model.js +++ b/app/models/form_field.server.model.js @@ -5,11 +5,27 @@ */ var mongoose = require('mongoose'), relationship = require('mongoose-relationship'), + mUtilities = require('mongoose-utilities'), _ = require('lodash'), Schema = mongoose.Schema; +var FieldOptionSchema = new Schema({ + option_id: { + type: Number, + }, + + option_title: { + type: String, + }, + + option_value: { + type: String, + trim: true, + }, +}); + /** - * Question Schema + * FormField Schema */ var FormFieldSchema = new Schema({ // formSubmission: { @@ -18,18 +34,10 @@ var FormFieldSchema = new Schema({ // childPath: 'form_fields' // }, - created: { - type: Date, - default: Date.now - }, - lastModified: { - type: Date, - default: Date.now - }, title: { type: String, trim: true, - required: 'Field title cannot be blank' + required: 'Field Title cannot be blank', }, description: { type: String, @@ -41,10 +49,7 @@ var FormFieldSchema = new Schema({ ref: 'LogicJump' }, - //DAVID: TODO: SEMI-URGENT: Need to come up with a schema for field options - fieldOptions: [{ - type: Schema.Types.Mixed - }], + fieldOptions: [FieldOptionSchema], required: { type: Boolean, default: true, @@ -60,14 +65,18 @@ var FormFieldSchema = new Schema({ }, fieldType: { type: String, - required: 'Field type cannot be blank', + required: true, validate: [validateFormFieldType, 'Invalid field type'] }, fieldValue: Schema.Types.Mixed }); // FormFieldSchema.plugin(relationship, { relationshipPathName:'formSubmission' }); - +FormFieldSchema.plugin(mUtilities.timestamp, { + createdPath: 'created', + modifiedPath: 'lastModified', + useVirtual: false +}); FormFieldSchema.static('validTypes', function(){ return [ 'textfield', @@ -124,8 +133,8 @@ function validateFormFieldType(value) { return false; }; -var cloneFieldSchema = _.cloneDeep(FormFieldSchema); +// var cloneFieldSchema = _.cloneDeep(FormFieldSchema); mongoose.model('Field', FormFieldSchema); -module.exports = cloneFieldSchema; +module.exports = FormFieldSchema; diff --git a/app/models/form_submission.server.model.js b/app/models/form_submission.server.model.js index 2d631669..23e3597f 100644 --- a/app/models/form_submission.server.model.js +++ b/app/models/form_submission.server.model.js @@ -11,60 +11,59 @@ var mongoose = require('mongoose'), config = require('../../config/config'), path = require('path'), fs = require('fs-extra'), - Field = mongoose.model('Field'), + mUtilities = require('mongoose-utilities'), soap = require('soap'), + async = require('async'), FieldSchema = require('./form_field.server.model.js'), OscarSecurity = require('../../scripts/oscarhost/OscarSecurity'); - + var newDemoTemplate = { - "activeCount": 0, - "address": "", - "alias": "", - "anonymous": "", - "chartNo": "", - "children":"", - "citizenship":"", - "city": "", - "dateJoined": null, - "dateOfBirth": "", - "email": "", - "firstName": "", - "hin": 9146509343, - "lastName": "", - "lastUpdateDate": null, - "monthOfBirth": "", - "officialLanguage": "", - "phone": "", - "phone2": "", - "providerNo": 0, - "province": "", - "sex": "", - "spokenLanguage": "", - "postal": "", - "yearOfBirth": "" + 'activeCount': 0, + 'address': '', + 'alias': '', + 'anonymous': '', + 'chartNo': '', + 'children':'', + 'citizenship':'', + 'city': '', + 'dateJoined': null, + 'dateOfBirth': '', + 'email': '', + 'firstName': '', + 'hin': 9146509343, + 'lastName': '', + 'lastUpdateDate': null, + 'monthOfBirth': '', + 'officialLanguage': '', + 'phone': '', + 'phone2': '', + 'providerNo': 0, + 'province': '', + 'sex': '', + 'spokenLanguage': '', + 'postal': '', + 'yearOfBirth': '' }; /** * Form Submission Schema */ var FormSubmissionSchema = new Schema({ - title:{ + title: { type: String }, - created: { - type: Date, - default: Date.now - }, admin: { type: Schema.Types.ObjectId, ref: 'User', required: true }, - form_fields: [FieldSchema], + form_fields: { + type: [Schema.Types.Mixed], + }, form: { - type:Schema.Types.ObjectId, - ref:'Form', + type: Schema.Types.ObjectId, + ref: 'Form', required: true }, @@ -99,74 +98,104 @@ var FormSubmissionSchema = new Schema({ }); +FormSubmissionSchema.plugin(mUtilities.timestamp, { + createdPath: 'created', + modifiedPath: 'lastModified', + useVirtual: false +}); + //Oscarhost API hook -FormSubmissionSchema.post('save', function (next) { - if(this.form.plugins.oscarhost.baseUrl){ +FormSubmissionSchema.pre('save', function (next) { + + var self = this; + mongoose.model('Form').findById(self.form, function(err, _form){ + var form_ids = _.map(_.pluck(_form.form_fields, '_id'), function(id){ return ''+id;}), + submission_ids = _.pluck(self.form_fields, '_id'); - var url_login = this.form.plugins.oscarhost.baseUrl+'/LoginService?wsdl', - url_demo = this.form.plugins.oscarhost.baseUrl+'/DemographicService?wsdl'; - var options = { - ignoredNamespaces: { - namespaces: ['targetNamespace', 'typedNamespace'], - override: true - } - } + console.log('Form form_field ids\n--------'); + console.log(form_ids); + console.log('FormSubmission form_field ids\n--------'); + console.log(submission_ids); - //Generate demographics from hashmap - var generateDemo = function(formFields, conversionMap, demographicsTemplate){ - var _generatedDemo = {}; - for(var field in formFields){ - if(demographicsTemplate.hasOwnProperty(conversionMap[field._id])){ - var propertyName = conversionMap[field._id]; + if(err) next(err); + // console.log(_form); + // console.log('should push to api'); + // console.log( (!this.oscarDemoNum && !!_form.plugins.oscarhost.baseUrl && !!_form.plugins.oscarhost.settings.fieldMap) ); + if(!this.oscarDemoNum && _form.plugins.oscarhost.baseUrl && _form.plugins.oscarhost.settings.fieldMap){ + console.log('OSCARHOST API HOOK'); + var url_login = _form.plugins.oscarhost.baseUrl+'/LoginService?wsdl', + url_demo = _form.plugins.oscarhost.baseUrl+'/DemographicService?wsdl'; - if(propertyName === "unparsedDOB"){ - var date = Date.parse(field.fieldValue); - generatedDemo['dateOfBirth'] = date.getDate(); - generatedDemo['yearOfBirth'] = date.getFullYear(); - generatedDemo['monthOfBirth'] = date.getMonth(); - }else{ - generatedDemo[propertyName] = field.fieldValue; - } + var args_login = {arg0: config.oscarhost.auth.user, arg1: config.oscarhost.auth.pass}; - } - } - return _generatedDemo; - } + var options = { + ignoredNamespaces: { + namespaces: ['targetNamespace', 'typedNamespace'], + override: true + } + }; - var submissionDemographic = generateDemo(this.form_fields, this.form.plugin.oscarhost.settings.fieldMap, newDemoTemplate); + //Generate demographics from hashmap + var generateDemo = function(formFields, conversionMap, demographicsTemplate){ + var _generatedDemo = {}; + for(var field in formFields){ + if(demographicsTemplate.hasOwnProperty(conversionMap[field._id])){ + var propertyName = conversionMap[field._id]; - async.waterfall([ - function (callback) { - //Authenticate with API - soap.createClient(url_login, options, function(err, client) { - client.login(args_login, function (err, result) { - if(err) callback(err); - callback(null, result.return); - }); - }); - }, + if(propertyName === 'unparsedDOB'){ + var date = Date.parse(field.fieldValue); + _generatedDemo['dateOfBirth'] = date.getDate(); + _generatedDemo['yearOfBirth'] = date.getFullYear(); + _generatedDemo['monthOfBirth'] = date.getMonth(); + }else{ + _generatedDemo[propertyName] = field.fieldValue; + } - function (security_obj, callback) { - //Force Add Demographic - if(this.plugins.oscarhost.settings.updateType === 'force_add'){ - soap.createClient(url_demo, options, function(err, client) { - client.setSecurity(new OscarSecurity(security_obj.securityId, security_obj.securityTokenKey) ); + } + } + return _generatedDemo; + }; - client.addDemographic({ arg0: exampleDemo }, function (err, result) { + var submissionDemographic = generateDemo(self.form_fields, _form.plugins.oscarhost.settings.fieldMap, newDemoTemplate); + + async.waterfall([ + function (callback) { + //Authenticate with API + soap.createClient(url_login, options, function(err, client) { + client.login(args_login, function (err, result) { if(err) callback(err); - - callback(null, result); + callback(null, result.return); }); }); - } - }, + }, + + function (security_obj, callback) { + //Force Add Demographic + if(_form.plugins.oscarhost.settings.updateType === 'force_add'){ + soap.createClient(url_demo, options, function(err, client) { + client.setSecurity(new OscarSecurity(security_obj.securityId, security_obj.securityTokenKey) ); + + client.addDemographic({ arg0: submissionDemographic }, function (err, result) { + if(err) callback(err); + callback(null, result); + }); + }); + } + }, + + ], function(err, result) { + if(err) next(err); + console.log(result); + console.log('hello'); + this.oscarDemoNum = parseInt(result.return, 10); + next(); + }); + }else{ + next(); + } + + }); - ], function(err, result) { - if(err) throw err; - console.log(result); - this.oscarDemoNum = parseInt(result.return, 10); - }); - } }); //Check for IP Address of submitting person diff --git a/app/models/user.server.model.js b/app/models/user.server.model.js index 34d43026..9168ffb8 100755 --- a/app/models/user.server.model.js +++ b/app/models/user.server.model.js @@ -8,6 +8,7 @@ var mongoose = require('mongoose'), crypto = require('crypto'), config = require('../../config/config'), fs = require('fs-extra'), + mUtilities = require('mongoose-utilities'), path = require('path'); /** @@ -102,6 +103,11 @@ UserSchema.virtual('displayName').get(function () { return this.firstName + ' ' + this.lastName; }); +UserSchema.plugin(mUtilities.timestamp, { + createdPath: 'created', + modifiedPath: 'lastModified', + useVirtual: false +}); //Create folder for user's pdfs UserSchema.pre('save', function (next) { diff --git a/app/tests/form.server.model.test.js b/app/tests/form.server.model.test.js index 5945c487..df3e10ad 100644 --- a/app/tests/form.server.model.test.js +++ b/app/tests/form.server.model.test.js @@ -12,44 +12,6 @@ var should = require('should'), config = require('../../config/config'), FormSubmission = mongoose.model('FormSubmission'); - -var exampleDemo = { - activeCount: 1, - unparsedDOB: '', - address: '880-9650 Velit. St.', - chartNo: '', - city: '', - dateJoined: Date.now(), - dateOfBirth: '10', - displayName: 'LITTLE, URIAH', - email: '', - familyDoctor: '', - firstName: 'Uriah F.', - hcType: 'BC', - hin: '', - hsAlertCount: 0, - lastName: 'Little', - lastUpdateDate: Date.now(), - lastUpdateUser: '', - links: '', - monthOfBirth: '05', - officialLanguage: 'English', - patientStatus: 'AC', - patientStatusDate: Date.now(), - phone: '250-', - phone2: '', - postal: "S4M 7T8", - providerNo: '4', - province: 'BC', - rosterStatus: '', - sex: 'M', - sexDesc: 'Female', - sin: '', - spokenLanguage: 'English', - title: 'MS.', - yearOfBirth: '2015' -} - /** * Globals */ @@ -59,50 +21,64 @@ var user, myForm, mySubmission; * Unit tests */ describe('Form Model Unit Tests:', function() { + beforeEach(function(done) { - Form.remove().exec(function() { - User.remove().exec(done); - }); - }); - beforeEach(function(done) { + user = new User({ firstName: 'Full', lastName: 'Name', displayName: 'Full Name', email: 'test@test.com', username: 'username', - password: 'password' + password: 'password', + provider: 'local' }); - user.save(function() { + user.save(function(err) { + + if(err){ + console.log(err.errors); + done(err); + } + myForm = new Form({ title: 'Form Title', admin: user, language: 'english', form_fields: [ - {'fieldType':'textfield', 'title':'First Name', 'fieldValue': ''}, - {'fieldType':'checkbox', 'title':'nascar', 'fieldValue': ''}, - {'fieldType':'checkbox', 'title':'hockey', 'fieldValue': ''} + {'fieldType':'textfield', title:'First Name', 'fieldValue': ''}, + {'fieldType':'checkbox', title:'nascar', 'fieldValue': ''}, + {'fieldType':'checkbox', title:'hockey', 'fieldValue': ''} ] }); + done(); }); }); describe('Method Save', function() { it('should be able to save without problems', function(done) { - return myForm.save(function(err) { + myForm.save(function(err) { should.not.exist(err); done(); }); }); it('should be able to show an error when try to save without title', function(done) { - var _form = myForm; + var _form = new Form({ + title: 'Form Title', + admin: user, + language: 'english', + form_fields: [ + {'fieldType':'textfield', title:'First Name', 'fieldValue': ''}, + {'fieldType':'checkbox', title:'nascar', 'fieldValue': ''}, + {'fieldType':'checkbox', title:'hockey', 'fieldValue': ''} + ] + }); _form.title = ''; - return _form.save(function(err) { + _form.save(function(err) { should.exist(err); should.equal(err.errors.title.message, 'Form Title cannot be blank'); done(); diff --git a/app/tests/form_submission.model.test.js b/app/tests/form_submission.model.test.js index 204494ff..a068e201 100644 --- a/app/tests/form_submission.model.test.js +++ b/app/tests/form_submission.model.test.js @@ -38,7 +38,7 @@ var exampleDemo = { patientStatusDate: Date.now(), phone: '250-', phone2: '', - postal: "S4M 7T8", + postal: 'S4M 7T8', providerNo: '4', province: 'BC', rosterStatus: '', @@ -48,7 +48,24 @@ var exampleDemo = { spokenLanguage: 'English', title: 'MS.', yearOfBirth: '2015' -} +}; + +var sampleFormFields = [ + {'fieldType':'textfield', 'title':'What\'s your first name', 'fieldValue': ''}, + {'fieldType':'textfield', 'title':'And your last name', 'fieldValue': ''}, + {'fieldType':'radio', 'title':'And your sex', 'fieldOptions': [{ 'option_id': 0, 'option_title': 'Male', 'option_value': 'M' }, { 'option_id': 1, 'option_title': 'Female', 'option_value': 'F' }], 'fieldValue': ''}, + {'fieldType':'date', 'title':'When were you born?', 'fieldValue': ''}, + {'fieldType':'number', 'title':'What\'s your phone #?', 'fieldValue': ''} +]; + +var sampleSubmission = [ + {'fieldType':'textfield', 'title':'What\'s your first name', 'fieldValue': 'David'}, + {'fieldType':'textfield', 'title':'And your last name', 'fieldValue': 'Baldwynn'}, + {'fieldType':'radio', 'title':'And your sex', 'fieldValue': 0, 'fieldOptions': [{ 'option_id': 0, 'option_title': 'Male', 'option_value': 'M' }, { 'option_id': 1, 'option_title': 'Female', 'option_value': 'F' }]}, + {'fieldType':'date', 'title':'When were you born?', 'fieldValue': Date.now()}, + {'fieldType':'number', 'title':'What\'s your phone #?', 'fieldValue': '6043158008'} +]; + /** * Globals @@ -64,17 +81,20 @@ describe('FormSubmission Model Unit Tests:', function() { firstName: 'Full', lastName: 'Name', displayName: 'Full Name', - email: 'test1@test.com', - username: 'test1@test.com', - password: 'password' + email: 'test1@test.com'+Date.now(), + username: 'test1@test.com'+Date.now(), + password: 'password', + provider: 'local' }); - user.save(function(err, _user) { - if(err) done(err); - + user.save(function(err) { + if(err){ + console.log(err.errors); + done(err); + } myForm = new Form({ - title: 'Form Title', - admin: _user, + title: 'Form Title1', + admin: user, language: 'english', form_fields: [ {'fieldType':'textfield', 'title':'What\'s your first name', 'fieldValue': ''}, @@ -87,7 +107,6 @@ describe('FormSubmission Model Unit Tests:', function() { oscarhost: { baseUrl: config.oscarhost.baseUrl, settings: { - lookupField: '', updateType: 'force_add', }, auth: config.oscarhost.auth, @@ -95,13 +114,34 @@ describe('FormSubmission Model Unit Tests:', function() { } }); - done(); + myForm.save(function(err, form){ + if(err){ + console.log(err.errors); + done(err); + } + + var submissionFields = _.clone(myForm.form_fields); + for(var z=0; z=1.20.0", "mongoose": "~3.8.8", + "mongoose-utilities": "^0.1.1", "morgan": "~1.4.1", "multer": "~0.1.8", "node-pdffiller": "~0.0.5",