plugin-financials/routes/budgets.js
2025-11-03 13:51:33 +02:00

240 lines
No EOL
6 KiB
JavaScript

const express = require('express');
const router = express.Router();
const { budgetRepository, budgetItemRepository } = require('../repositories');
/**
* Check if site has access to budgeting feature (premium)
* Budgeting is available in Professional and Enterprise plans
*/
async function hasBudgetingAccess(site_id) {
// TODO: Implement subscription check
// For now, assume all sites have access for testing
return true;
}
/**
* GET /api/plugins/financials/budgets
* Get all budgets for a site
*/
router.get('/', async (req, res) => {
try {
const { site_id } = req.query;
if (!site_id) {
return res.status(400).json({
success: false,
error: 'site_id query parameter is required'
});
}
// Check feature access
if (!(await hasBudgetingAccess(site_id))) {
return res.status(403).json({
success: false,
error: 'Budgeting feature not available',
message: 'Please upgrade to Professional or Enterprise plan to access budgeting features'
});
}
const budgets = await budgetRepository.findBySiteId(site_id);
res.json({
success: true,
data: budgets,
message: 'Budgets retrieved successfully'
});
} catch (error) {
console.error('Failed to get budgets:', error);
res.status(500).json({
success: false,
error: 'Failed to retrieve budgets',
message: error.message
});
}
});
/**
* GET /api/plugins/financials/budgets/:id
* Get budget 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: 'site_id is required'
});
}
// Check feature access
if (!(await hasBudgetingAccess(site_id))) {
return res.status(403).json({
success: false,
error: 'Budgeting feature not available',
message: 'Please upgrade to Professional or Enterprise plan to access budgeting features'
});
}
const budget = await budgetRepository.findById(id);
if (!budget) {
return res.status(404).json({
success: false,
error: 'Budget not found'
});
}
// Verify budget belongs to site
if (budget.site_id !== site_id) {
return res.status(403).json({
success: false,
error: 'Access denied'
});
}
// Get budget items
const items = await budgetItemRepository.findByBudgetId(id);
res.json({
success: true,
data: {
...budget,
items
},
message: 'Budget details retrieved successfully'
});
} catch (error) {
console.error('Failed to get budget:', error);
res.status(500).json({
success: false,
error: 'Failed to retrieve budget',
message: error.message
});
}
});
/**
* POST /api/plugins/financials/budgets
* Create a new budget
*/
router.post('/', async (req, res) => {
try {
const { site_id, name, description, fiscal_year, start_date, end_date, total_amount, status, items, created_by } = req.body;
if (!site_id || !name || !fiscal_year || !start_date || !end_date || !total_amount) {
return res.status(400).json({
success: false,
error: 'Missing required fields',
message: 'Site ID, name, fiscal year, start date, end date, and total amount are required'
});
}
// Check feature access
if (!(await hasBudgetingAccess(site_id))) {
return res.status(403).json({
success: false,
error: 'Budgeting feature not available',
message: 'Please upgrade to Professional or Enterprise plan to access budgeting features'
});
}
const budget = await budgetRepository.createBudget({
site_id,
name,
description,
fiscal_year,
start_date,
end_date,
total_amount,
status,
created_by: created_by || req.user?.id || 'system'
});
// Create budget items if provided
if (items && Array.isArray(items)) {
for (const item of items) {
await budgetItemRepository.createItem({
budget_id: budget.id,
account_id: item.account_id,
planned_amount: item.planned_amount,
notes: item.notes
});
}
}
res.status(201).json({
success: true,
data: budget,
message: 'Budget created successfully'
});
} catch (error) {
console.error('Failed to create budget:', error);
res.status(500).json({
success: false,
error: 'Failed to create budget',
message: error.message
});
}
});
/**
* POST /api/plugins/financials/budgets/:id/items
* Add budget item
*/
router.post('/:id/items', async (req, res) => {
try {
const { id } = req.params;
const { account_id, planned_amount, notes } = req.body;
const { site_id } = req.query;
if (!site_id) {
return res.status(400).json({
success: false,
error: 'site_id is required'
});
}
// Validate required fields
if (!account_id || !planned_amount) {
return res.status(400).json({
success: false,
error: 'Missing required fields',
message: 'Account ID and planned amount are required'
});
}
// Check feature access
if (!(await hasBudgetingAccess(site_id))) {
return res.status(403).json({
success: false,
error: 'Budgeting feature not available',
message: 'Please upgrade to Professional or Enterprise plan to access budgeting features'
});
}
const item = await budgetItemRepository.createItem({
budget_id: id,
account_id,
planned_amount,
notes
});
res.status(201).json({
success: true,
data: item,
message: 'Budget item added successfully'
});
} catch (error) {
console.error('Failed to add budget item:', error);
res.status(500).json({
success: false,
error: 'Failed to add budget item',
message: error.message
});
}
});
module.exports = router;