Payment Requests
Self-service payment request system where administrators submit outgoing payment requests linked to fiscal invoices, and the finance team reviews, approves, schedules, and tracks payments through a defined lifecycle — integrated with Zoho Books for invoice management and automatic payment status synchronization.
Overview
The Payment Requests module allows any authorized administrator to create payment requests (optionally linked to existing invoices), which then go through an approval workflow managed by the finance team. Requests can be linked to invoices from the Zoho invoicing system, or created manually with tax configuration. The module supports multi-country tax handling via dynamic tax options per Zoho organization.
Key Concepts
| Concept | Description |
|---|---|
| Payment request | A record requesting an outgoing payment to a provider, with optional invoice linkage, classification, and banking data |
| Request status | Lifecycle state: pending, approved, rejected, programmed, paid, cancelled |
| Invoice linkage | Requests can be linked to existing zoho_invoices records by UUID search, auto-filling provider and amount data |
| Payment classification | Accounting account from zoho_accounts tree, used to classify the expense in Zoho Books |
| Tax configuration | Dynamic tax options per Zoho organization via zoho_organization_taxes table, used when programming requests without a linked invoice |
| Provider banking | Approved providers show read-only bank data; unapproved providers require bank, CLABE, and supporting documents |
| Auto-paid | Automatic status transition to paid when the linked invoice is paid via STP or marked as paid manually |
| Slack notifications | DM to creator on status changes (approve, reject, program, pay); channel alert when a user corrects/resubmits a request |
Data Flow
Main Flow: Create and Submit Payment Request
Flow: Approval and Programming
Flow: Automatic Payment Sync
Backend Structure
Route File
backend/routes/
└── finances.routes.js # Payment request routes under /finances/payment-requestsController and Library
- Controller:
backend/controllers/finances.controller.js— HTTP handlers delegating to the payment requests utility. - Library:
backend/libraries/payment-requests.util.js— Business logic for CRUD, status transitions, invoice creation, tax options, provider search, Slack notifications. - Constants:
backend/constants/finances.constants.js— Status enum, transition map, event types, Slack channel.
Integration Points
backend/jobs/zoho-payments.jobs.js— CallssyncPaymentRequestStatusafter STP payment completion.backend/libraries/zoho.util.js— CallssyncPaymentRequestStatusinmarkAsPaid().backend/jobs/zoho.jobs.js—processZohoBillusesoverride_account_idfrom linked payment requests.
Permissions
| Permission name | Use |
|---|---|
menu-payment-requests | Access own requests (create, view, delete pending, resubmit rejected) |
payment-requests-manage | Finance team — manage all requests (approve, reject, program, cancel, edit) |
Database
Tables
| Table | Purpose |
|---|---|
payment_requests | Request data: provider, amount, invoice linkage, status, banking, file URLs, audit fields |
payment_request_events | Full event history: status changes, edits, invoice linking, PDF uploads |
zoho_organization_taxes | Tax options per Zoho organization (rate, code, type, zoho_tax_id) |
zoho_invoices | Linked invoices (existing table) |
zoho_invoice_issuers | Provider/issuer data with bank details (existing table) |
zoho_invoice_receivers | Receiver/organization data (existing table) |
zoho_accounts | Accounting classification tree (existing table) |
Key Fields (payment_requests)
| Column | Description |
|---|---|
status | One of: pending, approved, rejected, programmed, paid, cancelled |
invoice_id | FK to zoho_invoices (nullable — null for manual requests) |
receiver_id | FK to zoho_invoice_receivers |
account_id | FK to zoho_accounts (payment classification) |
created_by | FK to users (request creator) |
reviewed_by | FK to users (admin who approved/rejected) |
programmed_by | FK to users (admin who scheduled payment) |
payment_date | Scheduled payment date (set when programmed) |
Key Decisions
| Decision | Reasoning | Alternatives Considered |
|---|---|---|
| Single approval level | Simplicity for V1; multi-level approval can be added later | Multi-level approval chain (complexity) |
| Invoice reclassification on programming | Ensures Zoho Books account matches the payment request classification | Manual reclassification (error-prone) |
| Dynamic tax options from zoho_organization_taxes | Multi-country support without hardcoded tax logic | Hardcoded per-country taxes (not scalable) |
| Fire-and-forget Slack notifications | Status transitions are not blocked by notification failures | Queued notifications (more complex) |
| Scoped visibility (own vs all) | Regular admins see only their requests; finance sees everything | Single permission level (less secure) |
Dependencies
- Internal: Zoho util (invoice sync, vendor lookup), Auth (JWT, permissions), Slack util (notifications), Queue system (Bull for zoho_bill jobs).
- External: Zoho Books API (invoice creation, reclassification), Slack API (DM and channel notifications), S3 (file storage).
Related Documentation
- API Endpoints — Endpoint reference for payment requests
- UI Screens & Flows — Frontend screens and components
- User Guide — How to use payment requests in the app
