amélrioration

This commit is contained in:
2026-06-18 21:45:05 +02:00
parent fea1d787ca
commit b2e73b4fe7
3 changed files with 249 additions and 31 deletions
+9
View File
@@ -2003,4 +2003,13 @@ console.log('[DB] Migrations 2FA OK');
}
}
{
// Migration : assigned_to sur tickets
const cols = db.prepare("PRAGMA table_info(tickets)").all().map(c => c.name);
if (!cols.includes('assigned_to')) {
db.exec("ALTER TABLE tickets ADD COLUMN assigned_to INTEGER REFERENCES users(id) ON DELETE SET NULL");
console.log('[DB] tickets: colonne assigned_to ajoutée');
}
}
export default db;
+27 -4
View File
@@ -144,8 +144,11 @@ router.get('/:id', (req, res) => {
const isAdmin = role === 'admin';
const ticket = db.prepare(`
SELECT t.*, u.display_name as user_name, u.email as user_email
FROM tickets t JOIN users u ON u.id = t.user_id
SELECT t.*, u.display_name as user_name, u.email as user_email,
a.display_name as assigned_name
FROM tickets t
JOIN users u ON u.id = t.user_id
LEFT JOIN users a ON a.id = t.assigned_to
WHERE t.id = ?
`).get(req.params.id);
@@ -194,7 +197,12 @@ router.post('/:id/messages', upload.array('attachments', 10), (req, res) => {
}
}
db.prepare("UPDATE tickets SET updated_at = datetime('now') WHERE id = ?").run(ticket.id);
// Réouverture automatique si l'émetteur répond sur un ticket en attente
if (!isAdmin && ticket.status === 'pending') {
db.prepare("UPDATE tickets SET status = 'open', updated_at = datetime('now') WHERE id = ?").run(ticket.id);
} else {
db.prepare("UPDATE tickets SET updated_at = datetime('now') WHERE id = ?").run(ticket.id);
}
return messageId;
});
@@ -224,7 +232,7 @@ router.post('/:id/messages', upload.array('attachments', 10), (req, res) => {
// ── PATCH /api/tickets/:id/status — résoudre / rouvrir (admin) ────────────
router.patch('/:id/status', requireAdmin, (req, res) => {
const { status } = req.body;
if (!['open', 'resolved'].includes(status)) return res.status(400).json({ error: 'Statut invalide' });
if (!['open', 'resolved', 'pending'].includes(status)) return res.status(400).json({ error: 'Statut invalide' });
const ticket = db.prepare('SELECT id FROM tickets WHERE id = ?').get(req.params.id);
if (!ticket) return res.status(404).json({ error: 'Ticket introuvable' });
@@ -234,6 +242,21 @@ router.patch('/:id/status', requireAdmin, (req, res) => {
res.json({ ok: true });
});
// ── PATCH /api/tickets/:id/assign — assigner à un admin ──────────────────────
router.patch('/:id/assign', requireAdmin, (req, res) => {
const { assigned_to } = req.body; // null pour désassigner
if (assigned_to !== null && assigned_to !== undefined) {
const admin = db.prepare("SELECT id FROM users WHERE id = ? AND role = 'admin'").get(assigned_to);
if (!admin) return res.status(400).json({ error: 'Utilisateur invalide ou non admin' });
}
const ticket = db.prepare('SELECT id FROM tickets WHERE id = ?').get(req.params.id);
if (!ticket) return res.status(404).json({ error: 'Ticket introuvable' });
db.prepare("UPDATE tickets SET assigned_to = ?, updated_at = datetime('now') WHERE id = ?")
.run(assigned_to ?? null, req.params.id);
res.json({ ok: true });
});
// ── PUT /api/tickets/:id/messages/:msgId — éditer un message (5 min) ────────
router.put('/:id/messages/:msgId', (req, res) => {
const { id: userId } = req.user;