Files
cannaiq/backend/dist/routes/changes.js
Kelly 66e07b2009 fix(monitor): remove non-existent worker columns from job_run_logs query
The job_run_logs table tracks scheduled job orchestration, not individual
worker jobs. Worker info (worker_id, worker_hostname) belongs on
dispensary_crawl_jobs, not job_run_logs.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-03 18:45:05 -07:00

153 lines
5.0 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = require("express");
const middleware_1 = require("../auth/middleware");
const migrate_1 = require("../db/migrate");
const router = (0, express_1.Router)();
router.use(middleware_1.authMiddleware);
// Get all changes with optional status filter
router.get('/', async (req, res) => {
try {
const { status } = req.query;
let query = `
SELECT
dc.id,
dc.dispensary_id,
dc.field_name,
dc.old_value,
dc.new_value,
dc.source,
dc.confidence_score,
dc.change_notes,
dc.status,
dc.requires_recrawl,
dc.created_at,
dc.reviewed_at,
dc.reviewed_by,
dc.rejection_reason,
d.name as dispensary_name,
d.slug as dispensary_slug,
d.city,
d.state
FROM dispensary_changes dc
JOIN dispensaries d ON dc.dispensary_id = d.id
`;
const params = [];
if (status) {
query += ` WHERE dc.status = $1`;
params.push(status);
}
query += ` ORDER BY dc.created_at DESC`;
const result = await migrate_1.pool.query(query, params);
res.json({ changes: result.rows });
}
catch (error) {
console.error('Error fetching changes:', error);
res.status(500).json({ error: 'Failed to fetch changes' });
}
});
// Get changes statistics (for alert banner)
router.get('/stats', async (req, res) => {
try {
const result = await migrate_1.pool.query(`
SELECT
COUNT(*) FILTER (WHERE status = 'pending') as pending_count,
COUNT(*) FILTER (WHERE status = 'pending' AND requires_recrawl = TRUE) as pending_recrawl_count,
COUNT(*) FILTER (WHERE status = 'approved') as approved_count,
COUNT(*) FILTER (WHERE status = 'rejected') as rejected_count
FROM dispensary_changes
`);
res.json(result.rows[0]);
}
catch (error) {
console.error('Error fetching change stats:', error);
res.status(500).json({ error: 'Failed to fetch change stats' });
}
});
// Approve a change and apply it to the dispensary
router.post('/:id/approve', async (req, res) => {
const client = await migrate_1.pool.connect();
try {
await client.query('BEGIN');
const { id } = req.params;
const userId = req.user?.id; // From auth middleware
// Get the change record
const changeResult = await client.query(`
SELECT * FROM dispensary_changes WHERE id = $1 AND status = 'pending'
`, [id]);
if (changeResult.rows.length === 0) {
await client.query('ROLLBACK');
return res.status(404).json({ error: 'Pending change not found' });
}
const change = changeResult.rows[0];
// Apply the change to the dispensary table
const updateQuery = `
UPDATE dispensaries
SET ${change.field_name} = $1, updated_at = CURRENT_TIMESTAMP
WHERE id = $2
RETURNING *
`;
const dispensaryResult = await client.query(updateQuery, [
change.new_value,
change.dispensary_id
]);
if (dispensaryResult.rows.length === 0) {
await client.query('ROLLBACK');
return res.status(404).json({ error: 'Dispensary not found' });
}
// Mark the change as approved
await client.query(`
UPDATE dispensary_changes
SET
status = 'approved',
reviewed_at = CURRENT_TIMESTAMP,
reviewed_by = $1
WHERE id = $2
`, [userId, id]);
await client.query('COMMIT');
res.json({
message: 'Change approved and applied',
dispensary: dispensaryResult.rows[0],
requires_recrawl: change.requires_recrawl
});
}
catch (error) {
await client.query('ROLLBACK');
console.error('Error approving change:', error);
res.status(500).json({ error: 'Failed to approve change' });
}
finally {
client.release();
}
});
// Reject a change with optional reason
router.post('/:id/reject', async (req, res) => {
try {
const { id } = req.params;
const { reason } = req.body;
const userId = req.user?.id; // From auth middleware
const result = await migrate_1.pool.query(`
UPDATE dispensary_changes
SET
status = 'rejected',
reviewed_at = CURRENT_TIMESTAMP,
reviewed_by = $1,
rejection_reason = $2
WHERE id = $3 AND status = 'pending'
RETURNING *
`, [userId, reason, id]);
if (result.rows.length === 0) {
return res.status(404).json({ error: 'Pending change not found' });
}
res.json({
message: 'Change rejected',
change: result.rows[0]
});
}
catch (error) {
console.error('Error rejecting change:', error);
res.status(500).json({ error: 'Failed to reject change' });
}
});
exports.default = router;