Archived
2

separated groups and suppliers for material PUT and POST

This commit is contained in:
VLE2FE 2020-05-29 10:40:17 +02:00
parent 14ba1655ba
commit 48b1a9da6e
4 changed files with 96 additions and 44 deletions

View File

@ -1,10 +1,12 @@
import should from 'should/as-function'; import should from 'should/as-function';
import _ from 'lodash'; import _ from 'lodash';
import MaterialModel from '../models/material'; import MaterialModel from '../models/material';
import MaterialGroupModel from '../models/material_groups';
import MaterialSupplierModel from '../models/material_suppliers';
import TestHelper from "../test/helper"; import TestHelper from "../test/helper";
import globals from '../globals'; import globals from '../globals';
// TODO: separate supplier/ material name into own collections
describe('/material', () => { describe('/material', () => {
let server; let server;
@ -267,10 +269,20 @@ describe('/material', () => {
MaterialModel.findById('100000000000000000000001').lean().exec((err, data) => { MaterialModel.findById('100000000000000000000001').lean().exec((err, data) => {
if (err) return done(err); if (err) return done(err);
should(data).have.property('status',globals.status.validated); should(data).have.property('status',globals.status.validated);
MaterialGroupModel.find({name: 'PA46'}).lean().exec((err, data) => {
if (err) return done(err);
should(data).have.lengthOf(1);
should(data[0]._id.toString()).be.eql('900000000000000000000001');
MaterialSupplierModel.find({name: 'DSM'}).lean().exec((err, data) => {
if (err) return done(err);
should(data).have.lengthOf(1);
should(data[0]._id.toString()).be.eql('110000000000000000000001');
done(); done();
}); });
}); });
}); });
});
});
it('keeps only one unchanged property', done => { it('keeps only one unchanged property', done => {
TestHelper.request(server, done, { TestHelper.request(server, done, {
method: 'put', method: 'put',
@ -302,12 +314,24 @@ describe('/material', () => {
MaterialModel.findById('100000000000000000000001').lean().exec((err, data:any) => { MaterialModel.findById('100000000000000000000001').lean().exec((err, data:any) => {
if (err) return done(err); if (err) return done(err);
data._id = data._id.toString(); data._id = data._id.toString();
data.group_id = data.group_id.toString();
data.supplier_id = data.supplier_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'}], status: 0, __v: 0}); should(data).be.eql({_id: '100000000000000000000001', name: 'UltramidTKR4355G7_2', supplier_id: '110000000000000000000002', group_id: '900000000000000000000002', mineral: '0', glass_fiber: '35', carbon_fiber: '0', numbers: [{color: 'black', number: '5514212901'}, {color: 'signalviolet', number: '5514612901'}], status: 0, __v: 0});
MaterialGroupModel.find({name: 'PA6/6T'}).lean().exec((err, data) => {
if (err) return done(err);
should(data).have.lengthOf(1);
should(data[0]._id.toString()).be.eql('900000000000000000000002');
MaterialSupplierModel.find({name: 'BASF'}).lean().exec((err, data) => {
if (err) return done(err);
should(data).have.lengthOf(1);
should(data[0]._id.toString()).be.eql('110000000000000000000002');
done(); done();
}); });
}); });
}); });
});
});
it('accepts a color without number', done => { it('accepts a color without number', done => {
TestHelper.request(server, done, { TestHelper.request(server, done, {
method: 'put', method: 'put',
@ -436,8 +460,10 @@ describe('/material', () => {
MaterialModel.findById('100000000000000000000002').lean().exec((err, data: any) => { MaterialModel.findById('100000000000000000000002').lean().exec((err, data: any) => {
if (err) return done(err); if (err) return done(err);
data._id = data._id.toString(); data._id = data._id.toString();
data.group_id = data.group_id.toString();
data.supplier_id = data.supplier_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: '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} should(data).be.eql({_id: '100000000000000000000002', name: 'Ultramid T KR 4355 G7', supplier_id: '110000000000000000000002', group_id: '900000000000000000000002', mineral: 0, glass_fiber: 35, carbon_fiber: 0, numbers: [{color: 'black', number: '5514212901'}, {color: 'signalviolet', number: '5514612901'}], status: -1, __v: 0}
); );
done(); done();
}); });
@ -583,23 +609,28 @@ describe('/material', () => {
req: {name: 'Crastin CE 2510', supplier: 'Du Pont', group: 'PBT', mineral: 0, glass_fiber: 30, carbon_fiber: 0, numbers: []} req: {name: 'Crastin CE 2510', supplier: 'Du Pont', group: 'PBT', mineral: 0, glass_fiber: 30, carbon_fiber: 0, numbers: []}
}).end(err => { }).end(err => {
if (err) return done (err); if (err) return done (err);
MaterialModel.find({name: 'Crastin CE 2510'}).lean().exec((err, data: any) => { MaterialModel.find({name: 'Crastin CE 2510'}).lean().exec((err, materialData: any) => {
if (err) return done (err); if (err) return done (err);
should(data).have.lengthOf(1); should(materialData).have.lengthOf(1);
should(data[0]).have.only.keys('_id', 'name', 'supplier', 'group', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers', 'status', '__v'); should(materialData[0]).have.only.keys('_id', 'name', 'supplier_id', 'group_id', 'mineral', 'glass_fiber', 'carbon_fiber', 'numbers', 'status', '__v');
should(data[0]).have.property('_id'); should(materialData[0]).have.property('name', 'Crastin CE 2510');
should(data[0]).have.property('name', 'Crastin CE 2510'); should(materialData[0]).have.property('mineral', '0');
should(data[0]).have.property('supplier', 'Du Pont'); should(materialData[0]).have.property('glass_fiber', '30');
should(data[0]).have.property('group', 'PBT'); should(materialData[0]).have.property('carbon_fiber', '0');
should(data[0]).have.property('mineral', '0'); should(materialData[0]).have.property('status',globals.status.new);
should(data[0]).have.property('glass_fiber', '30'); should(materialData[0].numbers).have.lengthOf(0);
should(data[0]).have.property('carbon_fiber', '0'); MaterialGroupModel.findById(materialData[0].group_id).lean().exec((err, data) => {
should(data[0]).have.property('status',globals.status.new); if (err) return done(err);
should(data[0].numbers).have.lengthOf(0); should(data).have.property('name', 'PBT')
MaterialSupplierModel.findById(materialData[0].supplier_id).lean().exec((err, data) => {
if (err) return done(err);
should(data).have.property('name', 'Du Pont');
done(); done();
}); });
}); });
}); });
});
});
it('accepts a color without number', done => { it('accepts a color without number', done => {
TestHelper.request(server, done, { TestHelper.request(server, done, {
method: 'post', method: 'post',
@ -625,11 +656,9 @@ 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', 'status', '__v'); should(data[0]).have.only.keys('_id', 'name', 'supplier_id', 'group_id', '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('group', 'PBT');
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');

View File

@ -4,8 +4,8 @@ import _ from 'lodash';
import MaterialValidate from './validate/material'; import MaterialValidate from './validate/material';
import MaterialModel from '../models/material' import MaterialModel from '../models/material'
import SampleModel from '../models/sample'; import SampleModel from '../models/sample';
import MaterialGroupsModel from '../models/material_groups'; import MaterialGroupModel from '../models/material_groups';
import MaterialSuppliersModel from '../models/material_suppliers'; import MaterialSupplierModel from '../models/material_suppliers';
import IdValidate from './validate/id'; import IdValidate from './validate/id';
import res400 from './validate/res400'; import res400 from './validate/res400';
import mongoose from 'mongoose'; import mongoose from 'mongoose';
@ -20,11 +20,7 @@ router.get('/materials', (req, res, next) => {
MaterialModel.find({status:globals.status.validated}).populate('group_id').populate('supplier_id').lean().exec((err, data) => { MaterialModel.find({status:globals.status.validated}).populate('group_id').populate('supplier_id').lean().exec((err, data) => {
if (err) return next(err); if (err) return next(err);
console.log(data);
data.forEach((material: any) => { // map group and supplier
material.group = material.group_id.name;
material.supplier = material.supplier_id.name;
});
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
}); });
}); });
@ -34,10 +30,7 @@ router.get('/materials/:state(new|deleted)', (req, res, next) => {
MaterialModel.find({status: globals.status[req.params.state]}).populate('group_id').populate('supplier_id').lean().exec((err, data) => { MaterialModel.find({status: globals.status[req.params.state]}).populate('group_id').populate('supplier_id').lean().exec((err, data) => {
if (err) return next(err); if (err) return next(err);
data.forEach((material: any) => { // map group and supplier
material.group = material.group_id.name;
material.supplier = material.supplier_id.name;
});
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
}); });
}); });
@ -52,8 +45,6 @@ router.get('/material/' + IdValidate.parameter(), (req, res, next) => {
return res.status(404).json({status: 'Not found'}); return res.status(404).json({status: 'Not found'});
} }
data.group = data.group_id.name;
data.supplier = data.supplier_id.name;
if (data.status === globals.status.deleted && !req.auth(res, ['maintain', 'admin'], 'all')) return; // deleted materials only available for maintain/admin if (data.status === globals.status.deleted && !req.auth(res, ['maintain', 'admin'], 'all')) return; // deleted materials only available for maintain/admin
res.json(MaterialValidate.output(data)); res.json(MaterialValidate.output(data));
}); });
@ -62,7 +53,7 @@ router.get('/material/' + IdValidate.parameter(), (req, res, next) => {
router.put('/material/' + IdValidate.parameter(), (req, res, next) => { router.put('/material/' + IdValidate.parameter(), (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: material} = MaterialValidate.input(req.body, 'change'); let {error, value: material} = MaterialValidate.input(req.body, 'change');
if (error) return res400(error, res); if (error) return res400(error, res);
MaterialModel.findById(req.params.id).lean().exec(async (err, materialData: any) => { MaterialModel.findById(req.params.id).lean().exec(async (err, materialData: any) => {
@ -75,13 +66,21 @@ router.put('/material/' + IdValidate.parameter(), (req, res, next) => {
if (material.hasOwnProperty('name') && material.name !== materialData.name) { if (material.hasOwnProperty('name') && material.name !== materialData.name) {
if (!await nameCheck(material, res, next)) return; if (!await nameCheck(material, res, next)) return;
} }
if (material.hasOwnProperty('group')) {
material = await groupResolve(material, next);
if (!material) return;
}
if (material.hasOwnProperty('supplier')) {
material = await supplierResolve(material, next);
if (!material) return;
}
// check for changes // check for changes
if (!_.isEqual(_.pick(IdValidate.stringify(materialData), _.keys(material)), material)) { if (!_.isEqual(_.pick(IdValidate.stringify(materialData), _.keys(material)), IdValidate.stringify(material))) {
material.status = globals.status.new; // set status to new material.status = globals.status.new; // set status to new
} }
await MaterialModel.findByIdAndUpdate(req.params.id, material, {new: true}).lean().exec((err, data) => { await MaterialModel.findByIdAndUpdate(req.params.id, material, {new: true}).populate('group_id').populate('supplier_id').lean().exec((err, data) => {
if (err) return next(err); if (err) return next(err);
res.json(MaterialValidate.output(data)); res.json(MaterialValidate.output(data));
}); });
@ -97,7 +96,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.findByIdAndUpdate(req.params.id, {status:globals.status.deleted}).lean().exec((err, data) => { MaterialModel.findByIdAndUpdate(req.params.id, {status:globals.status.deleted}).populate('group_id').populate('supplier_id').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'});
@ -122,17 +121,24 @@ router.put('/material/restore/' + IdValidate.parameter(), (req, res, next) => {
}); });
}); });
router.post('/material/new', async (req, res, next) => { // TODO: check supplier and group, also for PUT and DELETE 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;
const {error, value: material} = MaterialValidate.input(req.body, 'new'); let {error, value: material} = MaterialValidate.input(req.body, 'new');
if (error) return res400(error, res); if (error) return res400(error, res);
if (!await nameCheck(material, res, next)) return; if (!await nameCheck(material, res, next)) return;
material = await groupResolve(material, next);
if (!material) return;
material = await supplierResolve(material, next);
if (!material) return;
material.status = globals.status.new; // set status to new material.status = globals.status.new; // set status to new
await new MaterialModel(material).save((err, data) => { await new MaterialModel(material).save(async (err, data) => {
if (err) return next(err); if (err) return next(err);
await data.populate('group_id').populate('supplier_id').execPopulate().catch(err => next(err));
if (data instanceof Error) return;
res.json(MaterialValidate.output(data.toObject())); res.json(MaterialValidate.output(data.toObject()));
}); });
}); });
@ -140,7 +146,7 @@ router.post('/material/new', async (req, res, next) => { // TODO: check supplie
router.get('/material/groups', (req, res, next) => { router.get('/material/groups', (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;
MaterialGroupsModel.find().lean().exec((err, data: any) => { MaterialGroupModel.find().lean().exec((err, data: any) => {
if (err) return next(err); if (err) return next(err);
res.json(_.compact(data.map(e => MaterialValidate.outputGroups(e.name)))); // validate all and filter null values from validation errors res.json(_.compact(data.map(e => MaterialValidate.outputGroups(e.name)))); // validate all and filter null values from validation errors
@ -150,7 +156,7 @@ router.get('/material/groups', (req, res, next) => {
router.get('/material/suppliers', (req, res, next) => { router.get('/material/suppliers', (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;
MaterialSuppliersModel.find().lean().exec((err, data: any) => { MaterialSupplierModel.find().lean().exec((err, data: any) => {
if (err) return next(err); if (err) return next(err);
res.json(_.compact(data.map(e => MaterialValidate.outputSuppliers(e.name)))); // validate all and filter null values from validation errors res.json(_.compact(data.map(e => MaterialValidate.outputSuppliers(e.name)))); // validate all and filter null values from validation errors
@ -170,3 +176,19 @@ async function nameCheck (material, res, next) { // check if name was already t
} }
return true; return true;
} }
async function groupResolve (material, next) {
const groupData = await MaterialGroupModel.findOneAndUpdate({name: material.group}, {name: material.group}, {upsert: true, new: true}).lean().exec().catch(err => next(err)) as any;
if (groupData instanceof Error) return false;
material.group_id = groupData._id;
delete material.group;
return material;
}
async function supplierResolve (material, next) {
const supplierData = await MaterialSupplierModel.findOneAndUpdate({name: material.supplier}, {name: material.supplier}, {upsert: true, new: true}).lean().exec().catch(err => next(err)) as any;
if (supplierData instanceof Error) return false;
material.supplier_id = supplierData._id;
delete material.supplier;
return material;
}

View File

@ -5,7 +5,6 @@ import TemplateMeasurementModel from '../models/measurement_template';
import TestHelper from "../test/helper"; import TestHelper from "../test/helper";
// TODO: do not allow usage of old templates for new samples // TODO: do not allow usage of old templates for new samples
// TODO: remove number_prefix
// TODO: template parameters are not allowed to be condition_template // TODO: template parameters are not allowed to be condition_template
describe('/template', () => { describe('/template', () => {

View File

@ -70,6 +70,8 @@ export default class MaterialValidate { // validate input for material
static output (data) { // validate output and strip unwanted properties, returns null if not valid static output (data) { // validate output and strip unwanted properties, returns null if not valid
data = IdValidate.stringify(data); data = IdValidate.stringify(data);
data.group = data.group_id.name;
data.supplier = data.supplier_id.name;
const {value, error} = Joi.object({ const {value, error} = Joi.object({
_id: IdValidate.get(), _id: IdValidate.get(),
name: this.material.name, name: this.material.name,