Server Script Hooks for Document Events

Server Script Hooks for Document Events

In Frappe, Server Script Hooks allow custom Python logic to be executed during the document lifecycle. The following hooks correspond to various stages in the lifecycle of a document:


Order of Execution in Document Lifecycle

Here's the sequence of hooks for document events:

  1. Before Insert
    Triggered before a new document is inserted into the database.

    • Use this to perform validations or initialize values.
    • Cancelling at this stage prevents the document from being saved.
      # Example: Set default values
      if not doc.some_field:
          doc.some_field = "Default Value"
      
  2. After Insert
    Triggered immediately after a new document is inserted into the database.

    • Use this to perform actions like notifications or updates in related documents.
    • Document is saved in the database at this point.
      # Example: Send an alert on document creation
      frappe.publish_realtime("Document Created", message=f"New {doc.doctype} created: {doc.name}")
      
  3. Before Save
    Triggered before a document is saved (either inserted or updated).

    • Commonly used for validations or calculations.
    • Cancelling prevents the document from being saved.
      # Example: Prevent saving if total is zero
      if doc.total == 0:
          frappe.throw("Total cannot be zero!")
      
  4. After Save
    Triggered after a document is successfully saved in the database.

    • Use this to perform post-save actions like updating linked documents or notifications.
      # Example: Update a linked document
      frappe.db.set_value("Related DocType", doc.linked_field, "status", "Updated")
      
  5. Before Submit
    Triggered before a document is submitted (transition from Draft to Submitted).

    • Used for final validations or checks.
    • Cancelling prevents the document from being submitted.
      # Example: Ensure mandatory fields before submission
      if not doc.mandatory_field:
          frappe.throw("Mandatory Field is required before submission!")
      
  6. After Submit
    Triggered immediately after a document is submitted.

    • Use this for follow-up actions, such as creating related documents or notifications.
      # Example: Log submission
      frappe.logger().info(f"{doc.doctype} {doc.name} submitted successfully.")
      
  7. Before Cancel
    Triggered before a document is cancelled (transition from Submitted to Cancelled).

    • Cancelling this prevents the document from being cancelled.
      # Example: Prevent cancellation if linked documents exist
      if frappe.db.exists("Linked DocType", {"link_name": doc.name}):
          frappe.throw("Cannot cancel. Linked documents exist!")
      
  8. After Cancel
    Triggered immediately after a document is cancelled.

    • Use this for cleanup tasks like notifying users or reverting changes in related documents.
      # Example: Notify about cancellation
      frappe.publish_realtime("Document Cancelled", message=f"{doc.doctype} {doc.name} was cancelled.")
      
  9. Before Delete
    Triggered before a document is deleted from the database.

    • Cancelling this prevents the document from being deleted.
      # Example: Prevent deletion if conditions are not met
      if not doc.allow_deletion:
          frappe.throw("This document cannot be deleted!")
      
  10. After Delete
    Triggered after a document is deleted from the database.

    • Use this to clean up related data or log deletion events.
      # Example: Log deletion
      frappe.logger().info(f"{doc.doctype} {doc.name} was deleted.")
      

Overall Order of Document Hooks

For a typical lifecycle: 1. Before Insert 2. After Insert 3. Before Save (for updates) 4. After Save 5. Before Submit 6. After Submit 7. Before Cancel 8. After Cancel 9. Before Delete 10. After Delete


Key Considerations

  • Cancelling: You can stop the execution of certain events (like insert, save, submit, or delete) by raising an exception (frappe.throw()).
  • Validation vs. Action: Use Before hooks for validation and After hooks for performing actions.
  • Chaining Effects: Hooks like After Save can trigger other hooks indirectly, so design logic carefully to avoid infinite loops.
Discard
Save
Was this article helpful?

On this page