Organization Settings
Self-service configuration module for managing Zoho organization resources — taxes, chart of accounts, and bank accounts — with bidirectional synchronization to Zoho Books API.
Overview
The Organization Settings module gives the finance team a unified interface to configure per-organization resources that were previously managed through SQL scripts or direct Zoho Books access. It centralizes tax configuration, chart of accounts management, and bank account registration into a tabbed offcanvas panel accessible from the organizations list.
Key Concepts
| Concept | Description |
|---|---|
| Organization | A Zoho Books organization (receiver entity) representing a legal entity with its own tax rules and accounts |
| Individual Tax | A single tax rate (e.g., IVA 16%) synced bidirectionally with Zoho Books |
| Tax Group | A combined retention composed of 2+ individual taxes, stored as a single Zoho tax group ID |
| Chart of Account | A 2-level hierarchical classification for expenses/income, synced from Zoho's chart of accounts |
| Bank Account | A payment method (bank, cash, credit card) linked to a Zoho bank account |
| Sync Preview | A comparison between Zoho's remote data and local DB, showing what's missing before bulk import |
Data Flow
Tax CRUD with Zoho Sync
Account Sync from Zoho
Bank Sync from Zoho
Backend Structure
Business Logic
backend/libraries/
└── organization-settings.util.js # All business logic (taxes, accounts, banks)The utility class handles:
- Tax CRUD with Zoho sync dispatch (individual vs. group)
- Account CRUD with 2-level hierarchy validation and Zoho sync
- Bank CRUD with activate/deactivate toggle
- Sync preview (compare Zoho remote vs. local DB) for taxes, accounts, and banks
- Bulk sync (insert missing records from Zoho)
Zoho Service Methods
backend/services/zoho/index.js| Method | Zoho Endpoint | Purpose |
|---|---|---|
listTaxes(orgId, taxType) | GET /v3/settings/taxes | Fetch all taxes (or by type) |
getTaxGroup(orgId, groupId) | GET /v3/settings/taxgroups/{id} | Fetch group member details |
createTax / updateTax / deleteTax | POST/PUT/DELETE /v3/settings/taxes | Individual tax CRUD |
createTaxGroup / updateTaxGroup / deleteTaxGroup | POST/PUT/DELETE /v3/settings/taxgroups | Tax group CRUD |
listChartOfAccounts(orgId, accountType) | GET /v3/chartofaccounts | Fetch accounts with optional type filter |
createChartOfAccount / updateChartOfAccount | POST/PUT /v3/chartofaccounts | Account CRUD |
markChartOfAccountActive / markChartOfAccountInactive | POST /v3/chartofaccounts/{id}/active|inactive | Toggle account status |
listBankAccounts(orgId) | GET /v3/bankaccounts | Fetch all bank accounts |
Controller & Routes
All handlers are in backend/controllers/finances.controller.js and routes in backend/routes/finances.routes.js under the /finances/organization/ prefix.
Database
Tables
| Table | Purpose |
|---|---|
zoho_organization_taxes | Unified storage for individual taxes and tax groups (self-referencing via child_ids) |
zoho_accounts | Chart of accounts with 2-level hierarchy (parent_account_id), linked to departments |
zoho_banks | Bank/payment method accounts per organization |
zoho_invoice_receivers | Organizations (used as read-only source for the organization list) |
Entity Relationship
Key Fields
zoho_organization_taxes
| Column | Type | Description |
|---|---|---|
id | INT (PK) | Auto-increment |
zoho_organization_id | INT | Reference to receiver's Zoho org ID |
tax_key | VARCHAR(50) | Unique key per org (auto-generated from label) |
label | VARCHAR(100) | Human-readable name |
rate | DECIMAL(10,6) | Tax rate as decimal (0.16 = 16%) |
tax_type | ENUM | transferred or retained |
type | ENUM | individual or group |
child_ids | JSON | Array of IDs from same table (groups only) |
zoho_tax_id | VARCHAR(100) | Zoho Books tax/group ID |
zoho_accounts
| Column | Type | Description |
|---|---|---|
id | INT (PK) | Auto-increment |
organization_id | VARCHAR(100) | Zoho organization ID |
account_id | VARCHAR(100) | Zoho chart of accounts ID |
name | VARCHAR(120) | Normalized identifier (auto-generated from description) |
description | VARCHAR(255) | Human-readable name |
account_type | VARCHAR(100) | Zoho account type (expense, income, asset, etc.) |
parent_account_id | INT (FK, self) | Parent account for 2-level nesting |
department_id | INT (FK) | Department assignment (parent accounts only) |
active | TINYINT | 1 = active, 0 = inactive |
zoho_banks
| Column | Type | Description |
|---|---|---|
id | INT (PK) | Auto-increment |
organization_id | VARCHAR(100) | Zoho organization ID |
account_id | VARCHAR(100) | Zoho bank account ID |
name | VARCHAR(100) | Normalized identifier (auto-generated from description) |
description | VARCHAR(255) | Human-readable name |
account_type | VARCHAR(50) | bank, cash, or credit_card |
active | TINYINT | 1 = active, 0 = inactive |
Key Decisions
| Decision | Reasoning | Alternatives Considered |
|---|---|---|
Unified zoho_organization_taxes table for individuals + groups | Groups behave identically to individual taxes in the API. Self-referencing child_ids JSON avoids pivot table complexity. | Separate group table + pivot (more JOINs, 3-table schema) |
| 2-level max hierarchy for accounts | Zoho Books supports parent/child accounts but not deeper nesting. Matches Zoho's constraint. | Unlimited nesting (over-engineering, Zoho doesn't support it) |
Auto-generated name from description | Technical identifiers (name) are normalized from user input (description) to avoid user mistakes and ensure consistency. | Manual name entry (error-prone, inconsistent formatting) |
| Account type filter for sync | Zoho can have hundreds of accounts. Filtering by type (Expense, Income, etc.) before fetching prevents overwhelming the user. | Fetch all at once (too many results, slow UI) |
| Department assignment only on parent accounts | Sub-accounts inherit context from their parent. Assigning departments at child level creates redundancy. | Department on all levels (confusing, contradictory assignments) |
| Activate/deactivate instead of delete | Preserves referential integrity — existing invoices and payment requests may reference these records. | Hard delete (breaks references), soft delete without toggle (no reactivation) |
Dependencies
- Internal: Payment Requests module (uses
getTaxOptionsfor tax selection), Invoice Form (shared tax options) - External: Zoho Books API (bidirectional sync for taxes, accounts, banks)
Related Documentation
- API Endpoints — Complete endpoint reference for this module
- UI Screens & Flows — Frontend screens and user interactions
- User Guide — End-user instructions
