* fix(accounts): wrap loose finance_book in max() in Trial Balance (Simple) (Postgres)
The Trial Balance (Simple) Query Report selects `finance_book` but groups only
by `fiscal_year, company, posting_date, account`. PostgreSQL rejects the
non-grouped, non-aggregated column:
column "tabGL Entry.finance_book" must appear in the GROUP BY clause or be
used in an aggregate function
MariaDB tolerates it and returns an arbitrary finance_book per group.
Wrapping it in `max(finance_book)` keeps the row count identical (the GROUP BY
is unchanged) and makes PostgreSQL valid. Adding finance_book to GROUP BY would
split each group into N rows and change the MariaDB row count, so it is not an
option. This replaces MariaDB's previously arbitrary finance_book value with a
deterministic one (the only sanctioned MariaDB-output change); the row count is
preserved.
* fix(accounts): make Sales Partners Commission valid on Postgres (ORDER BY + div-by-zero)
The Sales Partners Commission Query Report had two PostgreSQL problems:
1. It ended with `ORDER BY "Total Commission:Currency:120"`, but the alias the
query produces is `"Total Commission:Currency:170"` (width 170, not 120), so
the ORDER BY never referenced a real output column. On MariaDB a double-quoted
token is a string literal — a no-op sort that never errored. On PostgreSQL a
double-quoted token is an identifier, so it errors with
`column "Total Commission:Currency:120" does not exist` (and single-quoting it
instead trips `non-integer constant in ORDER BY`). Since the clause was always
a no-op on MariaDB, it is removed — MariaDB's group-order output is unchanged
and the report runs on PostgreSQL.
2. `sum(total_commission)*100 / sum(amount_eligible_for_commission)` has an
unguarded divisor: the inner query filters `total_commission`/`base_net_total`
but not `amount_eligible_for_commission`, so a partner whose rows sum to 0
there makes MariaDB return NULL but PostgreSQL raise `division by zero`. Wrap
it in `NULLIF(sum(amount_eligible_for_commission), 0)` — NULL on both engines.
Both verified live on MariaDB and PostgreSQL.
Accounts module contains masters and transactions to manage a traditional double entry accounting system.
Accounting heads are called "Accounts" and they can be groups in a tree like "Chart of Accounts"
Entries are:
- Journal Entries
- Sales Invoice (Itemised)
- Purchase Invoice (Itemised)
All accounting entries are stored in the General Ledger
Payment Ledger
Transactions on Receivable and Payable Account types will also be stored in Payment Ledger. This is so that payment reconciliation process only requires update on this ledger.
Key Fields
| Field | Description |
|---|---|
account_type |
Receivable/Payable |
account |
Accounting head |
party |
Party Name |
voucher_no |
Voucher No |
against_voucher_no |
Linked voucher(secondary effect) |
amount |
can be +ve/-ve |
Design
debit and credit have been replaced with account_type and amount. against_voucher_no is populated for all entries. So, outstanding amount can be calculated by summing up amount only using against_voucher_no.
Ex:
- Consider an invoice for ₹100 and a partial payment of ₹80 against that invoice. Payment Ledger will have following entries.
| voucher_no | against_voucher_no | amount |
|---|---|---|
| SINV-01 | SINV-01 | 100 |
| PAY-01 | SINV-01 | -80 |
- Reconcile a Credit Note against an invoice using a Journal Entry
An invoice for ₹100 partially reconciled against a credit of ₹70 using a Journal Entry. Payment Ledger will have the following entries.
| voucher_no | against_voucher_no | amount |
|---|---|---|
| SINV-01 | SINV-01 | 100 |
| CR-NOTE-01 | CR-NOTE-01 | -70 |
| JE-01 | CR-NOTE-01 | +70 |
| JE-01 | SINV-01 | -70 |