391 lines
12 KiB
JavaScript
391 lines
12 KiB
JavaScript
const ControllerMaster = require('./controller-master.js');
|
|
const Database = require('../database/database.js');
|
|
const Logger = require('../logger.js');
|
|
|
|
const PgFormat = require('pg-format');
|
|
|
|
// C
|
|
|
|
// R
|
|
|
|
async function SearchByTag(fuzzyTag) {
|
|
await Database.Query('BEGIN TRANSACTION;');
|
|
const dbres = await Database.Query(`
|
|
SELECT lego_set.id, lego_set.name, tag.name AS "tag", inv.price, inv.new_price AS "discount", inv.stock
|
|
FROM lego_set
|
|
LEFT JOIN lego_set_tag AS tags ON tags.set_id = lego_set.id
|
|
LEFT JOIN tag AS tag ON tags.tag = tag.id
|
|
LEFT JOIN lego_set_inventory AS inv ON inv.set_id = lego_set.id
|
|
WHERE tag.name ~* $1
|
|
`, [fuzzyTag]).catch(() => {
|
|
return {
|
|
error: 'Database error',
|
|
};
|
|
});
|
|
if (dbres.error) {
|
|
Database.Query('ROLLBACK TRANSACTION;');
|
|
Logger.Error(dbres.error);
|
|
return dbres;
|
|
}
|
|
Database.Query('COMMIT TRANSACTION;');
|
|
|
|
// validate database response
|
|
if (dbres.rows.length === 0) {
|
|
return {
|
|
error: 'Sets not found',
|
|
long: 'The sets you are looking for do not exist',
|
|
};
|
|
}
|
|
|
|
let sets = dbres.rows;
|
|
// combine tags into a single array
|
|
for (const set of sets) {
|
|
set.type = 'set';
|
|
set.tags = [];
|
|
}
|
|
|
|
// combine (joined) rows into a single array
|
|
sets = sets.reduce((arr, current) => {
|
|
if (!arr.some(item => item.id === current.id)) {
|
|
arr.push(current);
|
|
}
|
|
|
|
arr.find(item => item.id === current.id).tags.push(current.tag);
|
|
return arr;
|
|
}, []);
|
|
|
|
return sets;
|
|
}
|
|
|
|
async function Search(fuzzyStrings) {
|
|
await Database.Query('BEGIN TRANSACTION;');
|
|
const dbres = await Database.Query(PgFormat(`
|
|
SELECT lego_set.id, lego_set.name, tag.name AS "tag", inv.price, inv.new_price AS "discount", inv.stock
|
|
FROM lego_set
|
|
LEFT JOIN lego_set_tag AS tags ON tags.set_id = lego_set.id
|
|
LEFT JOIN tag AS tag ON tags.tag = tag.id
|
|
LEFT JOIN lego_set_inventory AS inv ON inv.set_id = lego_set.id
|
|
WHERE lego_set.id ~* ANY(ARRAY[%L]) OR lego_set.name ~* ANY(ARRAY[%L]) OR tag.name ~* ANY(ARRAY[%L])
|
|
`, fuzzyStrings, fuzzyStrings, fuzzyStrings), []).catch(() => {
|
|
return {
|
|
error: 'Database error',
|
|
};
|
|
});
|
|
if (dbres.error) {
|
|
Database.Query('ROLLBACK TRANSACTION;');
|
|
Logger.Error(dbres.error);
|
|
return dbres;
|
|
}
|
|
Database.Query('COMMIT TRANSACTION;');
|
|
|
|
// validate database response
|
|
if (dbres.rows.length === 0) {
|
|
return {
|
|
error: 'Set not found',
|
|
long: 'The sets you are looking for do not exist',
|
|
};
|
|
}
|
|
|
|
// order by levenshtine distance
|
|
let sets = dbres.rows;
|
|
sets.sort((a, b) => {
|
|
const aName = a.name.toLowerCase();
|
|
const bName = b.name.toLowerCase();
|
|
const aTag = a.tag.toLowerCase();
|
|
const bTag = b.tag.toLowerCase();
|
|
const aFuzzy = fuzzyStrings[0].toLowerCase();
|
|
const bFuzzy = fuzzyStrings[0].toLowerCase();
|
|
|
|
const aDist = ControllerMaster.LevenshteinDistance(aName, aFuzzy);
|
|
const bDist = ControllerMaster.LevenshteinDistance(bName, bFuzzy);
|
|
const aTagDist = ControllerMaster.LevenshteinDistance(aTag, aFuzzy);
|
|
const bTagDist = ControllerMaster.LevenshteinDistance(bTag, bFuzzy);
|
|
|
|
if (aDist < bDist) {
|
|
return -1;
|
|
} else if (aDist > bDist) {
|
|
return 1;
|
|
} else {
|
|
if (aTagDist < bTagDist) {
|
|
return -1;
|
|
} else if (aTagDist > bTagDist) {
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
});
|
|
|
|
// combine tags into a single array
|
|
for (const set of sets) {
|
|
set.type = 'set';
|
|
set.tags = [];
|
|
}
|
|
|
|
// combine (joined) rows into a single array
|
|
sets = sets.reduce((arr, current) => {
|
|
if (!arr.some(item => item.id === current.id)) {
|
|
arr.push(current);
|
|
}
|
|
|
|
arr.find(item => item.id === current.id).tags.push(current.tag);
|
|
return arr;
|
|
}, []);
|
|
|
|
return sets;
|
|
}
|
|
|
|
async function SumPrices(setsArray, quantityArray) {
|
|
await Database.Query('BEGIN TRANSACTION;');
|
|
const dbres = await Database.Query(PgFormat(`
|
|
SELECT COALESCE(new_price, price) AS "price"
|
|
FROM lego_set
|
|
LEFT JOIN lego_set_inventory AS set_inventory ON set_inventory.set_id = lego_set.id
|
|
WHERE lego_set.id IN (%L);
|
|
`, setsArray), []).catch(() => {
|
|
return {
|
|
error: 'Database error',
|
|
};
|
|
});
|
|
if (dbres.error) {
|
|
Database.Query('ROLLBACK TRANSACTION;');
|
|
Logger.Error(dbres.error);
|
|
return dbres;
|
|
}
|
|
Database.Query('COMMIT TRANSACTION;');
|
|
|
|
// validate database response
|
|
if (dbres.rows.length === 0) {
|
|
return {
|
|
error: 'Bricks not found',
|
|
long: 'The bricks you are looking for do not exist',
|
|
};
|
|
}
|
|
|
|
let sum = 0;
|
|
for (let i = 0; i < dbres.rows.length; i++) {
|
|
sum += parseFloat(dbres.rows[i].price) * parseFloat(quantityArray[i]);
|
|
}
|
|
|
|
return sum;
|
|
}
|
|
|
|
async function GetSet(setId) {
|
|
await Database.Query('BEGIN TRANSACTION;');
|
|
const dbres = await Database.Query(`
|
|
SELECT lego_set.id, lego_set.name, description, tag.name AS "tag",
|
|
set_contents.brick_id, set_contents.amount, inv.price,
|
|
date_released, weight, dimensions_x, dimensions_y, dimensions_z,
|
|
new_price AS "discount", inv.stock, inv.last_updated AS "last_stock_update"
|
|
FROM lego_set
|
|
LEFT JOIN lego_set_inventory AS inv ON inv.set_id = lego_set.id
|
|
LEFT JOIN lego_set_tag AS tags ON tags.set_id = lego_set.id
|
|
LEFT JOIN tag AS tag ON tags.tag = tag.id
|
|
LEFT JOIN set_descriptor AS set_contents ON set_contents.set_id = lego_set.id
|
|
WHERE lego_set.id = $1;
|
|
`, [setId]).catch(() => {
|
|
return {
|
|
error: 'Database error',
|
|
};
|
|
});
|
|
if (dbres.error) {
|
|
Database.Query('ROLLBACK TRANSACTION;');
|
|
Logger.Error(dbres.error);
|
|
return dbres;
|
|
}
|
|
Database.Query('COMMIT TRANSACTION;');
|
|
|
|
// validate database response
|
|
if (dbres.rows.length === 0) {
|
|
return {
|
|
error: 'Set not found',
|
|
long: 'The set you are looking for does not exist',
|
|
};
|
|
}
|
|
|
|
const tags = dbres.rows.reduce((acc, cur) => {
|
|
acc.add(cur.tag);
|
|
return acc;
|
|
}, new Set());
|
|
|
|
const bricks = dbres.rows.reduce((acc, cur) => {
|
|
acc[cur.brick_id] = cur.amount;
|
|
return acc;
|
|
}, {});
|
|
|
|
const set = dbres.rows[0];
|
|
set.includedBricks = bricks;
|
|
set.tags = Array.from(tags);
|
|
set.type = 'set';
|
|
|
|
return set;
|
|
}
|
|
|
|
async function GetSets(page, resPerPage) {
|
|
await Database.Query('BEGIN TRANSACTION;');
|
|
const countRes = await Database.Query('SELECT COUNT (*) FROM lego_set;');
|
|
const dbres = await Database.Query(`
|
|
SELECT
|
|
lego_set.id, lego_set.name, price, new_price AS "discount", tag.name AS "tag", inv.stock
|
|
FROM lego_set
|
|
LEFT JOIN lego_set_inventory as inv ON lego_set.id = inv.set_id
|
|
LEFT JOIN lego_set_tag AS tags ON tags.set_id = lego_set.id
|
|
LEFT JOIN tag AS tag ON tags.tag = tag.id
|
|
ORDER BY id ASC
|
|
LIMIT $1
|
|
OFFSET $2;`,
|
|
[resPerPage, page * resPerPage]).catch(() => {
|
|
return {
|
|
error: 'Database error',
|
|
};
|
|
});
|
|
if (dbres.error) {
|
|
Database.Query('ROLLBACK TRANSACTION;');
|
|
Logger.Error(dbres.error);
|
|
return dbres;
|
|
}
|
|
Database.Query('COMMIT TRANSACTION;');
|
|
|
|
const total = parseInt(countRes.rows[0].count);
|
|
|
|
// validate database response
|
|
if (dbres.rows.length === 0) {
|
|
return {
|
|
error: 'No sets found',
|
|
long: 'There are no sets to display',
|
|
};
|
|
}
|
|
|
|
let sets = dbres.rows;
|
|
|
|
for (const set of sets) {
|
|
set.type = 'set';
|
|
set.tags = [];
|
|
}
|
|
|
|
|
|
// combine (joined) rows into a single array
|
|
sets = sets.reduce((arr, current) => {
|
|
if (!arr.some(item => item.id === current.id)) {
|
|
arr.push(current);
|
|
}
|
|
|
|
arr.find(item => item.id === current.id).tags.push(current.tag);
|
|
return arr;
|
|
}, []);
|
|
|
|
return { total, sets };
|
|
}
|
|
|
|
async function GetSetsByDate(page, resPerPage) {
|
|
await Database.Query('BEGIN TRANSACTION;');
|
|
const countRes = await Database.Query('SELECT COUNT (*) FROM lego_set;');
|
|
const dbres = await Database.Query(`
|
|
SELECT
|
|
lego_set.id, lego_set.name, price, new_price AS "discount", tag.name AS "tag", date_released, inv.stock
|
|
FROM lego_set
|
|
LEFT JOIN lego_set_inventory as inv ON lego_set.id = inv.set_id
|
|
LEFT JOIN lego_set_tag AS tags ON tags.set_id = lego_set.id
|
|
LEFT JOIN tag AS tag ON tags.tag = tag.id
|
|
ORDER BY date_released::int DESC
|
|
LIMIT $1
|
|
OFFSET $2;`,
|
|
[resPerPage, page * resPerPage]).catch(() => {
|
|
return {
|
|
error: 'Database error',
|
|
};
|
|
});
|
|
if (dbres.error) {
|
|
Database.Query('ROLLBACK TRANSACTION;');
|
|
Logger.Error(dbres.error);
|
|
return dbres;
|
|
}
|
|
Database.Query('COMMIT TRANSACTION;');
|
|
|
|
const total = parseInt(countRes.rows[0].count);
|
|
|
|
// validate database response
|
|
if (dbres.rows.length === 0) {
|
|
return {
|
|
error: 'No sets found',
|
|
long: 'There are no sets to display',
|
|
};
|
|
}
|
|
|
|
let sets = dbres.rows;
|
|
|
|
for (const set of sets) {
|
|
set.type = 'set';
|
|
set.tags = [];
|
|
}
|
|
|
|
// combine (joined) rows into a single array
|
|
sets = sets.reduce((arr, current) => {
|
|
if (!arr.some(item => item.id === current.id)) {
|
|
arr.push(current);
|
|
}
|
|
|
|
arr.find(item => item.id === current.id).tags.push(current.tag);
|
|
return arr;
|
|
}, []);
|
|
|
|
return { total, sets };
|
|
}
|
|
|
|
// U
|
|
|
|
async function RemoveSetStock(setIdList, quantityList) {
|
|
await Database.Query('BEGIN TRANSACTION;');
|
|
for (let i = 0; i < setIdList.length; i++) {
|
|
const dbres = await Database.Query(`
|
|
UPDATE lego_set_inventory
|
|
SET stock = stock - $1
|
|
WHERE set_id = $2;
|
|
`, [quantityList[i], setIdList[i]]).catch(() => {
|
|
return {
|
|
error: 'Database error',
|
|
};
|
|
});
|
|
if (dbres.error) {
|
|
Database.Query('ROLLBACK TRANSACTION;');
|
|
Logger.Error(dbres.error);
|
|
return dbres;
|
|
}
|
|
}
|
|
Database.Query('COMMIT TRANSACTION;');
|
|
return true;
|
|
}
|
|
|
|
async function UpdateStock(setId, newStock) {
|
|
await Database.Query('BEGIN TRANSACTION;');
|
|
const dbres = await Database.Query(`
|
|
UPDATE lego_set_inventory
|
|
SET stock = $1
|
|
WHERE set_id = $2;
|
|
`, [newStock, setId]).catch(() => {
|
|
return {
|
|
error: 'Database error',
|
|
};
|
|
});
|
|
if (dbres.error) {
|
|
Database.Query('ROLLBACK TRANSACTION;');
|
|
Logger.Error(dbres.error);
|
|
return dbres;
|
|
}
|
|
Database.Query('COMMIT TRANSACTION;');
|
|
return true;
|
|
}
|
|
|
|
// D
|
|
|
|
module.exports = {
|
|
SearchByTag,
|
|
Search,
|
|
SumPrices,
|
|
GetSet,
|
|
GetSets,
|
|
GetSetsByDate,
|
|
RemoveSetStock,
|
|
UpdateStock,
|
|
};
|