Files
defi-arbitrage/docs/accounting/CHART_OF_ACCOUNTS_QUICK_FIXES.md
T
2026-03-02 12:14:07 -08:00

237 lines
6.0 KiB
Markdown

# Chart of Accounts - Quick Fix Implementation Guide
**Priority**: 🔴 Critical fixes to make routes accessible and secure
---
## Fix 1: Register Routes in Main App
**File**: `src/integration/api-gateway/app.ts`
**Add after line 252**:
```typescript
import chartOfAccountsRoutes from '@/core/accounting/chart-of-accounts.routes';
// ... existing code ...
app.use('/api/accounting/chart-of-accounts', chartOfAccountsRoutes);
```
**Location**: Add around line 252, after `nostroVostroRoutes`.
---
## Fix 2: Fix Route Conflict
**File**: `src/core/accounting/chart-of-accounts.routes.ts`
**Problem**: `/initialize` route conflicts with `/:accountCode` route.
**Solution**: Move `/initialize` route BEFORE parameterized routes:
```typescript
const router = Router();
// ✅ Initialize route FIRST (before parameterized routes)
router.post('/initialize', async (req, res) => {
// ... existing code ...
});
// Then other routes
router.get('/', async (req, res) => {
// ... existing code ...
});
// Parameterized routes come last
router.get('/:accountCode', async (req, res) => {
// ... existing code ...
});
```
---
## Fix 3: Add Basic Authentication
**File**: `src/core/accounting/chart-of-accounts.routes.ts`
**Add at top**:
```typescript
import { zeroTrustAuthMiddleware } from '@/integration/api-gateway/middleware/auth.middleware';
```
**Protect sensitive routes**:
```typescript
// Initialize - Admin only
router.post('/initialize',
zeroTrustAuthMiddleware,
async (req, res) => {
// Check if user has admin role
if (req.user?.role !== 'ADMIN') {
return res.status(403).json({ error: 'Admin access required' });
}
// ... existing code ...
}
);
// Create - Accountant/Admin
router.post('/',
zeroTrustAuthMiddleware,
async (req, res) => {
if (!['ACCOUNTANT', 'ADMIN'].includes(req.user?.role || '')) {
return res.status(403).json({ error: 'Insufficient permissions' });
}
// ... existing code ...
}
);
// Update - Accountant/Admin
router.put('/:accountCode',
zeroTrustAuthMiddleware,
async (req, res) => {
if (!['ACCOUNTANT', 'ADMIN'].includes(req.user?.role || '')) {
return res.status(403).json({ error: 'Insufficient permissions' });
}
// ... existing code ...
}
);
```
---
## Fix 4: Add Basic Input Validation
**File**: `src/core/accounting/chart-of-accounts.routes.ts`
**Add validation helper**:
```typescript
function validateAccountCode(code: string): boolean {
return /^\d{4,10}$/.test(code);
}
function validateCategory(category: string): boolean {
return ['ASSET', 'LIABILITY', 'EQUITY', 'REVENUE', 'EXPENSE', 'OTHER'].includes(category);
}
function validateNormalBalance(balance: string): boolean {
return ['DEBIT', 'CREDIT'].includes(balance);
}
```
**Add to POST route**:
```typescript
router.post('/', async (req, res) => {
try {
const { accountCode, accountName, category, normalBalance } = req.body;
// Validate required fields
if (!accountCode || !accountName || !category || !normalBalance) {
return res.status(400).json({ error: 'Missing required fields' });
}
// Validate format
if (!validateAccountCode(accountCode)) {
return res.status(400).json({ error: 'Account code must be 4-10 digits' });
}
if (!validateCategory(category)) {
return res.status(400).json({ error: 'Invalid category' });
}
if (!validateNormalBalance(normalBalance)) {
return res.status(400).json({ error: 'Normal balance must be DEBIT or CREDIT' });
}
const account = await chartOfAccountsService.createAccount(req.body);
res.status(201).json({ account });
} catch (error: any) {
res.status(400).json({ error: error.message });
}
});
```
---
## Fix 5: Add Parent Account Validation
**File**: `src/core/accounting/chart-of-accounts.service.ts`
**Update `createAccount` method**:
```typescript
async createAccount(account: Omit<ChartOfAccount, 'id'>): Promise<ChartOfAccount> {
// Validate parent exists if provided
if (account.parentAccountCode) {
const parent = await this.getAccountByCode(account.parentAccountCode);
if (!parent) {
throw new Error(`Parent account ${account.parentAccountCode} not found`);
}
// Validate category matches parent
if (parent.category !== account.category) {
throw new Error(`Account category must match parent category (${parent.category})`);
}
// Validate level is parent level + 1
if (account.level !== parent.level + 1) {
throw new Error(`Account level must be ${parent.level + 1} (parent level + 1)`);
}
}
// Validate normal balance matches category
const expectedBalance = this.getExpectedNormalBalance(account.category);
if (account.normalBalance !== expectedBalance) {
throw new Error(`Normal balance for ${account.category} should be ${expectedBalance}`);
}
// ... rest of existing implementation
}
private getExpectedNormalBalance(category: AccountCategory): 'DEBIT' | 'CREDIT' {
switch (category) {
case AccountCategory.ASSET:
case AccountCategory.EXPENSE:
return 'DEBIT';
case AccountCategory.LIABILITY:
case AccountCategory.EQUITY:
case AccountCategory.REVENUE:
return 'CREDIT';
default:
return 'DEBIT';
}
}
```
---
## Testing the Fixes
After implementing fixes 1-3, test:
```bash
# Test route registration
curl http://localhost:3000/api/accounting/chart-of-accounts
# Test initialize (should require auth)
curl -X POST http://localhost:3000/api/accounting/chart-of-accounts/initialize
# Test create with validation
curl -X POST http://localhost:3000/api/accounting/chart-of-accounts \
-H "Content-Type: application/json" \
-d '{"accountCode": "9999", "accountName": "Test Account"}'
# Should return validation error
```
---
## Summary
These 5 fixes address the most critical issues:
1. ✅ Routes will be accessible
2. ✅ Route conflicts resolved
3. ✅ Basic security added
4. ✅ Input validation added
5. ✅ Data integrity improved
**Estimated Time**: 2-3 hours
**Priority**: 🔴 Critical