const express = require('express'); const router = express.Router(); const { chartOfAccountsRepository, generalLedgerRepository } = require('../repositories'); /** * GET /api/plugins/financials/accounts * Get all accounts for the site */ router.get('/', async (req, res) => { try { const { site_id } = req.query; if (!site_id) { return res.status(400).json({ success: false, error: 'Missing required parameter: site_id' }); } // Get accounts from database using repository const accounts = await chartOfAccountsRepository.findBySiteId(site_id, { orderBy: 'account_code', orderDirection: 'asc' }); res.json({ success: true, data: accounts, message: 'Chart of accounts retrieved successfully' }); } catch (error) { console.error('Failed to get accounts:', error); res.status(500).json({ success: false, error: 'Failed to retrieve accounts', message: error.message }); } }); /** * GET /api/plugins/financials/accounts/:id * Get account by ID */ router.get('/:id', async (req, res) => { try { const { id } = req.params; const { site_id } = req.query; if (!site_id) { return res.status(400).json({ success: false, error: 'Missing required parameter: site_id' }); } // Get account from database const account = await chartOfAccountsRepository.findById(id); if (!account) { return res.status(404).json({ success: false, error: 'Account not found' }); } // Verify account belongs to site if (account.site_id !== site_id) { return res.status(403).json({ success: false, error: 'Access denied' }); } res.json({ success: true, data: account, message: 'Account details retrieved successfully' }); } catch (error) { console.error('Failed to get account:', error); res.status(500).json({ success: false, error: 'Failed to retrieve account', message: error.message }); } }); /** * POST /api/plugins/financials/accounts * Create new account */ router.post('/', async (req, res) => { try { const { site_id, account_code, account_name, account_type, parent_account_id, description, is_active } = req.body; // Validate required fields if (!site_id || !account_code || !account_name || !account_type) { return res.status(400).json({ success: false, error: 'Missing required fields', message: 'Site ID, account code, name, and type are required' }); } // Require authenticated user for created_by if (!req.user || !req.user.id) { return res.status(401).json({ success: false, error: 'Authentication required' }); } // Create account using repository const newAccount = await chartOfAccountsRepository.createAccount({ site_id, account_code, account_name, account_type, parent_account_id, description, is_active, created_by: req.user.id }); res.status(201).json({ success: true, data: newAccount, message: 'Account created successfully' }); } catch (error) { console.error('Failed to create account:', error); // Friendly handling of unique-violation or duplicate if (error && (error.code === '23505' || (typeof error.message === 'string' && /duplicate|exists/i.test(error.message)))) { return res.status(409).json({ success: false, error: 'Account code already exists', details: error.detail || error.message }); } // Ensure JSON response even for unexpected errors return res.status(500).json({ success: false, error: 'Failed to create account', details: error && (error.message || String(error)) }); } }); /** * PUT /api/plugins/financials/accounts/:id * Update account */ router.put('/:id', async (req, res) => { try { const { id } = req.params; const { site_id, account_name, description, is_active } = req.body; if (!site_id) { return res.status(400).json({ success: false, error: 'Missing required parameter: site_id' }); } // Get existing account const existingAccount = await chartOfAccountsRepository.findById(id); if (!existingAccount) { return res.status(404).json({ success: false, error: 'Account not found' }); } // Verify account belongs to site if (existingAccount.site_id !== site_id) { return res.status(403).json({ success: false, error: 'Access denied' }); } // Update account const updatedAccount = await chartOfAccountsRepository.updateAccount(id, { account_name, description, is_active }); res.json({ success: true, data: updatedAccount, message: 'Account updated successfully' }); } catch (error) { console.error('Failed to update account:', error); res.status(500).json({ success: false, error: 'Failed to update account', message: error.message }); } }); /** * DELETE /api/plugins/financials/accounts/:id * Delete account */ router.delete('/:id', async (req, res) => { try { const { id } = req.params; const { site_id } = req.query; if (!site_id) { return res.status(400).json({ success: false, error: 'Missing required parameter: site_id' }); } // Get existing account const existingAccount = await chartOfAccountsRepository.findById(id); if (!existingAccount) { return res.status(404).json({ success: false, error: 'Account not found' }); } // Verify account belongs to site if (existingAccount.site_id !== site_id) { return res.status(403).json({ success: false, error: 'Access denied' }); } // Check if account has transactions const hasTransactions = await chartOfAccountsRepository.hasTransactions(id); if (hasTransactions) { return res.status(400).json({ success: false, error: 'Cannot delete account with existing transactions', message: 'Please deactivate the account instead' }); } // Delete account await chartOfAccountsRepository.deleteById(id); res.json({ success: true, message: 'Account deleted successfully' }); } catch (error) { console.error('Failed to delete account:', error); res.status(500).json({ success: false, error: 'Failed to delete account', message: error.message }); } }); /** * GET /api/plugins/financials/accounts/:id/balance * Get account balance */ router.get('/:id/balance', async (req, res) => { try { const { id } = req.params; const { site_id, start_date, end_date } = req.query; if (!site_id) { return res.status(400).json({ success: false, error: 'Missing required parameter: site_id' }); } // Get account const account = await chartOfAccountsRepository.findById(id); if (!account) { return res.status(404).json({ success: false, error: 'Account not found' }); } // Calculate balance from transaction lines using General Ledger const options = {}; if (start_date) options.startDate = start_date; if (end_date) options.endDate = end_date; const balance = await generalLedgerRepository.getAccountBalance(id, site_id, options); balance.currency = 'USD'; res.json({ success: true, data: balance, message: 'Account balance retrieved successfully' }); } catch (error) { console.error('Failed to get account balance:', error); res.status(500).json({ success: false, error: 'Failed to retrieve account balance', message: error.message }); } }); module.exports = router;