Files
ns_erpnext_app/ns_app/hooks.py
Norman King acd7df1129 feat(statements): bill late fee as a collectible Sales Invoice
Charge a late-payment fee when statements are generated so the customer's
receivable reflects it (the gap ERPNext Dunning leaves — it never
increases AR). The fee is billed as a submitted Sales Invoice (item ->
Dunning Type income account, rate = computed fee) rather than a Journal
Entry, so the app's existing payment flow (Run Payment / AutoPay /
multi-invoice) charges and settles it automatically via its Sales Invoice
references — a bare JE would sit uncollected.

Fee schedule/amounts come from the existing Dunning Type settings (yearly
rate_of_interest + flat dunning_fee), interest computed with ERPNext's own
Dunning formula. The fee Item is configured via a new Late Fee Item custom
field on Dunning Type (created in an after_migrate hook; ns_app/setup.py).
Nothing is auto-seeded: generation stops with a clear error if no Dunning
Type is configured or its income account / fee item is unset.

Billing is idempotent per customer/company/month, and prior fee invoices
are excluded from the interest base (no fee-on-fee). The fee invoice shows
on the statement flagged 'late fee', folded into Total Due (which equals
the customer's balance and is fully collectible).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 19:35:04 -04:00

39 lines
846 B
Python

app_name = "ns_app"
app_title = "NS App"
app_publisher = "NS Innovations"
app_description = "Custom ERPNext extensions"
app_email = "dev@nsinnovations.net"
app_license = "MIT"
# Load on every page
app_include_js = [
"/assets/ns_app/js/customer_quick_entry.js"
]
# Load on Sales Invoice form
doctype_js = {
"Sales Invoice": "public/js/sales_invoice.js"
}
# Load on Customer list view (adds "Generate Statements" action)
doctype_list_js = {
"Customer": "public/js/customer_list.js"
}
# Ensure custom fields exist after every migrate
after_migrate = "ns_app.setup.after_migrate"
# Fixtures tracked in Git
fixtures = [
{
"dt": "Print Format",
"filters": [
["name", "in", [
"NS Invoice",
"NS Sales Order",
"NS Quotation"
]]
]
}
]