From 2c250e0111b75d9b3429611fe5803d88ea962c81 Mon Sep 17 00:00:00 2001 From: VLE2FE Date: Mon, 24 Aug 2020 12:37:19 +0200 Subject: [PATCH] added notes.comment field and filter --- data_import/spectrum-fix.js | 70 +++++++++++++++++++++++++++++++++++ package.json | 3 +- src/routes/sample.spec.ts | 39 +++++++++++++++++++ src/routes/sample.ts | 23 +++++++++--- src/routes/user.ts | 2 +- src/routes/validate/sample.ts | 12 ++++-- 6 files changed, 139 insertions(+), 10 deletions(-) create mode 100644 data_import/spectrum-fix.js diff --git a/data_import/spectrum-fix.js b/data_import/spectrum-fix.js new file mode 100644 index 0000000..2cf38b6 --- /dev/null +++ b/data_import/spectrum-fix.js @@ -0,0 +1,70 @@ +const axios = require('axios'); + + +const host = 'http://localhost:3000'; +// const host = 'https://definma-api.apps.de1.bosch-iot-cloud.com'; + +let errors = []; + +async function fix() { + let res = await axios({ + method: 'get', + url: host + '/samples?status[]=new&status[]=validated&status[]=deleted&fields[]=_id&fields[]=number', + auth: { + username: 'admin', + password: 'Abc123!#' + } + }).catch(err => { + if (err.response) { + console.error(err.response.data); + errors.push(`Could not fetch samples: ${JSON.stringify(err.response.data)}`); + } + }); + console.log(res.data); + // for all samples + for (let sampleIndex in res.data) { + console.log(`SAMPLE ${sampleIndex}/${res.data.length}`); + const measurements = await axios({ // get all measurements + method: 'get', + url: host + '/measurement/sample/' + res.data[sampleIndex]._id, + auth: { + username: 'admin', + password: 'Abc123!#' + } + }).catch(err => { + if (err.response) { + console.error(err.response.data); + errors.push(`Could not fetch measurements: ${JSON.stringify(err.response.data)}`); + } + }); + + if (measurements && measurements.data) { // found measurements + for (let measurementIndex in measurements.data) { + console.log(`${measurementIndex}/${measurements.data.length}`); + const measurement = measurements.data[measurementIndex]; + if (measurement.values.hasOwnProperty('dpt')) { // is spectrum + await axios({ // get all measurements + method: 'put', + url: host + '/measurement/' + measurement._id, + auth: { + username: 'admin', + password: 'Abc123!#' + }, + data: {values: {dpt: measurement.values.dpt + .filter(e => e.length === 2) + .map(e => e.map(el => parseFloat(el))) + }} + }).catch(err => { + if (err.response) { + console.error(err.response.data); + errors.push(`Could not save measurements: ${JSON.stringify(err.response.data)}`); + } + }); + } + } + } + } + console.log(errors); +} + +fix(); \ No newline at end of file diff --git a/package.json b/package.json index 7854a57..2097e66 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "start-local": "node dist/index.js", "loadDev": "node dist/test/loadDev.js", "coverage": "tsc && nyc --reporter=html --reporter=text mocha dist/**/**.spec.js --timeout 5000", - "import": "node data_import/import.js" + "import": "node data_import/import.js", + "spectrum-fix": "node data_import/spectrum-fix.js" }, "keywords": [], "author": "", diff --git a/src/routes/sample.spec.ts b/src/routes/sample.spec.ts index a4498d0..0aee97c 100644 --- a/src/routes/sample.spec.ts +++ b/src/routes/sample.spec.ts @@ -402,6 +402,45 @@ describe('/sample', () => { done(); }); }); + it('filters for empty comments', done => { + TestHelper.request(server, done, { + method: 'get', + url: '/samples?status[]=new&status[]=validated&fields[]=number&fields[]=notes.comment&filters[]=%7B%22mode%22%3A%22in%22%2C%22field%22%3A%22notes.comment%22%2C%22values%22%3A%5Bnull%2C%22%22%5D%7D', + auth: {basic: 'janedoe'}, + httpStatus: 200 + }).end((err, res) => { + if (err) return done(err); + const json = require('../test/db.json'); + should(res.body).have.lengthOf( + json.collections.samples + .filter(e => e.status !== 'deleted') + .filter(e => e.note_id === null || json.collections.notes.find(el => el._id.toString() == e.note_id.toString()).comment === '') + .length + ); + should(res.body).matchEach(sample => { + should(sample.notes.comment).be.equalOneOf(null, ''); + }); + done(); + }); + }); + it('returns comment fields', done => { + TestHelper.request(server, done, { + method: 'get', + url: '/samples?status[]=new&status[]=validated&fields[]=number&fields[]=notes.comment', + auth: {basic: 'janedoe'}, + httpStatus: 200 + }).end((err, res) => { + if (err) return done(err); + console.log(res.body); + const json = require('../test/db.json'); + should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status !== 'deleted').length); + should(res.body).matchEach(sample => { + should(sample).have.only.keys('number', 'notes'); + should(sample.notes).have.only.keys('comment'); + }); + done(); + }); + }); it('rejects returning spectral data for a write user', done => { TestHelper.request(server, done, { method: 'get', diff --git a/src/routes/sample.ts b/src/routes/sample.ts index a8d9357..c55d42c 100644 --- a/src/routes/sample.ts +++ b/src/routes/sample.ts @@ -255,6 +255,11 @@ router.get('/samples', async (req, res, next) => { ); // measurement filters } + if (sortFilterKeys.find(e => e === 'notes.comment')) { + addNotes(queryPtr); + addFilterQueries(queryPtr, filters.filters.filter(e => e.field === 'notes.comment')); + } + // count total number of items before $skip and $limit, only works when from-id is not specified and spectra are not // included if (!filters.fields.find(e => @@ -279,11 +284,8 @@ router.get('/samples', async (req, res, next) => { && e !== filters.sort[0] // field was not in sort ); - if (fieldsToAdd.find(e => e === 'notes')) { // add notes - queryPtr.push( - {$lookup: {from: 'notes', localField: 'note_id', foreignField: '_id', as: 'notes'}}, - {$addFields: {notes: { $arrayElemAt: ['$notes', 0]}}} - ); + if (fieldsToAdd.find(e => /^notes(\..+|$)/m.test(e))) { // add notes + addNotes(queryPtr); } if (fieldsToAdd.find(e => /material\./.test(e)) && !materialAdded) { // add material, was not added already @@ -857,6 +859,17 @@ function addMeasurements(queryPtr, templates) { ); } +function addNotes(queryPtr) { // add note fields with default, if no notes are found + queryPtr.push( + {$lookup: {from: 'notes', localField: 'note_id', foreignField: '_id', as: 'notes'}}, + {$addFields: {notes: {$cond: [ + {'$arrayElemAt': ['$notes', 0]}, + {'$arrayElemAt': ['$notes', 0]}, + {comment: null, sample_references: []} + ]}}} + ); +} + function dateToOId (date) { // convert date to ObjectId return mongoose.Types.ObjectId(Math.floor(date / 1000).toString(16) + '0000000000000000'); } diff --git a/src/routes/user.ts b/src/routes/user.ts index 976c1a7..8c60eda 100644 --- a/src/routes/user.ts +++ b/src/routes/user.ts @@ -65,7 +65,7 @@ router.put('/user:username([/](?!key|new).?*|/?)', async (req, res, next) => { await UserModel.findOneAndUpdate({name: username}, user, {new: true}).log(req).lean().exec( (err, data:any) => { if (err) return next(err); if (data) { - if (data.mail !== oldUserData.email) { // mail address was changed, send notice to old address + if (data.email !== oldUserData.email) { // mail address was changed, send notice to old address Mail.send(oldUserData.email, 'Email change in your DeFinMa database account', 'Hi,

Your email address of your DeFinMa account was changed to ' + data.mail + '

If you actually did this, just delete this email.' + diff --git a/src/routes/validate/sample.ts b/src/routes/validate/sample.ts index 6e8e497..9c5ad0d 100644 --- a/src/routes/validate/sample.ts +++ b/src/routes/validate/sample.ts @@ -28,7 +28,8 @@ export default class SampleValidate { notes: Joi.object({ comment: Joi.string() .max(512) - .allow(''), + .allow('') + .allow(null), sample_references: Joi.array() .items(Joi.object({ @@ -78,6 +79,7 @@ export default class SampleValidate { 'batch', 'added', 'status', + 'notes.comment', 'material.name', 'material.supplier', 'material.group', @@ -196,6 +198,7 @@ export default class SampleValidate { data.filters[i] = decodeURIComponent(data.filters[i]); } catch (ignore) {} + console.log(data.filters[i]); data.filters[i] = JSON.parse(data.filters[i]); data.filters[i].values = data.filters[i].values.map(e => { // validate filter values if (e === null) { // null values are always allowed @@ -223,11 +226,14 @@ export default class SampleValidate { }); field = 'value'; } + else if (field === 'notes.comment') { + field = 'comment'; + validator = this.sample.notes + } else { validator = Joi.object(this.sample); } const {value, error} = validator.validate({[field]: e}); - console.log(error); if (error) throw error; // reject invalid values return value[field]; }); @@ -260,7 +266,7 @@ export default class SampleValidate { new RegExp('^(' + this.fieldKeys.join('|').replace(/\./g, '\\.').replace(/\*/g, '.+') + ')$', 'm') ).messages({'string.pattern.base': 'Invalid filter field name'}), values: Joi.array().items(Joi.alternatives().try( - Joi.string().max(128), Joi.number(), Joi.boolean(), Joi.date().iso(), Joi.object(), null + Joi.string().max(128).allow(''), Joi.number(), Joi.boolean(), Joi.date().iso(), Joi.object(), null )).min(1) })).default([]) }).with('to-page', 'page-size').validate(data);