Dashboard tweaks, add bulk /check-upcs endpoint for import validation
This commit is contained in:
@@ -1931,6 +1931,76 @@ router.post('/generate-upc', async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Bulk "does this UPC already exist" check for the import validator.
|
||||
// The one-at-a-time alternative is /search-products?q=<upc>, but that runs a
|
||||
// five-column LIKE '%q%' scan across ten joined tables (~6s each) and every call
|
||||
// queues on the single shared connection from getDbConnection() — a 20-product
|
||||
// batch takes minutes. This answers the whole batch with one indexed IN() lookup
|
||||
// on idx_upc. Matches /check-upc-and-generate-sku's semantics: `upc` only, not upc_2.
|
||||
const MAX_UPCS_PER_CHECK = 500;
|
||||
|
||||
router.get('/check-upcs', async (req, res) => {
|
||||
const { upcs } = req.query;
|
||||
|
||||
if (!upcs) {
|
||||
return res.status(400).json({ error: 'upcs query parameter is required' });
|
||||
}
|
||||
|
||||
// Dedupe and keep only well-formed barcodes — anything else can't match the
|
||||
// column anyway, and dropping it keeps the IN() list tight.
|
||||
const upcList = [...new Set(
|
||||
String(upcs).split(',').map(s => s.trim()).filter(s => /^\d{8,14}$/.test(s))
|
||||
)];
|
||||
|
||||
if (upcList.length === 0) {
|
||||
return res.json({ found: {}, checked: 0 });
|
||||
}
|
||||
|
||||
if (upcList.length > MAX_UPCS_PER_CHECK) {
|
||||
return res.status(400).json({
|
||||
error: `Too many UPCs (${upcList.length}); send at most ${MAX_UPCS_PER_CHECK} per request`
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const { connection } = await getDbConnection();
|
||||
|
||||
const placeholders = upcList.map(() => '?').join(',');
|
||||
const [rows] = await connection.query(
|
||||
`SELECT pid, upc, itemnumber, description FROM products WHERE upc IN (${placeholders})`,
|
||||
upcList
|
||||
);
|
||||
|
||||
// idx_upc is non-unique, so a UPC can legitimately hit more than one product.
|
||||
// Report the lowest pid (the original) and say how many share it.
|
||||
const found = {};
|
||||
for (const row of rows) {
|
||||
const key = String(row.upc);
|
||||
const existing = found[key];
|
||||
if (!existing) {
|
||||
found[key] = {
|
||||
pid: row.pid,
|
||||
itemNumber: row.itemnumber,
|
||||
title: row.description,
|
||||
matchCount: 1
|
||||
};
|
||||
continue;
|
||||
}
|
||||
existing.matchCount += 1;
|
||||
if (row.pid < existing.pid) {
|
||||
existing.pid = row.pid;
|
||||
existing.itemNumber = row.itemnumber;
|
||||
existing.title = row.description;
|
||||
}
|
||||
}
|
||||
|
||||
return res.json({ found, checked: upcList.length });
|
||||
} catch (error) {
|
||||
console.error('Error checking UPCs:', error);
|
||||
return res.status(500).json({ error: 'Failed to check UPCs', details: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Endpoint to check UPC and generate item number
|
||||
router.get('/check-upc-and-generate-sku', async (req, res) => {
|
||||
const { upc, supplierId } = req.query;
|
||||
|
||||
Reference in New Issue
Block a user