Archived
2

separated groups and suppliers for material GET

This commit is contained in:
VLE2FE 2020-05-28 17:05:23 +02:00
parent c7d25bd7cb
commit 14ba1655ba
13 changed files with 291 additions and 33 deletions

View File

@ -19,9 +19,9 @@
500:
$ref: 'api.yaml#/components/responses/500'
/materials/{group}:
/materials/{state}:
parameters:
- $ref: 'api.yaml#/components/parameters/Group'
- $ref: 'api.yaml#/components/parameters/State'
get:
summary: lists all new/deleted materials
description: 'Auth: basic, levels: maintain, admin'
@ -168,5 +168,51 @@
$ref: 'api.yaml#/components/responses/401'
403:
$ref: 'api.yaml#/components/responses/403'
500:
$ref: 'api.yaml#/components/responses/500'
/material/groups:
get:
summary: list all existing material groups
description: 'Auth: all, levels: read, write, maintain, dev, admin'
tags:
- /material
responses:
200:
description: all material groups
content:
application/json:
schema:
type: array
items:
type: string
example: PA66
401:
$ref: 'api.yaml#/components/responses/401'
403:
$ref: 'api.yaml#/components/responses/403'
500:
$ref: 'api.yaml#/components/responses/500'
/material/suppliers:
get:
summary: list all existing material suppliers
description: 'Auth: all, levels: read, write, maintain, dev, admin'
tags:
- /material
responses:
200:
description: all material suppliers
content:
application/json:
schema:
type: array
items:
type: string
example: BASF
401:
$ref: 'api.yaml#/components/responses/401'
403:
$ref: 'api.yaml#/components/responses/403'
500:
$ref: 'api.yaml#/components/responses/500'

View File

@ -14,7 +14,7 @@ Name:
schema:
type: string
Group:
State:
name: group
description: 'possible values: new, deleted'
in: path

View File

@ -19,9 +19,9 @@
500:
$ref: 'api.yaml#/components/responses/500'
/samples/{group}:
/samples/{state}:
parameters:
- $ref: 'api.yaml#/components/parameters/Group'
- $ref: 'api.yaml#/components/parameters/State'
get:
summary: all new/deleted samples in overview
description: 'Auth: basic, levels: maintain, admin'

View File

@ -1,9 +1,11 @@
import mongoose from 'mongoose';
import MaterialSupplierModel from '../models/material_suppliers';
import MaterialGroupsModel from '../models/material_groups';
const MaterialSchema = new mongoose.Schema({
name: {type: String, index: {unique: true}},
supplier: String,
group: String,
supplier_id: {type: mongoose.Schema.Types.ObjectId, ref: MaterialSupplierModel},
group_id: {type: mongoose.Schema.Types.ObjectId, ref: MaterialGroupsModel},
mineral: String,
glass_fiber: String,
carbon_fiber: String,

View File

@ -0,0 +1,7 @@
import mongoose from 'mongoose';
const MaterialGroupsSchema = new mongoose.Schema({
name: {type: String, index: {unique: true}}
});
export default mongoose.model('material_groups', MaterialGroupsSchema);

View File

@ -0,0 +1,7 @@
import mongoose from 'mongoose';
const MaterialSuppliersSchema = new mongoose.Schema({
name: {type: String, index: {unique: true}}
});
export default mongoose.model('material_suppliers', MaterialSuppliersSchema);

View File

@ -4,7 +4,6 @@ import MaterialModel from '../models/material';
import TestHelper from "../test/helper";
import globals from '../globals';
// TODO: color name must be unique to get color number
// TODO: separate supplier/ material name into own collections
describe('/material', () => {
@ -80,7 +79,7 @@ describe('/material', () => {
});
});
describe('GET /materials/{group}', () => {
describe('GET /materials/{state}', () => {
it('returns all new materials', done => {
TestHelper.request(server, done, {
method: 'get',
@ -767,4 +766,92 @@ describe('/material', () => {
});
});
});
describe('GET /material/groups', () => {
it('returns all groups', done => {
TestHelper.request(server, done, {
method: 'get',
url: '/material/groups',
auth: {basic: 'janedoe'},
httpStatus: 200
}).end((err, res) => {
if (err) return done(err);
const json = require('../test/db.json');
should(res.body).have.lengthOf(json.collections.material_groups.length);
should(res.body[0]).be.eql(json.collections.material_groups[0].name);
should(res.body).matchEach(group => {
should(group).be.type('string');
});
done();
});
});
it('works with an API key', done => {
TestHelper.request(server, done, {
method: 'get',
url: '/material/groups',
auth: {basic: 'janedoe'},
httpStatus: 200
}).end((err, res) => {
if (err) return done(err);
const json = require('../test/db.json');
should(res.body).have.lengthOf(json.collections.material_groups.length);
should(res.body[0]).be.eql(json.collections.material_groups[0].name);
should(res.body).matchEach(group => {
should(group).be.type('string');
});
done();
});
});
it('rejects unauthorized requests', done => {
TestHelper.request(server, done, {
method: 'get',
url: '/material/groups',
httpStatus: 401
});
});
});
describe('GET /material/suppliers', () => {
it('returns all suppliers', done => {
TestHelper.request(server, done, {
method: 'get',
url: '/material/suppliers',
auth: {basic: 'janedoe'},
httpStatus: 200
}).end((err, res) => {
if (err) return done(err);
const json = require('../test/db.json');
should(res.body).have.lengthOf(json.collections.material_suppliers.length);
should(res.body[0]).be.eql(json.collections.material_suppliers[0].name);
should(res.body).matchEach(supplier => {
should(supplier).be.type('string');
});
done();
});
});
it('works with an API key', done => {
TestHelper.request(server, done, {
method: 'get',
url: '/material/suppliers',
auth: {key: 'janedoe'},
httpStatus: 200
}).end((err, res) => {
if (err) return done(err);
const json = require('../test/db.json');
should(res.body).have.lengthOf(json.collections.material_suppliers.length);
should(res.body[0]).be.eql(json.collections.material_suppliers[0].name);
should(res.body).matchEach(supplier => {
should(supplier).be.type('string');
});
done();
});
});
it('rejects unauthorized requests', done => {
TestHelper.request(server, done, {
method: 'get',
url: '/material/suppliers',
httpStatus: 401
});
});
});
});

View File

@ -4,6 +4,8 @@ import _ from 'lodash';
import MaterialValidate from './validate/material';
import MaterialModel from '../models/material'
import SampleModel from '../models/sample';
import MaterialGroupsModel from '../models/material_groups';
import MaterialSuppliersModel from '../models/material_suppliers';
import IdValidate from './validate/id';
import res400 from './validate/res400';
import mongoose from 'mongoose';
@ -16,17 +18,26 @@ const router = express.Router();
router.get('/materials', (req, res, next) => {
if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'all')) return;
MaterialModel.find({status:globals.status.validated}).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);
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
});
});
router.get('/materials/:group(new|deleted)', (req, res, next) => {
router.get('/materials/:state(new|deleted)', (req, res, next) => {
if (!req.auth(res, ['maintain', 'admin'], 'basic')) return;
MaterialModel.find({status: globals.status[req.params.group]}).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);
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
});
});
@ -34,12 +45,15 @@ router.get('/materials/:group(new|deleted)', (req, res, next) => {
router.get('/material/' + IdValidate.parameter(), (req, res, next) => {
if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'all')) return;
MaterialModel.findById(req.params.id).lean().exec((err, data: any) => {
MaterialModel.findById(req.params.id).populate('group_id').populate('supplier_id').lean().exec((err, data: any) => {
if (err) return next(err);
if (!data) {
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
res.json(MaterialValidate.output(data));
});
@ -108,7 +122,7 @@ router.put('/material/restore/' + IdValidate.parameter(), (req, res, next) => {
});
});
router.post('/material/new', async (req, res, next) => {
router.post('/material/new', async (req, res, next) => { // TODO: check supplier and group, also for PUT and DELETE
if (!req.auth(res, ['write', 'maintain', 'dev', 'admin'], 'basic')) return;
const {error, value: material} = MaterialValidate.input(req.body, 'new');
@ -123,6 +137,26 @@ router.post('/material/new', async (req, res, next) => {
});
});
router.get('/material/groups', (req, res, next) => {
if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'all')) return;
MaterialGroupsModel.find().lean().exec((err, data: any) => {
if (err) return next(err);
res.json(_.compact(data.map(e => MaterialValidate.outputGroups(e.name)))); // validate all and filter null values from validation errors
});
});
router.get('/material/suppliers', (req, res, next) => {
if (!req.auth(res, ['read', 'write', 'maintain', 'dev', 'admin'], 'all')) return;
MaterialSuppliersModel.find().lean().exec((err, data: any) => {
if (err) return next(err);
res.json(_.compact(data.map(e => MaterialValidate.outputSuppliers(e.name)))); // validate all and filter null values from validation errors
});
});
module.exports = router;

View File

@ -3,6 +3,7 @@ import MeasurementModel from '../models/measurement';
import TestHelper from "../test/helper";
import globals from '../globals';
// TODO: test unique material names and produced error code
describe('/measurement', () => {
let server;

View File

@ -84,7 +84,7 @@ describe('/sample', () => {
});
});
describe('GET /samples/{group}', () => {
describe('GET /samples/{state}', () => {
it('returns all new samples', done => {
TestHelper.request(server, done, {
method: 'get',

View File

@ -27,10 +27,10 @@ router.get('/samples', (req, res, next) => {
})
});
router.get('/samples/:group(new|deleted)', (req, res, next) => {
router.get('/samples/:state(new|deleted)', (req, res, next) => {
if (!req.auth(res, ['maintain', 'admin'], 'basic')) return;
SampleModel.find({status: globals.status[req.params.group]}).lean().exec((err, data) => {
SampleModel.find({status: globals.status[req.params.state]}).lean().exec((err, data) => {
if (err) return next(err);
res.json(_.compact(data.map(e => SampleValidate.output(e)))); // validate all and filter null values from validation errors
});

View File

@ -83,6 +83,16 @@ export default class MaterialValidate { // validate input for material
return error !== undefined? null : value;
}
static outputGroups (data) {// validate groups output and strip unwanted properties, returns null if not valid
const {value, error} = this.material.group.validate(data, {stripUnknown: true});
return error !== undefined? null : value;
}
static outputSuppliers (data) {// validate suppliers output and strip unwanted properties, returns null if not valid
const {value, error} = this.material.supplier.validate(data, {stripUnknown: true});
return error !== undefined? null : value;
}
static outputV() { // return output validator
return Joi.object({
_id: IdValidate.get(),

View File

@ -149,8 +149,8 @@
{
"_id": {"$oid":"100000000000000000000001"},
"name": "Stanyl TW 200 F8",
"supplier": "DSM",
"group": "PA46",
"supplier_id": {"$oid":"110000000000000000000001"},
"group_id": {"$oid":"900000000000000000000001"},
"mineral": 0,
"glass_fiber": 40,
"carbon_fiber": 0,
@ -170,8 +170,8 @@
{
"_id": {"$oid":"100000000000000000000002"},
"name": "Ultramid T KR 4355 G7",
"supplier": "BASF",
"group": "PA6/6T",
"supplier_id": {"$oid":"110000000000000000000002"},
"group_id": {"$oid":"900000000000000000000002"},
"mineral": 0,
"glass_fiber": 35,
"carbon_fiber": 0,
@ -191,8 +191,8 @@
{
"_id": {"$oid":"100000000000000000000003"},
"name": "PA GF 50 black (2706)",
"supplier": "Akro-Plastic",
"group": "PA66+PA6I/6T",
"supplier_id": {"$oid":"110000000000000000000003"},
"group_id": {"$oid":"900000000000000000000003"},
"mineral": 0,
"glass_fiber": 0,
"carbon_fiber": 0,
@ -204,8 +204,8 @@
{
"_id": {"$oid":"100000000000000000000004"},
"name": "Schulamid 66 GF 25 H",
"supplier": "Schulmann",
"group": "PA66",
"supplier_id": {"$oid":"110000000000000000000004"},
"group_id": {"$oid":"900000000000000000000004"},
"mineral": 0,
"glass_fiber": 25,
"carbon_fiber": 0,
@ -221,8 +221,8 @@
{
"_id": {"$oid":"100000000000000000000005"},
"name": "Amodel A 1133 HS",
"supplier": "Solvay",
"group": "PPA",
"supplier_id": {"$oid":"110000000000000000000005"},
"group_id": {"$oid":"900000000000000000000005"},
"mineral": 0,
"glass_fiber": 33,
"carbon_fiber": 0,
@ -238,8 +238,8 @@
{
"_id": {"$oid":"100000000000000000000006"},
"name": "PK-HM natural (4773)",
"supplier": "Akro-Plastic",
"group": "PK",
"supplier_id": {"$oid":"110000000000000000000003"},
"group_id": {"$oid":"900000000000000000000006"},
"mineral": 0,
"glass_fiber": 0,
"carbon_fiber": 0,
@ -255,8 +255,8 @@
{
"_id": {"$oid":"100000000000000000000007"},
"name": "Ultramid A4H",
"supplier": "BASF",
"group": "PA66",
"supplier_id": {"$oid":"110000000000000000000002"},
"group_id": {"$oid":"900000000000000000000004"},
"mineral": 0,
"glass_fiber": 0,
"carbon_fiber": 0,
@ -272,8 +272,8 @@
{
"_id": {"$oid":"100000000000000000000008"},
"name": "Latamid 66 H 2 G 30",
"supplier": "LATI",
"group": "PA66",
"supplier_id": {"$oid":"110000000000000000000006"},
"group_id": {"$oid":"900000000000000000000004"},
"mineral": 0,
"glass_fiber": 30,
"carbon_fiber": 0,
@ -287,6 +287,70 @@
"__v": 0
}
],
"material_groups": [
{
"_id": {"$oid":"900000000000000000000001"},
"name": "PA46",
"__v": 0
},
{
"_id": {"$oid":"900000000000000000000002"},
"name": "PA6/6T",
"__v": 0
},
{
"_id": {"$oid":"900000000000000000000003"},
"name": "PA66+PA6I/6T",
"__v": 0
},
{
"_id": {"$oid":"900000000000000000000004"},
"name": "PA66",
"__v": 0
},
{
"_id": {"$oid":"900000000000000000000005"},
"name": "PPA",
"__v": 0
},
{
"_id": {"$oid":"900000000000000000000006"},
"name": "PK",
"__v": 0
}
],
"material_suppliers": [
{
"_id": {"$oid":"110000000000000000000001"},
"name": "DSM",
"__v": 0
},
{
"_id": {"$oid":"110000000000000000000002"},
"name": "BASF",
"__v": 0
},
{
"_id": {"$oid":"110000000000000000000003"},
"name": "Akro-Plastic",
"__v": 0
},
{
"_id": {"$oid":"110000000000000000000004"},
"name": "Schulmann",
"__v": 0
},
{
"_id": {"$oid":"110000000000000000000005"},
"name": "Solvay",
"__v": 0
},
{
"_id": {"$oid":"110000000000000000000006"},
"name": "LATI",
"__v": 0
}
],
"measurements": [
{
"_id": {"$oid":"800000000000000000000001"},