Files
MixedAssets/server/routes/close.js

80 lines
3.2 KiB
JavaScript

const express = require('express');
const { requireCapability } = require('../middleware/auth');
const close = require('../services/closePeriods');
const router = express.Router();
const reader = requireCapability('finance.view');
const closer = requireCapability('finance.close');
// Period close (month-end / year-end). All scoped to the active company (req.companyId).
router.get('/close-periods', reader, (req, res) => {
res.json({ periods: close.listPeriods(req.companyId, req.query.book || null) });
});
// Step definitions for the wizard (month vs year).
router.get('/close-periods/step-defs', reader, (req, res) => {
res.json({ month: close.stepDefs('month'), year: close.stepDefs('year') });
});
router.post('/close-periods/start', closer, (req, res, next) => {
try {
const period = close.getOrStart(req.companyId, req.body.book, req.body.period_type || 'month', req.body.fiscal_year, req.body.period_month, req.user.id);
res.status(201).json({ period, steps: close.stepDefs(period.period_type) });
} catch (error) {
next(error);
}
});
router.get('/close-periods/:id', reader, (req, res) => {
const period = close.getPeriod(req.params.id, req.companyId);
if (!period) return res.status(404).json({ error: 'Close period not found' });
return res.json({ period, steps: close.stepDefs(period.period_type), data: close.stepData(period, req.companyId) });
});
function withPeriod(handler) {
return (req, res, next) => {
const period = close.getPeriod(req.params.id, req.companyId);
if (!period) return res.status(404).json({ error: 'Close period not found' });
try {
return handler(period, req, res);
} catch (error) {
return next(error);
}
};
}
router.post('/close-periods/:id/steps/:key', closer, withPeriod((period, req, res) => {
res.json({ period: close.recordStep(period.id, req.params.key, req.body || {}, req.user.id, req.companyId) });
}));
router.post('/close-periods/:id/post-depreciation', closer, withPeriod((period, req, res) => {
const summary = close.postDepreciation(period, req.user.id, req.companyId);
res.json({ summary, period: close.getPeriod(period.id, req.companyId) });
}));
router.post('/close-periods/:id/post-disposals', closer, withPeriod((period, req, res) => {
res.json({ result: close.postDisposalEntries(period, req.user.id, req.companyId) });
}));
router.post('/close-periods/:id/reconcile', closer, withPeriod((period, req, res) => {
const reconciliation = close.reconcile(period, req.companyId);
res.json({ reconciliation, period: close.getPeriod(period.id, req.companyId) });
}));
router.post('/close-periods/:id/wip/:assetId/capitalize', closer, withPeriod((period, req, res) => {
const asset = close.capitalizeWip(Number(req.params.assetId), req.body || {}, req.user.id, req.companyId);
if (!asset) return res.status(404).json({ error: 'Asset not found' });
return res.json({ asset });
}));
router.post('/close-periods/:id/finalize', closer, withPeriod((period, req, res) => {
res.json({ period: close.finalize(period, req.user.id, req.companyId, req.body || {}) });
}));
router.post('/close-periods/:id/reopen', closer, withPeriod((period, req, res) => {
res.json({ period: close.reopen(period.id, req.user.id, req.companyId) });
}));
module.exports = router;