Hiệu chỉnh xóa batch mềm

This commit is contained in:
Truong Vo 2026-04-03 10:53:48 +07:00
parent def35fceff
commit d7bf701d0e
1 changed files with 82 additions and 50 deletions

102
server.js
View File

@ -24,17 +24,41 @@ const db = new sqlite3.Database('./products.db', (err) => {
console.log('Connected to products database.');
});
// Create tables
db.serialize(() => {
// Batches table
db.run(`CREATE TABLE IF NOT EXISTS batches (
function runInitAsync(sql, params = []) {
return new Promise((resolve, reject) => {
db.run(sql, params, (err) => {
if (err) reject(err);
else resolve();
});
});
}
function allInitAsync(sql, params = []) {
return new Promise((resolve, reject) => {
db.all(sql, params, (err, rows) => {
if (err) reject(err);
else resolve(rows);
});
});
}
async function initializeDatabase() {
await runInitAsync(`CREATE TABLE IF NOT EXISTS batches (
id INTEGER PRIMARY KEY AUTOINCREMENT,
batch_name TEXT NOT NULL UNIQUE,
createdAt DATETIME DEFAULT CURRENT_TIMESTAMP
createdAt DATETIME DEFAULT CURRENT_TIMESTAMP,
status INTEGER NOT NULL DEFAULT 0
)`);
// Items table (for valid items)
db.run(`CREATE TABLE IF NOT EXISTS items (
// Migration for existing databases: add status column if missing
const columns = await allInitAsync(`PRAGMA table_info(batches)`);
const hasStatusColumn = columns.some((col) => col.name === 'status');
if (!hasStatusColumn) {
await runInitAsync(`ALTER TABLE batches ADD COLUMN status INTEGER NOT NULL DEFAULT 0`);
console.log('Added status column to batches table.');
}
await runInitAsync(`CREATE TABLE IF NOT EXISTS items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
batch_id INTEGER NOT NULL,
brand TEXT,
@ -45,8 +69,7 @@ db.serialize(() => {
FOREIGN KEY (batch_id) REFERENCES batches(id) ON DELETE CASCADE
)`);
// Items_mix table (for mixed MPN items)
db.run(`CREATE TABLE IF NOT EXISTS items_mix (
await runInitAsync(`CREATE TABLE IF NOT EXISTS items_mix (
id INTEGER PRIMARY KEY AUTOINCREMENT,
batch_id INTEGER NOT NULL,
brand TEXT,
@ -58,13 +81,14 @@ db.serialize(() => {
)`);
// Create indexes for better performance
db.run(`CREATE INDEX IF NOT EXISTS idx_items_batch_id ON items(batch_id)`);
db.run(`CREATE INDEX IF NOT EXISTS idx_items_mix_batch_id ON items_mix(batch_id)`);
db.run(`CREATE INDEX IF NOT EXISTS idx_items_mpn ON items(mpn)`);
db.run(`CREATE INDEX IF NOT EXISTS idx_items_sn ON items(sn)`);
db.run(`CREATE INDEX IF NOT EXISTS idx_items_brand ON items(brand)`);
db.run(`CREATE INDEX IF NOT EXISTS idx_items_mix_brand ON items_mix(brand)`);
});
await runInitAsync(`CREATE INDEX IF NOT EXISTS idx_items_batch_id ON items(batch_id)`);
await runInitAsync(`CREATE INDEX IF NOT EXISTS idx_items_mix_batch_id ON items_mix(batch_id)`);
await runInitAsync(`CREATE INDEX IF NOT EXISTS idx_batches_status ON batches(status)`);
await runInitAsync(`CREATE INDEX IF NOT EXISTS idx_items_mpn ON items(mpn)`);
await runInitAsync(`CREATE INDEX IF NOT EXISTS idx_items_sn ON items(sn)`);
await runInitAsync(`CREATE INDEX IF NOT EXISTS idx_items_brand ON items(brand)`);
await runInitAsync(`CREATE INDEX IF NOT EXISTS idx_items_mix_brand ON items_mix(brand)`);
}
// ==================== BATCH API ROUTES ====================
@ -220,13 +244,12 @@ app.get('/api/batch/get-all', (req, res) => {
const column = validColumns.includes(sortBy) ? sortBy : 'id';
const order = sortOrder.toUpperCase() === 'ASC' ? 'ASC' : 'DESC';
let query = 'SELECT * FROM batches';
let countQuery = 'SELECT COUNT(*) as total FROM batches';
let params = [];
const whereConditions = ['status = 0'];
let searchParams = [];
if (search) {
const searchCondition = `
WHERE
(
batch_name LIKE ?
OR id LIKE ?
OR EXISTS (
@ -239,24 +262,26 @@ app.get('/api/batch/get-all', (req, res) => {
WHERE items_mix.batch_id = batches.id
AND sn LIKE ?
)
)
`;
query += searchCondition;
countQuery += searchCondition;
whereConditions.push(searchCondition);
const searchParam = `%${search}%`;
params = [searchParam, searchParam, searchParam, searchParam];
}
searchParams = [searchParam, searchParam, searchParam, searchParam];
}
query += ` ORDER BY ${column} ${order} LIMIT ? OFFSET ?`;
params.push(limit, offset);
const whereClause = ` WHERE ${whereConditions.join(' AND ')}`;
const countQuery = `SELECT COUNT(*) as total FROM batches${whereClause}`;
const query = `SELECT * FROM batches${whereClause} ORDER BY ${column} ${order} LIMIT ? OFFSET ?`;
const countParams = [...searchParams];
const queryParams = [...searchParams, limit, offset];
db.get(countQuery, search ? params.slice(0, 2) : [], (err, countRow) => {
db.get(countQuery, countParams, (err, countRow) => {
if (err) {
return res.status(500).json({ error: err.message });
}
db.all(query, params, (err, batches) => {
db.all(query, queryParams, (err, batches) => {
if (err) {
return res.status(500).json({ error: err.message });
}
@ -320,7 +345,7 @@ app.get('/api/batch/get-all', (req, res) => {
app.get('/api/batch/get/:id', (req, res) => {
const id = req.params.id;
db.get('SELECT * FROM batches WHERE id = ?', [id], (err, batch) => {
db.get('SELECT * FROM batches WHERE id = ? AND status = 0', [id], (err, batch) => {
if (err) {
return res.status(500).json({ error: err.message });
}
@ -353,11 +378,11 @@ app.get('/api/batch/get/:id', (req, res) => {
});
});
// Delete batch (cascade delete items and items_mix)
// Soft delete batch (update status from 0 to 1)
app.delete('/api/batch/delete/:id', (req, res) => {
const id = req.params.id;
db.run('DELETE FROM batches WHERE id = ?', id, function (err) {
db.run('UPDATE batches SET status = 1 WHERE id = ? AND status = 0', [id], function (err) {
if (err) {
return res.status(500).json({ error: err.message });
}
@ -366,7 +391,7 @@ app.delete('/api/batch/delete/:id', (req, res) => {
return res.status(404).json({ error: 'Batch not found' });
}
res.json({ success: true, deleted: this.changes });
res.json({ success: true, updated: this.changes, deleted: this.changes });
});
});
@ -428,6 +453,13 @@ app.get('/', (req, res) => {
});
const PORT = process.env.PORT || 4444;
app.listen(PORT, () => {
initializeDatabase()
.then(() => {
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
});
})
.catch((err) => {
console.error('Database initialization failed:', err.message);
process.exit(1);
});