Skip to content
ERPNext Data Model
Esc
navigateopen⌘Jpreview
On this page

Invoice Discounting (Factoring)

A design reference for pledging accounts-receivable balances as collateral for a short-term loan

1. Requirements

1.1 Functional requirements

  • Let a legal entity bundle outstanding sales invoices into a single financing arrangement, pledged as collateral for a short-term loan against a financier, with a start date and a period in days from which an end date is derived automatically.
  • Prevent an invoice from being pledged twice — an invoice already in another submitted arrangement cannot join a new one — and never let a pledged row’s amount exceed that invoice’s actual outstanding balance.
  • The moment the arrangement is confirmed, reclassify the receivable balance of every pledged invoice into a dedicated clearing account, so the ledger shows immediately that collection rights are encumbered, before any cash moves.
  • Record the cash disbursement from the financier, net of bank charges, and book the corresponding loan liability; later, close the arrangement, repay the financier, and correctly handle whichever pledged invoices the customer has — or hasn’t — paid back by then.
  • Ensure any later settlement raised against a pledged invoice resolves automatically to whichever ledger account currently holds that invoice’s balance, never the original account, once the arrangement is disbursed or settled.
  • Surface the discounting state on the invoice itself, as a flag and a status-label suffix, so receivables reporting shows which invoices are financed.

1.2 Non-functional requirements

  • Guarded transitions: a disbursement or closing posting is rejected outright if the arrangement isn’t currently in the exact prior status that posting expects — no silent status drift.
  • Auditability: every stage after the initial pledge is a real, human-reviewed, submittable journal referencing the arrangement by name, not a background job.
  • Currency correctness: the initial reclassification posting converts the invoice’s outstanding balance to the legal entity’s base currency using that invoice’s own conversion rate.

1.3 Constraints

  • Built from just two records: the arrangement header and a child table of pledged invoice rows. There is no separate financier master — only a designated loan-liability account and a bank account chosen at arrangement creation.
  • Disbursement and settlement are not postings the arrangement submits on its own; it only prepares an unsaved journal, and its status advances only once that journal is later submitted or cancelled.
  • Only the accounts-receivable side is covered — no equivalent payable-side factoring workflow exists in this module.

2. High-Level Design

2.1 Component diagram

2.2 What submitting the arrangement does

On submit — after the validations in §3.4 pass — the arrangement sums its pledged rows into a total amount, derives the loan end date from the start date and period, flags every pledged sales invoice as discounted, posts the Stage 1 movement in §3.2 into the general-ledger posting funnel described in the general-ledger design (tagged against each invoice as source voucher), and advances its own status to Sanctioned.


3. Deep Dive

3.1 Data model

Discounting Arrangement — the header record: posting date, loan start date, loan period (days), a read-only computed loan end date, the pledged-invoice table, a computed total amount, an optional bank-charges amount, and the accounts named in §2.1, all scoped to the arrangement’s legal entity.

Pledged Invoice Line — one row per pledged sales invoice: the invoice link, customer and posting date (fetched from the invoice), outstanding amount, and the invoice’s own original receivable account, retained so the sanctioning posting knows which account to move the balance out of.

3.2 Status lifecycle and ledger movements

Each transition after Draft is driven by a real posting, not a status field set directly. The three stages, in the debit/credit shape the code produces:

Stage 1 — Sanctioning (posted automatically on the arrangement’s own submit, once per pledged invoice, converted to the legal entity’s base currency):

Dr  Discounting Clearing Account          outstanding_amount
    Cr  <the invoice's own original receivable account>   outstanding_amount

Both legs carry the customer as party and the invoice as source voucher — only the account holding the balance changes.

Stage 2 — Disbursement (drafted by “Disburse Loan”; takes effect once the operator submits it):

Dr  Bank Account                     total_amount − bank_charges
Dr  Bank Charges Account             bank_charges        (only if bank_charges > 0)
    Cr  Financier Loan Account            total_amount
Dr  Discounted Receivable Account    outstanding_amount   (per pledged invoice)
    Cr  Discounting Clearing Account      outstanding_amount   (per pledged invoice)

Submitting this journal flips the arrangement from Sanctioned to Disbursed; it’s rejected if the arrangement isn’t currently Sanctioned.

Stage 3 — Settlement / Close (drafted by “Close Loan”):

Dr  Financier Loan Account            total_amount
    Cr  Bank Account                       total_amount

This always repays the financier. A second pair of legs is appended per pledged invoice, only if the loan closes before its computed end date and that invoice still shows an outstanding balance — the customer hasn’t paid it back, so this is a short payment relative to the loan closing:

Cr  Discounted Receivable Account     outstanding_amount   (invoice still open)
Dr  Unpaid Receivable Account         outstanding_amount   (invoice still open)

If the loan closes at or after its end date, or the invoice is already paid off, these two legs are omitted — the balance is assumed already resolved through the customer-payment path below. Submitting the settlement journal flips the arrangement from Disbursed to Settled, only if it is currently Disbursed.

3.3 How a customer’s eventual payment closes the loop

Every place that raises a settlement entry against a sales invoice — a manual receipt or a general journal “money received” posting — first asks a resolver for that invoice’s current receivable account instead of assuming its original one: if the invoice’s arrangement is Disbursed, it returns the Discounted Receivable Account; if Settled, the Unpaid Receivable Account; otherwise the invoice’s ordinary account, unchanged.

This is what lets the customer’s payment land correctly regardless of stage: the settlement’s debit leg hits whichever account currently carries the balance, drives the invoice’s outstanding amount to zero as an ordinary payment would, and leaves nothing stray in the original account (already zeroed by Stage 1).

The invoice’s computed status reflects this: while its arrangement is Disbursed and the invoice would otherwise show Unpaid, Partly Paid, or Overdue, the label gets an “and Discounted” suffix — a display detail from a lookup that checks specifically for the Disbursed state.

3.4 Error handling

  • Duplicate / over-pledging: rejected at save time against all currently-submitted arrangements and the invoice’s live outstanding balance.
  • Missing loan terms: submit is blocked if start date or period is absent.
  • Out-of-sequence postings: the disbursement and settlement journals each assert the arrangement’s current status before changing it; cancelling either journal reverses the status symmetrically.

4. Scale and Reliability

This is a low-volume, manually-operated back-office workflow, not a high-throughput integration: arrangements are created a handful at a time, and every advancing step needs a person to submit a drafted journal, so there’s no concurrency concern comparable to transaction-processing paths elsewhere in the system. What matters is correctness — the status guard on each journal stops a posting happening twice or out of order, and the resolver being consulted by every settlement path (not a dedicated one) stops a customer payment from missing the reclassified balance. The main operational risk is human delay between drafting a journal and submitting it: the arrangement sits in its prior status with no reminder or timeout observed in this module.


5. Trade-off Analysis

Decision Trade-off
Two-step, human-reviewed postings (draft, then manual submit) Lets an accountant correct amounts before they post, at the cost of a status that can sit “in between” if nobody submits the drafted journal.
Three separate receivable accounts (Clearing, Discounted, Unpaid) instead of one Self-documents which stage a balance is in, at the cost of more chart-of-accounts setup per arrangement.
Financier represented only by a loan account and a bank account, no financier master Minimal setup, but nowhere to record financier-specific terms (rate, limit, tenure) beyond one arrangement.
Receivable resolution done centrally, consulted by every settlement path One point of correctness, but the invoice’s own receivable field becomes misleading read in isolation.
Early-close re-pointing keyed off “is the end date still in the future” Cheap to compute, but conflates financier-initiated and voluntary early repayment into one boolean.

6. What to Revisit as the System Grows

  • Stuck-arrangement monitoring: nothing flags an arrangement whose journal was drafted but never submitted; a simple aging report would close that gap.
  • Financier as a first-class party: today the financier is implicit in an account choice; multiple financiers with different terms would call for promoting it to its own linked record.
  • Cancellation safety: the arrangement’s cancellation path does not appear to check whether a linked disbursement or settlement journal is still submitted, nor cascade-cancel one — worth hardening before real volume.

This is a genuinely small module — two records and three status-changing postings — so this document is intentionally short; the source offers no further workflow depth to justify padding it.

Was this page helpful?