implemented paging
This commit is contained in:
parent
ac72d8a975
commit
cd2962e186
@ -12,6 +12,24 @@
|
|||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
example: all
|
example: all
|
||||||
|
- name: last-id
|
||||||
|
description: last id of current page, if not given the results are displayed from start
|
||||||
|
in: query
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
example: 5ea0450ed851c30a90e70894
|
||||||
|
- name: to-page
|
||||||
|
description: relative change of pages, use negative values to get back, defaults to 0 (if last-id is given, the sample after is the first of the result, so the next page is selected automatically), works only together with page-size
|
||||||
|
in: query
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
example: 1
|
||||||
|
- name: page-size
|
||||||
|
description: number of items per page
|
||||||
|
in: query
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
example: 30
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: samples overview
|
description: samples overview
|
||||||
@ -25,6 +43,8 @@
|
|||||||
$ref: 'api.yaml#/components/responses/400'
|
$ref: 'api.yaml#/components/responses/400'
|
||||||
401:
|
401:
|
||||||
$ref: 'api.yaml#/components/responses/401'
|
$ref: 'api.yaml#/components/responses/401'
|
||||||
|
404:
|
||||||
|
$ref: 'api.yaml#/components/responses/404'
|
||||||
500:
|
500:
|
||||||
$ref: 'api.yaml#/components/responses/500'
|
$ref: 'api.yaml#/components/responses/500'
|
||||||
|
|
||||||
|
@ -46,6 +46,9 @@ SampleRefs:
|
|||||||
$ref: 'api.yaml#/components/schemas/Id'
|
$ref: 'api.yaml#/components/schemas/Id'
|
||||||
user_id:
|
user_id:
|
||||||
$ref: 'api.yaml#/components/schemas/Id'
|
$ref: 'api.yaml#/components/schemas/Id'
|
||||||
|
added:
|
||||||
|
type: string
|
||||||
|
example: 1970-01-01T00:00:00.000Z
|
||||||
Sample:
|
Sample:
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: 'api.yaml#/components/schemas/_Id'
|
- $ref: 'api.yaml#/components/schemas/_Id'
|
||||||
|
@ -0,0 +1,485 @@
|
|||||||
|
const csv = require('csv-parser');
|
||||||
|
const fs = require('fs');
|
||||||
|
const axios = require('axios');
|
||||||
|
const {Builder} = require('selenium-webdriver');
|
||||||
|
const chrome = require('selenium-webdriver/chrome');
|
||||||
|
const pdfReader = require('pdfreader');
|
||||||
|
const iconv = require('iconv-lite');
|
||||||
|
|
||||||
|
const metadata = 'C:\\Users\\vle2fe\\Documents\\Data\\Rng_200622\\VZ.csv'; // metadata file
|
||||||
|
const nmDocs = 'C:\\Users\\vle2fe\\Documents\\Data\\Rng_200622\\nmDocs'; // NormMaster Documents
|
||||||
|
const dptFiles = 'C:\\Users\\vle2fe\\Documents\\Data\\Rng_200622\\DPT'; // Spectrum files
|
||||||
|
let data = []; // metadata contents
|
||||||
|
let materials = {};
|
||||||
|
let samples = [];
|
||||||
|
let normMaster = {};
|
||||||
|
|
||||||
|
// TODO: integrate measurement device information from DPT names using different users
|
||||||
|
// TODO: supplier: other for supplierless samples
|
||||||
|
|
||||||
|
main();
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
if (0) { // materials
|
||||||
|
await getNormMaster();
|
||||||
|
await importCsv();
|
||||||
|
await allMaterials();
|
||||||
|
fs.writeFileSync('./data_import/materials.json', JSON.stringify(materials));
|
||||||
|
await saveMaterials();
|
||||||
|
}
|
||||||
|
else if (0) { // samples
|
||||||
|
await importCsv();
|
||||||
|
await allSamples();
|
||||||
|
await saveSamples();
|
||||||
|
}
|
||||||
|
else if (0) { // DPT
|
||||||
|
await allDpts();
|
||||||
|
}
|
||||||
|
else if (1) { // KF/VZ
|
||||||
|
await importCsv();
|
||||||
|
await allKfVz();
|
||||||
|
}
|
||||||
|
else if (0) { // pdf test
|
||||||
|
console.log(await readPdf('N28_BN22-O010_2018-03-08.pdf'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function importCsv() {
|
||||||
|
await new Promise(resolve => {
|
||||||
|
fs.createReadStream(metadata)
|
||||||
|
.pipe(iconv.decodeStream('win1252'))
|
||||||
|
.pipe(csv())
|
||||||
|
.on('data', (row) => {
|
||||||
|
data.push(row);
|
||||||
|
})
|
||||||
|
.on('end', () => {
|
||||||
|
console.info('CSV file successfully processed');
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function allDpts() {
|
||||||
|
let res = await axios({
|
||||||
|
method: 'get',
|
||||||
|
url: 'http://localhost:3000/template/measurements',
|
||||||
|
auth: {
|
||||||
|
username: 'admin',
|
||||||
|
password: 'Abc123!#'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const measurement_template = res.data.find(e => e.name === 'spectrum')._id;
|
||||||
|
res = await axios({
|
||||||
|
method: 'get',
|
||||||
|
url: 'http://localhost:3000/samples?status=all',
|
||||||
|
auth: {
|
||||||
|
username: 'admin',
|
||||||
|
password: 'Abc123!#'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const sampleIds = {};
|
||||||
|
res.data.forEach(sample => {
|
||||||
|
sampleIds[sample.number] = sample._id;
|
||||||
|
});
|
||||||
|
const regex = /.*?_(.*?)_(\d+|\d+_\d+).DPT/;
|
||||||
|
const dpts = fs.readdirSync(dptFiles);
|
||||||
|
for (let i in dpts) {
|
||||||
|
const regexRes = regex.exec(dpts[i])
|
||||||
|
if (regexRes && sampleIds[regexRes[1]]) { // found matching sample
|
||||||
|
console.log(dpts[i]);
|
||||||
|
const f = fs.readFileSync(dptFiles + '\\' + dpts[i], 'utf-8');
|
||||||
|
const data = {
|
||||||
|
sample_id: sampleIds[regexRes[1]],
|
||||||
|
values: {},
|
||||||
|
measurement_template
|
||||||
|
};
|
||||||
|
data.values.dpt = f.split('\r\n').map(e => e.split(','));
|
||||||
|
await axios({
|
||||||
|
method: 'post',
|
||||||
|
url: 'http://localhost:3000/measurement/new',
|
||||||
|
auth: {
|
||||||
|
username: 'admin',
|
||||||
|
password: 'Abc123!#'
|
||||||
|
},
|
||||||
|
data
|
||||||
|
}).catch(err => {
|
||||||
|
console.log(dpts[i]);
|
||||||
|
console.error(err.response.data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function allKfVz() {
|
||||||
|
let res = await axios({
|
||||||
|
method: 'get',
|
||||||
|
url: 'http://localhost:3000/template/measurements',
|
||||||
|
auth: {
|
||||||
|
username: 'admin',
|
||||||
|
password: 'Abc123!#'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const kf_template = res.data.find(e => e.name === 'kf')._id;
|
||||||
|
const vz_template = res.data.find(e => e.name === 'vz')._id;
|
||||||
|
res = await axios({
|
||||||
|
method: 'get',
|
||||||
|
url: 'http://localhost:3000/samples?status=all',
|
||||||
|
auth: {
|
||||||
|
username: 'admin',
|
||||||
|
password: 'Abc123!#'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const sampleIds = {};
|
||||||
|
res.data.forEach(sample => {
|
||||||
|
sampleIds[sample.number] = sample._id;
|
||||||
|
});
|
||||||
|
for (let index in data) {
|
||||||
|
console.info(`${index}/${data.length}`);
|
||||||
|
let sample = data[index];
|
||||||
|
if (sample['Sample number'] !== '') {
|
||||||
|
if (sample['KF in Gew%']) {
|
||||||
|
await axios({
|
||||||
|
method: 'post',
|
||||||
|
url: 'http://localhost:3000/measurement/new',
|
||||||
|
auth: {
|
||||||
|
username: 'admin',
|
||||||
|
password: 'Abc123!#'
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
sample_id: sampleIds[sample['Sample number']],
|
||||||
|
measurement_template: kf_template,
|
||||||
|
values: {
|
||||||
|
'weight %': sample['KF in Gew%'],
|
||||||
|
'standard deviation': sample['Stabwn']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
console.log(sample['Sample number']);
|
||||||
|
console.error(err.response.data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (sample['VZ (ml/g)']) {
|
||||||
|
await axios({
|
||||||
|
method: 'post',
|
||||||
|
url: 'http://localhost:3000/measurement/new',
|
||||||
|
auth: {
|
||||||
|
username: 'admin',
|
||||||
|
password: 'Abc123!#'
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
sample_id: sampleIds[sample['Sample number']],
|
||||||
|
measurement_template: vz_template,
|
||||||
|
values: {
|
||||||
|
vz: sample['VZ (ml/g)']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
console.log(sample['Sample number']);
|
||||||
|
console.error(err.response.data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function allSamples() {
|
||||||
|
let res = await axios({
|
||||||
|
method: 'get',
|
||||||
|
url: 'http://localhost:3000/materials?status=all',
|
||||||
|
auth: {
|
||||||
|
username: 'admin',
|
||||||
|
password: 'Abc123!#'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const dbMaterials = {}
|
||||||
|
res.data.forEach(m => {
|
||||||
|
dbMaterials[m.name] = m;
|
||||||
|
})
|
||||||
|
res = await axios({
|
||||||
|
method: 'get',
|
||||||
|
url: 'http://localhost:3000/samples?status=all',
|
||||||
|
auth: {
|
||||||
|
username: 'admin',
|
||||||
|
password: 'Abc123!#'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const sampleColors = {};
|
||||||
|
res.data.forEach(sample => {
|
||||||
|
sampleColors[sample.number] = sample.color;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
for (let index in data) {
|
||||||
|
console.info(`${index}/${data.length}`);
|
||||||
|
let sample = data[index];
|
||||||
|
if (sample['Sample number'] !== '' && sample['Supplier'] !== '' && sample['Granulate/Part'] !== '') { // TODO: wait for decision about samples without suppliers/color/type
|
||||||
|
const material = dbMaterials[trim(sample['Material name'])];
|
||||||
|
if (!material) { // could not find material, skipping sample
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
console.log(sample['Material name']);
|
||||||
|
console.log(material._id);
|
||||||
|
samples.push({
|
||||||
|
number: sample['Sample number'],
|
||||||
|
type: sample['Granulate/Part'],
|
||||||
|
batch: sample['Charge/batch granulate/part'] || '',
|
||||||
|
material_id: material._id,
|
||||||
|
notes: {
|
||||||
|
comment: sample['Comments']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const si = samples.length - 1;
|
||||||
|
if (sample['Material number'] !== '' && material.numbers.find(e => e.number === sample['Material number'])) { // TODO: fix because of false material/material number
|
||||||
|
samples[si].color = material.numbers.find(e => e.number === sample['Material number']).color;
|
||||||
|
}
|
||||||
|
else if (sample['Color'] && sample['Color'] !== '') {
|
||||||
|
samples[si].color = material.numbers.find(e => e.color.indexOf(sample['Color']) >= 0).color;
|
||||||
|
}
|
||||||
|
else if (sampleColors[sample['Sample number'].split('_')[0]]) { // derive color from main sample for kf/vz
|
||||||
|
samples[si].color = sampleColors[sample['Sample number'].split('_')[0]];
|
||||||
|
}
|
||||||
|
else { // TODO: no color information at all
|
||||||
|
samples.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveSamples() {
|
||||||
|
for (let i in samples) {
|
||||||
|
console.info(`${i}/${samples.length}`);
|
||||||
|
await axios({
|
||||||
|
method: 'post',
|
||||||
|
url: 'http://localhost:3000/sample/new',
|
||||||
|
auth: {
|
||||||
|
username: 'admin',
|
||||||
|
password: 'Abc123!#'
|
||||||
|
},
|
||||||
|
data: samples[i]
|
||||||
|
}).catch(err => {
|
||||||
|
console.log(samples[i]);
|
||||||
|
console.error(err.response.data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
console.info('saved all samples');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function allMaterials() {
|
||||||
|
for (let index in data) {
|
||||||
|
let sample = data[index];
|
||||||
|
if (sample['Sample number'] !== '' && sample['Supplier'] !== '') { // TODO: wait for decision about supplierless samples
|
||||||
|
sample['Material name'] = trim(sample['Material name']);
|
||||||
|
if (materials.hasOwnProperty(sample['Material name'])) { // material already found at least once
|
||||||
|
if (sample['Material number'] !== '') {
|
||||||
|
if (materials[sample['Material name']].numbers.length === 0 || !materials[sample['Material name']].numbers.find(e => e.number === stripSpaces(sample['Material number']))) { // new material number
|
||||||
|
if (materials[sample['Material name']].numbers.find(e => e.color === sample['Color'] && e.number === '')) { // color already in list, only number missing
|
||||||
|
materials[sample['Material name']].numbers.find(e => e.color === sample['Color'] && e.number === '').number = stripSpaces(sample['Material number']);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
materials[sample['Material name']].numbers.push({color: sample['Color'], number: stripSpaces(sample['Material number'])});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (sample['Color'] !== '') {
|
||||||
|
if (!materials[sample['Material name']].numbers.find(e => e.color === stripSpaces(sample['Color']))) { // new material color
|
||||||
|
materials[sample['Material name']].numbers.push({color: sample['Color'], number: ''});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // new material
|
||||||
|
console.info(`${index}/${data.length} ${sample['Material name']}`);
|
||||||
|
materials[sample['Material name']] = {
|
||||||
|
name: sample['Material name'],
|
||||||
|
supplier: sample['Supplier'],
|
||||||
|
group: sample['Material']
|
||||||
|
};
|
||||||
|
let tmp = /M(\d+)/.exec(sample['Reinforcing material']);
|
||||||
|
materials[sample['Material name']].mineral = tmp ? tmp[1] : 0;
|
||||||
|
tmp = /GF(\d+)/.exec(sample['Reinforcing material']);
|
||||||
|
materials[sample['Material name']].glass_fiber = tmp ? tmp[1] : 0;
|
||||||
|
tmp = /CF(\d+)/.exec(sample['Reinforcing material']);
|
||||||
|
materials[sample['Material name']].carbon_fiber = tmp ? tmp[1] : 0;
|
||||||
|
materials[sample['Material name']].numbers = await numbersFetch(sample);
|
||||||
|
console.log(materials[sample['Material name']]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveMaterials() {
|
||||||
|
const mKeys = Object.keys(materials)
|
||||||
|
for (let i in mKeys) {
|
||||||
|
await axios({
|
||||||
|
method: 'post',
|
||||||
|
url: 'http://localhost:3000/material/new',
|
||||||
|
auth: {
|
||||||
|
username: 'admin',
|
||||||
|
password: 'Abc123!#'
|
||||||
|
},
|
||||||
|
data: materials[mKeys[i]]
|
||||||
|
}).catch(err => {
|
||||||
|
console.log(materials[mKeys[i]]);
|
||||||
|
console.error(err.response.data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
console.info('saved all materials');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function numbersFetch(sample) {
|
||||||
|
let nm = [];
|
||||||
|
let res = [];
|
||||||
|
if (sample['Material number']) { // sample has a material number
|
||||||
|
nm = normMaster[stripSpaces(sample['Material number'])]? [normMaster[stripSpaces(sample['Material number'])]] : [];
|
||||||
|
}
|
||||||
|
else { // try finding via material name
|
||||||
|
nm = Object.keys(normMaster).filter(e => normMaster[e].nameSpaceless === stripSpaces(sample['Material name'])).map(e => normMaster[e]);
|
||||||
|
}
|
||||||
|
if (nm.length > 0) {
|
||||||
|
for (let i in nm) {
|
||||||
|
// if (!fs.readdirSync(nmDocs).find(e => e.indexOf(nm[i].doc.replace(/ /g, '_')) >= 0)) { // document not loaded
|
||||||
|
// await getNormMasterDoc(nm[i].url.replace(/ /g, '%20'));
|
||||||
|
// }
|
||||||
|
// if (!fs.readdirSync(nmDocs).find(e => e.indexOf(nm[i].doc.replace(/ /g, '_')) >= 0)) { // document not loaded
|
||||||
|
// console.info('Retrying download...');
|
||||||
|
// await getNormMasterDoc(nm[i].url.replace(/ /g, '%20'), 2.2);
|
||||||
|
// }
|
||||||
|
// if (!fs.readdirSync(nmDocs).find(e => e.indexOf(nm[i].doc.replace(/ /g, '_')) >= 0)) { // document not loaded
|
||||||
|
// console.info('Retrying download again...');
|
||||||
|
// await getNormMasterDoc(nm[i].url.replace(/ /g, '%20'), 5);
|
||||||
|
// }
|
||||||
|
if (fs.readdirSync(nmDocs).find(e => e.indexOf(nm[i].doc.replace(/ /g, '_')) >= 0)) { // document loaded
|
||||||
|
res = await readPdf(fs.readdirSync(nmDocs).find(e => e.indexOf(nm[i].doc.replace(/ /g, '_')) >= 0));
|
||||||
|
}
|
||||||
|
if (res.length > 0) { // no results
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (i + 1 >= nm.length) {
|
||||||
|
console.error('Download failed!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (res.length === 0) { // no results
|
||||||
|
if (sample['Color'] !== '' || sample['Material number'] !== '') {
|
||||||
|
return [{color: sample['Color'], number: sample['Material number']}];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!res.find(e => e.number === sample['Material number'])) { // sometimes norm master does not include sample number even if listed
|
||||||
|
res.push({color: sample['Color'], number: sample['Material number']});
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getNormMaster(fetchAgain = false) {
|
||||||
|
if (fetchAgain) {
|
||||||
|
console.info('fetching norm master...');
|
||||||
|
const res = await axios({
|
||||||
|
method: 'get',
|
||||||
|
url: 'http://rb-normen.bosch.com/cgi-bin/searchRBNorm4TradeName'
|
||||||
|
});
|
||||||
|
|
||||||
|
console.info('finding documents...');
|
||||||
|
let match;
|
||||||
|
// const regex = /<tr>.*?<td>.*?<\/span>(.*?)<\/td><td>(\d+)<\/td>.*?<a href="(.*?)"/gm;
|
||||||
|
const regex = /<tr>.*?<td>.*?<\/span>(.*?)<\/td><td>(\d+)<\/td><td>40.*?<a href="(.*?)".*?<\/a>(.*?)<\/td>/gm; // only valid materials
|
||||||
|
do {
|
||||||
|
match = regex.exec(res.data);
|
||||||
|
if (match) {
|
||||||
|
normMaster[match[2]] = {name: match[1], nameSpaceless: stripSpaces(match[1]), number: match[2], url: match[3], doc: match[4]};
|
||||||
|
}
|
||||||
|
} while (match);
|
||||||
|
fs.writeFileSync('./data_import/normMaster.json', JSON.stringify(normMaster));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
normMaster = JSON.parse(fs.readFileSync('./data_import/normMaster.json'), 'utf-8');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNormMasterDoc(url, timing = 1) {
|
||||||
|
console.log(url);
|
||||||
|
return new Promise(async resolve => {
|
||||||
|
const options = new chrome.Options();
|
||||||
|
options.setUserPreferences({
|
||||||
|
"download.default_directory": nmDocs,
|
||||||
|
"download.prompt_for_download": false,
|
||||||
|
"download.directory_upgrade": true,
|
||||||
|
"plugins.always_open_pdf_externally": true
|
||||||
|
});
|
||||||
|
let driver = await new Builder().forBrowser('chrome').setChromeOptions(options).build();
|
||||||
|
let timeout = 7000 * timing;
|
||||||
|
try {
|
||||||
|
await driver.get(url);
|
||||||
|
if (await driver.getCurrentUrl() !== 'https://rb-wam-saml.bosch.com/tfim/sps/normmaster/saml20/login') { // got document selection page
|
||||||
|
timeout = 11000 * timing;
|
||||||
|
await driver.executeScript('Array.prototype.slice.call(document.querySelectorAll(\'.functionlink\')).filter(e => e.innerText === \'English\')[0].click()').catch(() => {timeout = 0; });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
setTimeout(async () => { // wait until download is finished
|
||||||
|
await driver.quit();
|
||||||
|
resolve();
|
||||||
|
}, timeout);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function readPdf(file) {
|
||||||
|
return new Promise(async resolve => {
|
||||||
|
const countdown = 100; // value for text timeout
|
||||||
|
let table = 0; // > 0 when in correct table area
|
||||||
|
let rows = []; // found table rows
|
||||||
|
let lastY = 0; // y of last row
|
||||||
|
let lastX = 0; // right x of last item
|
||||||
|
let lastText = ''; // text of last item
|
||||||
|
let lastLastText = ''; // text of last last item
|
||||||
|
await new pdfReader.PdfReader().parseFileItems(nmDocs + '\\' + file, (err, item) => {
|
||||||
|
if (item && item.text) {
|
||||||
|
if ((stripSpaces(lastLastText + lastText + item.text).toLowerCase().indexOf('colordesignationsupplier') >= 0) || (stripSpaces(lastLastText + lastText + item.text).toLowerCase().indexOf('colordesignatiomsupplier') >= 0)) { // table area starts
|
||||||
|
table = countdown;
|
||||||
|
}
|
||||||
|
if (table > 0) {
|
||||||
|
// console.log(item);
|
||||||
|
// console.log(item.y - lastY);
|
||||||
|
// console.log(item.text);
|
||||||
|
if (item.y - lastY > 0.8 && Math.abs(item.x - lastX) > 5) { // new row
|
||||||
|
lastY = item.y;
|
||||||
|
rows.push(item.text);
|
||||||
|
}
|
||||||
|
else { // still the same row row
|
||||||
|
rows[rows.length - 1] += (item.x - lastX > 1.1 ? '$' : '') + item.text; // push to row, detect if still same cell
|
||||||
|
}
|
||||||
|
lastX = (item.w * 0.055) + item.x;
|
||||||
|
|
||||||
|
if (/\d \d\d\d \d\d\d \d\d\d/.test(item.text)) {
|
||||||
|
table = countdown;
|
||||||
|
}
|
||||||
|
table --;
|
||||||
|
if (table <= 0 || item.text.toLowerCase().indexOf('release document') >= 0 || item.text.toLowerCase().indexOf('normative references') >= 0) { // table area ended
|
||||||
|
table = -1;
|
||||||
|
// console.log(rows);
|
||||||
|
rows = rows.filter(e => /^\d{10}/m.test(stripSpaces(e))); // filter non-table rows
|
||||||
|
resolve(rows.map(e => {return {color: e.split('$')[3], number: stripSpaces(e.split('$')[0])}; }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastLastText = lastText;
|
||||||
|
lastText = item.text;
|
||||||
|
}
|
||||||
|
if (!item && table !== -1) { // document ended
|
||||||
|
rows = rows.filter(e => /^\d{10}/m.test(stripSpaces(e))); // filter non-table rows
|
||||||
|
resolve(rows.map(e => {return {color: e.split('$')[3], number: stripSpaces(e.split('$')[0])}; }));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function stripSpaces(s) {
|
||||||
|
return s ? s.replace(/ /g,'') : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function trim(s) {
|
||||||
|
return s.replace(/(^\s+|\s+$)/gm, '');
|
||||||
|
}
|
505
package-lock.json
generated
505
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,8 @@
|
|||||||
"start": "node index.js",
|
"start": "node index.js",
|
||||||
"dev": "nodemon -e ts,yaml --exec \"tsc && node dist/index.js || exit 1\"",
|
"dev": "nodemon -e ts,yaml --exec \"tsc && node dist/index.js || exit 1\"",
|
||||||
"loadDev": "node dist/test/loadDev.js",
|
"loadDev": "node dist/test/loadDev.js",
|
||||||
"coverage": "tsc && nyc --reporter=html --reporter=text mocha dist/**/**.spec.js --timeout 5000"
|
"coverage": "tsc && nyc --reporter=html --reporter=text mocha dist/**/**.spec.js --timeout 5000",
|
||||||
|
"import": "node data_import/import.js"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
@ -45,9 +46,13 @@
|
|||||||
"@types/node": "^13.1.6",
|
"@types/node": "^13.1.6",
|
||||||
"@types/qs": "^6.9.1",
|
"@types/qs": "^6.9.1",
|
||||||
"@types/serve-static": "^1.13.3",
|
"@types/serve-static": "^1.13.3",
|
||||||
|
"csv-parser": "^2.3.3",
|
||||||
|
"iconv-lite": "^0.6.0",
|
||||||
"mocha": "^7.1.2",
|
"mocha": "^7.1.2",
|
||||||
"nodemon": "^2.0.3",
|
"nodemon": "^2.0.3",
|
||||||
"nyc": "^15.0.1",
|
"nyc": "^15.0.1",
|
||||||
|
"pdfreader": "^1.0.7",
|
||||||
|
"selenium-webdriver": "^4.0.0-alpha.7",
|
||||||
"should": "^13.2.3",
|
"should": "^13.2.3",
|
||||||
"supertest": "^4.0.2",
|
"supertest": "^4.0.2",
|
||||||
"tslint": "^5.20.1",
|
"tslint": "^5.20.1",
|
||||||
|
@ -10,6 +10,7 @@ import mongoose from 'mongoose';
|
|||||||
// TODO: generate output for ML in format DPT -> data, implement filtering, field selection
|
// TODO: generate output for ML in format DPT -> data, implement filtering, field selection
|
||||||
// TODO: generate csv
|
// TODO: generate csv
|
||||||
// TODO: write script for data import
|
// TODO: write script for data import
|
||||||
|
// TODO: allowed types: tension rod, part, granulate, other
|
||||||
|
|
||||||
describe('/sample', () => {
|
describe('/sample', () => {
|
||||||
let server;
|
let server;
|
||||||
@ -18,6 +19,7 @@ describe('/sample', () => {
|
|||||||
afterEach(done => TestHelper.afterEach(server, done));
|
afterEach(done => TestHelper.afterEach(server, done));
|
||||||
after(done => TestHelper.after(done));
|
after(done => TestHelper.after(done));
|
||||||
|
|
||||||
|
// TODO: sort, added date filter, has measurements/condition filter
|
||||||
describe('GET /samples', () => {
|
describe('GET /samples', () => {
|
||||||
it('returns all samples', done => {
|
it('returns all samples', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
@ -30,7 +32,7 @@ describe('/sample', () => {
|
|||||||
const json = require('../test/db.json');
|
const json = require('../test/db.json');
|
||||||
should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status ===globals.status.validated).length);
|
should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status ===globals.status.validated).length);
|
||||||
should(res.body).matchEach(sample => {
|
should(res.body).matchEach(sample => {
|
||||||
should(sample).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'condition', 'material_id', 'note_id', 'user_id');
|
should(sample).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'condition', 'material_id', 'note_id', 'user_id', 'added');
|
||||||
should(sample).have.property('_id').be.type('string');
|
should(sample).have.property('_id').be.type('string');
|
||||||
should(sample).have.property('number').be.type('string');
|
should(sample).have.property('number').be.type('string');
|
||||||
should(sample).have.property('type').be.type('string');
|
should(sample).have.property('type').be.type('string');
|
||||||
@ -41,6 +43,7 @@ describe('/sample', () => {
|
|||||||
should(sample).have.property('material_id').be.type('string');
|
should(sample).have.property('material_id').be.type('string');
|
||||||
should(sample).have.property('note_id');
|
should(sample).have.property('note_id');
|
||||||
should(sample).have.property('user_id').be.type('string');
|
should(sample).have.property('user_id').be.type('string');
|
||||||
|
should(sample).have.property('added').be.type('string');
|
||||||
});
|
});
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -56,7 +59,7 @@ describe('/sample', () => {
|
|||||||
const json = require('../test/db.json');
|
const json = require('../test/db.json');
|
||||||
should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status ===globals.status.validated).length);
|
should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status ===globals.status.validated).length);
|
||||||
should(res.body).matchEach(sample => {
|
should(res.body).matchEach(sample => {
|
||||||
should(sample).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'condition', 'material_id', 'note_id', 'user_id');
|
should(sample).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'condition', 'material_id', 'note_id', 'user_id', 'added');
|
||||||
should(sample).have.property('_id').be.type('string');
|
should(sample).have.property('_id').be.type('string');
|
||||||
should(sample).have.property('number').be.type('string');
|
should(sample).have.property('number').be.type('string');
|
||||||
should(sample).have.property('type').be.type('string');
|
should(sample).have.property('type').be.type('string');
|
||||||
@ -67,6 +70,7 @@ describe('/sample', () => {
|
|||||||
should(sample).have.property('material_id').be.type('string');
|
should(sample).have.property('material_id').be.type('string');
|
||||||
should(sample).have.property('note_id');
|
should(sample).have.property('note_id');
|
||||||
should(sample).have.property('user_id').be.type('string');
|
should(sample).have.property('user_id').be.type('string');
|
||||||
|
should(sample).have.property('added').be.type('string');
|
||||||
});
|
});
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
@ -82,7 +86,7 @@ describe('/sample', () => {
|
|||||||
const json = require('../test/db.json');
|
const json = require('../test/db.json');
|
||||||
should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status ===globals.status.new).length);
|
should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status ===globals.status.new).length);
|
||||||
should(res.body).matchEach(sample => {
|
should(res.body).matchEach(sample => {
|
||||||
should(sample).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'condition', 'material_id', 'note_id', 'user_id');
|
should(sample).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'condition', 'material_id', 'note_id', 'user_id', 'added');
|
||||||
should(sample).have.property('_id').be.type('string');
|
should(sample).have.property('_id').be.type('string');
|
||||||
should(sample).have.property('number').be.type('string');
|
should(sample).have.property('number').be.type('string');
|
||||||
should(sample).have.property('type').be.type('string');
|
should(sample).have.property('type').be.type('string');
|
||||||
@ -92,10 +96,114 @@ describe('/sample', () => {
|
|||||||
should(sample).have.property('material_id').be.type('string');
|
should(sample).have.property('material_id').be.type('string');
|
||||||
should(sample).have.property('note_id');
|
should(sample).have.property('note_id');
|
||||||
should(sample).have.property('user_id').be.type('string');
|
should(sample).have.property('user_id').be.type('string');
|
||||||
|
should(sample).have.property('added').be.type('string');
|
||||||
});
|
});
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('uses the given page size', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/samples?status=all&page-size=3',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 200
|
||||||
|
}).end((err, res) => {
|
||||||
|
if (err) return done(err);
|
||||||
|
should(res.body).have.lengthOf(3);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('returns results starting after last-id', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/samples?status=all&last-id=400000000000000000000002',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 200
|
||||||
|
}).end((err, res) => {
|
||||||
|
if (err) return done(err);
|
||||||
|
should(res.body[0]).have.property('_id', '400000000000000000000003');
|
||||||
|
should(res.body[1]).have.property('_id', '400000000000000000000004');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('returns the right page number', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/samples?status=all&to-page=2&page-size=2',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 200
|
||||||
|
}).end((err, res) => {
|
||||||
|
if (err) return done(err);
|
||||||
|
should(res.body[0]).have.property('_id', '400000000000000000000006');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('works with negative page numbers', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/samples?status=all&to-page=-1&page-size=2&last-id=400000000000000000000004',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 200
|
||||||
|
}).end((err, res) => {
|
||||||
|
if (err) return done(err);
|
||||||
|
should(res.body[0]).have.property('_id', '400000000000000000000001');
|
||||||
|
should(res.body[1]).have.property('_id', '400000000000000000000002');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('returns an empty array for a page number out of range', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/samples?status=all&to-page=100&page-size=2',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 200
|
||||||
|
}).end((err, res) => {
|
||||||
|
if (err) return done(err);
|
||||||
|
should(res.body).have.lengthOf(0);
|
||||||
|
should(res.body).be.eql([]);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('returns an empty array for a page number out of negative range', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/samples?status=all&to-page=-100&page-size=3&last-id=400000000000000000000004',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 200
|
||||||
|
}).end((err, res) => {
|
||||||
|
if (err) return done(err);
|
||||||
|
should(res.body).have.lengthOf(0);
|
||||||
|
should(res.body).be.eql([]);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects a negative page size', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/samples?page-size=-3',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 400,
|
||||||
|
res: {status: 'Invalid body format', details: '"page-size" must be larger than or equal to 1'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects an invalid last-id', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/samples?last-id=40000000000h000000000002',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 400,
|
||||||
|
res: {status: 'Invalid body format', details: '"last-id" with value "40000000000h000000000002" fails to match the required pattern: /[0-9a-f]{24}/'}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('rejects a to-page without page-size', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/samples?to-page=3',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 400,
|
||||||
|
res: {status: 'Invalid body format', details: '"to-page" missing required peer "page-size"'}
|
||||||
|
});
|
||||||
|
});
|
||||||
it('rejects an invalid state name', done => {
|
it('rejects an invalid state name', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'get',
|
method: 'get',
|
||||||
@ -127,7 +235,7 @@ describe('/sample', () => {
|
|||||||
let asyncCounter = res.body.length;
|
let asyncCounter = res.body.length;
|
||||||
should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status ===globals.status.new).length);
|
should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status ===globals.status.new).length);
|
||||||
should(res.body).matchEach(sample => {
|
should(res.body).matchEach(sample => {
|
||||||
should(sample).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'condition', 'material_id', 'note_id', 'user_id');
|
should(sample).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'condition', 'material_id', 'note_id', 'user_id', 'added');
|
||||||
should(sample).have.property('_id').be.type('string');
|
should(sample).have.property('_id').be.type('string');
|
||||||
should(sample).have.property('number').be.type('string');
|
should(sample).have.property('number').be.type('string');
|
||||||
should(sample).have.property('type').be.type('string');
|
should(sample).have.property('type').be.type('string');
|
||||||
@ -140,6 +248,7 @@ describe('/sample', () => {
|
|||||||
should(sample).have.property('material_id').be.type('string');
|
should(sample).have.property('material_id').be.type('string');
|
||||||
should(sample).have.property('note_id');
|
should(sample).have.property('note_id');
|
||||||
should(sample).have.property('user_id').be.type('string');
|
should(sample).have.property('user_id').be.type('string');
|
||||||
|
should(sample).have.property('added').be.type('string');
|
||||||
SampleModel.findById(sample._id).lean().exec((err, data) => {
|
SampleModel.findById(sample._id).lean().exec((err, data) => {
|
||||||
should(data).have.property('status',globals.status.new);
|
should(data).have.property('status',globals.status.new);
|
||||||
if (--asyncCounter === 0) {
|
if (--asyncCounter === 0) {
|
||||||
@ -161,7 +270,7 @@ describe('/sample', () => {
|
|||||||
let asyncCounter = res.body.length;
|
let asyncCounter = res.body.length;
|
||||||
should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status === -1).length);
|
should(res.body).have.lengthOf(json.collections.samples.filter(e => e.status === -1).length);
|
||||||
should(res.body).matchEach(sample => {
|
should(res.body).matchEach(sample => {
|
||||||
should(sample).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'condition', 'material_id', 'note_id', 'user_id');
|
should(sample).have.only.keys('_id', 'number', 'type', 'color', 'batch', 'condition', 'material_id', 'note_id', 'user_id', 'added');
|
||||||
should(sample).have.property('_id').be.type('string');
|
should(sample).have.property('_id').be.type('string');
|
||||||
should(sample).have.property('number').be.type('string');
|
should(sample).have.property('number').be.type('string');
|
||||||
should(sample).have.property('type').be.type('string');
|
should(sample).have.property('type').be.type('string');
|
||||||
@ -174,6 +283,7 @@ describe('/sample', () => {
|
|||||||
should(sample).have.property('material_id').be.type('string');
|
should(sample).have.property('material_id').be.type('string');
|
||||||
should(sample).have.property('note_id');
|
should(sample).have.property('note_id');
|
||||||
should(sample).have.property('user_id').be.type('string');
|
should(sample).have.property('user_id').be.type('string');
|
||||||
|
should(sample).have.property('added').be.type('string');
|
||||||
SampleModel.findById(sample._id).lean().exec((err, data) => {
|
SampleModel.findById(sample._id).lean().exec((err, data) => {
|
||||||
should(data).have.property('status',globals.status.deleted);
|
should(data).have.property('status',globals.status.deleted);
|
||||||
if (--asyncCounter === 0) {
|
if (--asyncCounter === 0) {
|
||||||
@ -269,7 +379,7 @@ describe('/sample', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('PUT /sample/{id}', () => {
|
describe('PUT /sample/{id}', () => { // TODO: fix tests, work on /samples
|
||||||
it('returns the right sample', done => {
|
it('returns the right sample', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'put',
|
method: 'put',
|
||||||
@ -277,7 +387,7 @@ describe('/sample', () => {
|
|||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {},
|
req: {},
|
||||||
res: {_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002'}
|
res: {_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002', added: '2004-01-10T13:37:04.000Z'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('keeps unchanged properties', done => {
|
it('keeps unchanged properties', done => {
|
||||||
@ -289,7 +399,7 @@ describe('/sample', () => {
|
|||||||
req: {type: 'granulate', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', notes: {}}
|
req: {type: 'granulate', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', notes: {}}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(res.body).be.eql({_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002'});
|
should(res.body).be.eql({_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002', added: '2004-01-10T13:37:04.000Z'});
|
||||||
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', 'condition', 'material_id', 'note_id', 'user_id', 'status', '__v');
|
should(data).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id', 'status', '__v');
|
||||||
@ -316,7 +426,7 @@ describe('/sample', () => {
|
|||||||
req: {type: 'granulate'}
|
req: {type: 'granulate'}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(res.body).be.eql({_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002'});
|
should(res.body).be.eql({_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002', added: '2004-01-10T13:37:04.000Z'});
|
||||||
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.property('status',globals.status.validated);
|
should(data).have.property('status',globals.status.validated);
|
||||||
@ -333,7 +443,7 @@ describe('/sample', () => {
|
|||||||
req: {condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}}
|
req: {condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(res.body).be.eql({_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002'});
|
should(res.body).be.eql({_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002', added: '2004-01-10T13:37:04.000Z'});
|
||||||
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.property('status',globals.status.validated);
|
should(data).have.property('status',globals.status.validated);
|
||||||
@ -350,7 +460,7 @@ describe('/sample', () => {
|
|||||||
req: {notes: {comment: 'Stoff gesperrt', sample_references: []}}
|
req: {notes: {comment: 'Stoff gesperrt', sample_references: []}}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done(err);
|
if (err) return done(err);
|
||||||
should(res.body).be.eql({_id: '400000000000000000000002', number: '21', type: 'granulate', color: 'natural', batch: '1560237365', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000001', note_id: '500000000000000000000001', user_id: '000000000000000000000002'});
|
should(res.body).be.eql({_id: '400000000000000000000002', number: '21', type: 'granulate', color: 'natural', batch: '1560237365', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000001', note_id: '500000000000000000000001', user_id: '000000000000000000000002', added: '2004-01-10T13:37:04.000Z'});
|
||||||
SampleModel.findById('400000000000000000000002').lean().exec((err, data: any) => {
|
SampleModel.findById('400000000000000000000002').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', 'condition', 'material_id', 'note_id', 'user_id', 'status', '__v');
|
should(data).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id', 'status', '__v');
|
||||||
@ -627,7 +737,7 @@ describe('/sample', () => {
|
|||||||
auth: {basic: 'janedoe'},
|
auth: {basic: 'janedoe'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {condition: {}},
|
req: {condition: {}},
|
||||||
res: {_id: '400000000000000000000006', number: 'Rng36', type: 'granulate', color: 'black', batch: '', condition: {}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002'}
|
res: {_id: '400000000000000000000006', number: 'Rng36', type: 'granulate', color: 'black', batch: '', condition: {}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002', added: '2004-01-10T13:37:04.000Z'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects an old version of a condition template', done => {
|
it('rejects an old version of a condition template', done => {
|
||||||
@ -647,7 +757,7 @@ describe('/sample', () => {
|
|||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {condition: {p1: 36, condition_template: '200000000000000000000004'}},
|
req: {condition: {p1: 36, condition_template: '200000000000000000000004'}},
|
||||||
res: {_id: '400000000000000000000004', number: '32', type: 'granulate', color: 'black', batch: '1653000308', condition: {p1: 36, condition_template: '200000000000000000000004'}, material_id: '100000000000000000000005', note_id: '500000000000000000000003', user_id: '000000000000000000000003'}
|
res: {_id: '400000000000000000000004', number: '32', type: 'granulate', color: 'black', batch: '1653000308', condition: {p1: 36, condition_template: '200000000000000000000004'}, material_id: '100000000000000000000005', note_id: '500000000000000000000003', user_id: '000000000000000000000003', added: '2004-01-10T13:37:04.000Z'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects an changing back to an empty condition', done => {
|
it('rejects an changing back to an empty condition', done => {
|
||||||
@ -694,7 +804,7 @@ describe('/sample', () => {
|
|||||||
auth: {basic: 'admin'},
|
auth: {basic: 'admin'},
|
||||||
httpStatus: 200,
|
httpStatus: 200,
|
||||||
req: {},
|
req: {},
|
||||||
res: {_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', condition: {condition_template: '200000000000000000000001', material: 'copper', weeks: 3}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002'}
|
res: {_id: '400000000000000000000001', number: '1', type: 'granulate', color: 'black', batch: '', condition: {condition_template: '200000000000000000000001', material: 'copper', weeks: 3}, material_id: '100000000000000000000004', note_id: null, user_id: '000000000000000000000002', added: '2004-01-10T13:37:04.000Z'}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('rejects requests from a read user', done => {
|
it('rejects requests from a read user', done => {
|
||||||
@ -1085,7 +1195,7 @@ describe('/sample', () => {
|
|||||||
req: {color: 'black', type: 'granulate', batch: '1560237365', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}
|
req: {color: 'black', type: 'granulate', batch: '1560237365', condition: {material: 'copper', weeks: 3, condition_template: '200000000000000000000001'}, material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done (err);
|
if (err) return done (err);
|
||||||
should(res.body).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id');
|
should(res.body).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id', 'added');
|
||||||
should(res.body).have.property('_id').be.type('string');
|
should(res.body).have.property('_id').be.type('string');
|
||||||
should(res.body).have.property('number', 'Rng37');
|
should(res.body).have.property('number', 'Rng37');
|
||||||
should(res.body).have.property('color', 'black');
|
should(res.body).have.property('color', 'black');
|
||||||
@ -1095,6 +1205,8 @@ describe('/sample', () => {
|
|||||||
should(res.body).have.property('material_id', '100000000000000000000001');
|
should(res.body).have.property('material_id', '100000000000000000000001');
|
||||||
should(res.body).have.property('note_id').be.type('string');
|
should(res.body).have.property('note_id').be.type('string');
|
||||||
should(res.body).have.property('user_id', '000000000000000000000002');
|
should(res.body).have.property('user_id', '000000000000000000000002');
|
||||||
|
should(res.body).have.property('added').be.type('string');
|
||||||
|
should(new Date().getTime() - new Date(res.body.added).getTime()).be.below(1000);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1198,7 +1310,7 @@ describe('/sample', () => {
|
|||||||
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}
|
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done (err);
|
if (err) return done (err);
|
||||||
should(res.body).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id');
|
should(res.body).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id', 'added');
|
||||||
should(res.body).have.property('_id').be.type('string');
|
should(res.body).have.property('_id').be.type('string');
|
||||||
should(res.body).have.property('number', 'Fe1');
|
should(res.body).have.property('number', 'Fe1');
|
||||||
should(res.body).have.property('color', 'black');
|
should(res.body).have.property('color', 'black');
|
||||||
@ -1207,6 +1319,8 @@ describe('/sample', () => {
|
|||||||
should(res.body).have.property('material_id', '100000000000000000000001');
|
should(res.body).have.property('material_id', '100000000000000000000001');
|
||||||
should(res.body).have.property('note_id').be.type('string');
|
should(res.body).have.property('note_id').be.type('string');
|
||||||
should(res.body).have.property('user_id', '000000000000000000000004');
|
should(res.body).have.property('user_id', '000000000000000000000004');
|
||||||
|
should(res.body).have.property('added').be.type('string');
|
||||||
|
should(new Date().getTime() - new Date(res.body.added).getTime()).be.below(1500);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1219,7 +1333,7 @@ describe('/sample', () => {
|
|||||||
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}
|
req: {color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}}
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done (err);
|
if (err) return done (err);
|
||||||
should(res.body).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id');
|
should(res.body).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id', 'added');
|
||||||
should(res.body).have.property('_id').be.type('string');
|
should(res.body).have.property('_id').be.type('string');
|
||||||
should(res.body).have.property('number', 'Rng37');
|
should(res.body).have.property('number', 'Rng37');
|
||||||
should(res.body).have.property('color', 'black');
|
should(res.body).have.property('color', 'black');
|
||||||
@ -1229,6 +1343,8 @@ describe('/sample', () => {
|
|||||||
should(res.body).have.property('material_id', '100000000000000000000001');
|
should(res.body).have.property('material_id', '100000000000000000000001');
|
||||||
should(res.body).have.property('note_id').be.type('string');
|
should(res.body).have.property('note_id').be.type('string');
|
||||||
should(res.body).have.property('user_id', '000000000000000000000002');
|
should(res.body).have.property('user_id', '000000000000000000000002');
|
||||||
|
should(res.body).have.property('added').be.type('string');
|
||||||
|
should(new Date().getTime() - new Date(res.body.added).getTime()).be.below(1000);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -1271,7 +1387,7 @@ describe('/sample', () => {
|
|||||||
req: {number: 'Rng34', color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
req: {number: 'Rng34', color: 'black', type: 'granulate', batch: '1560237365', material_id: '100000000000000000000001', notes: {comment: 'Testcomment', sample_references: [{sample_id: '400000000000000000000003', relation: 'part to this sample'}]}},
|
||||||
}).end((err, res) => {
|
}).end((err, res) => {
|
||||||
if (err) return done (err);
|
if (err) return done (err);
|
||||||
should(res.body).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id');
|
should(res.body).have.only.keys('_id', 'number', 'color', 'type', 'batch', 'condition', 'material_id', 'note_id', 'user_id', 'added');
|
||||||
should(res.body).have.property('_id').be.type('string');
|
should(res.body).have.property('_id').be.type('string');
|
||||||
should(res.body).have.property('number', 'Rng34');
|
should(res.body).have.property('number', 'Rng34');
|
||||||
should(res.body).have.property('color', 'black');
|
should(res.body).have.property('color', 'black');
|
||||||
@ -1281,6 +1397,8 @@ describe('/sample', () => {
|
|||||||
should(res.body).have.property('material_id', '100000000000000000000001');
|
should(res.body).have.property('material_id', '100000000000000000000001');
|
||||||
should(res.body).have.property('note_id').be.type('string');
|
should(res.body).have.property('note_id').be.type('string');
|
||||||
should(res.body).have.property('user_id', '000000000000000000000003');
|
should(res.body).have.property('user_id', '000000000000000000000003');
|
||||||
|
should(res.body).have.property('added').be.type('string');
|
||||||
|
should(new Date().getTime() - new Date(res.body.added).getTime()).be.below(1000);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -25,22 +25,43 @@ router.get('/samples', (req, res, next) => {
|
|||||||
const {error, value: filters} = SampleValidate.query(req.query);
|
const {error, value: filters} = SampleValidate.query(req.query);
|
||||||
if (error) return res400(error, res);
|
if (error) return res400(error, res);
|
||||||
|
|
||||||
let conditions;
|
let status;
|
||||||
|
|
||||||
if (filters.hasOwnProperty('status')) {
|
if (filters.hasOwnProperty('status')) {
|
||||||
if(filters.status === 'all') {
|
if(filters.status === 'all') {
|
||||||
conditions = {$or: [{status: globals.status.validated}, {status: globals.status.new}]}
|
status = {$or: [{status: globals.status.validated}, {status: globals.status.new}]}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
conditions = {status: globals.status[filters.status]};
|
status = {status: globals.status[filters.status]};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // default
|
else { // default
|
||||||
conditions = {status: globals.status.validated};
|
status = {status: globals.status.validated};
|
||||||
|
}
|
||||||
|
const query = SampleModel.find(status);
|
||||||
|
|
||||||
|
if (filters['page-size']) {
|
||||||
|
query.limit(filters['page-size']);
|
||||||
}
|
}
|
||||||
|
|
||||||
SampleModel.find(conditions).lean().exec((err, data) => {
|
if (filters['last-id']) {
|
||||||
|
if (filters['to-page'] && filters['to-page'] < 0) {
|
||||||
|
query.lte('_id', mongoose.Types.ObjectId(filters['last-id'])); // TODO: consider sorting
|
||||||
|
query.sort({_id: -1});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
query.gt('_id', mongoose.Types.ObjectId(filters['last-id'])); // TODO: consider sorting
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filters['to-page']) {
|
||||||
|
query.skip(Math.abs(filters['to-page']) * filters['page-size']); // TODO: check order for negative numbers
|
||||||
|
}
|
||||||
|
|
||||||
|
query.lean().exec((err, data) => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
|
if (filters['to-page'] && filters['to-page'] < 0) {
|
||||||
|
data.reverse();
|
||||||
|
}
|
||||||
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
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
@ -44,7 +44,11 @@ export default class SampleValidate {
|
|||||||
Joi.date()
|
Joi.date()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
})
|
}),
|
||||||
|
|
||||||
|
added: Joi.date()
|
||||||
|
.iso()
|
||||||
|
.min('1970-01-01T00:00:00.000Z')
|
||||||
};
|
};
|
||||||
|
|
||||||
static input (data, param) { // validate input, set param to 'new' to make all attributes required
|
static input (data, param) { // validate input, set param to 'new' to make all attributes required
|
||||||
@ -85,6 +89,7 @@ export default class SampleValidate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static output (data, param = 'refs') { // validate output and strip unwanted properties, returns null if not valid
|
static output (data, param = 'refs') { // validate output and strip unwanted properties, returns null if not valid
|
||||||
|
data.added = data._id.getTimestamp();
|
||||||
data = IdValidate.stringify(data);
|
data = IdValidate.stringify(data);
|
||||||
let joiObject;
|
let joiObject;
|
||||||
if (param === 'refs') {
|
if (param === 'refs') {
|
||||||
@ -97,7 +102,8 @@ export default class SampleValidate {
|
|||||||
condition: this.sample.condition,
|
condition: this.sample.condition,
|
||||||
material_id: IdValidate.get(),
|
material_id: IdValidate.get(),
|
||||||
note_id: IdValidate.get().allow(null),
|
note_id: IdValidate.get().allow(null),
|
||||||
user_id: IdValidate.get()
|
user_id: IdValidate.get(),
|
||||||
|
added: this.sample.added
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else if(param === 'details') {
|
else if(param === 'details') {
|
||||||
@ -123,7 +129,10 @@ export default class SampleValidate {
|
|||||||
|
|
||||||
static query (data) {
|
static query (data) {
|
||||||
return Joi.object({
|
return Joi.object({
|
||||||
status: Joi.string().valid('validated', 'new', 'all')
|
status: Joi.string().valid('validated', 'new', 'all'),
|
||||||
}).validate(data);
|
'last-id': IdValidate.get(),
|
||||||
|
'to-page': Joi.number().integer(),
|
||||||
|
'page-size': Joi.number().integer().min(1)
|
||||||
|
}).with('to-page', 'page-size').validate(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user