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:
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"
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}")
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!")
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")
- Use this to perform post-save actions like updating linked documents or notifications.
Before Submit
Triggered before a document is submitted (transition fromDraft
toSubmitted
).- 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!")
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.")
- Use this for follow-up actions, such as creating related documents or notifications.
Before Cancel
Triggered before a document is cancelled (transition fromSubmitted
toCancelled
).- 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!")
- Cancelling this prevents the document from being cancelled.
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.")
- Use this for cleanup tasks like notifying users or reverting changes in related documents.
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!")
- Cancelling this prevents the document from being deleted.
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.")
- Use this to clean up related data or log deletion events.
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 andAfter
hooks for performing actions. - Chaining Effects: Hooks like
After Save
can trigger other hooks indirectly, so design logic carefully to avoid infinite loops.