feat: Implement new General Ledger frontend section with comprehensive report screens and cash/bank account management

- Added a new Ledgers sidebar section for statutory-format financial reports and cash/bank-account management.
- Introduced dedicated GL client for API interactions, handling response envelopes and error management.
- Developed report screens for Trial Balance, Balance Sheet, General Ledger, Profit & Loss, Cash Flow, Budget vs Actual, and a new Tax Report.
- Implemented CSV download functionality alongside existing PDF downloads for all report screens.
- Separated Cash and Bank accounts into distinct tables/endpoints, with updated create forms and unified list view.
- Created a new Accounts section for Cheque Management, moving Cash/Bank Accounts from the Ledgers section.
- Updated RBAC navigation to include new permissions and sub-navigation items for the added features.
- Ensured compliance with GL's updated API contract, including renaming fields and adjusting response shapes.
- Addressed various bugs and presentation issues, enhancing user experience across the new module.
This commit is contained in:
2026-07-31 17:57:55 +05:30
parent 76484c7268
commit 22657f0910
49 changed files with 5707 additions and 27 deletions
@@ -0,0 +1,55 @@
// Client-side UX validation only (docs/20-FRONTEND.md §3.1) — required fields the browser
// already knows about. Everything else is server-authoritative and surfaced via the GL
// service's own error message (lib/error-map.ts).
export function validateBankAccountForm(input: { accountName: string }): Record<string, string> {
const errors: Record<string, string> = {}
if (!input.accountName.trim()) errors.accountName = "Account name is required"
return errors
}
export function validateChequeBookForm(input: {
branchId: string
bankAccountId: string
chequeBookNo: string
startChequeNo: string
endChequeNo: string
totalLeaves: string
receivedDate: string
}): Record<string, string> {
const errors: Record<string, string> = {}
if (!input.branchId.trim()) errors.branchId = "Branch ID is required"
if (!input.bankAccountId) errors.bankAccountId = "Select a bank account"
if (!input.chequeBookNo.trim()) errors.chequeBookNo = "Cheque book number is required"
if (!input.startChequeNo.trim()) errors.startChequeNo = "Start cheque number is required"
if (!input.endChequeNo.trim()) errors.endChequeNo = "End cheque number is required"
if (!input.totalLeaves.trim()) errors.totalLeaves = "Total leaves is required"
if (!input.receivedDate) errors.receivedDate = "Received date is required"
return errors
}
export function validateIssueChequeForm(input: { payeeName: string; issueDate: string; amount: string }): Record<string, string> {
const errors: Record<string, string> = {}
if (!input.payeeName.trim()) errors.payeeName = "Payee name is required"
if (!input.issueDate) errors.issueDate = "Issue date is required"
if (!input.amount.trim() || Number(input.amount) <= 0) errors.amount = "Amount must be greater than 0"
return errors
}
export function validateReceivedChequeForm(input: {
companyId: string
receivedFromName: string
chequeNo: string
chequeDate: string
amount: string
receivedDate: string
}): Record<string, string> {
const errors: Record<string, string> = {}
if (!input.companyId.trim()) errors.companyId = "Company ID is required"
if (!input.receivedFromName.trim()) errors.receivedFromName = "Received-from name is required"
if (!input.chequeNo.trim()) errors.chequeNo = "Cheque number is required"
if (!input.chequeDate) errors.chequeDate = "Cheque date is required"
if (!input.amount.trim() || Number(input.amount) <= 0) errors.amount = "Amount must be greater than 0"
if (!input.receivedDate) errors.receivedDate = "Received date is required"
return errors
}