DocumentChange API

Documentation •
In this article

The DocumentChange API allows extensions to change the content or any open Banana Accounting file.

Use Cases

The DocumentChange API can be used for:

  • Add, modify and delete rows in a Table.
  • Add, modifify and remove columns in a Table.
  • Modify the File Properties
  • Importing Transactions.
  • Importing Accounts, Suppliers and Customers.
  • Importing Invoice and Estimates.
  • Create sort of "macro" that takes a user input to create one or multiple transactions.
  • Calculate and modify columns content.

Examples

Logic of the change process

Contrary to other APIs that allow to directly modify the data, Banana Accounting has decided for an approach that gives the user full control of such data.

The user can preview the changes and approve or discard:

  1. Create a Productivity or Import Extension.
  2. The Extensions main function exec()returns a JSON document that describes what changes will be applied to the file content.
  3. The program shows to the user what changes will take place and will ask the permission to apply the changes.
    Changes are discarded if not approved.
  4. If the user agrees, the changes are applied to the document.
  5. The user can undo and redo the changes.

Example of an Extension using a DocumentChange

The extension create a DocumentChange and return to the program.


// Creates a JSON DocumentChange which adds a row to the transaction table.
//
// @id = ch.banana.example.documentpatch
// @api = 1.0
// @pubdate = 2020-05-25
// @doctype = *.*
// @description = JSON Change adding a row
// @task = app.command
// @timeout = -1
function exec() {
var strChange = ` {
  "format": "documentChange",
  "error": "",
  "data": [
    {
      "document": {
        "dataUnits": [ {
            "nameXml": "Transactions",
            "data": {
              "rowLists": [ {
                  "rows": [ {
                      "fields": {
                        "Date": "20200525",
                        "Description": "Total sales 24-05-2020",
                        "Amount": "2000"
                      },
                      "operation": {
                        "name": "add"
                      }, 
                      "style": { 
                        "fontSize": 12,
                        "bold": true
                      } } ]
              } ]
        } } ]
    } } ]
} `;
var jsonChange = JSON.parse(strChange);
return jsonChange;
}

Structure of DocumentChange

The documentChange consists of a JSON object with a list of document changes (data). Each document change (document) contains the list of changes that must be applied to the accounting file. The basic structure is:


{
    "format": "documentChange",
    "error": "",
    "data": [{
        //First document
        "document": {
            "id": "firstChange",
            "dataUnits": [{
                "data": {
                    "rowLists": [{
                        "nameXml": "Base",
                        "rows": [{
                            "operation": {
                                "name": "modify"
                            },
                            "fields": {
                                "SectionXml": "Base",
                                "IdXml": "HeaderLeft",
                                "ValueXml": "Changed header1 with documentChange"
                            }
                        }]
                    }],
                },
                "nameXml": "FileInfo",
                "nid": ""
            }]
        }
    }, {
        //Second document
        "document": {
            "id": "secondChange",
            "dataUnits": [{
                "data": {
                    "rowLists": [{
                        "rows": [{
                            "operation": {
                                "name": "delete",
                                "sequence": "10"
                            }
                        }]
                    }]
                },
                "nameXml": "Transactions"
            }]
        }
    }, {
        //Third document
        "document": {
            "id": "secondChange",
            "dataUnits": [{
                "data": {
                    "rowLists": [{
                        "rows": [{ // remove the existing account at line 7
                            "operation": {
                                "name": "delete",
                                "sequence": "7"
                            }
                        }, { // add a new account at line 7
                            "fields": {
                                "Date": "2019-01-04",
                                "Description": "Bank Account",
                                "Account": "1001"
                            },
                            "operation": {
                                "name": "add",
                                "sequence": "7"
                            }
                        }]
                    }]
                },
                "nameXml": "Accounts"
            }]
        }
    }, {
        //Fourth document
        "document": {
            "id": "secondChange",
            "dataUnits": [{
                "data": {
                    "rowLists": [{
                        "rows": [{ //add first transaction
                                "fields": {
                                    "Date": "2019-01-04",
                                    "Description": "Purchase of goods",
                                    "AccountDebit": "4200",
                                    "AccountCredit": "2001",
                                    "Amount": "1300"
                                },
                                "operation": {
                                    "name": "add"
                                }
                            },
                            { // add second transaction, using the account added in the previous document
                                "fields": {
                                    "Date": "2019-01-05",
                                    "Description": "Sell of goods",
                                    "AccountDebit": "1001",
                                    "AccountCredit": "3000",
                                    "Amount": "1500"
                                },
                                "operation": {
                                    "name": "add"
                                }
                            }
                        ]
                    }]
                },
                "nameXml": "Transactions"
            }]
        }
    }]
}

Multiple change steps

The JSON document that includes the changes to be applied, can be segmented into several steps. This allows to do complex changes to the accounting file, without triggering errors.

Let's assume you need to remove and add accounts and transactions at the same time. If you add transactions that use a new account before the account is added, there will be an error. The multi-step approach allows you to submit a change that ensures system integrity. In this case the script will return a JSON object with a list of document changes,

  • First document: Change the accounting settings
  • Second document: Remove existing transactions
  • Third document: Remove and add accounts
  • Fourth document: Add the new transactions

{ 
"format": "documentChange",
"error": "",
"data": [{
    //First document
    "document": {
        "id": "firstChange",
        "dataUnits": [{
            "data": {
                "rowLists": [{
                    "nameXml": "Base",
                    "rows": [{
                        "operation": {
                            "name": "modify"
                        },
                        "fields": {
                            "SectionXml": "Base",
                            "IdXml": "HeaderLeft",
                            "ValueXml": "Changed header1 with documentChange"
                        }
                    }]
                }],
            },
            "nameXml": "FileInfo",
            "nid": ""
        }]
    }
}, {
    //Second document
    "document": {
        "id": "secondChange",
        "dataUnits": [{
            "data": {
                "rowLists": [{
                    "rows": [{
                        "operation": {
                            "name": "delete",
                            "sequence": "10"
                        }
                    }]
                }]
            },
            "nameXml": "Transactions"
        }]
    }
}, {
    //Third document
    "document": {
        "id": "secondChange",
        "dataUnits": [{
            "data": {
                "rowLists": [{
                    "rows": [{ // remove the existing account at line 7
                        "operation": {
                            "name": "delete",
                            "sequence": "7"
                        }
                    }, { // add a new account at line 7
                        "fields": {
                            "Date": "2019-01-04",
                            "Description": "Bank Account",
                            "Account": "1001"
                        },
                        "operation": {
                            "name": "add",
                            "sequence": "7"
                        }
                    }]
                }]
            },
            "nameXml": "Accounts"
        }]
    }
}, {
    //Fourth document
    "document": {
        "id": "secondChange",
        "dataUnits": [{
            "data": {
                "rowLists": [{
                    "rows": [{ //add first transaction
                            "fields": {
                                "Date": "2019-01-04",
                                "Description": "Purchase of goods",
                                "AccountDebit": "4200",
                                "AccountCredit": "2001",
                                "Amount": "1300"
                            },
                            "operation": {
                                "name": "add"
                            }
                        },
                        { // add second transaction, using the account added in the previous document
                            "fields": {
                                "Date": "2019-01-05",
                                "Description": "Sell of goods",
                                "AccountDebit": "1001",
                                "AccountCredit": "3000",
                                "Amount": "1500"
                            },
                            "operation": {
                                "name": "add"
                            }
                        }
                    ]
                }]
            },
            "nameXml": "Transactions"
        }]
    }
 }]
}

Properties of DocumentChange

  • format need to be "documentChange"
  • error used to return an error from the script.
  • data is a JSON array of JSON objects (documents) with the changes to be applied.
    • Each element of the array is a single change.
    • Changes are applied in sequence.
  • document is a change to be applied to the accounting file
    • id document identifier (usually empty).
      "id":"currentRow" used by JsAction::updateRow()
    • dataUnits the element to be changed (corresponds to the table in the accounting file).
    • fileVersion the version of the documentChange specification
    • cursorPosition cursor position when changes have been applied
      • operation "move" The cursor moves to the last position of the content (the only attribute available at the moment. Future attributes: select, deselect)
      • tableName xml tablename, where to position the cursor
      • columnName xml columnname, where to position the cursor
      • rowNr index of the row, where to position the cursor (-1 move to the last row of the table)
    • creator information regarding the change.
      • executionDate time stamp of the script that has created the change.
      • executionTime h.
      • name (description) comment .
      • version version of the script.

Properties of DataUnits

The dataUnits array element defines the dataUnits which is going to be changed and includes also the list of changes.

  • nameXml is the xml name of the data structure.
    It can be
    • A name of an existing Table ("Account, Transactions, ...)
    • FileInfo for the file properties.
  • nid is the id of the data structure. It is optional and can be passed in place of the nameXml
  • rowLists Is an array containing rows
  • rows Is an array containing all the rows can be also defined as "Views" when we are working with columns
  • fields Is an Object which defines the field that are going to be modified by the JSON Change (Example: "Description", "Amount")
  • viewList Is an object containing the array views
  • views Is an  array containing views
  • view Is an array of columns
  • style Is an object which define the row style
    • fontSize define the size of the font, can ben one of 8, 10, 12, 14 or 0 (use default style)
    • bold true for bold
    • italic true for italic
  • operation Is an object which defines the operation that has to be executes on the relative row or column.
    • name define the type of operation
      • add, add a new row
        • sequence: 1.1 to add after the row 1.
        • sequence: 1.2 to add after the 1.1
        • if no sequence is given the row is added to the end of the table.
      • delete 
        sequence indicates the row or column to be deleted from the accounting file.
      • modify 
        sequence indicates the row or column we want to modify with the previously specified fields or properties
      • move
        sequence indicates the row or column we want to move and moveTo the row or column destination;
      • replace
        sequence indicates the row or column we want to replace with the previously specified fields or properties;
    • sequence 
      Is the row or column number. The sequence is always referred to the status of the file, prior to the changes.
      • Use 1.1 to add a new row after the existing row at line 1.

 

Sequence property

When indicating the row or column to be modified, deleted or added, the existing row/column number is always used as the basis. This simplifies creating a JSON change.

When indicating a change, the row/column number must be specified:

  • Command Modify: the number of the row to be modified.
    For example sequence: 1, will change the existing row 1
  • Command Replace: the number of the row to be replaced. 
    The content of the row is completely replaced. It is like removing a line and adding a new one.
    For example sequence: 1, will replace the exiting row 1
  • Command Add: the index of the row to be added.  If no sequence is indicated, the new row will be appended.
    For example 1.1 add a line after the row 1.
  • Command Delete: the number of the row to be deleted,
    For example sequence: 1, will remove the existing row 1
  • Command Move: the number of the row to be moved.
    For example sequence: 1, move: 5.1 will move row 1 after the existing row 5.

The engine that applies the changes :

  • Prior to applying the changes, save within the line the "original" sequence.
    In this way, when existing row are deleted or new one are added the original sequence is maintained.
  • It does apply the changes using the saved sequence.
  • At the end of the change process the rows are sorted using the sequence number.
    Rows that have not been changed, maintain the original sequence.

Convenience class for Document change

The DocumentChange class provide a convenient way to create a Document change JSon.

 

 

Help us improve the documentation

We welcome feedback on how to improve this page.

Tell us what theme needs a better explanation or how to clarify a topic.

Share this article: Twitter | Facebook | LinkedIn | Email