Document type is used for registering accounting events and actions. You can post and unpost  them. During post action you can make one or more records into zero or more Journals. Using Documents, you represent past and present transactions.

To create a Document, go to the Data types section from the Project Menu. Then unfold Add new dropdown and click Document.

Documents have a timestamp field by which they are uniquely sorted. If two documents have the same timestamp (the situation can be reproduced only with the help of a code) then they are sorted by serial number.

Serial number is the auto-generated document identificator.

You can view a Document using the corresponding view.

The page that shows all the Documents at once can be opened by adding ”documentTimeline/view” to the application’s URL, for example, https://my-app/en/documentTimeline/view. It is useful when you have two or more different documents.


Post/unpost actions

During post action Document makes 1+ records into 0+ journals (we can write to nowhere). This is the only way to create Journals. During on post action, timesamp and serial number fields are auto-generated.

You can post documents only if sufficient conditions are satisfied. For example, you have 10 bottles of wine in the Warehouse. And you need to post a buy 11 bottles document. Naturally, the document can not be posted.  

If a document is unposted, it changes its look on the index pages of the application and its registers are deleted.

If the document is posted again, journals return back.

To create an action that will be triggered on document post, from the right menu of Document’s web page inside the Builder, Advanced, select On document post.

The example of an On document post is provided below. Here Journal type Product movements is used for recording. For each item from the Products bought collection we create a new Journal Movement, fill in its fields, and finally, we use add to journal block.

Any calculations should be executed only for the purpose of recording correct values into Journals. In a normal case, the document that executes on Post should execute calculations based only on his own data and data available in journals at the point of execution. This ensures both correct and repeatable time-dependent processing.

Document posting settings

In the App settings, you can change Posting options.

By default, Post all documents in single transaction option is chosen.

If you post a document in such a mode, the algorithm is as follows:

Generate posting for Document A.

Compare journals.

If nothing changed: End posting

Else: Start a long transaction.

        Delete all entries whose date > document A date.

        Post one by one all documents.

        If a document can not be posted:

                Backup long transaction

                End (document A can not be posted)

  • Document A has been successfully posted

Here, to post a single document we check whether its changes satisfy the conditions for all later documents, and only then it is posted.

But if you have a large number of documents to be posted, furthermore, you are sure that a single document cannot affect the rest, then you can use Post/Unpost single document option to complete the operation without consuming additional resources.

The third option, Post each document in separate transaction, is dangerous and is recommended only for testing purposes. This option posts only the series of documents that can be posted, with the risk that the rest can become unposted.

For example, your ERP has up-to-date stock data and after posting an old document an error occurs. And you see that your correct stock data becomes outdated. The backup cannot be made.

If Post on save is marked, then the Post action will be triggered every time you save a Document.

Warning: It is not recommended to use Documents in real-time applications.

Possible problems

Documents can not have system instances. Technically documents can have fields referring to other documents. However, such references should be avoided where possible.

As a rule, documents should not modify other documents. If a document needs some data available in other documents, most of the time the data should be retrieved from the postings made by other documents and not directly.

Imagine that we have documents:

  • D4 (youngest)
  • D3
  • D2
  • D1 (oldest)

Let's assume that all of them are in the posted state. Now we change D2. It causes automatic execution of D2.on post(), D3.on post(), D4.on post(). If updates were allowed, this would lead to the following critical problems.

a) D3.on post() updates D2 , directly on indirectly (via some of nested function calls). This causes D2 to post again and we've got an infinite loop.

b) Let's assume that D1...D4 are of the same type and have a field employee of type Person. Let's assume that all 4 documents reference the same employee E1(name: john, surname: smith, salary: 1000). We have to write this salary to Journal.

D1 reads E1.salary , writes (E1.salary + 100) to D1.journal.salary and sets E1.salary to (E1.salary + 100) ⇒ E1.salary = 1100

D2 reads E1.salary , writes (E1.salary + 100) to D2.journal.salary and sets E1.salary to (E1.salary + 100) ⇒ E1.salary = 1200

D3 reads E1.salary , writes (E1.salary + 100) to D3.journal.salary and sets E1.salary to (E1.salary + 100)  ⇒ E1.salary = 1300

D4 reads E1.salary , writes (E1.salary + 100) to D4.journal.salary and sets E1.salary to (E1.salary + 100)  ⇒ E1.salary = 1400

Journal looks like:

D4.salary = 1400

D3.salary = 1300

D2.salary = 1200

D1.salary = 1100

Now unpost all the documents and post them again. No data in documents has changed but Journal would look like

D4.salary = 1800

D3.salary = 1700

D2.salary = 1600

D1.salary = 1500

That is clearly unacceptable. It happened because D1...D4 used not register-dependent data (E1.salary) when producing their records. While we could try to work around this problem by implementing some logic in the calculation that would reset somehow E1.salary to 1000 by D1, this approach would be unsustainable in a more complex case where D1...D4 are of different types.