Skip to content

Latest commit

 

History

History
106 lines (87 loc) · 8.33 KB

File metadata and controls

106 lines (87 loc) · 8.33 KB

Frappe Core Doctype: Audit Trail

The Audit Trail Doctype in Frappe is a Single Doctype that functions as a tool or an interface for users (typically System Managers) to view the history of changes for a specific document. It leverages Frappe's versioning system to display differences between amended versions of a document.

Core Purpose

  • To provide a user interface for viewing the detailed change history of a specific document.
  • To compare different versions of a document that has been amended.
  • To show changes in field values, as well as rows added, removed, or modified in child tables.
  • To help users understand how a document has evolved over time, especially for submittable and versioned Doctypes.

Key Files Defining Audit Trail

  • audit_trail.json: Defines the schema of the Audit Trail single Doctype, including its fields which act as filters and display areas.
  • audit_trail.py: Contains the server-side Python controller logic to fetch document versions and compute differences.
  • audit_trail.js: Handles client-side JavaScript for user interactions, fetching data from the server, and rendering the audit trail view using HTML templates.
  • audit_trail.html: An HTML template used by audit_trail.js to render the main comparison table of field changes between document versions.
  • audit_trail_rows_added_removed.html: An HTML template used by audit_trail.js to render tables showing rows added or removed in child tables.
  • test_audit_trail.py: Contains unit tests for the server-side logic.

audit_trail.json - Schema Definition

As a Single Doctype, this JSON defines the fields that make up the Audit Trail tool's interface.

  • issingle: 1: Marks this as a Single Doctype.
  • Key Fields:
    • doctype_name (Link to DocType, Required): The user selects the Doctype of the document they wish to audit.
      • The client-side script filters this to show only Doctypes with track_changes=1 and is_submittable=1.
    • document (Dynamic Link, options: doctype_name, Required): The user selects the specific document name to audit.
      • The client-side script filters this to show documents that have been amended (amended_from is not null) and fall within the optional date range.
    • start_date (Date), end_date (Date): Optional date filters to narrow down the versions to compare.
    • version_table (HTML, Hidden): A placeholder field where the client-side script will render the main audit trail comparison table using the audit_trail.html template.
    • rows_added (HTML): A placeholder for rendering details of rows added to child tables, using audit_trail_rows_added_removed.html.
    • rows_removed (HTML): A placeholder for rendering details of rows removed from child tables, using audit_trail_rows_added_removed.html.
    • Section breaks (rows_added_section, rows_removed_section) for these HTML fields are initially hidden and shown only if there's data.
  • hide_toolbar: 1: The standard Doctype toolbar is hidden.
  • Permissions:
    • "System Manager" role has read and write access. "Write" access allows saving the selected doctype_name, document, and date range so the System Manager can easily return to this specific audit view.

audit_trail.py - Server-Side Logic

The Python controller is responsible for fetching document versions and calculating the differences.

  • AuditTrail(Document) Class:
    • validate(): Ensures that doctype_name and document fields are filled and that the selected document exists for the given Doctype.
    • compare_document() (Whitelisted Method):
      • This is the core method called by the client-side script.
      • get_amended_documents(): Traverses the amendment chain of the selected document (via the amended_from field) backwards, up to 5 versions or until the start_date is reached. It returns the document names in chronological order.
      • It then iterates through this chain of amended documents, using frappe.core.doctype.version.version.get_diff() to compare each document with its previous version. get_diff identifies changes in:
        • Field values (diff.changed).
        • Child table rows added (diff.added).
        • Child table rows removed (diff.removed).
        • Child table rows modified (diff.row_changed).
      • get_diff_grid(), get_rows_added_removed_grid(), get_rows_updated_grid(): These helper methods process the raw diff output from get_diff. They structure this data into dictionaries, mapping internal fieldnames to their user-friendly labels, and preparing it for easy rendering by the client-side templates.
      • The method returns the list of amended document names and the structured dictionary of changes.
  • Helper Functions:
    • get_field_label(): Converts fieldnames to their display labels, handling fields in child Doctypes.
    • filter_fields_for_gridview(): Prepares data from a child table row for display by selecting only fields marked in_list_view.

audit_trail.js - Client-Side Logic

This script manages the user interface, triggers the backend comparison, and renders the results.

  • refresh(frm):
    • Auto-population: If navigating from a document form, it tries to pre-fill "DocType" and "Document" fields and automatically fetch the audit trail.
    • Disables Save: frm.disable_save() is called as this is a view/tool.
    • Dynamic Queries: Sets up filtered queries for doctype_name (only track_changes, submittable) and document (amended, within date range).
    • Primary Action: Configures a "Compare" button that triggers frm.events.get_audit_trail_for_document(frm).
  • Date Field Logic (start_date, end_date change handlers):
    • Ensures start_date is not after end_date.
    • Validates that the selected document's creation date is within the specified range; clears the document field if not.
  • get_audit_trail_for_document(frm):
    • Calls the compare_document method on the server via frm.call().
    • On success, it receives the amendment chain and the structured diff data.
    • Calls render_changed_fields and render_rows_added_or_removed to display this data.
  • render_changed_fields(...):
    • Uses frappe.render_template("audit_trail", ...), passing the document names and field changes, to generate HTML.
    • Injects the rendered HTML into the version_table field's wrapper and makes the field visible.
  • render_rows_added_or_removed(...):
    • Uses frappe.render_template("audit_trail_rows_added_removed", ...) for both added and removed rows in child tables.
    • Injects the HTML into the respective rows_added and rows_removed field wrappers.
    • Makes the corresponding sections visible only if they contain data.

HTML Templates

  • audit_trail.html: This template is responsible for rendering the main comparison table. It likely iterates through the document versions (columns) and the changed fields (rows), displaying the values of each field across different versions.
  • audit_trail_rows_added_removed.html: This template is used to display tables of rows that were added or removed in child Doctypes between versions. It iterates through the child tables and then the rows within them.

How It's Used

  1. A System Manager navigates to "Audit Trail" (usually found via the Awesomebar).
  2. They select a "DocType" (e.g., "Sales Order").
  3. They select a specific "Document" (e.g., "SO-00123").
  4. Optionally, they can specify a "Start Date" and "End Date".
  5. Clicking "Compare" triggers the process:
    • The client-side script calls the server.
    • The server fetches the relevant amended versions of "SO-00123".
    • It computes the differences between these versions.
    • The differences are returned to the client.
    • The client-side script uses the HTML templates to render a view showing:
      • A table comparing field values across versions.
      • Sections detailing rows added to child tables.
      • Sections detailing rows removed from child tables.
      • Sections detailing changes within existing child table rows.

The Audit Trail provides a powerful way to track the detailed history and evolution of important documents within Frappe.