BETTERZON-94: Adding API endpoint to deactivate price listings as a vendor manager (#48)

This commit is contained in:
Patrick 2021-05-16 13:11:22 +02:00 committed by GitHub
parent b185e4e5e3
commit 061d1a46e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 69 additions and 13 deletions

View File

@ -31,7 +31,7 @@ export const findAll = async (): Promise<Prices> => {
let priceRows = []; let priceRows = [];
try { try {
conn = await pool.getConnection(); conn = await pool.getConnection();
const rows = await conn.query('SELECT price_id, product_id, vendor_id, price_in_cents, timestamp FROM prices'); const rows = await conn.query('SELECT price_id, product_id, vendor_id, price_in_cents, timestamp FROM prices WHERE active_listing = true');
for (let row in rows) { for (let row in rows) {
if (row !== 'meta') { if (row !== 'meta') {
let price: Price = { let price: Price = {
@ -72,7 +72,7 @@ export const find = async (id: number): Promise<Price> => {
let price: any; let price: any;
try { try {
conn = await pool.getConnection(); conn = await pool.getConnection();
const rows = await conn.query('SELECT price_id, product_id, vendor_id, price_in_cents, timestamp FROM prices WHERE price_id = ?', id); const rows = await conn.query('SELECT price_id, product_id, vendor_id, price_in_cents, timestamp FROM prices WHERE price_id = ? AND active_listing = true', id);
for (let row in rows) { for (let row in rows) {
if (row !== 'meta') { if (row !== 'meta') {
price = rows[row]; price = rows[row];
@ -99,7 +99,7 @@ export const findByProduct = async (product: number): Promise<Prices> => {
let priceRows = []; let priceRows = [];
try { try {
conn = await pool.getConnection(); conn = await pool.getConnection();
const rows = await conn.query('SELECT price_id, product_id, vendor_id, price_in_cents, timestamp FROM prices WHERE product_id = ?', product); const rows = await conn.query('SELECT price_id, product_id, vendor_id, price_in_cents, timestamp FROM prices WHERE product_id = ? AND active_listing = true', product);
for (let row in rows) { for (let row in rows) {
if (row !== 'meta') { if (row !== 'meta') {
priceRows.push(rows[row]); priceRows.push(rows[row]);
@ -142,16 +142,16 @@ export const findByType = async (product: string, type: string): Promise<Prices>
'PARTITION BY p.vendor_id ' + 'PARTITION BY p.vendor_id ' +
'ORDER BY p.timestamp DESC) AS rk ' + 'ORDER BY p.timestamp DESC) AS rk ' +
'FROM prices p ' + 'FROM prices p ' +
'WHERE product_id = ? AND vendor_id != 1) ' + 'WHERE product_id = ? AND vendor_id != 1 AND active_listing = true) ' +
'SELECT s.* ' + 'SELECT s.* ' +
'FROM summary s ' + 'FROM summary s ' +
'WHERE s.rk = 1 '), product); 'WHERE s.rk = 1 '), product);
} else if (type === 'lowest') { } else if (type === 'lowest') {
// Used to get the lowest prices for this product over a period of time // Used to get the lowest prices for this product over a period of time
rows = await conn.query('SELECT price_id, product_id, vendor_id, MIN(price_in_cents) as price_in_cents, timestamp FROM prices WHERE product_id = ? AND vendor_id != 1 GROUP BY DAY(timestamp) ORDER BY timestamp', product); rows = await conn.query('SELECT price_id, product_id, vendor_id, MIN(price_in_cents) as price_in_cents, timestamp FROM prices WHERE product_id = ? AND vendor_id != 1 AND active_listing = true GROUP BY DAY(timestamp) ORDER BY timestamp', product);
} else { } else {
// If no type is given, return all prices for this product // If no type is given, return all prices for this product
rows = await conn.query('SELECT price_id, product_id, vendor_id, price_in_cents, timestamp FROM prices WHERE product_id = ? AND vendor_id != 1', product); rows = await conn.query('SELECT price_id, product_id, vendor_id, price_in_cents, timestamp FROM prices WHERE product_id = ? AND vendor_id != 1 AND active_listing = true', product);
} }
for (let row in rows) { for (let row in rows) {
@ -188,13 +188,13 @@ export const findByVendor = async (product: string, vendor: string, type: string
let rows = []; let rows = [];
if (type === 'newest') { if (type === 'newest') {
// Used to get the newest price for this product and vendor // Used to get the newest price for this product and vendor
rows = await conn.query('SELECT price_id, product_id, vendor_id, price_in_cents, timestamp FROM prices WHERE product_id = ? AND vendor_id = ? ORDER BY timestamp DESC LIMIT 1', [product, vendor]); rows = await conn.query('SELECT price_id, product_id, vendor_id, price_in_cents, timestamp FROM prices WHERE product_id = ? AND vendor_id = ? AND active_listing = true ORDER BY timestamp DESC LIMIT 1', [product, vendor]);
} else if (type === 'lowest') { } else if (type === 'lowest') {
// Used to get the lowest prices for this product and vendor in all time // Used to get the lowest prices for this product and vendor in all time
rows = await conn.query('SELECT price_id, product_id, vendor_id, MIN(price_in_cents) as price_in_cents, timestamp FROM prices WHERE product_id = ? AND vendor_id = ? LIMIT 1', [product, vendor]); rows = await conn.query('SELECT price_id, product_id, vendor_id, MIN(price_in_cents) as price_in_cents, timestamp FROM prices WHERE product_id = ? AND vendor_id = ? AND active_listing = true LIMIT 1', [product, vendor]);
} else { } else {
// If no type is given, return all prices for this product and vendor // If no type is given, return all prices for this product and vendor
rows = await conn.query('SELECT price_id, product_id, vendor_id, price_in_cents, timestamp FROM prices WHERE product_id = ? AND vendor_id = ?', [product, vendor]); rows = await conn.query('SELECT price_id, product_id, vendor_id, price_in_cents, timestamp FROM prices WHERE product_id = ? AND vendor_id = ? AND active_listing = true', [product, vendor]);
} }
for (let row in rows) { for (let row in rows) {
@ -237,7 +237,7 @@ export const getBestDeals = async (amount: number): Promise<Prices> => {
' ROW_NUMBER() OVER(\n' + ' ROW_NUMBER() OVER(\n' +
' PARTITION BY p.product_id, p.vendor_id\n' + ' PARTITION BY p.product_id, p.vendor_id\n' +
' ORDER BY p.timestamp DESC) AS rk\n' + ' ORDER BY p.timestamp DESC) AS rk\n' +
' FROM prices p)\n' + ' FROM prices p WHERE active_listing = true)\n' +
'SELECT s.*\n' + 'SELECT s.*\n' +
'FROM summary s\n' + 'FROM summary s\n' +
'WHERE s.rk = 1'); 'WHERE s.rk = 1');
@ -298,7 +298,6 @@ export const getBestDeals = async (amount: number): Promise<Prices> => {
let maxAmt = Math.min(amount, deals.length); let maxAmt = Math.min(amount, deals.length);
for (let dealIndex = 0; dealIndex < maxAmt; dealIndex++) { for (let dealIndex = 0; dealIndex < maxAmt; dealIndex++) {
//console.log(deals[dealIndex]);
priceRows.push(deals[dealIndex] as Price); priceRows.push(deals[dealIndex] as Price);
} }
@ -338,7 +337,7 @@ export const findListByProducts = async (productIds: [number]): Promise<Prices>
' ORDER BY p.timestamp DESC) AS rk\n' + ' ORDER BY p.timestamp DESC) AS rk\n' +
' FROM prices p' + ' FROM prices p' +
' WHERE p.product_id IN (?)' + ' WHERE p.product_id IN (?)' +
' AND p.vendor_id != 1)\n' + ' AND p.vendor_id != 1 AND active_listing = true)\n' +
'SELECT s.*\n' + 'SELECT s.*\n' +
'FROM summary s\n' + 'FROM summary s\n' +
'WHERE s.rk = 1', [productIds]); 'WHERE s.rk = 1', [productIds]);

View File

@ -34,7 +34,6 @@ vendorsRouter.get('/', async (req: Request, res: Response) => {
// GET vendors/managed // GET vendors/managed
vendorsRouter.get('/managed', async (req: Request, res: Response) => { vendorsRouter.get('/managed', async (req: Request, res: Response) => {
console.log('here');
try { try {
// Authenticate user // Authenticate user
const user_ip = req.connection.remoteAddress ?? ''; const user_ip = req.connection.remoteAddress ?? '';
@ -86,3 +85,27 @@ vendorsRouter.get('/search/:term', async (req: Request, res: Response) => {
res.status(500).send(JSON.stringify({'message': 'Internal Server Error. Try again later.'})); res.status(500).send(JSON.stringify({'message': 'Internal Server Error. Try again later.'}));
} }
}); });
// PUT /manage/deactivatelisting
vendorsRouter.put('/manage/deactivatelisting', async (req: Request, res: Response) => {
try {
// Authenticate user
const user_ip = req.connection.remoteAddress ?? '';
const user = await UserService.checkSessionWithCookie(req.cookies.betterauth, user_ip);
// Get required parameters
const vendor_id = req.body.vendor_id;
const product_id = req.body.product_id;
const success = await VendorService.deactivateListing(user.user_id, vendor_id, product_id);
if(success) {
res.sendStatus(200);
} else {
res.sendStatus(500);
}
} catch (e) {
console.log('Error handling a request: ' + e.message);
res.status(500).send(JSON.stringify({'message': 'Internal Server Error. Try again later.'}));
}
});

View File

@ -151,3 +151,37 @@ export const getManagedShops = async (user_id: number): Promise<Vendors> => {
return vendorRows; return vendorRows;
}; };
/**
* Deactivates a product listing for a specific vendor
* @param user_id The user id of the issuing user
* @param vendor_id The vendor id of the vendor to deactivate the listing for
* @param product_id The product id of the product to deactivate the listing for
*/
export const deactivateListing = async (user_id: number, vendor_id: number, product_id: number): Promise<Boolean> => {
let conn;
try {
conn = await pool.getConnection();
// Check if the user is authorized to manage the requested vendor
const user_vendor_rows = await conn.query('SELECT vendor_id FROM vendors WHERE vendor_id = ? AND admin_id = ?', [vendor_id, user_id]);
if (user_vendor_rows.length !== 1) {
return false;
}
const status = await conn.query('UPDATE prices SET active_listing = false WHERE vendor_id = ? and product_id = ?', [vendor_id, product_id]);
if(status.affectedRows > 0){
return true;
}
return false;
} catch (err) {
throw err;
} finally {
if (conn) {
conn.end();
}
}
return false;
};