Merge pull request #8 in ~VLE2FE/dfop-api from status to develop
* commit '806b77eecf2e0f24e65a604b2c6f6d736e5e2903': adjusted material adjusted sample adjusted condition
This commit is contained in:
		@@ -34,6 +34,7 @@ info:
 | 
				
			|||||||
      <li>0: newly added/changed</li>
 | 
					      <li>0: newly added/changed</li>
 | 
				
			||||||
      <li>10: validated</li>
 | 
					      <li>10: validated</li>
 | 
				
			||||||
    </ul>
 | 
					    </ul>
 | 
				
			||||||
 | 
					    <a href="https://sourcecode.socialcoding.bosch.com/users/vle2fe/repos/dfop-api/">Bitbucket repository</a>
 | 
				
			||||||
# TODO: Link to new documentation page
 | 
					# TODO: Link to new documentation page
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,7 @@
 | 
				
			|||||||
  get:
 | 
					  get:
 | 
				
			||||||
    summary: condition by id
 | 
					    summary: condition by id
 | 
				
			||||||
    description: 'Auth: all, levels: read, write, maintain, dev, admin'
 | 
					    description: 'Auth: all, levels: read, write, maintain, dev, admin'
 | 
				
			||||||
 | 
					    x-doc: status handling (accessible (only for maintain/admin))?  # TODO
 | 
				
			||||||
    tags:
 | 
					    tags:
 | 
				
			||||||
      - /condition
 | 
					      - /condition
 | 
				
			||||||
    responses:
 | 
					    responses:
 | 
				
			||||||
@@ -24,6 +25,7 @@
 | 
				
			|||||||
  put:
 | 
					  put:
 | 
				
			||||||
    summary: change condition
 | 
					    summary: change condition
 | 
				
			||||||
    description: 'Auth: basic, levels: write, maintain, dev, admin <br>Only maintain and admin are allowed to reference samples created by another user'
 | 
					    description: 'Auth: basic, levels: write, maintain, dev, admin <br>Only maintain and admin are allowed to reference samples created by another user'
 | 
				
			||||||
 | 
					    x-doc: status is reset to 0 on any changes
 | 
				
			||||||
    tags:
 | 
					    tags:
 | 
				
			||||||
      - /condition
 | 
					      - /condition
 | 
				
			||||||
    security:
 | 
					    security:
 | 
				
			||||||
@@ -61,6 +63,7 @@
 | 
				
			|||||||
  delete:
 | 
					  delete:
 | 
				
			||||||
    summary: delete condition
 | 
					    summary: delete condition
 | 
				
			||||||
    description: 'Auth: basic, levels: write, maintain, dev, admin'
 | 
					    description: 'Auth: basic, levels: write, maintain, dev, admin'
 | 
				
			||||||
 | 
					    x-doc: sets status to -1
 | 
				
			||||||
    tags:
 | 
					    tags:
 | 
				
			||||||
      - /condition
 | 
					      - /condition
 | 
				
			||||||
    security:
 | 
					    security:
 | 
				
			||||||
@@ -83,6 +86,7 @@
 | 
				
			|||||||
  post:
 | 
					  post:
 | 
				
			||||||
    summary: add condition
 | 
					    summary: add condition
 | 
				
			||||||
    description: 'Auth: basic, levels: write, maintain, dev, admin <br>Only maintain and admin are allowed to reference samples created by another user'
 | 
					    description: 'Auth: basic, levels: write, maintain, dev, admin <br>Only maintain and admin are allowed to reference samples created by another user'
 | 
				
			||||||
 | 
					    x-doc: 'Adds status: 0 automatically'
 | 
				
			||||||
    tags:
 | 
					    tags:
 | 
				
			||||||
      - /condition
 | 
					      - /condition
 | 
				
			||||||
    security:
 | 
					    security:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@
 | 
				
			|||||||
  get:
 | 
					  get:
 | 
				
			||||||
    summary: lists all materials
 | 
					    summary: lists all materials
 | 
				
			||||||
    description: 'Auth: all, levels: read, write, maintain, dev, admin'
 | 
					    description: 'Auth: all, levels: read, write, maintain, dev, admin'
 | 
				
			||||||
 | 
					    x-doc: returns only materials with status 10  # TODO: methods /materials/new|deleted
 | 
				
			||||||
    tags:
 | 
					    tags:
 | 
				
			||||||
      - /material
 | 
					      - /material
 | 
				
			||||||
    responses:
 | 
					    responses:
 | 
				
			||||||
@@ -24,6 +25,7 @@
 | 
				
			|||||||
  get:
 | 
					  get:
 | 
				
			||||||
    summary: get material details
 | 
					    summary: get material details
 | 
				
			||||||
    description: 'Auth: all, levels: read, write, maintain, dev, admin'
 | 
					    description: 'Auth: all, levels: read, write, maintain, dev, admin'
 | 
				
			||||||
 | 
					    x-doc: status handling (accessible (only for maintain/admin))?  # TODO
 | 
				
			||||||
    tags:
 | 
					    tags:
 | 
				
			||||||
      - /material
 | 
					      - /material
 | 
				
			||||||
    responses:
 | 
					    responses:
 | 
				
			||||||
@@ -42,6 +44,7 @@
 | 
				
			|||||||
  put:
 | 
					  put:
 | 
				
			||||||
    summary: change material
 | 
					    summary: change material
 | 
				
			||||||
    description: 'Auth: basic, levels: write, maintain, dev, admin'
 | 
					    description: 'Auth: basic, levels: write, maintain, dev, admin'
 | 
				
			||||||
 | 
					    x-doc: status is reset to 0 on any changes
 | 
				
			||||||
    tags:
 | 
					    tags:
 | 
				
			||||||
      - /material
 | 
					      - /material
 | 
				
			||||||
    security:
 | 
					    security:
 | 
				
			||||||
@@ -72,6 +75,7 @@
 | 
				
			|||||||
  delete:
 | 
					  delete:
 | 
				
			||||||
    summary: delete material
 | 
					    summary: delete material
 | 
				
			||||||
    description: 'Auth: basic, levels: write, maintain, dev, admin'
 | 
					    description: 'Auth: basic, levels: write, maintain, dev, admin'
 | 
				
			||||||
 | 
					    x-doc: sets status to -1
 | 
				
			||||||
    tags:
 | 
					    tags:
 | 
				
			||||||
      - /material
 | 
					      - /material
 | 
				
			||||||
    security:
 | 
					    security:
 | 
				
			||||||
@@ -94,6 +98,7 @@
 | 
				
			|||||||
  post:
 | 
					  post:
 | 
				
			||||||
    summary: add material
 | 
					    summary: add material
 | 
				
			||||||
    description: 'Auth: basic, levels: write, maintain, dev, admin'
 | 
					    description: 'Auth: basic, levels: write, maintain, dev, admin'
 | 
				
			||||||
 | 
					    x-doc: 'Adds status: 0 automatically'
 | 
				
			||||||
    tags:
 | 
					    tags:
 | 
				
			||||||
      - /material
 | 
					      - /material
 | 
				
			||||||
    security:
 | 
					    security:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,8 +2,9 @@
 | 
				
			|||||||
  parameters:
 | 
					  parameters:
 | 
				
			||||||
    - $ref: 'api.yaml#/components/parameters/Id'
 | 
					    - $ref: 'api.yaml#/components/parameters/Id'
 | 
				
			||||||
  get:
 | 
					  get:
 | 
				
			||||||
    summary: TODO measurement values by id
 | 
					    summary: measurement values by id
 | 
				
			||||||
    description: 'Auth: all, levels: read, write, maintain, dev, admin'
 | 
					    description: 'Auth: all, levels: read, write, maintain, dev, admin'
 | 
				
			||||||
 | 
					    x-doc: status handling (accessible (only for maintain/admin))?  # TODO
 | 
				
			||||||
    tags:
 | 
					    tags:
 | 
				
			||||||
      - /measurement
 | 
					      - /measurement
 | 
				
			||||||
    responses:
 | 
					    responses:
 | 
				
			||||||
@@ -57,6 +58,7 @@
 | 
				
			|||||||
  delete:
 | 
					  delete:
 | 
				
			||||||
    summary: delete measurement
 | 
					    summary: delete measurement
 | 
				
			||||||
    description: 'Auth: basic, levels: write, maintain, dev, admin'
 | 
					    description: 'Auth: basic, levels: write, maintain, dev, admin'
 | 
				
			||||||
 | 
					    x-doc: sets status to -1
 | 
				
			||||||
    tags:
 | 
					    tags:
 | 
				
			||||||
      - /measurement
 | 
					      - /measurement
 | 
				
			||||||
    security:
 | 
					    security:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@
 | 
				
			|||||||
  get:
 | 
					  get:
 | 
				
			||||||
    summary: all samples in overview
 | 
					    summary: all samples in overview
 | 
				
			||||||
    description: 'Auth: all, levels: read, write, maintain, dev, admin'
 | 
					    description: 'Auth: all, levels: read, write, maintain, dev, admin'
 | 
				
			||||||
 | 
					    x-doc: returns only samples with status 10  # TODO: methods /samples/new|deleted
 | 
				
			||||||
    tags:
 | 
					    tags:
 | 
				
			||||||
      - /sample
 | 
					      - /sample
 | 
				
			||||||
    responses:
 | 
					    responses:
 | 
				
			||||||
@@ -23,6 +24,7 @@
 | 
				
			|||||||
  get:
 | 
					  get:
 | 
				
			||||||
    summary: TODO sample details
 | 
					    summary: TODO sample details
 | 
				
			||||||
    description: 'Auth: all, levels: read, write, maintain, dev, admin'
 | 
					    description: 'Auth: all, levels: read, write, maintain, dev, admin'
 | 
				
			||||||
 | 
					    x-doc: status handling (accessible (only for maintain/admin))?  # TODO
 | 
				
			||||||
    tags:
 | 
					    tags:
 | 
				
			||||||
      - /sample
 | 
					      - /sample
 | 
				
			||||||
    responses:
 | 
					    responses:
 | 
				
			||||||
@@ -43,6 +45,7 @@
 | 
				
			|||||||
  put:
 | 
					  put:
 | 
				
			||||||
    summary: change sample
 | 
					    summary: change sample
 | 
				
			||||||
    description: 'Auth: basic, levels: write, maintain, dev, admin <br>Only maintain and admin are allowed to edit samples created by another user'
 | 
					    description: 'Auth: basic, levels: write, maintain, dev, admin <br>Only maintain and admin are allowed to edit samples created by another user'
 | 
				
			||||||
 | 
					    x-doc: status is reset to 0 on any changes
 | 
				
			||||||
    tags:
 | 
					    tags:
 | 
				
			||||||
      - /sample
 | 
					      - /sample
 | 
				
			||||||
    security:
 | 
					    security:
 | 
				
			||||||
@@ -73,6 +76,7 @@
 | 
				
			|||||||
  delete:
 | 
					  delete:
 | 
				
			||||||
    summary: delete sample
 | 
					    summary: delete sample
 | 
				
			||||||
    description: 'Auth: basic, levels: write, maintain, dev, admin <br>Only maintain and admin are allowed to edit samples created by another user'
 | 
					    description: 'Auth: basic, levels: write, maintain, dev, admin <br>Only maintain and admin are allowed to edit samples created by another user'
 | 
				
			||||||
 | 
					    x-doc: sets status to -1, notes and references to this sample are also kept, only note_fields are updated accordingly
 | 
				
			||||||
    tags:
 | 
					    tags:
 | 
				
			||||||
      - /sample
 | 
					      - /sample
 | 
				
			||||||
    security:
 | 
					    security:
 | 
				
			||||||
@@ -95,6 +99,7 @@
 | 
				
			|||||||
  post:
 | 
					  post:
 | 
				
			||||||
    summary: add sample
 | 
					    summary: add sample
 | 
				
			||||||
    description: 'Auth: basic, levels: write, maintain, dev, admin'
 | 
					    description: 'Auth: basic, levels: write, maintain, dev, admin'
 | 
				
			||||||
 | 
					    x-doc: 'Adds status: 0 automatically'
 | 
				
			||||||
    tags:
 | 
					    tags:
 | 
				
			||||||
      - /sample
 | 
					      - /sample
 | 
				
			||||||
    security:
 | 
					    security:
 | 
				
			||||||
@@ -125,6 +130,7 @@
 | 
				
			|||||||
  get:
 | 
					  get:
 | 
				
			||||||
    summary: list all existing field names for custom notes fields
 | 
					    summary: list all existing field names for custom notes fields
 | 
				
			||||||
    description: 'Auth: all, levels: read, write, maintain, dev, admin'
 | 
					    description: 'Auth: all, levels: read, write, maintain, dev, admin'
 | 
				
			||||||
 | 
					    x-doc: integrity has to be ensured  # TODO: implement mechanism to regularly check note_fields
 | 
				
			||||||
    tags:
 | 
					    tags:
 | 
				
			||||||
      - /sample
 | 
					      - /sample
 | 
				
			||||||
    responses:
 | 
					    responses:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,8 @@ const ConditionSchema = new mongoose.Schema({
 | 
				
			|||||||
  sample_id: {type: mongoose.Schema.Types.ObjectId, ref: SampleModel},
 | 
					  sample_id: {type: mongoose.Schema.Types.ObjectId, ref: SampleModel},
 | 
				
			||||||
  number: String,
 | 
					  number: String,
 | 
				
			||||||
  parameters: mongoose.Schema.Types.Mixed,
 | 
					  parameters: mongoose.Schema.Types.Mixed,
 | 
				
			||||||
  treatment_template: {type: mongoose.Schema.Types.ObjectId, ref: TreatmentTemplateModel}
 | 
					  treatment_template: {type: mongoose.Schema.Types.ObjectId, ref: TreatmentTemplateModel},
 | 
				
			||||||
 | 
					  status: Number
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default mongoose.model('condition', ConditionSchema);
 | 
					export default mongoose.model('condition', ConditionSchema);
 | 
				
			||||||
@@ -10,7 +10,8 @@ const MaterialSchema = new mongoose.Schema({
 | 
				
			|||||||
  numbers: [{
 | 
					  numbers: [{
 | 
				
			||||||
    color: String,
 | 
					    color: String,
 | 
				
			||||||
    number: Number
 | 
					    number: Number
 | 
				
			||||||
  }]
 | 
					  }],
 | 
				
			||||||
 | 
					  status: Number
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default mongoose.model('material', MaterialSchema);
 | 
					export default mongoose.model('material', MaterialSchema);
 | 
				
			||||||
@@ -5,8 +5,8 @@ import MeasurementTemplateModel from './measurement_template';
 | 
				
			|||||||
const MeasurementSchema = new mongoose.Schema({
 | 
					const MeasurementSchema = new mongoose.Schema({
 | 
				
			||||||
  condition_id: {type: mongoose.Schema.Types.ObjectId, ref: ConditionModel},
 | 
					  condition_id: {type: mongoose.Schema.Types.ObjectId, ref: ConditionModel},
 | 
				
			||||||
  values: mongoose.Schema.Types.Mixed,
 | 
					  values: mongoose.Schema.Types.Mixed,
 | 
				
			||||||
  status: Number,
 | 
					  measurement_template: {type: mongoose.Schema.Types.ObjectId, ref: MeasurementTemplateModel},
 | 
				
			||||||
  measurement_template: {type: mongoose.Schema.Types.ObjectId, ref: MeasurementTemplateModel}
 | 
					  status: Number
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default mongoose.model('measurement', MeasurementSchema);
 | 
					export default mongoose.model('measurement', MeasurementSchema);
 | 
				
			||||||
@@ -9,10 +9,10 @@ const SampleSchema = new mongoose.Schema({
 | 
				
			|||||||
  type: String,
 | 
					  type: String,
 | 
				
			||||||
  color: String,
 | 
					  color: String,
 | 
				
			||||||
  batch: String,
 | 
					  batch: String,
 | 
				
			||||||
  validated: Boolean,
 | 
					 | 
				
			||||||
  material_id: {type: mongoose.Schema.Types.ObjectId, ref: MaterialModel},
 | 
					  material_id: {type: mongoose.Schema.Types.ObjectId, ref: MaterialModel},
 | 
				
			||||||
  note_id: {type: mongoose.Schema.Types.ObjectId, ref: NoteModel},
 | 
					  note_id: {type: mongoose.Schema.Types.ObjectId, ref: NoteModel},
 | 
				
			||||||
  user_id: {type: mongoose.Schema.Types.ObjectId, ref: UserModel}
 | 
					  user_id: {type: mongoose.Schema.Types.ObjectId, ref: UserModel},
 | 
				
			||||||
 | 
					  status: Number
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default mongoose.model('sample', SampleSchema);
 | 
					export default mongoose.model('sample', SampleSchema);
 | 
				
			||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
import should from 'should/as-function';
 | 
					import should from 'should/as-function';
 | 
				
			||||||
import ConditionModel from '../models/condition';
 | 
					import ConditionModel from '../models/condition';
 | 
				
			||||||
import TestHelper from "../test/helper";
 | 
					import TestHelper from "../test/helper";
 | 
				
			||||||
// TODO: status
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('/condition', () => {
 | 
					describe('/condition', () => {
 | 
				
			||||||
  let server;
 | 
					  let server;
 | 
				
			||||||
@@ -70,8 +70,32 @@ describe('/condition', () => {
 | 
				
			|||||||
        url: '/condition/700000000000000000000001',
 | 
					        url: '/condition/700000000000000000000001',
 | 
				
			||||||
        auth: {basic: 'janedoe'},
 | 
					        auth: {basic: 'janedoe'},
 | 
				
			||||||
        httpStatus: 200,
 | 
					        httpStatus: 200,
 | 
				
			||||||
        req: {parameters: {material: 'copper', weeks: 3}},
 | 
					        req: {parameters: {material: 'copper', weeks: 3}}
 | 
				
			||||||
        res: {_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'B1', treatment_template: '200000000000000000000001', parameters: {material: 'copper', weeks: 3}}
 | 
					      }).end((err, res) => {
 | 
				
			||||||
 | 
					        if (err) return done(err);
 | 
				
			||||||
 | 
					        should(res.body).be.eql({_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'B1', treatment_template: '200000000000000000000001', parameters: {material: 'copper', weeks: 3}});
 | 
				
			||||||
 | 
					        ConditionModel.findById('700000000000000000000001').lean().exec((err, data) => {
 | 
				
			||||||
 | 
					          if (err) return done(err);
 | 
				
			||||||
 | 
					          should(data).have.property('status', 10);
 | 
				
			||||||
 | 
					          done();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    it('keeps only one unchanged parameter', done => {
 | 
				
			||||||
 | 
					      TestHelper.request(server, done, {
 | 
				
			||||||
 | 
					        method: 'put',
 | 
				
			||||||
 | 
					        url: '/condition/700000000000000000000001',
 | 
				
			||||||
 | 
					        auth: {basic: 'janedoe'},
 | 
				
			||||||
 | 
					        httpStatus: 200,
 | 
				
			||||||
 | 
					        req: {parameters: {material: 'copper'}}
 | 
				
			||||||
 | 
					      }).end((err, res) => {
 | 
				
			||||||
 | 
					        if (err) return done(err);
 | 
				
			||||||
 | 
					        should(res.body).be.eql({_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'B1', treatment_template: '200000000000000000000001', parameters: {material: 'copper', weeks: 3}});
 | 
				
			||||||
 | 
					        ConditionModel.findById('700000000000000000000001').lean().exec((err, data) => {
 | 
				
			||||||
 | 
					          if (err) return done(err);
 | 
				
			||||||
 | 
					          should(data).have.property('status', 10);
 | 
				
			||||||
 | 
					          done();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    it('changes the given properties', done => {
 | 
					    it('changes the given properties', done => {
 | 
				
			||||||
@@ -86,9 +110,11 @@ describe('/condition', () => {
 | 
				
			|||||||
        should(res.body).be.eql({_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'B1', treatment_template: '200000000000000000000001', parameters: {material: 'hot air', weeks: 10}});
 | 
					        should(res.body).be.eql({_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'B1', treatment_template: '200000000000000000000001', parameters: {material: 'hot air', weeks: 10}});
 | 
				
			||||||
        ConditionModel.findById('700000000000000000000001').lean().exec((err, data: any) => {
 | 
					        ConditionModel.findById('700000000000000000000001').lean().exec((err, data: any) => {
 | 
				
			||||||
          if (err) return done(err);
 | 
					          if (err) return done(err);
 | 
				
			||||||
 | 
					          should(data).have.only.keys('_id', 'sample_id', 'number', 'parameters', 'treatment_template', 'status', '__v');
 | 
				
			||||||
          should(data.sample_id.toString()).be.eql('400000000000000000000001');
 | 
					          should(data.sample_id.toString()).be.eql('400000000000000000000001');
 | 
				
			||||||
          should(data).have.property('number', 'B1');
 | 
					          should(data).have.property('number', 'B1');
 | 
				
			||||||
          should(data.treatment_template.toString()).be.eql('200000000000000000000001');
 | 
					          should(data.treatment_template.toString()).be.eql('200000000000000000000001');
 | 
				
			||||||
 | 
					          should(data).have.property('status', 0);
 | 
				
			||||||
          should(data).have.property('parameters');
 | 
					          should(data).have.property('parameters');
 | 
				
			||||||
          should(data.parameters).have.property('material', 'hot air');
 | 
					          should(data.parameters).have.property('material', 'hot air');
 | 
				
			||||||
          should(data.parameters).have.property('weeks', 10);
 | 
					          should(data.parameters).have.property('weeks', 10);
 | 
				
			||||||
@@ -205,7 +231,7 @@ describe('/condition', () => {
 | 
				
			|||||||
  // TODO: rewrite delete methods -> set status for every database collection
 | 
					  // TODO: rewrite delete methods -> set status for every database collection
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  describe('DELETE /condition/{id}', () => {
 | 
					  describe('DELETE /condition/{id}', () => {
 | 
				
			||||||
    it('deletes the condition', done => {
 | 
					    it('sets the status to deleted', done => {
 | 
				
			||||||
      TestHelper.request(server, done, {
 | 
					      TestHelper.request(server, done, {
 | 
				
			||||||
        method: 'delete',
 | 
					        method: 'delete',
 | 
				
			||||||
        url: '/condition/700000000000000000000002',
 | 
					        url: '/condition/700000000000000000000002',
 | 
				
			||||||
@@ -214,14 +240,21 @@ describe('/condition', () => {
 | 
				
			|||||||
      }).end((err, res) => {
 | 
					      }).end((err, res) => {
 | 
				
			||||||
        if (err) return done(err);
 | 
					        if (err) return done(err);
 | 
				
			||||||
        should(res.body).be.eql({status: 'OK'});
 | 
					        should(res.body).be.eql({status: 'OK'});
 | 
				
			||||||
        ConditionModel.findById('700000000000000000000002').lean().exec((err, data) => {
 | 
					        ConditionModel.findById('700000000000000000000002').lean().exec((err, data: any) => {
 | 
				
			||||||
          if (err) return done(err);
 | 
					          if (err) return done(err);
 | 
				
			||||||
          should(data).be.null();
 | 
					          should(data).have.only.keys('_id', 'sample_id', 'number', 'parameters', 'treatment_template', 'status', '__v');
 | 
				
			||||||
 | 
					          should(data.sample_id.toString()).be.eql('400000000000000000000002');
 | 
				
			||||||
 | 
					          should(data).have.property('number', 'B1');
 | 
				
			||||||
 | 
					          should(data.treatment_template.toString()).be.eql('200000000000000000000001');
 | 
				
			||||||
 | 
					          should(data).have.property('status', -1);
 | 
				
			||||||
 | 
					          should(data).have.property('parameters');
 | 
				
			||||||
 | 
					          should(data.parameters).have.property('material', 'copper');
 | 
				
			||||||
 | 
					          should(data.parameters).have.property('weeks', 3);
 | 
				
			||||||
          done();
 | 
					          done();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    it('rejects a deleting a condition referenced by measurements');
 | 
					    it('rejects a deleting a condition referenced by measurements');  // TODO
 | 
				
			||||||
    it('rejects an invalid id', done => {
 | 
					    it('rejects an invalid id', done => {
 | 
				
			||||||
      TestHelper.request(server, done, {
 | 
					      TestHelper.request(server, done, {
 | 
				
			||||||
        method: 'delete',
 | 
					        method: 'delete',
 | 
				
			||||||
@@ -315,11 +348,11 @@ describe('/condition', () => {
 | 
				
			|||||||
        if (err) return done(err);
 | 
					        if (err) return done(err);
 | 
				
			||||||
        ConditionModel.findById(res.body._id).lean().exec((err, data: any) => {
 | 
					        ConditionModel.findById(res.body._id).lean().exec((err, data: any) => {
 | 
				
			||||||
          if (err) return done(err);
 | 
					          if (err) return done(err);
 | 
				
			||||||
          should(data).have.only.keys('_id', 'sample_id', 'number', 'parameters', 'treatment_template', '__v');
 | 
					          should(data).have.only.keys('_id', 'sample_id', 'number', 'parameters', 'treatment_template', 'status', '__v');
 | 
				
			||||||
          should(data).have.property('_id');
 | 
					 | 
				
			||||||
          should(data.sample_id.toString()).be.eql('400000000000000000000002');
 | 
					          should(data.sample_id.toString()).be.eql('400000000000000000000002');
 | 
				
			||||||
          should(data).have.property('number', 'B2');
 | 
					          should(data).have.property('number', 'B2');
 | 
				
			||||||
          should(data.treatment_template.toString()).be.eql('200000000000000000000001');
 | 
					          should(data.treatment_template.toString()).be.eql('200000000000000000000001');
 | 
				
			||||||
 | 
					          should(data).have.property('status', 0);
 | 
				
			||||||
          should(data).have.property('parameters');
 | 
					          should(data).have.property('parameters');
 | 
				
			||||||
          should(data.parameters).have.property('material', 'hot air');
 | 
					          should(data.parameters).have.property('material', 'hot air');
 | 
				
			||||||
          should(data.parameters).have.property('weeks', 10);
 | 
					          should(data.parameters).have.property('weeks', 10);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
import express from 'express';
 | 
					import express from 'express';
 | 
				
			||||||
import mongoose from 'mongoose';
 | 
					import mongoose from 'mongoose';
 | 
				
			||||||
 | 
					import _ from 'lodash';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import ConditionValidate from './validate/condition';
 | 
					import ConditionValidate from './validate/condition';
 | 
				
			||||||
import ParametersValidate from './validate/parameters';
 | 
					import ParametersValidate from './validate/parameters';
 | 
				
			||||||
@@ -30,7 +31,6 @@ router.put('/condition/' + IdValidate.parameter(), async (req, res, next) => {
 | 
				
			|||||||
  if (!req.auth(res, ['write', 'maintain', 'dev', 'admin'], 'basic')) return;
 | 
					  if (!req.auth(res, ['write', 'maintain', 'dev', 'admin'], 'basic')) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const {error, value: condition} = ConditionValidate.input(req.body, 'change');
 | 
					  const {error, value: condition} = ConditionValidate.input(req.body, 'change');
 | 
				
			||||||
  console.log(error);
 | 
					 | 
				
			||||||
  if (error) return res400(error, res);
 | 
					  if (error) return res400(error, res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const data = await ConditionModel.findById(req.params.id).lean().exec().catch(err => {next(err);}) as any;
 | 
					  const data = await ConditionModel.findById(req.params.id).lean().exec().catch(err => {next(err);}) as any;
 | 
				
			||||||
@@ -40,11 +40,15 @@ router.put('/condition/' + IdValidate.parameter(), async (req, res, next) => {
 | 
				
			|||||||
  if (!data) {
 | 
					  if (!data) {
 | 
				
			||||||
    res.status(404).json({status: 'Not found'});
 | 
					    res.status(404).json({status: 'Not found'});
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  // add properties needed for sampleIdCheck
 | 
				
			||||||
  condition.treatment_template = data.treatment_template;
 | 
					  condition.treatment_template = data.treatment_template;
 | 
				
			||||||
  condition.sample_id = data.sample_id;
 | 
					  condition.sample_id = data.sample_id;
 | 
				
			||||||
  if (!await sampleIdCheck(condition, req, res, next)) return;
 | 
					  if (!await sampleIdCheck(condition, req, res, next)) return;
 | 
				
			||||||
  if (condition.parameters) {
 | 
					  if (condition.parameters) {
 | 
				
			||||||
    condition.parameters = Object.assign(data.parameters, condition.parameters);
 | 
					    condition.parameters = _.assign({}, data.parameters, condition.parameters);
 | 
				
			||||||
 | 
					    if (!_.isEqual(condition.parameters, data.parameters)) {
 | 
				
			||||||
 | 
					      condition.status = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (!await treatmentCheck(condition, 'change', res, next)) return;
 | 
					  if (!await treatmentCheck(condition, 'change', res, next)) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -63,7 +67,7 @@ router.delete('/condition/' + IdValidate.parameter(), (req, res, next) => {
 | 
				
			|||||||
      res.status(404).json({status: 'Not found'});
 | 
					      res.status(404).json({status: 'Not found'});
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (!await sampleIdCheck(data, req, res, next)) return;
 | 
					    if (!await sampleIdCheck(data, req, res, next)) return;
 | 
				
			||||||
    await ConditionModel.findByIdAndDelete(req.params.id).lean().exec(async err => {
 | 
					    await ConditionModel.findByIdAndUpdate(req.params.id, {status: -1}).lean().exec(err => {
 | 
				
			||||||
      if (err) return next(err);
 | 
					      if (err) return next(err);
 | 
				
			||||||
      res.json({status: 'OK'});
 | 
					      res.json({status: 'OK'});
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@@ -80,6 +84,7 @@ router.post('/condition/new', async (req, res, next) => {
 | 
				
			|||||||
  if (!await numberCheck(condition, res, next)) return;
 | 
					  if (!await numberCheck(condition, res, next)) return;
 | 
				
			||||||
  if (!await treatmentCheck(condition, 'new', res, next)) return;
 | 
					  if (!await treatmentCheck(condition, 'new', res, next)) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  condition.status = 0;
 | 
				
			||||||
  await new ConditionModel(condition).save((err, data) => {
 | 
					  await new ConditionModel(condition).save((err, data) => {
 | 
				
			||||||
    if (err) return next(err);
 | 
					    if (err) return next(err);
 | 
				
			||||||
    res.json(ConditionValidate.output(data.toObject()));
 | 
					    res.json(ConditionValidate.output(data.toObject()));
 | 
				
			||||||
@@ -119,7 +124,6 @@ async function treatmentCheck (condition, param, res, next) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // validate parameters
 | 
					  // validate parameters
 | 
				
			||||||
  const {error, value: ignore} = ParametersValidate.input(condition.parameters, treatmentData.parameters, param);
 | 
					  const {error, value: ignore} = ParametersValidate.input(condition.parameters, treatmentData.parameters, param);
 | 
				
			||||||
  console.log(error);
 | 
					 | 
				
			||||||
  if (error) {res400(error, res); return false;}
 | 
					  if (error) {res400(error, res); return false;}
 | 
				
			||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -2,6 +2,8 @@ import should from 'should/as-function';
 | 
				
			|||||||
import MaterialModel from '../models/material';
 | 
					import MaterialModel from '../models/material';
 | 
				
			||||||
import TestHelper from "../test/helper";
 | 
					import TestHelper from "../test/helper";
 | 
				
			||||||
// TODO: status
 | 
					// TODO: status
 | 
				
			||||||
 | 
					// TODO: numbers with color only (no number)
 | 
				
			||||||
 | 
					// TODO: deal with numbers with leading zeros
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('/material', () => {
 | 
					describe('/material', () => {
 | 
				
			||||||
  let server;
 | 
					  let server;
 | 
				
			||||||
@@ -19,7 +21,8 @@ describe('/material', () => {
 | 
				
			|||||||
      }).end((err, res) => {
 | 
					      }).end((err, res) => {
 | 
				
			||||||
        if (err) return done(err);
 | 
					        if (err) return done(err);
 | 
				
			||||||
        const json = require('../test/db.json');
 | 
					        const json = require('../test/db.json');
 | 
				
			||||||
        should(res.body).have.lengthOf(json.collections.materials.length);
 | 
					        console.log(res.body);
 | 
				
			||||||
 | 
					        should(res.body).have.lengthOf(json.collections.materials.filter(e => e.status === 10).length);
 | 
				
			||||||
        should(res.body).matchEach(material => {
 | 
					        should(res.body).matchEach(material => {
 | 
				
			||||||
          should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers');
 | 
					          should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers');
 | 
				
			||||||
          should(material).have.property('_id').be.type('string');
 | 
					          should(material).have.property('_id').be.type('string');
 | 
				
			||||||
@@ -47,7 +50,7 @@ describe('/material', () => {
 | 
				
			|||||||
      }).end((err, res) => {
 | 
					      }).end((err, res) => {
 | 
				
			||||||
        if (err) return done(err);
 | 
					        if (err) return done(err);
 | 
				
			||||||
        const json = require('../test/db.json');
 | 
					        const json = require('../test/db.json');
 | 
				
			||||||
        should(res.body).have.lengthOf(json.collections.materials.length);
 | 
					        should(res.body).have.lengthOf(json.collections.materials.filter(e => e.status === 10).length);
 | 
				
			||||||
        should(res.body).matchEach(material => {
 | 
					        should(res.body).matchEach(material => {
 | 
				
			||||||
          should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers');
 | 
					          should(material).have.only.keys('_id', 'name', 'supplier', 'group', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers');
 | 
				
			||||||
          should(material).have.property('_id').be.type('string');
 | 
					          should(material).have.property('_id').be.type('string');
 | 
				
			||||||
@@ -136,8 +139,32 @@ describe('/material', () => {
 | 
				
			|||||||
        url: '/material/100000000000000000000001',
 | 
					        url: '/material/100000000000000000000001',
 | 
				
			||||||
        auth: {basic: 'janedoe'},
 | 
					        auth: {basic: 'janedoe'},
 | 
				
			||||||
        httpStatus: 200,
 | 
					        httpStatus: 200,
 | 
				
			||||||
        req: {name: 'Stanyl TW 200 F8', supplier: 'DSM', group: 'PA46', mineral: 0, glass_fiber: 40, carbon_fiber: 0, numbers: [{color: 'black', number: 5514263423}]},
 | 
					        req: {name: 'Stanyl TW 200 F8', supplier: 'DSM', group: 'PA46', mineral: 0, glass_fiber: 40, carbon_fiber: 0, numbers: [{color: 'black', number: 5514263423}, {color: 'natural', number: 5514263422}]}
 | 
				
			||||||
        res: {_id: '100000000000000000000001', name: 'Stanyl TW 200 F8', supplier: 'DSM', group: 'PA46', mineral: 0, glass_fiber: 40, carbon_fiber: 0, numbers: [{color: 'black', number: 5514263423}]}
 | 
					      }).end((err, res) => {
 | 
				
			||||||
 | 
					        if (err) return done(err);
 | 
				
			||||||
 | 
					        should(res.body).be.eql({_id: '100000000000000000000001', name: 'Stanyl TW 200 F8', supplier: 'DSM', group: 'PA46', mineral: 0, glass_fiber: 40, carbon_fiber: 0, numbers: [{color: 'black', number: 5514263423}, {color: 'natural', number: 5514263422}]});
 | 
				
			||||||
 | 
					        MaterialModel.findById('100000000000000000000001').lean().exec((err, data) => {
 | 
				
			||||||
 | 
					          if (err) return done(err);
 | 
				
			||||||
 | 
					          should(data).have.property('status', 10);
 | 
				
			||||||
 | 
					          done();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    it('keeps only one unchanged property', done => {
 | 
				
			||||||
 | 
					      TestHelper.request(server, done, {
 | 
				
			||||||
 | 
					        method: 'put',
 | 
				
			||||||
 | 
					        url: '/material/100000000000000000000001',
 | 
				
			||||||
 | 
					        auth: {basic: 'janedoe'},
 | 
				
			||||||
 | 
					        httpStatus: 200,
 | 
				
			||||||
 | 
					        req: {name: 'Stanyl TW 200 F8'}
 | 
				
			||||||
 | 
					      }).end((err, res) => {
 | 
				
			||||||
 | 
					        if (err) return done(err);
 | 
				
			||||||
 | 
					        should(res.body).be.eql({_id: '100000000000000000000001', name: 'Stanyl TW 200 F8', supplier: 'DSM', group: 'PA46', mineral: 0, glass_fiber: 40, carbon_fiber: 0, numbers: [{color: 'black', number: 5514263423}, {color: 'natural', number: 5514263422}]});
 | 
				
			||||||
 | 
					        MaterialModel.findById('100000000000000000000001').lean().exec((err, data) => {
 | 
				
			||||||
 | 
					          if (err) return done(err);
 | 
				
			||||||
 | 
					          should(data).have.property('status', 10);
 | 
				
			||||||
 | 
					          done();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    it('changes the given properties', done => {
 | 
					    it('changes the given properties', done => {
 | 
				
			||||||
@@ -155,8 +182,7 @@ describe('/material', () => {
 | 
				
			|||||||
          if (err) return done(err);
 | 
					          if (err) return done(err);
 | 
				
			||||||
          data._id = data._id.toString();
 | 
					          data._id = data._id.toString();
 | 
				
			||||||
          data.numbers = data.numbers.map(e => {return {color: e.color, number: e.number}});
 | 
					          data.numbers = data.numbers.map(e => {return {color: e.color, number: e.number}});
 | 
				
			||||||
          should(data).be.eql({_id: '100000000000000000000001', name: 'UltramidTKR4355G7_2', supplier: 'BASF', group: 'PA6/6T', mineral: '0', glass_fiber: '35', carbon_fiber: '0', numbers: [{color: 'black', number: 5514212901}, {color: 'signalviolet', number: 5514612901}], __v: 0}
 | 
					          should(data).be.eql({_id: '100000000000000000000001', name: 'UltramidTKR4355G7_2', supplier: 'BASF', group: 'PA6/6T', mineral: '0', glass_fiber: '35', carbon_fiber: '0', numbers: [{color: 'black', number: 5514212901}, {color: 'signalviolet', number: 5514612901}], status: 0, __v: 0});
 | 
				
			||||||
          );
 | 
					 | 
				
			||||||
          done();
 | 
					          done();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
@@ -268,7 +294,7 @@ describe('/material', () => {
 | 
				
			|||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  describe('DELETE /material/{id}', () => {
 | 
					  describe('DELETE /material/{id}', () => {
 | 
				
			||||||
    it('deletes the material', done => {
 | 
					    it('sets the status to deleted', done => {
 | 
				
			||||||
      TestHelper.request(server, done, {
 | 
					      TestHelper.request(server, done, {
 | 
				
			||||||
        method: 'delete',
 | 
					        method: 'delete',
 | 
				
			||||||
        url: '/material/100000000000000000000002',
 | 
					        url: '/material/100000000000000000000002',
 | 
				
			||||||
@@ -277,9 +303,12 @@ describe('/material', () => {
 | 
				
			|||||||
      }).end((err, res) => {
 | 
					      }).end((err, res) => {
 | 
				
			||||||
        if (err) return done(err);
 | 
					        if (err) return done(err);
 | 
				
			||||||
        should(res.body).be.eql({status: 'OK'});
 | 
					        should(res.body).be.eql({status: 'OK'});
 | 
				
			||||||
        MaterialModel.findById('100000000000000000000002').lean().exec((err, data) => {
 | 
					        MaterialModel.findById('100000000000000000000002').lean().exec((err, data: any) => {
 | 
				
			||||||
          if (err) return done(err);
 | 
					          if (err) return done(err);
 | 
				
			||||||
          should(data).be.null();
 | 
					          data._id = data._id.toString();
 | 
				
			||||||
 | 
					          data.numbers = data.numbers.map(e => {return {color: e.color, number: e.number}});
 | 
				
			||||||
 | 
					          should(data).be.eql({_id: '100000000000000000000002', name: 'Ultramid T KR 4355 G7', supplier: 'BASF', group: 'PA6/6T', mineral: 0, glass_fiber: 35, carbon_fiber: 0, numbers: [{color: 'black', number: 5514212901}, {color: 'signalviolet', number: 5514612901}], status: -1, __v: 0}
 | 
				
			||||||
 | 
					          );
 | 
				
			||||||
          done();
 | 
					          done();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
@@ -372,7 +401,7 @@ describe('/material', () => {
 | 
				
			|||||||
        MaterialModel.find({name: 'Crastin CE 2510'}).lean().exec((err, data: any) => {
 | 
					        MaterialModel.find({name: 'Crastin CE 2510'}).lean().exec((err, data: any) => {
 | 
				
			||||||
          if (err) return done (err);
 | 
					          if (err) return done (err);
 | 
				
			||||||
          should(data).have.lengthOf(1);
 | 
					          should(data).have.lengthOf(1);
 | 
				
			||||||
          should(data[0]).have.only.keys('_id', 'name', 'supplier', 'group', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers', '__v');
 | 
					          should(data[0]).have.only.keys('_id', 'name', 'supplier', 'group', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers', 'status', '__v');
 | 
				
			||||||
          should(data[0]).have.property('_id');
 | 
					          should(data[0]).have.property('_id');
 | 
				
			||||||
          should(data[0]).have.property('name', 'Crastin CE 2510');
 | 
					          should(data[0]).have.property('name', 'Crastin CE 2510');
 | 
				
			||||||
          should(data[0]).have.property('supplier', 'Du Pont');
 | 
					          should(data[0]).have.property('supplier', 'Du Pont');
 | 
				
			||||||
@@ -380,6 +409,7 @@ describe('/material', () => {
 | 
				
			|||||||
          should(data[0]).have.property('mineral', '0');
 | 
					          should(data[0]).have.property('mineral', '0');
 | 
				
			||||||
          should(data[0]).have.property('glass_fiber', '30');
 | 
					          should(data[0]).have.property('glass_fiber', '30');
 | 
				
			||||||
          should(data[0]).have.property('carbon_fiber', '0');
 | 
					          should(data[0]).have.property('carbon_fiber', '0');
 | 
				
			||||||
 | 
					          should(data[0]).have.property('status', 0);
 | 
				
			||||||
          should(data[0].numbers).have.lengthOf(0);
 | 
					          should(data[0].numbers).have.lengthOf(0);
 | 
				
			||||||
          done();
 | 
					          done();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,13 +8,14 @@ import IdValidate from './validate/id';
 | 
				
			|||||||
import res400 from './validate/res400';
 | 
					import res400 from './validate/res400';
 | 
				
			||||||
import mongoose from 'mongoose';
 | 
					import mongoose from 'mongoose';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: remove f() for await
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const router = express.Router();
 | 
					const router = express.Router();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
router.get('/materials', (req, res, next) => {
 | 
					router.get('/materials', (req, res, next) => {
 | 
				
			||||||
  if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'all')) return;
 | 
					  if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'all')) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  MaterialModel.find({}).lean().exec((err, data) => {
 | 
					  MaterialModel.find({status: 10}).lean().exec((err, data) => {
 | 
				
			||||||
    if (err) return next(err);
 | 
					    if (err) return next(err);
 | 
				
			||||||
    res.json(_.compact(data.map(e => MaterialValidate.output(e))));  // validate all and filter null values from validation errors
 | 
					    res.json(_.compact(data.map(e => MaterialValidate.output(e))));  // validate all and filter null values from validation errors
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
@@ -40,33 +41,24 @@ router.put('/material/' + IdValidate.parameter(), (req, res, next) => {
 | 
				
			|||||||
  const {error, value: material} = MaterialValidate.input(req.body, 'change');
 | 
					  const {error, value: material} = MaterialValidate.input(req.body, 'change');
 | 
				
			||||||
  if (error) return res400(error, res);
 | 
					  if (error) return res400(error, res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (material.hasOwnProperty('name')) {
 | 
					  MaterialModel.findById(req.params.id).lean().exec(async (err, materialData: any) => {
 | 
				
			||||||
    MaterialModel.find({name: material.name}).lean().exec((err, data) => {
 | 
					    if (!materialData) {
 | 
				
			||||||
      if (err) return next(err);
 | 
					      return res.status(404).json({status: 'Not found'});
 | 
				
			||||||
      if (data.length > 0 && data[0]._id != req.params.id) {
 | 
					    }
 | 
				
			||||||
        res.status(400).json({status: 'Material name already taken'});
 | 
					    if (material.hasOwnProperty('name') && material.name !== materialData.name) {
 | 
				
			||||||
        return;
 | 
					      if (!await nameCheck(material, res, next)) return;
 | 
				
			||||||
      }
 | 
					    }
 | 
				
			||||||
      else {
 | 
					 | 
				
			||||||
        f();
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  else {
 | 
					 | 
				
			||||||
    f();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function f() {  // to resolve async
 | 
					    // check for changes
 | 
				
			||||||
    MaterialModel.findByIdAndUpdate(req.params.id, material, {new: true}).lean().exec((err, data) => {
 | 
					    if (!_.isEqual(_.pick(IdValidate.stringify(materialData), _.keys(material)), material)) {
 | 
				
			||||||
 | 
					      material.status = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await MaterialModel.findByIdAndUpdate(req.params.id, material, {new: true}).lean().exec((err, data) => {
 | 
				
			||||||
      if (err) return next(err);
 | 
					      if (err) return next(err);
 | 
				
			||||||
      if (data) {
 | 
					      res.json(MaterialValidate.output(data));
 | 
				
			||||||
        res.json(MaterialValidate.output(data));
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      else {
 | 
					 | 
				
			||||||
        res.status(404).json({status: 'Not found'});
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
router.delete('/material/' + IdValidate.parameter(), (req, res, next) => {
 | 
					router.delete('/material/' + IdValidate.parameter(), (req, res, next) => {
 | 
				
			||||||
@@ -78,7 +70,7 @@ router.delete('/material/' + IdValidate.parameter(), (req, res, next) => {
 | 
				
			|||||||
    if (data.length) {
 | 
					    if (data.length) {
 | 
				
			||||||
      return res.status(400).json({status: 'Material still in use'});
 | 
					      return res.status(400).json({status: 'Material still in use'});
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    MaterialModel.findByIdAndDelete(req.params.id).lean().exec((err, data) => {
 | 
					    MaterialModel.findByIdAndUpdate(req.params.id, {status: -1}).lean().exec((err, data) => {
 | 
				
			||||||
      if (err) return next(err);
 | 
					      if (err) return next(err);
 | 
				
			||||||
      if (data) {
 | 
					      if (data) {
 | 
				
			||||||
        res.json({status: 'OK'});
 | 
					        res.json({status: 'OK'});
 | 
				
			||||||
@@ -90,26 +82,34 @@ router.delete('/material/' + IdValidate.parameter(), (req, res, next) => {
 | 
				
			|||||||
  });
 | 
					  });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
router.post('/material/new', (req, res, next) => {
 | 
					router.post('/material/new', async (req, res, next) => {
 | 
				
			||||||
  if (!req.auth(res, ['write', 'maintain', 'dev', 'admin'], 'basic')) return;
 | 
					  if (!req.auth(res, ['write', 'maintain', 'dev', 'admin'], 'basic')) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // validate input
 | 
					  // validate input
 | 
				
			||||||
  const {error, value: material} = MaterialValidate.input(req.body, 'new');
 | 
					  const {error, value: material} = MaterialValidate.input(req.body, 'new');
 | 
				
			||||||
  if (error) return res400(error, res);
 | 
					  if (error) return res400(error, res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  MaterialModel.find({name: material.name}).lean().exec((err, data) => {
 | 
					  if (!await nameCheck(material, res, next)) return;
 | 
				
			||||||
    if (err) return next(err);
 | 
					 | 
				
			||||||
    if (data.length > 0) {
 | 
					 | 
				
			||||||
      res.status(400).json({status: 'Material name already taken'});
 | 
					 | 
				
			||||||
      return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    new MaterialModel(material).save((err, data) => {
 | 
					  material.status = 0;
 | 
				
			||||||
      if (err) return next(err);
 | 
					  await new MaterialModel(material).save((err, data) => {
 | 
				
			||||||
      res.json(MaterialValidate.output(data.toObject()));
 | 
					    if (err) return next(err);
 | 
				
			||||||
    });
 | 
					    res.json(MaterialValidate.output(data.toObject()));
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = router;
 | 
					module.exports = router;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function nameCheck (material, res, next) {  // check if name was already taken
 | 
				
			||||||
 | 
					  const materialData = await MaterialModel.findOne({name: material.name}).lean().exec().catch(err => {next(err); return false;}) as any;
 | 
				
			||||||
 | 
					  if (materialData instanceof Error) {
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (materialData) {  // could not find material_id
 | 
				
			||||||
 | 
					    res.status(400).json({status: 'Material name already taken'});
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -74,6 +74,24 @@ describe('/measurement', () => {
 | 
				
			|||||||
        if (err) return done(err);
 | 
					        if (err) return done(err);
 | 
				
			||||||
        should(res.body).be.eql({_id: '800000000000000000000001', condition_id: '700000000000000000000001', values: {dpt: [[3997.12558,98.00555],[3995.08519,98.03253],[3993.04480,98.02657]]}, measurement_template: '300000000000000000000001'});
 | 
					        should(res.body).be.eql({_id: '800000000000000000000001', condition_id: '700000000000000000000001', values: {dpt: [[3997.12558,98.00555],[3995.08519,98.03253],[3993.04480,98.02657]]}, measurement_template: '300000000000000000000001'});
 | 
				
			||||||
        MeasurementModel.findById('800000000000000000000001').lean().exec((err, data: any) => {
 | 
					        MeasurementModel.findById('800000000000000000000001').lean().exec((err, data: any) => {
 | 
				
			||||||
 | 
					          if (err) return done(err);
 | 
				
			||||||
 | 
					          should(data).have.property('status', 10);
 | 
				
			||||||
 | 
					          done();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    it('keeps only one unchanged value', done => {
 | 
				
			||||||
 | 
					      TestHelper.request(server, done, {
 | 
				
			||||||
 | 
					        method: 'put',
 | 
				
			||||||
 | 
					        url: '/measurement/800000000000000000000002',
 | 
				
			||||||
 | 
					        auth: {basic: 'janedoe'},
 | 
				
			||||||
 | 
					        httpStatus: 200,
 | 
				
			||||||
 | 
					        req: {values: {'weight %': 0.5}}
 | 
				
			||||||
 | 
					      }).end((err, res) => {
 | 
				
			||||||
 | 
					        if (err) return done(err);
 | 
				
			||||||
 | 
					        should(res.body).be.eql({_id: '800000000000000000000002', condition_id: '700000000000000000000002', values: {'weight %': 0.5, 'standard deviation': 0.2}, measurement_template: '300000000000000000000002'});
 | 
				
			||||||
 | 
					        MeasurementModel.findById('800000000000000000000002').lean().exec((err, data: any) => {
 | 
				
			||||||
 | 
					          if (err) return done(err);
 | 
				
			||||||
          should(data).have.property('status', 10);
 | 
					          should(data).have.property('status', 10);
 | 
				
			||||||
          done();
 | 
					          done();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,12 +41,12 @@ router.put('/measurement/' + IdValidate.parameter(), async (req, res, next) => {
 | 
				
			|||||||
  // add properties needed for conditionIdCheck
 | 
					  // add properties needed for conditionIdCheck
 | 
				
			||||||
  measurement.measurement_template = data.measurement_template;
 | 
					  measurement.measurement_template = data.measurement_template;
 | 
				
			||||||
  measurement.condition_id = data.condition_id;
 | 
					  measurement.condition_id = data.condition_id;
 | 
				
			||||||
  if (measurement.hasOwnProperty('values') && !_.isEqual(measurement.values, data.values)) {
 | 
					 | 
				
			||||||
    measurement.status = 0;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  if (!await conditionIdCheck(measurement, req, res, next)) return;
 | 
					  if (!await conditionIdCheck(measurement, req, res, next)) return;
 | 
				
			||||||
  if (measurement.values) {
 | 
					  if (measurement.values) {
 | 
				
			||||||
    measurement.values = Object.assign(data.values, measurement.values);
 | 
					    measurement.values = _.assign({}, data.values, measurement.values);
 | 
				
			||||||
 | 
					    if (!_.isEqual(measurement.values, data.values)) {
 | 
				
			||||||
 | 
					      measurement.status = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (!await templateCheck(measurement, 'change', res, next)) return;
 | 
					  if (!await templateCheck(measurement, 'change', res, next)) return;
 | 
				
			||||||
  await MeasurementModel.findByIdAndUpdate(req.params.id, measurement, {new: true}).lean().exec((err, data) => {
 | 
					  await MeasurementModel.findByIdAndUpdate(req.params.id, measurement, {new: true}).lean().exec((err, data) => {
 | 
				
			||||||
@@ -64,7 +64,7 @@ router.delete('/measurement/' + IdValidate.parameter(), (req, res, next) => {
 | 
				
			|||||||
      res.status(404).json({status: 'Not found'});
 | 
					      res.status(404).json({status: 'Not found'});
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (!await conditionIdCheck(data, req, res, next)) return;
 | 
					    if (!await conditionIdCheck(data, req, res, next)) return;
 | 
				
			||||||
    await MeasurementModel.findByIdAndUpdate(req.params.id, {status: -1}).lean().exec(async err => {
 | 
					    await MeasurementModel.findByIdAndUpdate(req.params.id, {status: -1}).lean().exec(err => {
 | 
				
			||||||
      if (err) return next(err);
 | 
					      if (err) return next(err);
 | 
				
			||||||
      res.json({status: 'OK'});
 | 
					      res.json({status: 'OK'});
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,6 @@ import NoteFieldModel from '../models/note_field';
 | 
				
			|||||||
import TestHelper from "../test/helper";
 | 
					import TestHelper from "../test/helper";
 | 
				
			||||||
// TODO: generate sample number
 | 
					// TODO: generate sample number
 | 
				
			||||||
// TODO: think again which parameters are required at POST
 | 
					// TODO: think again which parameters are required at POST
 | 
				
			||||||
// TODO: status
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('/sample', () => {
 | 
					describe('/sample', () => {
 | 
				
			||||||
  let server;
 | 
					  let server;
 | 
				
			||||||
@@ -23,7 +22,7 @@ describe('/sample', () => {
 | 
				
			|||||||
      }).end((err, res) => {
 | 
					      }).end((err, res) => {
 | 
				
			||||||
        if (err) return done(err);
 | 
					        if (err) return done(err);
 | 
				
			||||||
        const json = require('../test/db.json');
 | 
					        const json = require('../test/db.json');
 | 
				
			||||||
        should(res.body).have.lengthOf(json.collections.samples.length);
 | 
					        should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status === 10).length);
 | 
				
			||||||
        should(res.body).matchEach(material => {
 | 
					        should(res.body).matchEach(material => {
 | 
				
			||||||
          should(material).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'material_id', 'note_id', 'user_id');
 | 
					          should(material).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'material_id', 'note_id', 'user_id');
 | 
				
			||||||
          should(material).have.property('_id').be.type('string');
 | 
					          should(material).have.property('_id').be.type('string');
 | 
				
			||||||
@@ -47,7 +46,7 @@ describe('/sample', () => {
 | 
				
			|||||||
      }).end((err, res) => {
 | 
					      }).end((err, res) => {
 | 
				
			||||||
        if (err) return done(err);
 | 
					        if (err) return done(err);
 | 
				
			||||||
        const json = require('../test/db.json');
 | 
					        const json = require('../test/db.json');
 | 
				
			||||||
        should(res.body).have.lengthOf(json.collections.samples.length);
 | 
					        should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status === 10).length);
 | 
				
			||||||
        should(res.body).matchEach(material => {
 | 
					        should(res.body).matchEach(material => {
 | 
				
			||||||
          should(material).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'material_id', 'note_id', 'user_id');
 | 
					          should(material).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'material_id', 'note_id', 'user_id');
 | 
				
			||||||
          should(material).have.property('_id').be.type('string');
 | 
					          should(material).have.property('_id').be.type('string');
 | 
				
			||||||
@@ -88,8 +87,41 @@ describe('/sample', () => {
 | 
				
			|||||||
        url: '/sample/400000000000000000000001',
 | 
					        url: '/sample/400000000000000000000001',
 | 
				
			||||||
        auth: {basic: 'janedoe'},
 | 
					        auth: {basic: 'janedoe'},
 | 
				
			||||||
        httpStatus: 200,
 | 
					        httpStatus: 200,
 | 
				
			||||||
        req: {number: '1', type: 'granulate', color: 'black', batch: '', material_id: '100000000000000000000004', notes: {}},
 | 
					        req: {number: '1', type: 'granulate', color: 'black', batch: '', material_id: '100000000000000000000004', notes: {}}
 | 
				
			||||||
        res: {_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002'}
 | 
					      }).end((err, res) => {
 | 
				
			||||||
 | 
					        if (err) return done(err);
 | 
				
			||||||
 | 
					        should(res.body).be.eql({_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002'});
 | 
				
			||||||
 | 
					        SampleModel.findById('400000000000000000000001').lean().exec((err, data: any) => {
 | 
				
			||||||
 | 
					          if (err) return done (err);
 | 
				
			||||||
 | 
					          should(data).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'material_id', 'note_id', 'user_id', 'status', '__v');
 | 
				
			||||||
 | 
					          should(data).have.property('_id');
 | 
				
			||||||
 | 
					          should(data).have.property('number', '1');
 | 
				
			||||||
 | 
					          should(data).have.property('color', 'black');
 | 
				
			||||||
 | 
					          should(data).have.property('type', 'granulate');
 | 
				
			||||||
 | 
					          should(data).have.property('batch', '');
 | 
				
			||||||
 | 
					          should(data.material_id.toString()).be.eql('100000000000000000000004');
 | 
				
			||||||
 | 
					          should(data.user_id.toString()).be.eql('000000000000000000000002');
 | 
				
			||||||
 | 
					          should(data).have.property('status', 10);
 | 
				
			||||||
 | 
					          should(data).have.property('note_id', null);
 | 
				
			||||||
 | 
					          done();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    it('keeps only one unchanged parameter', done => {
 | 
				
			||||||
 | 
					      TestHelper.request(server, done, {
 | 
				
			||||||
 | 
					        method: 'put',
 | 
				
			||||||
 | 
					        url: '/sample/400000000000000000000001',
 | 
				
			||||||
 | 
					        auth: {basic: 'janedoe'},
 | 
				
			||||||
 | 
					        httpStatus: 200,
 | 
				
			||||||
 | 
					        req: {type: 'granulate'}
 | 
				
			||||||
 | 
					      }).end((err, res) => {
 | 
				
			||||||
 | 
					        if (err) return done(err);
 | 
				
			||||||
 | 
					        should(res.body).be.eql({_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002'});
 | 
				
			||||||
 | 
					        SampleModel.findById('400000000000000000000001').lean().exec((err, data: any) => {
 | 
				
			||||||
 | 
					          if (err) return done (err);
 | 
				
			||||||
 | 
					          should(data).have.property('status', 10);
 | 
				
			||||||
 | 
					          done();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    it('changes the given properties', done => {
 | 
					    it('changes the given properties', done => {
 | 
				
			||||||
@@ -103,15 +135,15 @@ describe('/sample', () => {
 | 
				
			|||||||
        if (err) return done (err);
 | 
					        if (err) return done (err);
 | 
				
			||||||
        SampleModel.findById('400000000000000000000001').lean().exec((err, data: any) => {
 | 
					        SampleModel.findById('400000000000000000000001').lean().exec((err, data: any) => {
 | 
				
			||||||
          if (err) return done (err);
 | 
					          if (err) return done (err);
 | 
				
			||||||
          should(data).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'validated', 'material_id', 'note_id', 'user_id', '__v');
 | 
					          should(data).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'material_id', 'note_id', 'user_id', 'status', '__v');
 | 
				
			||||||
          should(data).have.property('_id');
 | 
					          should(data).have.property('_id');
 | 
				
			||||||
          should(data).have.property('number', '10');
 | 
					          should(data).have.property('number', '10');
 | 
				
			||||||
          should(data).have.property('color', 'signalviolet');
 | 
					          should(data).have.property('color', 'signalviolet');
 | 
				
			||||||
          should(data).have.property('type', 'part');
 | 
					          should(data).have.property('type', 'part');
 | 
				
			||||||
          should(data).have.property('batch', '114531');
 | 
					          should(data).have.property('batch', '114531');
 | 
				
			||||||
          should(data).have.property('validated').be.type('boolean');
 | 
					 | 
				
			||||||
          should(data.material_id.toString()).be.eql('100000000000000000000002');
 | 
					          should(data.material_id.toString()).be.eql('100000000000000000000002');
 | 
				
			||||||
          should(data.user_id.toString()).be.eql('000000000000000000000002');
 | 
					          should(data.user_id.toString()).be.eql('000000000000000000000002');
 | 
				
			||||||
 | 
					          should(data).have.property('status', 0);
 | 
				
			||||||
          should(data).have.property('note_id');
 | 
					          should(data).have.property('note_id');
 | 
				
			||||||
          NoteModel.findById(data.note_id).lean().exec((err, data: any) => {
 | 
					          NoteModel.findById(data.note_id).lean().exec((err, data: any) => {
 | 
				
			||||||
            if (err) return done (err);
 | 
					            if (err) return done (err);
 | 
				
			||||||
@@ -123,7 +155,7 @@ describe('/sample', () => {
 | 
				
			|||||||
            should(data.sample_references[0]).have.property('relation', 'part to this sample');
 | 
					            should(data.sample_references[0]).have.property('relation', 'part to this sample');
 | 
				
			||||||
            done();
 | 
					            done();
 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
        })
 | 
					        });
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    it('adjusts the note_fields correctly', done => {
 | 
					    it('adjusts the note_fields correctly', done => {
 | 
				
			||||||
@@ -315,7 +347,7 @@ describe('/sample', () => {
 | 
				
			|||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  describe('DELETE /sample/{id}', () => {
 | 
					  describe('DELETE /sample/{id}', () => {
 | 
				
			||||||
    it('deletes the sample', done => {
 | 
					    it('sets the status to deleted', done => {
 | 
				
			||||||
      TestHelper.request(server, done, {
 | 
					      TestHelper.request(server, done, {
 | 
				
			||||||
        method: 'delete',
 | 
					        method: 'delete',
 | 
				
			||||||
        url: '/sample/400000000000000000000001',
 | 
					        url: '/sample/400000000000000000000001',
 | 
				
			||||||
@@ -324,14 +356,23 @@ describe('/sample', () => {
 | 
				
			|||||||
      }).end((err, res) => {
 | 
					      }).end((err, res) => {
 | 
				
			||||||
        if (err) return done(err);
 | 
					        if (err) return done(err);
 | 
				
			||||||
        should(res.body).be.eql({status: 'OK'});
 | 
					        should(res.body).be.eql({status: 'OK'});
 | 
				
			||||||
        SampleModel.findById('400000000000000000000001').lean().exec((err, data) => {
 | 
					        SampleModel.findById('400000000000000000000001').lean().exec((err, data: any) => {
 | 
				
			||||||
          if (err) return done(err);
 | 
					          if (err) return done(err);
 | 
				
			||||||
          should(data).be.null();
 | 
					          should(data).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'material_id', 'note_id', 'user_id', 'status', '__v');
 | 
				
			||||||
 | 
					          should(data).have.property('_id');
 | 
				
			||||||
 | 
					          should(data).have.property('number', '1');
 | 
				
			||||||
 | 
					          should(data).have.property('color', 'black');
 | 
				
			||||||
 | 
					          should(data).have.property('type', 'granulate');
 | 
				
			||||||
 | 
					          should(data).have.property('batch', '');
 | 
				
			||||||
 | 
					          should(data.material_id.toString()).be.eql('100000000000000000000004');
 | 
				
			||||||
 | 
					          should(data.user_id.toString()).be.eql('000000000000000000000002');
 | 
				
			||||||
 | 
					          should(data).have.property('status', -1);
 | 
				
			||||||
 | 
					          should(data).have.property('note_id', null);
 | 
				
			||||||
          done();
 | 
					          done();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    it('deletes the notes of the sample', done => {
 | 
					    it('keeps the notes of the sample', done => {
 | 
				
			||||||
      TestHelper.request(server, done, {
 | 
					      TestHelper.request(server, done, {
 | 
				
			||||||
        method: 'delete',
 | 
					        method: 'delete',
 | 
				
			||||||
        url: '/sample/400000000000000000000002',
 | 
					        url: '/sample/400000000000000000000002',
 | 
				
			||||||
@@ -342,7 +383,9 @@ describe('/sample', () => {
 | 
				
			|||||||
        should(res.body).be.eql({status: 'OK'});
 | 
					        should(res.body).be.eql({status: 'OK'});
 | 
				
			||||||
        NoteModel.findById('500000000000000000000001').lean().exec((err, data) => {
 | 
					        NoteModel.findById('500000000000000000000001').lean().exec((err, data) => {
 | 
				
			||||||
          if (err) return done(err);
 | 
					          if (err) return done(err);
 | 
				
			||||||
          should(data).be.null();
 | 
					          should(data).have.only.keys('_id', 'comment', 'sample_references', '__v');
 | 
				
			||||||
 | 
					          should(data).have.property('comment', 'Stoff gesperrt');
 | 
				
			||||||
 | 
					          should(data).have.property('sample_references').with.lengthOf(0);
 | 
				
			||||||
          done();
 | 
					          done();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
@@ -367,7 +410,7 @@ describe('/sample', () => {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    it('resets references to this sample', done => {
 | 
					    it('keeps references to this sample', done => {
 | 
				
			||||||
      TestHelper.request(server, done, {
 | 
					      TestHelper.request(server, done, {
 | 
				
			||||||
        method: 'delete',
 | 
					        method: 'delete',
 | 
				
			||||||
        url: '/sample/400000000000000000000003',
 | 
					        url: '/sample/400000000000000000000003',
 | 
				
			||||||
@@ -377,10 +420,12 @@ describe('/sample', () => {
 | 
				
			|||||||
        if (err) return done(err);
 | 
					        if (err) return done(err);
 | 
				
			||||||
        should(res.body).be.eql({status: 'OK'});
 | 
					        should(res.body).be.eql({status: 'OK'});
 | 
				
			||||||
        setTimeout(() => {  // background action takes some time before we can check
 | 
					        setTimeout(() => {  // background action takes some time before we can check
 | 
				
			||||||
          NoteModel.findById('500000000000000000000003').lean().exec((err, data) => {
 | 
					          NoteModel.findById('500000000000000000000003').lean().exec((err, data: any) => {
 | 
				
			||||||
            if (err) return done(err);
 | 
					            if (err) return done(err);
 | 
				
			||||||
            console.log(data);
 | 
					            console.log(data);
 | 
				
			||||||
            should(data).have.property('sample_references').with.lengthOf(0);
 | 
					            should(data).have.property('sample_references').with.lengthOf(1);
 | 
				
			||||||
 | 
					            should(data.sample_references[0].id.toString()).be.eql('400000000000000000000003');
 | 
				
			||||||
 | 
					            should(data.sample_references[0]).have.property('relation', 'part to sample');
 | 
				
			||||||
            done();
 | 
					            done();
 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
        }, 100);
 | 
					        }, 100);
 | 
				
			||||||
@@ -398,7 +443,7 @@ describe('/sample', () => {
 | 
				
			|||||||
        should(res.body).be.eql({status: 'OK'});
 | 
					        should(res.body).be.eql({status: 'OK'});
 | 
				
			||||||
        SampleModel.findById('400000000000000000000001').lean().exec((err, data) => {
 | 
					        SampleModel.findById('400000000000000000000001').lean().exec((err, data) => {
 | 
				
			||||||
          if (err) return done(err);
 | 
					          if (err) return done(err);
 | 
				
			||||||
          should(data).be.null();
 | 
					          should(data).have.property('status', -1);
 | 
				
			||||||
          done();
 | 
					          done();
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
@@ -486,7 +531,7 @@ describe('/sample', () => {
 | 
				
			|||||||
        SampleModel.find({number: 'Rng172'}).lean().exec((err, data: any) => {
 | 
					        SampleModel.find({number: 'Rng172'}).lean().exec((err, data: any) => {
 | 
				
			||||||
          if (err) return done (err);
 | 
					          if (err) return done (err);
 | 
				
			||||||
          should(data).have.lengthOf(1);
 | 
					          should(data).have.lengthOf(1);
 | 
				
			||||||
          should(data[0]).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'material_id', 'note_id', 'user_id', '__v');
 | 
					          should(data[0]).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'material_id', 'note_id', 'user_id', 'status', '__v');
 | 
				
			||||||
          should(data[0]).have.property('_id');
 | 
					          should(data[0]).have.property('_id');
 | 
				
			||||||
          should(data[0]).have.property('number', 'Rng172');
 | 
					          should(data[0]).have.property('number', 'Rng172');
 | 
				
			||||||
          should(data[0]).have.property('color', 'black');
 | 
					          should(data[0]).have.property('color', 'black');
 | 
				
			||||||
@@ -494,6 +539,7 @@ describe('/sample', () => {
 | 
				
			|||||||
          should(data[0]).have.property('batch', '1560237365');
 | 
					          should(data[0]).have.property('batch', '1560237365');
 | 
				
			||||||
          should(data[0].material_id.toString()).be.eql('100000000000000000000001');
 | 
					          should(data[0].material_id.toString()).be.eql('100000000000000000000001');
 | 
				
			||||||
          should(data[0].user_id.toString()).be.eql('000000000000000000000002');
 | 
					          should(data[0].user_id.toString()).be.eql('000000000000000000000002');
 | 
				
			||||||
 | 
					          should(data[0]).have.property('status', 0);
 | 
				
			||||||
          should(data[0]).have.property('note_id');
 | 
					          should(data[0]).have.property('note_id');
 | 
				
			||||||
          NoteModel.findById(data[0].note_id).lean().exec((err, data: any) => {
 | 
					          NoteModel.findById(data[0].note_id).lean().exec((err, data: any) => {
 | 
				
			||||||
            if (err) return done (err);
 | 
					            if (err) return done (err);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,7 +16,7 @@ const router = express.Router();
 | 
				
			|||||||
router.get('/samples', (req, res, next) => {
 | 
					router.get('/samples', (req, res, next) => {
 | 
				
			||||||
  if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'all')) return;
 | 
					  if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'all')) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SampleModel.find({}).lean().exec((err, data) => {
 | 
					  SampleModel.find({status: 10}).lean().exec((err, data) => {
 | 
				
			||||||
    if (err) return next(err);
 | 
					    if (err) return next(err);
 | 
				
			||||||
    res.json(_.compact(data.map(e => SampleValidate.output(e))));  // validate all and filter null values from validation errors
 | 
					    res.json(_.compact(data.map(e => SampleValidate.output(e))));  // validate all and filter null values from validation errors
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
@@ -66,6 +66,11 @@ router.put('/sample/' + IdValidate.parameter(), (req, res, next) => {
 | 
				
			|||||||
      delete sample.notes;
 | 
					      delete sample.notes;
 | 
				
			||||||
      sample.note_id = data._id;
 | 
					      sample.note_id = data._id;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // check for changes
 | 
				
			||||||
 | 
					    if (!_.isEqual(_.pick(IdValidate.stringify(sampleData), _.keys(sample)), _.omit(sample, ['notes']))) {
 | 
				
			||||||
 | 
					      sample.status = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    SampleModel.findByIdAndUpdate(req.params.id, sample, {new: true}).lean().exec((err, data) => {
 | 
					    SampleModel.findByIdAndUpdate(req.params.id, sample, {new: true}).lean().exec((err, data) => {
 | 
				
			||||||
      if (err) return next(err);
 | 
					      if (err) return next(err);
 | 
				
			||||||
      res.json(SampleValidate.output(data));
 | 
					      res.json(SampleValidate.output(data));
 | 
				
			||||||
@@ -85,22 +90,15 @@ router.delete('/sample/' + IdValidate.parameter(), (req, res, next) => {
 | 
				
			|||||||
    // only maintain and admin are allowed to edit other user's data
 | 
					    // only maintain and admin are allowed to edit other user's data
 | 
				
			||||||
    if (sampleData.user_id.toString() !== req.authDetails.id && !req.auth(res, ['maintain', 'admin'], 'basic')) return;
 | 
					    if (sampleData.user_id.toString() !== req.authDetails.id && !req.auth(res, ['maintain', 'admin'], 'basic')) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SampleModel.findByIdAndDelete(req.params.id).lean().exec(err => {  // delete sample
 | 
					    SampleModel.findByIdAndUpdate(req.params.id, {status: -1}).lean().exec(err => {  // set sample status
 | 
				
			||||||
      if (err) return next(err);
 | 
					      if (err) return next(err);
 | 
				
			||||||
      if (sampleData.note_id !== null) {
 | 
					      if (sampleData.note_id !== null) {
 | 
				
			||||||
        NoteModel.findByIdAndDelete(sampleData.note_id).lean().exec((err, data: any) => {  // delete notes
 | 
					        NoteModel.findById(sampleData.note_id).lean().exec((err, data: any) => {  // find notes to update note_fields
 | 
				
			||||||
          if (err) return next(err);
 | 
					          if (err) return next(err);
 | 
				
			||||||
          console.log(data);
 | 
					 | 
				
			||||||
          if (data.hasOwnProperty('custom_fields')) {  // update note_fields
 | 
					          if (data.hasOwnProperty('custom_fields')) {  // update note_fields
 | 
				
			||||||
            customFieldsChange(Object.keys(data.custom_fields), -1);
 | 
					            customFieldsChange(Object.keys(data.custom_fields), -1);
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          res.json({status: 'OK'});
 | 
					          res.json({status: 'OK'});
 | 
				
			||||||
          NoteModel.updateMany({'sample_references.id': req.params.id}, {$unset: {'sample_references.$': null}}).lean().exec(err => {  // remove sample_references
 | 
					 | 
				
			||||||
            if (err) console.error(err);
 | 
					 | 
				
			||||||
            NoteModel.collection.updateMany({sample_references: null}, {$pull: {sample_references: null}}, err => {  // only works with native MongoDB driver somehow
 | 
					 | 
				
			||||||
              if (err) console.error(err);
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
          });
 | 
					 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      else {
 | 
					      else {
 | 
				
			||||||
@@ -124,6 +122,7 @@ router.post('/sample/new', async (req, res, next) => {
 | 
				
			|||||||
    customFieldsChange(Object.keys(sample.notes.custom_fields), 1);
 | 
					    customFieldsChange(Object.keys(sample.notes.custom_fields), 1);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  sample.status = 0;
 | 
				
			||||||
  new NoteModel(sample.notes).save((err, data) => {
 | 
					  new NoteModel(sample.notes).save((err, data) => {
 | 
				
			||||||
    if (err) return next(err);
 | 
					    if (err) return next(err);
 | 
				
			||||||
    delete sample.notes;
 | 
					    delete sample.notes;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,6 +6,7 @@ import TemplateTreatmentModel from '../models/treatment_template';
 | 
				
			|||||||
import TemplateMeasurementModel from '../models/measurement_template';
 | 
					import TemplateMeasurementModel from '../models/measurement_template';
 | 
				
			||||||
import res400 from './validate/res400';
 | 
					import res400 from './validate/res400';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: remove f() for await
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const router = express.Router();
 | 
					const router = express.Router();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,10 +7,10 @@
 | 
				
			|||||||
        "type": "granulate",
 | 
					        "type": "granulate",
 | 
				
			||||||
        "color": "black",
 | 
					        "color": "black",
 | 
				
			||||||
        "batch": "",
 | 
					        "batch": "",
 | 
				
			||||||
        "validated": true,
 | 
					 | 
				
			||||||
        "material_id": {"$oid":"100000000000000000000004"},
 | 
					        "material_id": {"$oid":"100000000000000000000004"},
 | 
				
			||||||
        "note_id": null,
 | 
					        "note_id": null,
 | 
				
			||||||
        "user_id": {"$oid":"000000000000000000000002"},
 | 
					        "user_id": {"$oid":"000000000000000000000002"},
 | 
				
			||||||
 | 
					        "status": 10,
 | 
				
			||||||
        "__v": 0
 | 
					        "__v": 0
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
@@ -19,10 +19,10 @@
 | 
				
			|||||||
        "type": "granulate",
 | 
					        "type": "granulate",
 | 
				
			||||||
        "color": "natural",
 | 
					        "color": "natural",
 | 
				
			||||||
        "batch": "1560237365",
 | 
					        "batch": "1560237365",
 | 
				
			||||||
        "validated": true,
 | 
					 | 
				
			||||||
        "material_id": {"$oid":"100000000000000000000001"},
 | 
					        "material_id": {"$oid":"100000000000000000000001"},
 | 
				
			||||||
        "note_id": {"$oid":"500000000000000000000001"},
 | 
					        "note_id": {"$oid":"500000000000000000000001"},
 | 
				
			||||||
        "user_id": {"$oid":"000000000000000000000002"},
 | 
					        "user_id": {"$oid":"000000000000000000000002"},
 | 
				
			||||||
 | 
					        "status": 10,
 | 
				
			||||||
        "__v": 0
 | 
					        "__v": 0
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
@@ -31,10 +31,10 @@
 | 
				
			|||||||
        "type": "part",
 | 
					        "type": "part",
 | 
				
			||||||
        "color": "black",
 | 
					        "color": "black",
 | 
				
			||||||
        "batch": "1704-005",
 | 
					        "batch": "1704-005",
 | 
				
			||||||
        "validated": false,
 | 
					 | 
				
			||||||
        "material_id": {"$oid":"100000000000000000000005"},
 | 
					        "material_id": {"$oid":"100000000000000000000005"},
 | 
				
			||||||
        "note_id": {"$oid":"500000000000000000000002"},
 | 
					        "note_id": {"$oid":"500000000000000000000002"},
 | 
				
			||||||
        "user_id": {"$oid":"000000000000000000000003"},
 | 
					        "user_id": {"$oid":"000000000000000000000003"},
 | 
				
			||||||
 | 
					        "status": 0,
 | 
				
			||||||
        "__v": 0
 | 
					        "__v": 0
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
@@ -43,10 +43,22 @@
 | 
				
			|||||||
        "type": "granulate",
 | 
					        "type": "granulate",
 | 
				
			||||||
        "color": "black",
 | 
					        "color": "black",
 | 
				
			||||||
        "batch": "1653000308",
 | 
					        "batch": "1653000308",
 | 
				
			||||||
        "validated": false,
 | 
					 | 
				
			||||||
        "material_id": {"$oid":"100000000000000000000005"},
 | 
					        "material_id": {"$oid":"100000000000000000000005"},
 | 
				
			||||||
        "note_id": {"$oid":"500000000000000000000003"},
 | 
					        "note_id": {"$oid":"500000000000000000000003"},
 | 
				
			||||||
        "user_id": {"$oid":"000000000000000000000003"},
 | 
					        "user_id": {"$oid":"000000000000000000000003"},
 | 
				
			||||||
 | 
					        "status": 0,
 | 
				
			||||||
 | 
					        "__v": 0
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "_id": {"$oid":"400000000000000000000005"},
 | 
				
			||||||
 | 
					        "number": "33",
 | 
				
			||||||
 | 
					        "type": "granulate",
 | 
				
			||||||
 | 
					        "color": "black",
 | 
				
			||||||
 | 
					        "batch": "1653000308",
 | 
				
			||||||
 | 
					        "material_id": {"$oid":"100000000000000000000005"},
 | 
				
			||||||
 | 
					        "note_id": {"$oid":"500000000000000000000003"},
 | 
				
			||||||
 | 
					        "user_id": {"$oid":"000000000000000000000003"},
 | 
				
			||||||
 | 
					        "status": -1,
 | 
				
			||||||
        "__v": 0
 | 
					        "__v": 0
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
@@ -116,6 +128,7 @@
 | 
				
			|||||||
            "number": 5514263422
 | 
					            "number": 5514263422
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
 | 
					        "status": 10,
 | 
				
			||||||
        "__v": 0
 | 
					        "__v": 0
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
@@ -136,6 +149,7 @@
 | 
				
			|||||||
            "number": 5514612901
 | 
					            "number": 5514612901
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
 | 
					        "status": 10,
 | 
				
			||||||
        "__v": 0
 | 
					        "__v": 0
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
@@ -148,6 +162,7 @@
 | 
				
			|||||||
        "carbon_fiber": 0,
 | 
					        "carbon_fiber": 0,
 | 
				
			||||||
        "numbers": [
 | 
					        "numbers": [
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
 | 
					        "status": 10,
 | 
				
			||||||
        "__v": 0
 | 
					        "__v": 0
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
@@ -164,6 +179,7 @@
 | 
				
			|||||||
            "number": 5513933405
 | 
					            "number": 5513933405
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
 | 
					        "status": 10,
 | 
				
			||||||
        "__v": 0
 | 
					        "__v": 0
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
@@ -180,6 +196,24 @@
 | 
				
			|||||||
            "number": 5514262406
 | 
					            "number": 5514262406
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
 | 
					        "status": 10,
 | 
				
			||||||
 | 
					        "__v": 0
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "_id": {"$oid":"100000000000000000000006"},
 | 
				
			||||||
 | 
					        "name": "PK-HM natural (4773)",
 | 
				
			||||||
 | 
					        "supplier": "Akro-Plastic",
 | 
				
			||||||
 | 
					        "group": "PK",
 | 
				
			||||||
 | 
					        "mineral": 0,
 | 
				
			||||||
 | 
					        "glass_fiber": 0,
 | 
				
			||||||
 | 
					        "carbon_fiber": 0,
 | 
				
			||||||
 | 
					        "numbers": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "color": "natural",
 | 
				
			||||||
 | 
					            "number": 10000000
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "status": -1,
 | 
				
			||||||
        "__v": 0
 | 
					        "__v": 0
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
@@ -193,6 +227,7 @@
 | 
				
			|||||||
          "weeks": 3
 | 
					          "weeks": 3
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "treatment_template": {"$oid":"200000000000000000000001"},
 | 
					        "treatment_template": {"$oid":"200000000000000000000001"},
 | 
				
			||||||
 | 
					        "status": 10,
 | 
				
			||||||
        "__v": 0
 | 
					        "__v": 0
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
@@ -204,6 +239,7 @@
 | 
				
			|||||||
          "weeks": 3
 | 
					          "weeks": 3
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "treatment_template": {"$oid":"200000000000000000000001"},
 | 
					        "treatment_template": {"$oid":"200000000000000000000001"},
 | 
				
			||||||
 | 
					        "status": 10,
 | 
				
			||||||
        "__v": 0
 | 
					        "__v": 0
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
@@ -215,6 +251,7 @@
 | 
				
			|||||||
          "weeks": 3
 | 
					          "weeks": 3
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "treatment_template": {"$oid":"200000000000000000000001"},
 | 
					        "treatment_template": {"$oid":"200000000000000000000001"},
 | 
				
			||||||
 | 
					        "status": 10,
 | 
				
			||||||
        "__v": 0
 | 
					        "__v": 0
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
@@ -226,6 +263,7 @@
 | 
				
			|||||||
          "weeks": 5
 | 
					          "weeks": 5
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "treatment_template": {"$oid":"200000000000000000000001"},
 | 
					        "treatment_template": {"$oid":"200000000000000000000001"},
 | 
				
			||||||
 | 
					        "status": 10,
 | 
				
			||||||
        "__v": 0
 | 
					        "__v": 0
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user