Interest Calculator for ERPNext v16 — Simple & Compound interest on GL balances
- Python 96.2%
- CSS 1.9%
- JavaScript 1.9%
- interest_rule.py: add from frappe import _, wrap error strings - interest_ledger.py: import Decimal helpers from engine (D, R2, to_float, constants) instead of duplicating 30 lines - interest_overdue_analysis.py: same — import from engine, remove duplicate helpers Eliminates code duplication. All Decimal logic is single-source in interest_calculation.py. |
||
|---|---|---|
| interest_calculator | ||
| README.md | ||
| requirements.txt | ||
| setup.py | ||
Interest Calculator
ERPNext v16 app for financial interest computation with full GL posting, tax compliance, and settlement tracking.
Features
Core Engine
- Simple & Compound Interest — configurable per rule
- Calculation Frequencies — Daily, Monthly, Quarterly, Half-Yearly, Yearly
- GL Filters — Account, Party Type, Party, Cost Centre, Project
- Balance Types — Any Balance, Debit Only (Overdue), Credit Only (Overdue)
- Base Amount — Closing Balance, Debit Total, or Credit Total
- Pure Decimal arithmetic —
ROUND_HALF_UPthroughout, no float drift - Leap-year aware — uses
calendar.monthrangefor month-end dates
GL Posting
- Auto-create Journal Entry on Submit — posts interest to GL
- Receivable & Payable — correct debit/credit for both directions
- Party integration — auto-applies party_type/party from rule to Receivable/Payable JE lines
Tax Compliance
- TDS (Tax Deducted at Source) — configurable per rule: section (194A/I/C/H/J), rate, threshold, account
- GST (Goods & Services Tax) — configurable per rule: treatment, rate, HSN/SAC code, account
- India Compliance compatible — passes GST accounts and GSTIN for validation when the India Compliance app is installed
Settlement Tracking
- Interest Settlement child table — record payment allocations with reference + TDS
- Computed fields —
total_settled,pending_interest,settlement_status(Accrued / Partially / Fully) - Works for both receivable and payable
Automation
- Batch Calculate — create Interest Calculations for multiple rules at once
- Scheduled Calculations —
Interest Scheduledoctype with daily cron job (Monthly/Quarterly/Yearly) - Auto-submit option — schedules can auto-submit created calculations
DocTypes
| DocType | Type | Purpose |
|---|---|---|
| Interest Rule | Master | Defines rate, method, frequency, GL filters, TDS, GST, and posting accounts |
| Interest Calculation | Transaction (Submittable) | Stores a calculation run with entries, JE reference, settlement data |
| Interest Calculation Entry | Child Table | One row per period with GL data + interest amount |
| Interest Settlement | Child Table | Payment allocations against an interest calculation |
| Interest Schedule | Master | Recurring calculation config for automation |
Reports
| Report | Type | Description |
|---|---|---|
| Interest Ledger | Script Report (file-based) | GL-style view: 3 modes — Saved Calc / On-the-fly / Aggregate. Full Decimal. |
| Interest Overdue Analysis | Script Report (file-based) | Aging report by party with 0-30/31-60/61-90/90+ day buckets |
Print Formats
| Format | Purpose |
|---|---|
| Interest Certificate | Professional PDF with period breakdown, TDS, settlement history, signatory line |
Architecture
Interest Calculation Workflow
Draft → [Calculate Interest] → Calculated → [Submit] → Submitted
↓
Auto-creates Journal Entry
(with TDS + GST if configured)
JE Structure (Receivable, ₹10,000 interest, 10% TDS, 18% GST)
Debit: Party Account ₹10,800 (gross + GST - TDS)
Credit: GST Payable ₹1,800
Credit: TDS Payable ₹1,000
Credit: Interest Income ₹10,000
JE Structure (Payable, same amounts)
Debit: Interest Expense ₹10,000
Debit: GST Input ₹1,800
Credit: TDS Payable ₹1,000
Credit: Party Account ₹10,800
Decimal Pipeline
GL Entry (float) → D() → Decimal arithmetic → quantize(ROUND_HALF_UP) → to_float() → Frappe field
All financial math uses Python's decimal.Decimal. float only touches data at the Frappe field boundary.
Installation
bench get-app https://git.ashu.io/ashuio/interest_calculator.git
bench --site <site-name> install-app interest_calculator
bench --site <site-name> migrate
bench build
Optional: India Compliance
For GST validation and GSTR reporting:
bench get-app https://github.com/resilient-tech/india-compliance --branch version-16
bench --site <site-name> install-app india_compliance
The Interest Calculator passes GST accounts and party GSTIN to Journal Entries. India Compliance hooks validate these on JE submit. No hard dependency.
Usage
Quick Start
- Create an Interest Rule — set rate, type, frequency, GL account, posting accounts
- Create an Interest Calculation — link the rule, set dates, click Calculate Interest
- Review entries — verify the period breakdown
- Submit — auto-creates Journal Entry with TDS/GST
- View — Interest Ledger report or Interest Certificate PDF
Batch Calculation
# Via bench console or API
frappe.call(
"interest_calculator.interest_calculator.doctype.interest_calculation.interest_calculation.batch_calculate",
interest_rules=json.dumps(["Rule A", "Rule B"]),
from_date="2026-01-01",
to_date="2026-06-30"
)
Scheduled Calculations
- Create an Interest Schedule — link a rule, set frequency + day of month
- Enable it — the daily cron picks it up automatically
- Set
auto_submitif you want auto-finalization
Formulas
Simple Interest:
Interest = Principal × Rate × (Days / 365)
Compound Interest:
A = P × (1 + r/n)^(n×t)
via exp(n×t × ln(1+r/n)) — pure Decimal, no float
Interest = A - P
Where n = compounding periods per year, t = time in years.
The 365-day year convention follows RBI guidelines for Indian banking — leap years are not adjusted.
Technical Notes
- Frappe v16 tested — file-based reports (
is_standard: Yes),before_submitvalidation guards - Button workaround — client script (
interest_calculation.js) bypasses Frappe v16run_doc_methodlist-format bug - Scheduler — daily cron in
hooks.pyrunsrun_scheduled_calculations()for enabled schedules - Naming —
IC-{####}autoname with series counter intabSeries - Cache discipline — clear
__pycache__+bench clear-cache+bench restartafter deploying Python updates - Stale code — Docker containers can accumulate root-owned file copies at shallow paths. Deploy only to the deep module path (where
__pycache__lives). Usedocker exec -u rootto nuke stale copies.
License
MIT © 2026 Ashutosh Varma