Ultimate Solid is a three-tier architecture software suite which includes:
- database server (Oracle 11gR2 Enterprise Edition or Oracle 12c Enterprise Edition);
- application server;
- print server;
- client applications.
The general model of interaction is presented in the diagram below:
As a rule, and that is highly recommended, that the database server (DBS) is located in the data center. To increase hardware fault tolerance and mitigate the risk of data loss, as well as to share the load, it is recommended to install a standby server/server cluster.
Based on similar considerations of fault tolerance and performance, the applications server (AS) which carries out processing of business logic and directly exchanges data flows with DBS, can also be scaled into a cluster. Due to the extremely high intensity of data exchange between AS-DBS, they should be located in close proximity to each other, at least within the same local network.
As opposed to AS-DBS, the print server (PS) is located at the same place with the printing devices and staff, thus reducing the load on communication channel to transfer smaller volumes of data.
With the help of the screen logic of client applications (CA), the user can view, enter and edit data.
Composition logic of Ultimate Solid — based solutions
An Ultimate Solid — based solution operated by the customer (as a rule, an ERP – system) consists of two logically and physically different essences: the platform and the configuration.
Ultimate Solid platform itself is an invariant kernel of the system (hereinafter the terms “platform” and “kernel” are interchangeable), which remains unchanged for any subject area and business logic. In other words, for any implementation of Ultima solution, the kernel of the system, a. k. a. the platform, is the same as for any other.
The platform makes the whole software complex functioning and provides the following tools and mechanisms:
- storing the users, their authorisation and permissions checks;
- communication between the applications;
- access to DBMS (saving system objects to database);
- managing configuration changes (versioning mechanism);
- converting raw data from DB to system objects;
- integration with the other systems — SOAP, JSON, REST, XML etc;
- development environment and configuration changes.
Configuration (for example, e-Trade and e-Service) — description of the subject area. In essence, it is implementation of business logic and its information framework. A certain solution working for a certain customer, though built on a basic configuration (e-Trade, e-Service — basic industry configurations), in 100% cases has its distinctive features which are formed in the process of creating a design assignment, the implementation process and subsequent operation of the implemented solution.
Configuration is a set of metadata describing business objects:
- handlers describing logics of interaction between business objects;
- server modules;
- client modules;
- user permissions.
The general model is presented in the diagram below:
The configuration is entirely stored in the database. Oracle 11gR2 Enterprise Edition or Oracle 12c Enterprise Edition with the following two schemes are used as DBMS:
- Kernel – static, it is the very scheme the application server loads configuration from when launched;
- Ultima — subject, where tables are created and data of the subject area are stored.
The kernel is unavailable for changes by an application developer; however, it provides an interface and tools for implementing business logic. The business logic itself, executed on the application server, is implemented in the form of classes in C# derived from the relevant classes of the platform (hereinafter such classes will be referred to as scripts). The screen logic is executed on the client application and is implemented in the form of modules in any .NET — compatible language.
The system provides the application developer with the finished:
- authorization and authentication mechanisms;
- mechanisms for transformation of objects, their downloading and storing to the database;
- business objects and business logic editor;
- mechanisms of communication between parts of an application;
- mechanisms for quick prototyping of user interfaces;
- system update without restart and many other.
The task of the application developer is using such tools to create a new and/or make changes to the existing configuration which is represented by a set of dictionaries, documents, totals, handlers, screen forms, etc. , and their descriptions.
The means of the subject area description
The system suggests formulating the description of the subject area by listing the dictionaries, link tables, documents, totals and scripts that handle various events in the system.
Dictionaries and link tables are meant for storing the static and rarely changing data. It won’t be too impolite to present them as simple tables.
This is one of the simplest objects in the system. For instance, the list of products sold or manufactured by the company can be a good example if presented in the form of a dictionary.
As soon as the system recognizes the description of a new dictionary (its name, a set of fields, etc. ), the developer can immediately use a form to create the list of the dictionary records and a form to edit the records. This allows a quick move to the implementation of other logic, without losing time to develop the interface. The link tables are meant to implement the many-to-many link. The description of the link table properties allows the system to automatically generate the ready data management interface and offer it to the user or the developer.
Documents and totals are the objects that are more complex.
Documents contain the information about a certain event in the subject area (for example, the sale of goods).
Documents are the composite objects, unlike dictionaries. Each document contains a standard header (the set of fields that is present in any document of the system), an individual header — the set of fields that exists only in this document, and a set of table parts (it can be empty or not — the number of the table parts for one document is not restricted, and this simplifies the formulation of the complex business logic to a great extent).
A table part allows you to keep a list of records within a single document (lines listing goods enjoy the highest demand here, but it isn’t the only example). The documents are closely related to the concept of a total.
A total is the object of the system, which allows describing the measured parameter of the subject area and keeps the record of its changes. A total can also be represented as a multidimensional cube: the system uses the same terminology — the dimensions and the variables. Thus, the document retains the information about the event and converts its data into a set of the totals’ changes. An example of a total can be the remaining goods stocked at the storehouses. This system object stores the information on the quantity of each product remaining at each storehouse. Accordingly, the sale document reduces the entire total of the goods remaining at the storehouses (for the goods in the document).
The following terminology will be used futher on:
- dictionary (a synonym for a dictionary type) — the dictionary type defines a set of fields and other properties;
- dictionary record — a specific line (or a specific object of the system) in a dictionary;
- link table (a synonym for an link table type) — similar to a dictionary, it defines what fields are present in a link table;
- document type — the description of the set of fields in a document header and other properties;
- document — one particular document containing information about an event.
A more formal description of the system objects can be found below.
Dictionaries store the information about the objects of the described model.
The system generates (for each dictionary) a class to represent a dictionary record. In addition, the system generates the SQL script to create the necessary tables (and other objects for the dictionary storage) in the database. Accordingly, each dictionary contains the records which fields can take the values of the following types:
- numbers — even and fractional (different types use different visual display);
- strings — short (2048 characters) and long (the size of which is limited only by server disk space);
- logical (Boolean) type;
- binary data (e. g. photos);
- references to other dictionaries.
Dictionaries can be of flat and tree types. They differ in their form of displaying the content — in a table or tree form, respectively.
Link tables are used for keeping the links between the dictionaries in the system. Link tables do not have their own form of display, but their data is available for viewing and editing in the screen forms of those dictionaries, which they link. For example, they help to set the storehouses/goods relations, when a large range of goods is stored at many storehouses:
Apart from keeping the links between the dictionaries, the link tables can also be a storage of some additional values. An example of this can be the situation when, in addition to the storehouses/goods relations, it is necessary to store the value of the minimum required reserve stock amount at the storehouse:
Totals contain information about the current state of the company’s measured performance indices, as well as the history of their changes. Each change of a total is called a transaction. If drawing an analogy to the accounting practices, it can be said that totals are the distant descendant of the book accounts concept, while a transaction, respectively — of the accounting records.
Totals consist of dimensions and variables. Each dimension of a total is a reference to a dictionary. Totals can have many dimensions, thus being multidimensional cubes.
Transactions show what changes occur with respect to each variable, and on what dimensions.
There are balance and non-balance totals.
The double-entry rule applies when introducing changes to a balance total: then every transaction is the transaction in pairs (with the opposite values-debit and credit) and their sum is always zero.
Double-entry is not applicable when introducing changes to the outcome of a non-balance total. Accordingly, one can not make a transaction between the balance and non-balance totals.
The system can automatically generate a standard report form for each total; this form has customizable grouping and filter mechanisms.
It might seem (at first glance) that the totals do not differ from the link tables mentioned above.
However, it is not so.
The difference lies in the fact that the values, which are stored in the link tables, are not the measured parameters; they are set manually. If there is a desire to implement the totals by using the link tables, you will have to develop the mechanisms for their completion (as well as the reporting forms and other tools) right from scratch.
The documents contain information about the events that took place; the events serve the basis for the transactions (or the totals’ changes) generation. Similarly to the dictionaries, the system generates a class for storing a single document, for each document type.
A document type sets:
- a set of fields in the header;
- a set of table parts;
- a set of document subtypes.
A document consists of:
- a common header — a set of fields, which is present in all types of documents;
- headers — a set of fields, which is present only in this document type;
- a set of table parts — the belonging to the document data array, which is of the same type as that for the dictionaries.
Table parts themselves are separate entities and are described separately as well.
The document type is defined by the set of its constituent types of table parts. There may be two table parts of the same type in a document. Similar to a dictionary, the system generates a class to represent a single record for each type of a table part. In contrast to a dictionaries, a table part record has a predefined set of fields, which allows linking it to the document.
The need for some or other types of documents is defined by the business logic. It may be, for example, the income documents, cash records documents, inventories etc.
The event (the information about which is stored in a document) can be stretched in time; for instance, the sale goes through such stages as order issuing, picking the goods from the storehouse stock, payment and dispatching. If the information about the intermediate stages has no absolute value, it is possible to sacrifice some of its accessibility (the information will remain, but in a less explicit form) in favor of the user’s or developer’s convenience, and to present the stages as the document subtypes. The document subtype’s analogy is the state. A developer specifies possible subtypes for each document type. Apart from the description of the subject area and the display of the current status, a system administrator allocates the rights to the individual system subtypes: for example, the administrator can give permission to perform all operations in a single subtype, and only to read the remaining subtypes.
As stated above, documents store information about an event, and the results allow decomposing this information into different sections. The conversion of data in the document into the total’s transaction is done with special programs (the transactional scripts or transaction processors, written by an application developer).
These scripts are run every time you save the document, and the system will take care and save that set of transactions in the database in a highly effective manner. In addition, apart from the transactional scripts, several scripts also get triggered during the process of saving; these scripts allow checking the arbitrary business rules. The following chapters describe the startup sequence in detail.
Let us see the example of the interrelations between the documents, totals and the transaction handler’s work.
To begin with, we'll buy the product "1" from the supplier "1" at the storehouse "1".
The receipts are recorded by using a document of a purchase type. Its header contains links to the relevant dictionaries which specify the supplier and the storehouse that the receipts will be credited to, and the table part will list the products to be bought:
3 dictionaries will be engaged in this process:
When saving the document "1" the transaction handler gets activated – it generates the transaction "504". Based on this transaction, the platform makes the following changes to the totals:
- the total named "the remaining stock at the storehouse (transaction)" will get the addition of an extra line that will increase the remaining stock of the product "1" at the storehouse "1" by the number and amount of the receipts;
- The total named "the contractors' debt” will get the addition of an extra line that will reduce the debt of the supplier "1" by the amount of the receipts.
For the total named "the remaining stock at the storehouse (transaction)" in the example above, the fields named document, product and storehouse remain without changes and will refer to the relevant tables; while such fields as the number and amount will undergo changes.
Having made the purchase, let us sell the same products.
Selling is performed via the document of the sale type. Its header contains links to the relevant dictionaries which specify the client and the storehouse that the sale will be made from, and the table part will list the products to be bought. The payment, related to the sales, is recorded by the document of the payment at the cash-desk type. Its header identifies the client and the cash-desk that accepts the payment, and the table part indicates the amount of payment:
At this stage (in addition to the mentioned above dictionaries) another dictionary gets engaged in the process:
When saving a document "3" the transaction handler gets activated; it generates the transactions "505" and "506". Based on these transactions, the kernel introduces the following two pairs of changes to the totals:
- the total named "the remaining stock at the storehouse (transaction)" will get the addition of an extra line that will reduce the remaining stock of the product "1" at the storehouse "1" by the number of the expenditure and the amount corresponding to the prime cost of the previous receipts;
- the total named "sales" will get the addition of an extra line that will increase the number of the product "1" sold to the client "2" by the amount of the prime cost of sales;
- the total named "sales" will get the addition of an extra line that will reduce the amount of the product "1" sold to the client "2" by the amount of sales (at the selling price); therefore, we generate the gross profit due to the difference in prices;
- the total named "the contractors' debt” will get the addition of an extra line, increasing the debt of the client "2" by the amount of sales.
When saving a document "2" the transaction handler gets activated; it generates the transaction "507".
Based on this transaction, the kernel introduces the following changes to the totals:
- the total named "the contractors' debt” will get the addition of an extra line, reducing the debt of the client "2" by the amount of payment;
- the total named “cash” will get the addition of an extra line, increasing the remaining amount of money at the cash-desk “1” by the amount of payment.
In reality, due to the difference in the purchase prices on the goods, the prime costs are calculated not that univocally as the example shows.
Let us see a case in point. Let’s buy the product "1" from another supplier "3" at a price different from the previous one (document "4"), and then sell it again to the client "4" (documents "5" and "6"):
When saving a document "4" the transaction handler gets activated; it generates the transaction "508". Based on this transaction, the kernel introduces the following changes to the totals:
- the total named "the remaining stock at the storehouse (transaction)" will get the addition of an extra line that will increase the remaining stock of the product "1" at the storehouse "1" by the number and the amount of the receipts;
- the total named "the contractors' debt” will get the addition of an extra line, reducing the debt of the supplier "3" by the amount of the receipts;
When saving a document "6" the transaction handler gets activated; it generates the transactions "509" and ‘510”. Based on these transactions, the kernel introduces the following two pairs of changes to the totals:
- the total named "the remaining stock at the storehouse (transactions)" will get the addition of an extra line that will reduce the remaining stock of the product "1" at the storehouse "1" by the number of the expenditure; the amount of that detraction, being the prime cost – the estimated value – has to be calculated; thus, the transaction is created with an empty field;
- the total named "sales" will get the addition of an extra line that will increase the number of the product "1" sold to the client "4"; the field amount is left blank again, since it is the prime costs;
- the total named "sales" will get the addition of an extra linethat will reduce the number of the product "1" sold to the client "4" by the amount of sales (at the selling price);
- the total named "the contractors' debt” will get the addition of an extra line, increasing the debt of the client "4" by the amount of sales.
When saving a document "5" the transaction handler gets activated; it generates the transaction "511”. Based on this transaction, the kernel introduces the following changes to the totals:
- the total named "the contractors' debt” will get the addition of an extra line, reducing the debt of the client "4" by the amount of payment;
- the total named “cash” will get the addition of an extra line, increasing the remaining amount of money at the cash-desk “1” by the amount of payment.
The totals’ variables left blank during the records of the transactions are called analytical. With regard to the total named "the remaining stock at the storehouse (transactions)" — this is a variable amount. In case of a purchase the amount is known to us, that is why it, being a part of a transaction, enters the total; but in case of an expenditure it requires to be calculated, so the field is left blank. The number variable is operational; we always know exactly what number of products we receive, write off, move or sell.
In order to explain how to calculate the prime costs, let us have a closer look at the totals’ storage structure.
Each total is implemented using four tables: two of them are operational and the other two are analytical. Like the variables, the information goes directly to the operating tables right after the recording of the transaction, while the analytical tables receive it upon the results of the totals’ calculation. The operating tables may contain analytical variables, such as, for instance, the table of the total named "the remaining stock at the storehouse (transactions)". The analytical variables of the operational total remain to be blank if the transaction does not contain their calculated values.
The tables can be discerned by their prefixes:
TB_tablename — the operational summary table, where per each set of dimensions only one set of collective meanings of variables is stored. In this example this is the table "the remaining stock at the storehouse (transactions)", where each product at the storehouse is assigned with only its current stock balance and its value;
TR_tablename — the operational detailed table that stores all the transactions. Having added up their variables for a particular set of dimensions, one can obtain the consolidated value stored in TB_tablename.
Additionally, this table stores the information about the documents and transactions that have led to the changes. In this example, this is the table "the remaining stock at the storehouse (transactions)";
TD_tablename — the detailed analytical table that stores the same transactions as the TR tablename, but the transactions are already calculated. It is filled upon the result of the totals' calculation. In this example, this is the table "the remaining stock at the storehouse (analytical transactions)";
TT_tablename — the analytical summary table that stores only one set of the collective meanings of variables (taken from the table TD_tablename) per each set of dimensions. In this example, a table "the remaining stock at the storehouse (analytical summary)".
In case of the last example: the total’s table named "the remaining stock at the storehouse”
will look as follows after the prime costs will be calculated:
The prime costs calculation itself is done by a handler — the driver of the total. The system implements the method of calculating the prime costs by FIFO, according to which the driver of the total calculates the total prime costs of sales, making two records in the table "the remaining stock at the storehouse (analytical transactions)". A developer has the opportunity to realize payment by another method, such as LIFO, or by average, as well as write another driver of the total — even though such action would be nothing more than a tribute to the prehistoric times of the accounting management, when the correct calculation of the prime costs by FIFO was not possible due to its incredible complexity.
The calculation of the totals is usually performed automatically (every hour), but the up-to-dateness of the totals may be as of the earlier time: if you make corrections in a document, and the corrections will result in the transactions changing the totals retrospectively, the data will be relevant up to the date of this document. In this respect, a report on the totals may be relevant as of the date earlier than the current one. The information about the date of the report’s relevance is displayed on the screen.
Above were mentioned the excerpts from the documentation of the Ultimate Solid platform developer. Accordingly, the continuation is in there, too.