const express = require('express'); const router = express.Router(); const { Client } = require('ssh2'); const mysql = require('mysql2/promise'); // Helper function to setup SSH tunnel async function setupSshTunnel() { const sshConfig = { host: process.env.PROD_SSH_HOST, port: process.env.PROD_SSH_PORT || 22, username: process.env.PROD_SSH_USER, privateKey: process.env.PROD_SSH_KEY_PATH ? require('fs').readFileSync(process.env.PROD_SSH_KEY_PATH) : undefined, compress: true }; const dbConfig = { host: process.env.PROD_DB_HOST || 'localhost', user: process.env.PROD_DB_USER, password: process.env.PROD_DB_PASSWORD, database: process.env.PROD_DB_NAME, port: process.env.PROD_DB_PORT || 3306, timezone: 'Z' }; return new Promise((resolve, reject) => { const ssh = new Client(); ssh.on('error', (err) => { console.error('SSH connection error:', err); reject(err); }); ssh.on('ready', () => { ssh.forwardOut( '127.0.0.1', 0, dbConfig.host, dbConfig.port, (err, stream) => { if (err) reject(err); resolve({ ssh, stream, dbConfig }); } ); }).connect(sshConfig); }); } // Get all options for import fields router.get('/field-options', async (req, res) => { let ssh; let connection; try { // Setup SSH tunnel and get database connection const tunnel = await setupSshTunnel(); ssh = tunnel.ssh; // Create MySQL connection over SSH tunnel connection = await mysql.createConnection({ ...tunnel.dbConfig, stream: tunnel.stream }); // Fetch companies (type 1) const [companies] = await connection.query(` SELECT cat_id, name FROM product_categories WHERE type = 1 ORDER BY name `); // Fetch artists (type 40) const [artists] = await connection.query(` SELECT cat_id, name FROM product_categories WHERE type = 40 ORDER BY name `); // Fetch sizes (type 50) const [sizes] = await connection.query(` SELECT cat_id, name FROM product_categories WHERE type = 50 ORDER BY name `); // Fetch themes with subthemes const [themes] = await connection.query(` SELECT t.cat_id, t.name AS display_name, t.type, t.name AS sort_theme, '' AS sort_subtheme, 1 AS level_order FROM product_categories t WHERE t.type = 20 UNION ALL SELECT ts.cat_id, CONCAT(t.name,' - ',ts.name) AS display_name, ts.type, t.name AS sort_theme, ts.name AS sort_subtheme, 2 AS level_order FROM product_categories ts JOIN product_categories t ON ts.master_cat_id = t.cat_id WHERE ts.type = 21 AND t.type = 20 ORDER BY sort_theme, sort_subtheme `); // Fetch categories with all levels const [categories] = await connection.query(` SELECT s.cat_id, s.name AS display_name, s.type, s.name AS sort_section, '' AS sort_category, '' AS sort_subcategory, '' AS sort_subsubcategory, 1 AS level_order FROM product_categories s WHERE s.type = 10 UNION ALL SELECT c.cat_id, CONCAT(s.name,' - ',c.name) AS display_name, c.type, s.name AS sort_section, c.name AS sort_category, '' AS sort_subcategory, '' AS sort_subsubcategory, 2 AS level_order FROM product_categories c JOIN product_categories s ON c.master_cat_id = s.cat_id WHERE c.type = 11 AND s.type = 10 UNION ALL SELECT sc.cat_id, CONCAT(s.name,' - ',c.name,' - ',sc.name) AS display_name, sc.type, s.name AS sort_section, c.name AS sort_category, sc.name AS sort_subcategory, '' AS sort_subsubcategory, 3 AS level_order FROM product_categories sc JOIN product_categories c ON sc.master_cat_id = c.cat_id JOIN product_categories s ON c.master_cat_id = s.cat_id WHERE sc.type = 12 AND c.type = 11 AND s.type = 10 UNION ALL SELECT ssc.cat_id, CONCAT(s.name,' - ',c.name,' - ',sc.name,' - ',ssc.name) AS display_name, ssc.type, s.name AS sort_section, c.name AS sort_category, sc.name AS sort_subcategory, ssc.name AS sort_subsubcategory, 4 AS level_order FROM product_categories ssc JOIN product_categories sc ON ssc.master_cat_id = sc.cat_id JOIN product_categories c ON sc.master_cat_id = c.cat_id JOIN product_categories s ON c.master_cat_id = s.cat_id WHERE ssc.type = 13 AND sc.type = 12 AND c.type = 11 AND s.type = 10 ORDER BY sort_section, sort_category, sort_subcategory, sort_subsubcategory `); // Fetch colors const [colors] = await connection.query(` SELECT color, name, hex_color FROM product_color_list ORDER BY \`order\` `); // Fetch suppliers const [suppliers] = await connection.query(` SELECT supplierid as value, companyname as label FROM suppliers WHERE companyname <> '' ORDER BY companyname `); // Fetch tax categories const [taxCategories] = await connection.query(` SELECT tax_code_id as value, name as label FROM product_tax_codes ORDER BY tax_code_id = 0 DESC, name `); res.json({ companies: companies.map(c => ({ label: c.name, value: c.cat_id.toString() })), artists: artists.map(a => ({ label: a.name, value: a.cat_id.toString() })), sizes: sizes.map(s => ({ label: s.name, value: s.cat_id.toString() })), themes: themes.map(t => ({ label: t.display_name, value: t.cat_id.toString(), type: t.type, level: t.level_order })), categories: categories.map(c => ({ label: c.display_name, value: c.cat_id.toString(), type: c.type, level: c.level_order })), colors: colors.map(c => ({ label: c.name, value: c.color, hexColor: c.hex_color })), suppliers: suppliers, taxCategories: taxCategories, shippingRestrictions: [ { label: "None", value: "0" }, { label: "US Only", value: "1" }, { label: "Limited Quantity", value: "2" }, { label: "US/CA Only", value: "3" }, { label: "No FedEx 2 Day", value: "4" }, { label: "North America Only", value: "5" } ] }); } catch (error) { console.error('Error fetching import field options:', error); res.status(500).json({ error: 'Failed to fetch import field options' }); } finally { if (connection) await connection.end(); if (ssh) ssh.end(); } }); // Get product lines for a specific company router.get('/product-lines/:companyId', async (req, res) => { let ssh; let connection; try { // Setup SSH tunnel and get database connection const tunnel = await setupSshTunnel(); ssh = tunnel.ssh; // Create MySQL connection over SSH tunnel connection = await mysql.createConnection({ ...tunnel.dbConfig, stream: tunnel.stream }); const [lines] = await connection.query(` SELECT cat_id as value, name as label FROM product_categories WHERE type = 2 AND master_cat_id = ? ORDER BY name `, [req.params.companyId]); res.json(lines.map(l => ({ label: l.label, value: l.value.toString() }))); } catch (error) { console.error('Error fetching product lines:', error); res.status(500).json({ error: 'Failed to fetch product lines' }); } finally { if (connection) await connection.end(); if (ssh) ssh.end(); } }); // Get sublines for a specific product line router.get('/sublines/:lineId', async (req, res) => { let ssh; let connection; try { // Setup SSH tunnel and get database connection const tunnel = await setupSshTunnel(); ssh = tunnel.ssh; // Create MySQL connection over SSH tunnel connection = await mysql.createConnection({ ...tunnel.dbConfig, stream: tunnel.stream }); const [sublines] = await connection.query(` SELECT cat_id as value, name as label FROM product_categories WHERE type = 3 AND master_cat_id = ? ORDER BY name `, [req.params.lineId]); res.json(sublines.map(s => ({ label: s.label, value: s.value.toString() }))); } catch (error) { console.error('Error fetching sublines:', error); res.status(500).json({ error: 'Failed to fetch sublines' }); } finally { if (connection) await connection.end(); if (ssh) ssh.end(); } }); module.exports = router;