Версия:

Working with tables.json

Creating a new entity begins with models/system/tables.json or individual JSON files in models/system/tables. This is partially described in the article “Class and Client Object Profile”.

Practice shows that a decomposed tables.json is not always convenient to work with, so moving class descriptions into a separate file makes sense if they are several classes with a common purpose. You definitely shouldn’t create a separate file for each individual class; it’s very inconvenient.

Classes implemented in the core are described in tablesCore.json or moved to separate files in models/system/tables (for example, order.json contains everything related to orders).

The tables.json itself contains an initial (incomplete) description of the class and its fields. Other settings for the class itself are set automatically and are available for editing through the system interface. Thus, you only need to set the most basic settings and briefly describe only the fields you need. In addition to the fields you describe, the system will automatically add several system fields, which, however, can be used in user logic, such as the created field.

Automatically Added Fields

Here we repeat a bit from the article “Automatically Created Fields”.

created. Type datetime. Automatically set when any record is created.

created_by_user_id. Automatically set to the ID of the user who created the record.

created_by_user. A virtual field, hidden by default, and therefore not participating in queries. The field pulls lastname from the users table. If necessary, you can make it visible and use it.

updated. Type datetime. Automatically set when any record is modified.

last_edited_by_user_id. Automatically set to the ID of the user modifying the record.

last_edited_by_user. A virtual field, hidden by default, and therefore not participating in queries. The field pulls lastname from the users table. If necessary, you can make it visible and use it.

deleted. Type datetime. Automatically set when a record is deleted.

deleted_by_user_id. Automatically set to the ID of the user deleting the record.

deleted_by_user. A virtual field, hidden by default, and therefore not participating in queries. The field pulls lastname from the users table. If necessary, you can make it visible and use it.

Hierarchical Fields

The system can determine that a table refers to itself and is therefore hierarchical. For such tables, the following fields will be automatically created: node_deep, parents_count, children_count. See Core Basic Concepts descriptions.

Filling tables.json

Fill in only the most basic information needed. See below for details.

Each class is a JSON object with the following structure:

The key of the object in the file is the class name.

It must satisfy the requirements for table naming in the DBMS (MariaDB in this version). Since a class in the core is both a table in the database and a class in JavaScript (see basic concepts), the developer will be able to call basic methods (and override them or write their own if necessary) using this name. In JS (or rather, in TS), the class will, of course, be capitalized according to JS requirements.

This key must exactly match the name field in the object within the “profile” field (example.profile.name must be “example”, and user.profile.name must be “user”).

profile Field

This is an object containing settings for the class itself (not its fields). In principle, any fields from the description in the article “Class Profile Fields” can be here, but usually only 3-5 fields are described.

name. Mentioned above (must match the key of the entire JSON object of the class).

name_ru. Doesn’t have to be in Russian, despite the field name. This is a user-friendly name for the class. It is this name that will be displayed in client components of tables and forms. It will also be inserted into generated messages during data manipulation of this class (see ending).

ending. Used in Russian to add declension when forming messages during data manipulation.

For example, for a feminine entity like “Location” (Локация), you cannot write “Location changed” (Локация изменен) in Russian; you need to write “Location changed” (Локация изменена). To do this, we write the letter “а” in the ending field, and the system starts forming messages correctly.

server_parent_table and server_parent_key. See description in the main article.

structure Field

This is an object of objects, where each object is a field (column) of the class.

type and length

Requires a mandatory description of the field type and its length (for some types), in the DBMS format (MariaDB).

Most common:

type:"bigint", length:"20". Often used for the “id” field. You might see it used in many places in existing code, including tables like dictionaries; this is because we didn’t pay special attention to it. It’s better to use field types that correspond to the expected volume of data. Note that if you specified id in a status dictionary as tinyint, and in another table you have a relationship field status_id (referring to the status table), then status_id must have the same type. For convenience, here is a table of MariaDB numeric type ranges (according to Copilot):

Data Type Size (bytes) SIGNED Range UNSIGNED Range
TINYINT 1 -128 to 127 0 to 255
SMALLINT 2 -32,768 to 32,767 0 to 65,535
MEDIUMINT 3 -8,388,608 to 8,388,607 0 to 16,777,215
INT / INTEGER 4 -2,147,483,648 to 2,147,483,647 0 to 4,294,967,295
BIGINT 8 -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 0 to 18,446,744,073,709,551,615

Do not use tinyint with length=1 as a numeric field, as it is used as a boolean (checkbox). Length for numeric fields determines the number of visible characters and affects output formatting in some cases (for example, when using ZEROFILL).

type:"tinyint", length:"1". Used as a boolean value (checkbox). Recognized by the system as boolean, not numeric. It follows that the system performs type casting and also sets the correct editor type by default.

type:"varchar", length:"255". Used for short texts. length can be different; it specifies the maximum number of characters that can be stored in the field. For utf8mb4 encoding (up to 4 bytes per character), the maximum is VARCHAR(16383). Choose length according to the data you plan to store, as MariaDB has a limit on the maximum size of a single row (65535 bytes). If you have many varchar fields, you might reach this limit. For fields with large volumes, it’s better to use TEXT, but it doesn’t support indexing and works slower.

type:"text". length does not need to be specified. If you need other dimensions, you can use them, for example, longtext.

type:"DECIMAL(15,2)". Other numbers are possible. length does not need to be specified. Used for fractional numbers, such as money/point amounts or percentages (DECIMAL(5,2)).

type:"datetime". length does not need to be specified. Used for storing date and time. In the database, date and time are stored in the standard MariaDB format (YYYY-MM-DD HH:mm:ss), but the core automatically handles formatting, so the get method will return it in a user-friendly format (DD.MM.YYYY HH:mm:ss). Values passed to methods (add/modify and custom ones) must be in the same user-friendly format (DD.MM.YYYY HH:mm:ss).

type:"date" and type:"time". Similar to datetime, but with the corresponding format.

Write in lowercase, except for DECIMAL.

For the “id” field, parameters such as "notNull": true, "autoInc": true, "primary_key": true are also usually specified, but in the current version of the core, they can be omitted; they will be added automatically. The “id” field can be omitted entirely — it will be created automatically.

name

This is a user-friendly name for the field. This is how the field will be labeled in client components like forms, frames, and tables.

If not specified, the field’s actual name will be used as the name.

is_virtual, from_table, keyword, return_column, join_table, concat

See the description of profile fields.

hint

Also frequently encountered. Allows defining a tooltip for the field. See the description of profile fields.

Other fields

Other profile fields can also be described in tables.json, but most settings are made in the interface or left at default.

See the description of profile fields.

Synchronization from tables.json

When the class you need is defined in tables.json (or any other suitable file like models/system/tables/*.json), it needs to be synchronized.

During synchronization, the core creates or updates (if already created) a table in the database, and fills or updates the class profile and its field profiles.

Class settings specified in tables.json will overwrite existing ones in the profile, but only those explicitly defined.

During synchronization, the full profile of the class, class fields, as well as its client objects and their fields, will be saved to a corresponding JSON file with the same name as the class in DB/migration.

For some system classes (e.g., “menu”), as well as all dictionaries of the ds_<dictionary_name> type, data (actual records from these tables) will also be saved.

Based on these files, another developer can get the latest updates to the database structure and profile settings. See “Database Migration Mechanism between Developers”.

To start synchronization, you need to go to the interface, in the System -> Classes menu.

Next, if the class has not yet been created, create a record in the table (the “Create” button above the table), filling in only one field, “name”. The value must match the key of the class you are creating in tables.json.

After creating the record or if it was already created, call the context menu by right-clicking on this row and select “Synchronize with tables.json”.