import express from 'express'; import dotenv from 'dotenv'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { getPool } from '../utils/db.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); dotenv.config({ path: path.join(__dirname, "../../.env") }); const router = express.Router(); // Phase 6.2: template edits require templates_write. Reads pass through. import { requirePermission } from '../../shared/auth/middleware.js'; router.use((req, res, next) => { if (req.method === 'GET' || req.method === 'HEAD' || req.method === 'OPTIONS') return next(); return requirePermission('templates_write')(req, res, next); }); // Get all templates router.get('/', async (req, res) => { try { const pool = getPool(); if (!pool) { throw new Error('Database pool not initialized'); } const result = await pool.query(` SELECT * FROM templates ORDER BY company ASC, product_type ASC `); res.json(result.rows); } catch (error) { console.error('Error fetching templates:', error); res.status(500).json({ error: 'Failed to fetch templates', details: error instanceof Error ? error.message : 'Unknown error' }); } }); // Get template by company and product type router.get('/:company/:productType', async (req, res) => { try { const { company, productType } = req.params; const pool = getPool(); if (!pool) { throw new Error('Database pool not initialized'); } const result = await pool.query(` SELECT * FROM templates WHERE company = $1 AND product_type = $2 `, [company, productType]); if (result.rows.length === 0) { return res.status(404).json({ error: 'Template not found' }); } res.json(result.rows[0]); } catch (error) { console.error('Error fetching template:', error); res.status(500).json({ error: 'Failed to fetch template', details: error instanceof Error ? error.message : 'Unknown error' }); } }); // Create new template router.post('/', async (req, res) => { try { const { company, product_type, supplier, msrp, cost_each, qty_per_unit, case_qty, hts_code, description, weight, length, width, height, tax_cat, size_cat, categories, ship_restrictions } = req.body; // Validate required fields if (!company || !product_type) { return res.status(400).json({ error: 'Company and Product Type are required' }); } const pool = getPool(); if (!pool) { throw new Error('Database pool not initialized'); } const result = await pool.query(` INSERT INTO templates ( company, product_type, supplier, msrp, cost_each, qty_per_unit, case_qty, hts_code, description, weight, length, width, height, tax_cat, size_cat, categories, ship_restrictions ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17) RETURNING * `, [ company, product_type, supplier, msrp, cost_each, qty_per_unit, case_qty, hts_code, description, weight, length, width, height, tax_cat, size_cat, categories, ship_restrictions ]); res.status(201).json(result.rows[0]); } catch (error) { console.error('Error creating template:', error); // Check for unique constraint violation (PostgreSQL error code 23505) if (error?.code === '23505') { return res.status(409).json({ error: 'A template already exists for this company and product type combination. Please edit the existing template instead.', }); } res.status(500).json({ error: 'Failed to create template', details: error instanceof Error ? error.message : 'Unknown error' }); } }); // Update template router.put('/:id', async (req, res) => { try { const { id } = req.params; const { company, product_type, supplier, msrp, cost_each, qty_per_unit, case_qty, hts_code, description, weight, length, width, height, tax_cat, size_cat, categories, ship_restrictions } = req.body; // Validate required fields if (!company || !product_type) { return res.status(400).json({ error: 'Company and Product Type are required' }); } const pool = getPool(); if (!pool) { throw new Error('Database pool not initialized'); } const result = await pool.query(` UPDATE templates SET company = $1, product_type = $2, supplier = $3, msrp = $4, cost_each = $5, qty_per_unit = $6, case_qty = $7, hts_code = $8, description = $9, weight = $10, length = $11, width = $12, height = $13, tax_cat = $14, size_cat = $15, categories = $16, ship_restrictions = $17 WHERE id = $18 RETURNING * `, [ company, product_type, supplier, msrp, cost_each, qty_per_unit, case_qty, hts_code, description, weight, length, width, height, tax_cat, size_cat, categories, ship_restrictions, id ]); if (result.rows.length === 0) { return res.status(404).json({ error: 'Template not found' }); } res.json(result.rows[0]); } catch (error) { console.error('Error updating template:', error); // Check for unique constraint violation (PostgreSQL error code 23505) if (error?.code === '23505') { return res.status(409).json({ error: 'A template already exists for this company and product type combination. Please edit the existing template instead.', }); } res.status(500).json({ error: 'Failed to update template', details: error instanceof Error ? error.message : 'Unknown error' }); } }); // Delete template router.delete('/:id', async (req, res) => { try { const { id } = req.params; const pool = getPool(); if (!pool) { throw new Error('Database pool not initialized'); } const result = await pool.query('DELETE FROM templates WHERE id = $1 RETURNING *', [id]); if (result.rows.length === 0) { return res.status(404).json({ error: 'Template not found' }); } res.json({ message: 'Template deleted successfully' }); } catch (error) { console.error('Error deleting template:', error); res.status(500).json({ error: 'Failed to delete template', details: error instanceof Error ? error.message : 'Unknown error' }); } }); // Error handling middleware router.use((err, req, res, next) => { console.error('Template route error:', err); res.status(500).json({ error: 'Internal server error', details: err.message }); }); export default router;