Stock is scoped to a catalog + cost centers only, per direction that physical GRV/stock-take/recipe transactions belong in an external system (Matrix), not this accounting app. Stock Control/GRN/Variance/ PPV GL accounts are now plain postable accounts rather than locked control accounts. Also fixes session loss on page refresh: auth stores now persist to localStorage, and ProtectedRoute waits for rehydration before deciding to redirect to login. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JWqiUSojMLUoN7mrJqdEbN
44 lines
1.7 KiB
TypeScript
44 lines
1.7 KiB
TypeScript
import { Request, Response } from 'express';
|
|
import { z } from 'zod';
|
|
import * as glAccountsService from './glAccounts.service';
|
|
|
|
const glAccountTypeSchema = z.enum(['ASSET', 'LIABILITY', 'EQUITY', 'INCOME', 'EXPENSE']);
|
|
const debitCreditSchema = z.enum(['DEBIT', 'CREDIT']);
|
|
const controlAccountTypeSchema = z.enum(['AR', 'AP', 'TAX_OUTPUT', 'TAX_INPUT', 'BANK', 'RETAINED_EARNINGS']);
|
|
|
|
export const createGLAccountSchema = z.object({
|
|
accountName: z.string().min(1),
|
|
accountType: glAccountTypeSchema,
|
|
normalBalance: debitCreditSchema,
|
|
isControlAccount: z.boolean().optional(),
|
|
controlType: controlAccountTypeSchema.optional(),
|
|
isPostable: z.boolean().optional(),
|
|
segmentSelections: z
|
|
.array(z.object({ segmentDefId: z.number().int(), segmentValueId: z.number().int() }))
|
|
.min(1),
|
|
});
|
|
|
|
export const listGLAccountsQuerySchema = z.object({
|
|
branchScope: z.string().optional(),
|
|
accountType: glAccountTypeSchema.optional(),
|
|
});
|
|
|
|
export async function createGLAccountHandler(req: Request, res: Response): Promise<void> {
|
|
const input = req.body as z.infer<typeof createGLAccountSchema>;
|
|
res.status(201).json(await glAccountsService.createGLAccount(input));
|
|
}
|
|
|
|
export async function listGLAccountsHandler(req: Request, res: Response): Promise<void> {
|
|
const { accountType } = req.query as unknown as z.infer<typeof listGLAccountsQuerySchema>;
|
|
res.json(await glAccountsService.listGLAccounts(req.branchScope!, accountType));
|
|
}
|
|
|
|
export async function getGLAccountHandler(req: Request, res: Response): Promise<void> {
|
|
const account = await glAccountsService.getGLAccountByCode(req.params.accountCode);
|
|
if (!account) {
|
|
res.status(404).json({ error: 'GL account not found' });
|
|
return;
|
|
}
|
|
res.json(account);
|
|
}
|