# Deferred Revenue Accounting Workflow in ERPNext: How to Process Deferred Expenses

> Learn the ERPNext deferred revenue accounting workflow and how to process deferred expenses. Automate recognition and GL entries with scheduled background jobs.

- Repository: [Frappe/erpnext](https://github.com/frappe/erpnext)
- Tags: how-to-guide
- Published: 2026-05-20

---

**ERPNext automates deferred revenue and expense recognition by spreading invoice amounts over service periods via scheduled background jobs that book GL entries monthly, using validation and calculation logic defined in [`erpnext/accounts/deferred_revenue.py`](https://github.com/frappe/erpnext/blob/main/erpnext/accounts/deferred_revenue.py).**

The deferred revenue accounting workflow in ERPNext handles subscription-based services and multi-period contracts by gradually recognizing income and expenses rather than recording them immediately upon invoicing. This open-source ERP system, maintained by Frappe, provides a complete framework for managing deferred expenses through automated monthly postings, manual processing capabilities, and comprehensive reporting tools that track actual versus expected recognition.

## Setting Up Deferred Revenue and Expense Items

Before processing deferred expenses or revenue, you must configure items to support gradual recognition over service periods. ERPNext defers amounts at the invoice line level based on flags set in the item master and company configuration.

### Configure Item Masters with Deferred Flags

In [`erpnext/stock/doctype/item/item.py`](https://github.com/frappe/erpnext/blob/main/erpnext/stock/doctype/item/item.py), each item can be configured with boolean fields that enable deferred accounting workflows. Navigate to **Stock > Item** and check **Enable Deferred Revenue** for sales items or **Enable Deferred Expense** for purchase items. When these flags are active, the system recognizes that amounts should not post immediately to income or expense accounts.

### Define Company Default Accounts

The [`erpnext/setup/doctype/company/company.py`](https://github.com/frappe/erpnext/blob/main/erpnext/setup/doctype/company/company.py) file (lines 260-261) manages default ledger accounts for deferred transactions. Configure **Default Deferred Revenue Account** and **Default Deferred Expense Account** in the **Company** master to ensure GL entries post to the correct balance sheet accounts when processing deferred expenses automatically.

### Invoice Line Configuration

When creating a **Sales Invoice** or **Purchase Invoice**, enable deferred accounting on each line item by checking **Enable Deferred Revenue** or **Enable Deferred Expense**. Set the **Service Start Date**, **Service End Date**, and optionally a **Service Stop Date** to define the recognition period. The system validates these dates using `validate_service_stop_date()` in [`erpnext/accounts/deferred_revenue.py`](https://github.com/frappe/erpnext/blob/main/erpnext/accounts/deferred_revenue.py) to ensure chronological consistency.

## The Three-Phase Deferred Revenue Accounting Workflow

ERPNext implements deferred accounting through a structured workflow that separates initial recording from periodic recognition.

### Phase 1: Invoice Creation and Validation

The workflow begins when you submit an invoice containing deferred items. The `validate_service_stop_date()` function (lines 24-33 in [`erpnext/accounts/deferred_revenue.py`](https://github.com/frappe/erpnext/blob/main/erpnext/accounts/deferred_revenue.py)) ensures service dates are logical and that stop dates fall within the service period. Upon submission, the invoice creates a receivable/payable entry, but the full amount remains in the deferred account rather than hitting revenue or expense accounts immediately.

### Phase 2: Periodic Posting via Scheduled Jobs

At month-end, the `process_deferred_accounting()` function (lines 32-49) executes as a background job. This function:

1. Checks the `automatically_process_deferred_accounting_entry` setting in Accounts Settings
2. Creates a **Process Deferred Accounting** document for each company and type (Income/Expense)
3. Triggers `book_deferred_income_or_expense()` to iterate through eligible invoice items
4. Generates GL entries for the portion of revenue or expense attributable to the current period

If errors occur during processing, ERPNext sends email notifications to system managers via the `send_mail()` function.

### Phase 3: Reporting and Recognition Tracking

The **Deferred Revenue & Expense** report aggregates recognition data using [`erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.py`](https://github.com/frappe/erpnext/blob/main/erpnext/accounts/report/deferred_revenue_and_expense/deferred_revenue_and_expense.py). This report displays actual posted amounts alongside simulated future postings generated by `simulate_future_posting()`, allowing finance teams to view recognized versus expected revenue across custom periods.

## How ERPNext Calculates Deferred Amounts

The core calculation logic in [`erpnext/accounts/deferred_revenue.py`](https://github.com/frappe/erpnext/blob/main/erpnext/accounts/deferred_revenue.py) determines how much revenue or expense to recognize in each period.

### Determining the Booking Window

The `get_booking_dates()` function (lines 28-85) calculates the start and end dates for the next posting slice. It evaluates the latest existing GL entry for the line item or defaults to the service start date, respecting service stop dates and month-end boundaries.

### Monthly vs. Day-Based Proration

ERPNext supports two calculation methods controlled by the `book_deferred_entries_based_on` setting:

- **Monthly-based** (default): `calculate_monthly_amount()` prorates the net amount over total service months, applying partial-month factors when periods don't align with calendar months
- **Day-based**: `calculate_amount()` spreads the net amount over exact service days

Both functions query `get_already_booked_amount()` to deduct previously recognized amounts, ensuring the final slice caps at the remaining balance (`base_amount = self.base_net_amount - already_booked_amount`).

### GL Entry Creation Methods

Depending on the **Accounts Settings** flag `book_deferred_entries_via_journal_entry`, ERPNext posts recognition through:

- **Direct GL entries** via `make_gl_entries()` (lines 64-84), debiting the expense/revenue account and crediting the deferred account
- **Journal Entry** documents via `book_revenue_via_journal_entry()` (lines 48-60)

Both methods link entries to the **Process Deferred Accounting** document through the `against_voucher_type` field.

## Processing Deferred Expenses Manually

While ERPNext runs deferred accounting automatically via scheduler, you can process deferred expenses manually for specific periods or data corrections.

Run the standard workflow from the bench console:

```python
from erpnext.accounts.deferred_revenue import process_deferred_accounting
process_deferred_accounting()  # Processes previous month for all companies

```

Alternatively, create a **Process Deferred Accounting** document manually in the UI:

1. Navigate to **Setup > Process Deferred Accounting**
2. Select **New** and configure:
   - **Company**: Target company
   - **Type**: Expense (or Income)
   - **Posting Date**, **Start Date**, **End Date**: Define the recognition period
3. Save and Submit to trigger `book_deferred_income_or_expense()`

## Summary

- **Deferred accounting** spreads revenue and expenses over service periods rather than recognizing them immediately upon invoicing
- **Configuration** requires enabling deferred flags on items, setting company default accounts in [`company.py`](https://github.com/frappe/erpnext/blob/main/company.py), and defining service dates on invoice lines
- **Automated processing** runs monthly via `process_deferred_accounting()` in [`deferred_revenue.py`](https://github.com/frappe/erpnext/blob/main/deferred_revenue.py), creating GL entries that move amounts from deferred balance sheet accounts to P&L accounts
- **Calculation methods** include monthly proration (`calculate_monthly_amount`) and day-based spreading (`calculate_amount`)
- **Manual processing** is available through the **Process Deferred Accounting** doctype or direct Python API calls for troubleshooting or mid-cycle adjustments
- **Reporting** via the **Deferred Revenue & Expense** report shows actual postings alongside simulated future periods

## Frequently Asked Questions

### How does ERPNext validate deferred service dates before processing?

ERPNext validates service dates using `validate_service_stop_date()` in [`erpnext/accounts/deferred_revenue.py`](https://github.com/frappe/erpnext/blob/main/erpnext/accounts/deferred_revenue.py) (lines 24-33). This function ensures the service stop date does not precede the start date and falls within the defined service period. If validation fails, the system prevents invoice submission with a clear error message, protecting against data integrity issues that would disrupt the deferred revenue accounting workflow.

### What is the difference between monthly-based and day-based deferred calculations?

Monthly-based calculation uses `calculate_monthly_amount()` to divide the total amount by the number of service months, handling partial months with proration factors. Day-based calculation uses `calculate_amount()` to spread amounts over exact calendar days. Monthly-based is the default method in ERPNext, configured via **Accounts Settings** under `book_deferred_entries_based_on`, and is generally preferred for subscription billing while day-based suits usage-based contracts.

### Can I process deferred expenses for a specific historical period if the scheduler missed a month?

Yes, ERPNext allows manual processing of deferred expenses through the **Process Deferred Accounting** doctype. Navigate to Setup > Process Deferred Accounting, create a new record selecting **Expense** as the type, and specify your target dates. Upon submission, the system executes the same `book_deferred_income_or_expense()` logic used by the automatic scheduler, creating the necessary GL entries or journal entries for that specific period without affecting other months.

### Where does ERPNext store the configuration for automatic deferred processing?

The automatic processing setting is stored in **Accounts Settings** under the field `automatically_process_deferred_accounting_entry`. When enabled, the system triggers `process_deferred_accounting()` via the scheduler at month-end. If disabled, you must manually create Process Deferred Accounting documents to recognize revenue or expenses. Company-specific default deferred accounts are configured in [`erpnext/setup/doctype/company/company.py`](https://github.com/frappe/erpnext/blob/main/erpnext/setup/doctype/company/company.py) (lines 260-267).