Frappe Frameworkplaintext

What is the Complete Document Event Lifecycle in Frappe and ERPNext?

Frappe Document Event Lifecycle

A comprehensive guide to the Frappe Framework's document event lifecycle, detailing the sequence of server-side and client-side hooks for Save, Submit, and Cancel actions.

Understanding the Frappe Document Lifecycle is crucial for any developer working with ERPNext or custom Frappe apps. The framework provides a rich set of 'hooks' or 'events' that allow you to inject custom logic at specific points in a document's journey—from its creation to submission, cancellation, and deletion. This guide provides a clear reference to the sequence of these events.

By leveraging the correct hook, you can enforce complex validation rules, automate calculations, modify data before it's saved, or trigger integrations with external systems. This reference details the execution order for both server-side (Python) and client-side (JavaScript) events, ensuring your custom scripts run exactly when intended.

Server-Side Event Sequence (New Document)plaintext
# If a Document is saved for the first time (is new):
  1. before_insert
  2. before_naming
  3. autoname
  4. before_validate
  5. validate
  6. before_save
  7. after_insert
  8. on_update
  9. on_change
Server-Side Event Sequences (Existing Document)plaintext
# If action is "Save":
  1. before_validate
  2. validate
  3. before_save
  4. on_update
  5. on_change

# If action is "Submit":
  1. before_validate
  2. validate
  3. before_submit
  4. on_update
  5. on_submit
  6. on_change

# If action is "Cancel":
  1. before_cancel
  2. on_cancel
  3. on_update

# If action is "Update After Submit":
  1. before_update_after_submit
  2. on_update_after_submit
  3. on_change
Client-Side Child Table Hooksjavascript
// These triggers are defined in a Client Script for a DocType
// Replace 'items' with the fieldname of your Child Table

frappe.ui.form.on('Sales Order', {
    // On child row add
    items_add: function(frm, cdt, cdn) {
        console.log("Row added");
    },
    // On child row move
    items_move: function(frm, cdt, cdn) {
        console.log("Row moved");
    },
    // Before child row remove
    before_items_remove: function(frm, cdt, cdn) {
        console.log("Row about to be removed");
    },
    // On child row remove
    items_remove: function(frm, cdt, cdn) {
        console.log("Row removed");
    }
});

Understanding This Code

What It Does

Provides a comprehensive reference list of the server-side and client-side event hooks in the Frappe Framework, detailing the exact sequence in which they are triggered during a document's lifecycle.

When To Use

Use this guide when developing Server Scripts or Client Scripts to ensure your custom logic executes at the correct stage. It's essential for adding validation, automation, data manipulation, and integrations.

Prerequisites

  • Basic understanding of Frappe DocTypes
  • Familiarity with Server Scripts or a DocType's Python controller file
  • Knowledge of Client Scripts for form-level interactions

Key Concepts

Important ideas to understand in this code

Document Lifecycle

In Frappe, the Document Lifecycle refers to the sequence of states and events a document goes through, such as 'Draft', 'Submitted', and 'Cancelled'. Each transition triggers specific server-side and client-side hooks.

Learn more

Server Scripts & DocType Controllers

Server-side hooks are typically implemented in the DocType's Python controller file (e.g., `my_doctype.py`) or through the 'Server Script' DocType in the UI. This is where you place logic that needs to run on the server.

Learn more

Client Scripts

Client-side hooks, like child table events, are defined in a Client Script. This JavaScript code runs in the user's browser and is used to control form behavior and user interactions.

Learn more

Step-by-Step Tutorial

Follow along to understand how this code works

1

Create a Server Script

Navigate to 'Server Script' in the Awesomebar and create a new script. Set 'DocType' to the document you want to target (e.g., 'Sales Order') and 'Script Type' to 'Before Save'.

plaintext
// No code needed for this step. Use the Frappe UI.
Next Step
2

Hook into the 'validate' Event

You can also hook into events directly in the DocType's Python controller. Here, we'll use the 'validate' method to check a condition before the document is saved.

python
from frappe.model.document import Document
import frappe

class SalesOrder(Document):
    def validate(self):
        if self.total > 10000 and not self.notes:
            frappe.throw("Notes are required for orders over 10,000")
Next Step
3

Test the Validation

Create a new Sales Order, set the total amount to be greater than 10,000, and leave the 'Notes' field empty. When you try to save, the system will prevent the action and display the error message from your script.

plaintext
// Try saving the document in the UI to see the validation message.

Common Issues & Solutions

Troubleshoot problems you might encounter