Skip to content

Commit

Permalink
refactor(service): delete unused observation update functions
Browse files Browse the repository at this point in the history
  • Loading branch information
restjohn committed Aug 10, 2024
1 parent 31f79fb commit 4aa5b8c
Show file tree
Hide file tree
Showing 2 changed files with 0 additions and 238 deletions.
169 changes: 0 additions & 169 deletions service/src/api/observation.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ Observation.prototype.getAll = function(options, callback) {
/**
* TODO: this can be deleted when these refs go away
* * routes/index.js
* * routes/observations.js
*/
Observation.prototype.getById = function(observationId, options, callback) {
if (typeof options === 'function') {
Expand All @@ -58,174 +57,6 @@ Observation.prototype.getById = function(observationId, options, callback) {
ObservationModel.getObservationById(this._event, observationId, options, callback);
};

Observation.prototype.validate = function(observation) {
const errors = {};
let message = '';

if (observation.type !== 'Feature') {
errors.type = { error: 'required', message: observation.type ? 'type is required' : 'type must equal "Feature"' };
message += observation.type ? '\u2022 type is required\n' : '\u2022 type must equal "Feature"\n'
}

// validate timestamp
const properties = observation.properties || {};
const timestampError = fieldFactory.createField({
type: 'date',
required: true,
name: 'timestamp',
title: 'Date'
}, properties).validate();
if (timestampError) {
errors.timestamp = timestampError;
message += `\u2022 ${timestampError.message}\n`;
}

// validate geometry
const geometryError = fieldFactory.createField({
type: 'geometry',
required: true,
name: 'geometry',
title: 'Location'
}, observation).validate();
if (geometryError) {
errors.geometry = geometryError;
message += `\u2022 ${geometryError.message}\n`;
}

const formEntries = properties.forms || [];
const formCount = formEntries.reduce((count, form) => {
count[form.formId] = (count[form.formId] || 0) + 1;
return count;
}, {})

const formDefinitions = {};

// Validate total number of forms
if (this._event.minObservationForms != null && formEntries.length < this._event.minObservationForms) {
errors.minObservationForms = new Error("Insufficient number of forms");
message += `\u2022 Total number of forms in observation must be at least ${this._event.minObservationForms}\n`;
}

if (this._event.maxObservationForms != null && formEntries.length > this._event.maxObservationForms) {
errors.maxObservationForms = new Error("Exceeded maximum number of forms");
message += `\u2022 Total number of forms in observation cannot be more than ${this._event.maxObservationForms}\n`;
}

// Validate forms min/max occurrences
const formError = {};
this._event.forms
.filter(form => !form.archived)
.forEach(formDefinition => {
formDefinitions[formDefinition._id] = formDefinition;

const count = formCount[formDefinition.id] || 0;
if (formDefinition.min && count < formDefinition.min) {
formError[formDefinition.id] = {
error: 'min',
message: `${formDefinition.name} form must be included in observation at least ${formDefinition.min} times`
}

message += `\u2022 ${formDefinition.name} form must be included in observation at least ${formDefinition.min} times\n`;
} else if (formDefinition.max && (count > formDefinition.max)) {
formError[formDefinition.id] = {
error: 'max',
message: `${formDefinition.name} form cannot be included in observation more than ${formDefinition.max} times`
}

message += `\u2022 ${formDefinition.name} form cannot be included in observation more than ${formDefinition.max} times\n`;
}
});

// TODO attachment-work, validate attachment restrictions and min/max

if (Object.keys(formError).length) {
errors.form = formError;
}

// Validate form fields
const formErrors = [];

formEntries.forEach(formEntry => {
let fieldsMessage = '';
const fieldsError = {};

formDefinitions[formEntry.formId].fields
.filter(fieldDefinition => !fieldDefinition.archived)
.forEach(fieldDefinition => {
const field = fieldFactory.createField(fieldDefinition, formEntry, observation);
const fieldError = field.validate();

if (fieldError) {
fieldsError[field.name] = fieldError;
fieldsMessage += ` \u2022 ${fieldError.message}\n`;
}
});

if (Object.keys(fieldsError).length) {
formErrors.push(fieldsError);
message += `${formDefinitions[formEntry.formId].name} form is invalid\n`;
message += fieldsMessage;
}
});

if (formErrors.length) {
errors.forms = formErrors
}

if (Object.keys(errors).length) {
const err = new Error('Invalid Observation');
err.name = 'ValidationError';
err.status = 400;
err.message = message;
err.errors = errors;
return err;
}
};

// TODO create is gone, do I need to figure out if this is an observation create?
Observation.prototype.update = function(observationId, observation, callback) {
if (this._user) observation.userId = this._user._id;
if (this._deviceId) observation.deviceId = this._deviceId;

const err = this.validate(observation);
if (err) return callback(err);

ObservationModel.updateObservation(this._event, observationId, observation, (err, updatedObservation) => {
if (updatedObservation) {
EventEmitter.emit(ObservationEvents.events.update, updatedObservation.toObject({event: this._event}), this._event, this._user);

// Remove any deleted attachments from file system
/*
TODO: this might not even work. observation form entries are not stored
with field entry keys for attachment fields, so finding attachments based
on matching form entry keys with form field names will not produce any
results.
*/
const {forms: formEntries = []} = observation.properties || {};
formEntries.forEach(formEntry => {
const formDefinition = this._event.forms.find(form => form._id === formEntry.formId);
Object.keys(formEntry).forEach(fieldName => {
const fieldDefinition = formDefinition.fields.find(field => field.name === fieldName);
if (fieldDefinition && fieldDefinition.type === 'attachment') {
const attachmentsField = formEntry[fieldName] || [];
attachmentsField.filter(attachmentField => attachmentField.action === 'delete').forEach(attachmentField => {
const attachment = observation.attachments.find(attachment => attachment._id.toString() === attachmentField.id);
if (attachment) {
console.info(`deleting attachment ${attachment.id} for field ${fieldName} on observation ${observation.id}`)
new Attachment(this._event, observation).delete(attachment._id, err => {
log.warn('Error removing deleted attachment from file system', err);
});
}
});
}
});
});
}

callback(err, updatedObservation);
});
};

Observation.prototype.addFavorite = function(observationId, user, callback) {
ObservationModel.addFavorite(this._event, observationId, user, callback);
};
Expand Down
69 changes: 0 additions & 69 deletions service/src/models/observation.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,75 +137,6 @@ exports.getObservationById = function (event, observationId, options, callback)
observationModel(event).findById(observationId, fields, callback);
};

exports.updateObservation = function (event, observationId, update, callback) {
let addAttachments = [];
let removeAttachments = [];
const { forms = [] } = update.properties || {};
forms.map(observationForm => {
observationForm._id = observationForm._id || new mongoose.Types.ObjectId();
delete observationForm.id;
return observationForm;
})
.forEach(formEntry => {
// TODO: move to app or web layer
const formDefinition = event.forms.find(form => form._id === formEntry.formId);
Object.keys(formEntry).forEach(fieldName => {
const fieldDefinition = formDefinition.fields.find(field => field.name === fieldName);
if (fieldDefinition && fieldDefinition.type === 'attachment') {
const attachments = formEntry[fieldName] || [];
addAttachments = addAttachments.concat(attachments
.filter(attachment => attachment.action === 'add')
.map(attachment => {
return {
observationFormId: formEntry._id,
fieldName: fieldName,
name: attachment.name,
contentType: attachment.contentType
}
}));

removeAttachments = removeAttachments.concat(attachments
.filter(attachment => attachment.action === 'delete')
.map(attachment => attachment.id)
);

delete formEntry[fieldName]
}
});
});

const ObservationModel = observationModel(event);
ObservationModel.findById(observationId)
.then(observation => {
if (!observation) {
observation = new ObservationModel({
_id: observationId,
userId: update.userId,
deviceId: update.deviceId,
states: [{ name: 'active', userId: update.userId }]
});
}

observation.type = update.type;
observation.geometry = update.geometry;
observation.properties = update.properties;
observation.attachments = observation.attachments.concat(addAttachments);
observation.attachments = observation.attachments.filter(attachment => {
return !removeAttachments.includes(attachment._id.toString())
});

return observation.save();
})
.then(observation => {
return observation
.populate([{ path: 'userId', select: 'displayName' }, { path: 'important.userId', select: 'displayName' }]);
})
.then(observation => {
callback(null, observation);
})
.catch(err => callback(err));
};

exports.removeObservation = function (event, observationId, callback) {
observationModel(event).findByIdAndRemove(observationId, callback);
};
Expand Down

0 comments on commit 4aa5b8c

Please sign in to comment.