import express from 'express'; import { body, validationResult } from 'express-validator'; import pool from '../config/database.js'; import { authenticateToken, requireTenant } from '../middleware/auth.js'; import { upload } from '../middleware/upload.js'; const router = express.Router(); router.use(authenticateToken, requireTenant); const baseSelect = ` SELECT r.*, k.name AS kunde_name, a.bezeichnung AS artikel_bezeichnung, a.pfand_betrag, m.name AS mitarbeiter_name FROM ruecknahmen r LEFT JOIN kunden k ON r.kunde_id = k.id LEFT JOIN artikel a ON r.artikel_id = a.id LEFT JOIN mitarbeiter m ON r.mitarbeiter_id = m.id`; router.get('/', async (req, res) => { try { const [rows] = await pool.query( `${baseSelect} WHERE r.tenant_id = ? ORDER BY r.erstellt_am DESC`, [req.user.tenant_id] ); res.json(rows); } catch (e) { res.status(500).json({ error: 'Serverfehler' }); } }); router.get('/kunde/:kunde_id', async (req, res) => { try { const [rows] = await pool.query( `${baseSelect} WHERE r.tenant_id = ? AND r.kunde_id = ? ORDER BY r.erstellt_am DESC`, [req.user.tenant_id, req.params.kunde_id] ); res.json(rows); } catch (e) { res.status(500).json({ error: 'Serverfehler' }); } }); router.post('/', upload.single('foto'), [ body('kunde_id').notEmpty(), body('artikel_id').notEmpty(), body('anzahl').isInt({ min: 1 }) ], async (req, res) => { const errors = validationResult(req); if (!errors.isEmpty()) return res.status(400).json({ errors: errors.array() }); const foto_url = req.file ? `/uploads/${req.file.filename}` : null; try { const [[k]] = await pool.query('SELECT id FROM kunden WHERE id=? AND tenant_id=?', [req.body.kunde_id, req.user.tenant_id]); const [[a]] = await pool.query('SELECT id FROM artikel WHERE id=? AND tenant_id=?', [req.body.artikel_id, req.user.tenant_id]); if (!k || !a) return res.status(400).json({ error: 'Kunde oder Artikel nicht im Tenant' }); const [result] = await pool.query( `INSERT INTO ruecknahmen (tenant_id, kunde_id, artikel_id, anzahl, foto_url, mitarbeiter_id) VALUES (?, ?, ?, ?, ?, ?)`, [req.user.tenant_id, req.body.kunde_id, req.body.artikel_id, req.body.anzahl, foto_url, req.user.id] ); const [rows] = await pool.query(`${baseSelect} WHERE r.id = ?`, [result.insertId]); res.status(201).json(rows[0]); } catch (e) { console.error('POST rücknahmen:', e); res.status(500).json({ error: 'Serverfehler' }); } }); router.delete('/:id', async (req, res) => { try { const [r] = await pool.query('DELETE FROM ruecknahmen WHERE id=? AND tenant_id=?', [req.params.id, req.user.tenant_id]); if (r.affectedRows === 0) return res.status(404).json({ error: 'Rücknahme nicht gefunden' }); res.json({ message: 'Rücknahme gelöscht' }); } catch (e) { res.status(500).json({ error: 'Serverfehler' }); } }); // POST /bulk - mehrere Positionen mit einem gemeinsamen Foto router.post('/bulk', upload.single('foto'), async (req, res) => { let positionen; try { positionen = JSON.parse(req.body.positionen || '[]'); } catch { return res.status(400).json({ error: 'positionen muss gueltiges JSON-Array sein' }); } if (!Array.isArray(positionen) || positionen.length === 0) return res.status(400).json({ error: 'Mindestens eine Position erforderlich' }); for (const p of positionen) { if (!p.artikel_id || !Number.isInteger(parseInt(p.anzahl)) || parseInt(p.anzahl) < 1) return res.status(400).json({ error: 'Jede Position braucht artikel_id und anzahl >= 1' }); } const kundeId = req.body.kunde_id; if (!kundeId) return res.status(400).json({ error: 'kunde_id fehlt' }); const foto_url = req.file ? `/uploads/${req.file.filename}` : null; const conn = await pool.getConnection(); try { await conn.beginTransaction(); const [[k]] = await conn.query('SELECT id FROM kunden WHERE id=? AND tenant_id=?', [kundeId, req.user.tenant_id]); if (!k) { await conn.rollback(); return res.status(400).json({ error: 'Kunde nicht im Tenant' }); } const artikelIds = positionen.map(p => p.artikel_id); const [artRows] = await conn.query( `SELECT id FROM artikel WHERE tenant_id=? AND id IN (?)`, [req.user.tenant_id, artikelIds] ); if (artRows.length !== new Set(artikelIds).size) { await conn.rollback(); return res.status(400).json({ error: 'Mindestens ein Artikel nicht im Tenant' }); } const insertedIds = []; for (const p of positionen) { const [r] = await conn.query( `INSERT INTO ruecknahmen (tenant_id, kunde_id, artikel_id, anzahl, foto_url, mitarbeiter_id) VALUES (?, ?, ?, ?, ?, ?)`, [req.user.tenant_id, kundeId, p.artikel_id, parseInt(p.anzahl), foto_url, req.user.id] ); insertedIds.push(r.insertId); } await conn.commit(); const [rows] = await pool.query( `${baseSelect} WHERE r.id IN (?) ORDER BY r.id`, [insertedIds] ); res.status(201).json({ count: rows.length, items: rows, foto_url }); } catch (e) { await conn.rollback(); console.error('POST ruecknahmen bulk:', e); res.status(500).json({ error: 'Serverfehler' }); } finally { conn.release(); } }); export default router;