# How to Perform Period Closing and Financial Year End in ERPNext: The Complete PCV Guide

> Master ERPNext period closing and financial year end with the complete Period Closing Voucher PCV guide. Learn to seal your fiscal year and carry forward balances accurately.

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

---

**The Period Closing Voucher (PCV) in ERPNext locks accounting periods by generating general ledger entries that carry profit and loss balances forward to a designated closing account, effectively sealing the financial year when the period end date matches the fiscal year end.**

The **period closing and financial year end** process in the `frappe/erpnext` repository centers on the `Period Closing Voucher` doctype. This document orchestrates validation, GL entry generation, and period sealing to ensure immutable financial records once a fiscal year closes.

## Understanding the Period Closing Voucher Workflow

The PCV process spans ten distinct validation and execution phases defined in [`erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py`](https://github.com/frappe/erpnext/blob/main/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py).

### Step 1: Determine the Accounting Period

The system calculates the closure range automatically. The `validate_start_and_end_date()` method (lines 49-68) sets the **Period Start Date** to the day after the last closed PCV for the same fiscal year and company, or the fiscal year start if no prior PCV exists. The **Period End Date** cannot exceed the fiscal year end date.

### Step 2: Enforce Year-End Dependencies

Before creating a PCV for a new fiscal year, the `check_if_previous_year_closed()` method (lines 70-99) verifies that all general ledger entries from the previous year have been properly closed. This prevents gaps in the accounting chain and ensures sequential closure.

### Step 3: Block Overlapping Closures

The `block_if_future_closing_voucher_exists()` method (lines 101-109) prevents users from creating overlapping vouchers. If any future PCV with a later `period_end_date` exists, the current voucher cannot be saved or submitted, maintaining chronological integrity.

### Step 4: Validate the Closing Account

The closing account must be a **Liability** or **Equity** account with a currency matching the company default. The `check_closing_account_type()` (lines 18-24) and `check_closing_account_currency()` (lines 26-31) methods enforce these constraints before submission.

### Step 5-6: Generate General Ledger Entries

Upon submission via `on_submit()` (lines 32-38), the voucher status changes to **In Progress** and triggers GL entry generation. The `get_pcv_gl_entries()` method calls three helper functions: `get_gle_for_pl_account()`, `get_gle_for_closing_account()`, and `get_gle_for_closing_entry()` (lines 85-165) to:

- Reverse profit-and-loss (P&L) accounts
- Transfer net balances to the **Closing Account**
- Create closing entries for balance-sheet accounts

### Step 7-8: Commit and Finalize Entries

The `process_gl_and_closing_entries()` helper (lines 64-73) executes `make_gl_entries()` and `make_closing_entries()`, which creates **Account Closing Balance** records in [`account_closing_balance.py`](https://github.com/frappe/erpnext/blob/main/account_closing_balance.py). Success updates `gle_processing_status` to **Completed**; failures store the error traceback in `error_message` (lines 74-84).

### Step 9: Cancellation and Reversal

Cancelling a PCV triggers `process_cancellation` and `cancel_gl_entries()` (lines 40-55), reversing GL entries and removing linked closing balances. The system blocks cancellation if future PCVs exist to prevent accounting gaps.

### Step 10: Seal the Financial Year

When the final PCV's `period_end_date` equals the fiscal year's `year_end_date` and processing completes, the fiscal year is effectively closed. The `validate_accounting_period_on_doc_save()` function in [`accounting_period.py`](https://github.com/frappe/erpnext/blob/main/accounting_period.py) (line 97) subsequently blocks any posting dates beyond this point.

## Creating a Period Closing Voucher via Python

You can programmatically create and submit a PCV using the Frappe Python API:

```python
import frappe
from frappe.utils import getdate

# Define fiscal year and company

fy = "2025-2026"
company = "My Company"

# Calculate automatic start/end dates

period_start, period_end = frappe.get_attr(
    "erpnext.accounts.doctype.period_closing_voucher.period_closing_voucher.get_period_start_end_date"
)(fy, company)

# Create the PCV document

pcv = frappe.get_doc({
    "doctype": "Period Closing Voucher",
    "company": company,
    "fiscal_year": fy,
    "period_start_date": period_start,
    "period_end_date": period_end,
    "closing_account_head": "Closing Account - MYC",  # Must be Liability or Equity

    "remarks": f"Closing period {period_start} to {period_end}"
})

# Insert and submit to trigger background processing

pcv.insert()
pcv.submit()
print(f"Submitted PCV {pcv.name}")

```

## Using the REST API for Financial Year End

For external integrations, create the voucher via REST:

```bash
curl -X POST https://erp.example.com/api/resource/Period%20Closing%20Voucher \
     -H "Authorization: token <api_key>:<api_secret>" \
     -H "Content-Type: application/json" \
     -d '{
           "company": "My Company",
           "fiscal_year": "2025-2026",
           "period_start_date": "2025-01-01",
           "period_end_date": "2025-12-31",
           "closing_account_head": "Closing Account - MYC",
           "remarks": "Year-end close"
         }'

```

To execute the closure, submit the document by calling:

```bash
POST /api/resource/Period%20Closing%20Voucher/{name}/actions/submit

```

## Monitoring PCV Processing Status

Check whether GL entries have posted successfully:

```python
pcv = frappe.get_doc("Period Closing Voucher", "PCV-2025-2026-001")
print(pcv.gle_processing_status)   # Returns: In Progress / Completed / Failed

if pcv.error_message:
    print("Processing error:", pcv.error_message)

```

## Core Implementation Files

The **period closing and financial year end** logic spans these critical files in the `frappe/erpnext` repository:

- **[`erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py`](https://github.com/frappe/erpnext/blob/main/erpnext/accounts/doctype/period_closing_voucher/period_closing_voucher.py)**: Contains `PeriodClosingVoucher` class with validation methods (`validate_start_and_end_date`, `check_if_previous_year_closed`), GL generation (`get_pcv_gl_entries`), and submission logic (`on_submit`).

- **[`erpnext/accounts/doctype/process_period_closing_voucher/process_period_closing_voucher.py`](https://github.com/frappe/erpnext/blob/main/erpnext/accounts/doctype/process_period_closing_voucher/process_period_closing_voucher.py)**: Background worker that processes GL entries asynchronously when the legacy controller flag is disabled.

- **[`erpnext/accounts/doctype/accounting_period/accounting_period.py`](https://github.com/frappe/erpnext/blob/main/erpnext/accounts/doctype/accounting_period/accounting_period.py)**: Enforces closed-period rules via `validate_accounting_period_on_doc_save()` to prevent backdated postings.

- **[`erpnext/accounts/doctype/fiscal_year/fiscal_year.py`](https://github.com/frappe/erpnext/blob/main/erpnext/accounts/doctype/fiscal_year/fiscal_year.py)**: Stores fiscal year boundaries referenced by the PCV validation logic.

- **[`erpnext/accounts/doctype/account_closing_balance/account_closing_balance.py`](https://github.com/frappe/erpnext/blob/main/erpnext/accounts/doctype/account_closing_balance/account_closing_balance.py)**: Persists closing balances generated during the PCV process.

- **[`erpnext/accounts/utils.py`](https://github.com/frappe/erpnext/blob/main/erpnext/accounts/utils.py)**: Provides `get_fiscal_year()` helper used when checking previous-year closure dependencies.

## Summary

- The **Period Closing Voucher (PCV)** is the sole mechanism in ERPNext for executing **period closing and financial year end** operations.
- Validation occurs in [`period_closing_voucher.py`](https://github.com/frappe/erpnext/blob/main/period_closing_voucher.py) through methods like `validate_start_and_end_date()` and `check_if_previous_year_closed()`.
- The **Closing Account** must be a Liability or Equity account matching the company currency, enforced by `check_closing_account_type()`.
- GL generation runs via `get_pcv_gl_entries()`, transferring P&L balances and creating **Account Closing Balance** records.
- Processing status tracks via `gle_processing_status` (In Progress → Completed/Failed).
- Once the final PCV reaches the fiscal year end date and completes processing, subsequent transactions are blocked by [`accounting_period.py`](https://github.com/frappe/erpnext/blob/main/accounting_period.py) validation.

## Frequently Asked Questions

### What is a Period Closing Voucher in ERPNext?

A **Period Closing Voucher (PCV)** is a document type in ERPNext that formally closes a range of accounting periods by generating general ledger entries. According to the source code in [`period_closing_voucher.py`](https://github.com/frappe/erpnext/blob/main/period_closing_voucher.py), it reverses profit-and-loss account balances, transfers the net amount to a designated closing account, and creates immutable closing balance records that prevent backdated modifications.

### Can I post transactions after closing a financial year in ERPNext?

No. Once the final PCV for a fiscal year is submitted and its `gle_processing_status` shows **Completed**, the `validate_accounting_period_on_doc_save()` method in [`accounting_period.py`](https://github.com/frappe/erpnext/blob/main/accounting_period.py) blocks any new documents with posting dates after the closed period. You must cancel the existing PCV to reopen the period, which reverses all associated GL entries via `process_cancellation`.

### What type of account should I select as the Closing Account?

The **Closing Account** must be a **Liability** or **Equity** account, as enforced by `check_closing_account_type()` in lines 18-24 of [`period_closing_voucher.py`](https://github.com/frappe/erpnext/blob/main/period_closing_voucher.py). Additionally, `check_closing_account_currency()` (lines 26-31) validates that the account currency matches the company default currency. Typically, this is a "Closing Account" or "Profit/Loss Appropriation" account.

### How do I check if my Period Closing Voucher processed successfully?

Query the `gle_processing_status` field on the PCV document. As implemented in `process_gl_and_closing_entries()` (lines 74-84), this field displays **In Progress** during background processing, **Completed** upon successful GL entry creation, or **Failed** with the specific error message stored in `error_message`.