In this article, I will talk about the simplest, in my opinion, way of integrating third-party applications with 1C configurations. The article will be of interest primarily to developers writing on
.Net Core ,
PHP and
Python .
There are many ways to integrate with 1C, an excellent
article from
1C itself is even devoted to this. In particular, you will learn from it that 1C supports the mechanisms of web services, which means we can implement our own service on the 1C side, and, as a result, our own ORM library on the client application side. One of these libraries will be discussed later.
Description of the technique in general terms
On the side of 1C
It all starts with the fact that the “Brom” extension is added to the 1C configuration, adding a new web service. The extension is freely available and licensed (MIT). The extension itself is not tied to a specific data model, and therefore can be installed on any configuration with support for compatibility mode 8.3.10 or higher.
Once the extension is installed, you must configure the rights of users who will have access to the web service methods, as well as publish the configuration on the web server so that the added service is accessible via the http (s) protocol. On the 1C side, nothing more is required.
On the client side
On the client side, the Brom package is connected, for example, for .Net Core this can be done with the command:
Install-Package Brom -Version 1.0.1-beta08
Or for Python:
pip install brome
After installing the package, it is enough to create a client object through which interaction with the remote 1C configuration will be carried out. Hereinafter I will cite the code in C #, but in PHP and Python it is similar. And so, you can create a client with one command:
dynamic = new (@" = http://mydomain.com/publication_name; = 1c_user_name; = 1c_user_pass ");
In the designer, it is enough to indicate the address of the published 1C configuration, and the data of the user to whom we have issued access rights to the extension. Once the client is created, we can proceed to the most interesting.
Call of procedures and functions 1C
Through the created bromine client we can call the procedures and functions defined in 1C. In this case, the called methods must be server-side and be contained either in the global context or in server modules (general modules or manager modules). For example, this is how the call to the function of the global context "Number Prescription" looks like:
string = .(2547, " = fr_FR");
The second parameter is a format string indicating localization (French). Parameters are transmitted in a natural form and do not require any additional conversion or packaging.
And this is how the call to the Find By Code function of the directory manager module will look like:
var = ...(840);
Here we called the function through the module manager directory "Currencies". The result of the call will be an object of the type "DirectoryReference". Now the resulting link to the object can be passed as a parameter to another function:
var = ..(, DateTime.Today);
This time we turned to the general module “Work with Currencies” and rescue its method “Get Currencies.”
The library supports working with complex data types, so it is possible to call methods that take input or return: Links, Arrays, Structures, Value Tables, Value Trees, system enumerations, etc. ... Some classes are specially implemented in the client library to simplify work with 1C.
The scope of remote methods can be flexibly configured by specifying them in the settings. So, for example, if you specify the "Directories. *. Find By Code" area, then only the "Find By Code" method will be available in all configuration directories. Thus, you can clearly indicate which methods an integrated application can use.
Work with links
References to objects allow not only to transfer a pointer to an object 1C, but also to receive data from the object itself. Working with links on the client side is as simple as in 1C. For example:
var = ...("00-000018", new Date(2017, 1, 1)); var = .; var = .; var = ..; foreach (var in .) { Console.WriteLine((., .)); }
Here we found a link to the document through the manager module and got the values of the fields of the document and its tabular part “Products”. After the first access to the field of the object, all its data is downloaded from the 1C server and stored on the client until the link is deleted by the garbage collector.
A link to the object can also be obtained on the client side without accessing the server. To do this, just know the unique identifier of the object:
var = ...(new Guid("5a32b6ab-4661-11e9-912a-38d547755ef7"));
You can also just get links to predefined collection items:
var = ...18_118;
Editing Objects
Having a link to the object, we can edit the data of the object. To do this, just create an object context:
var = .(); . = DateTime.Today; . = "00-000055"; ..(); var = ..() . = ...("000000104"); . = 3; .(.);
In this example, we created the context of the document through a link to the document, filled in some fields, added a line to the tabular section “Goods” and recorded the document in posting mode.
If you need to create a new object, then this is also possible:
Here we created a new group in the “Nomenclature” directory, then created a directory element and placed it in the created group.
Sampling
Like any decent ORM, the bromine client allows you to create samples from various 1C object collections. A selection is a collection of references to collection objects that satisfy a set of selection conditions. To create a selection, just create the “Selector” object:
var = ...(""); var = ...(); . (", , , ."). ("", false). ("", , .). (""). ("", .); foreach (var in ) { Console.WriteLine(": {0}; : {1}, : {2}; : {3}", ., ., ., .. ); }
In this example, we got a sample that contains elements of the “Nomenclature” directory, which are hierarchically in the “Furniture” group. We pointed out that in addition to the links themselves, it is necessary to load the data of some fields. Due to this, the data of these fields will be loaded with a single request, and access to them will not lead to additional server calls.
Query execution
Most often, the data stored in one collection becomes insufficient, and we need to get the data generated by a complex query. To fulfill requests, a special class “Request” is provided in the client library. Work with requests on the client side is very similar to work on the 1C side:
var = .(@" . , . , . . . = & "); .("", "-0001"); var = .(); foreach (var in ) { Console.WriteLine((., .)); }
Here we have created a simple query with a parameter that selects data from the "Nomenclature" directory. As a parameter, we passed the string article of the element. In the general case, the parameter value can also be links, system enumerations, and even arrays. As a result of the query, we returned the "Values Table", this class is implemented on the client side. In this example, we inferred the fields of the table rows using a loop.
On the 1C side, all requests are executed through the query builder, thanks to this, you can specify not only a finished request as a text, but also a request template containing markup for the builder:
var = .(@" 5 . , . , . { .*} ..( {(&)}, { ().*, ().*} ) { .} { .*, .*} ");
In this example, we specified a standardized request, the settings of which can be dynamically changed on the client side as necessary. Due to this, fields, selections and sortings can be indicated in the body of the main program code, and not inside the request body.
The Run method accepts the optional parameter "type of crawl of results." If you specify the crawl type “By grouping” or “By grouping with a hierarchy”, then instead of a table of values, the method will return a tree of values.
Also, instead of the Run method, you can call the Run Package method (to execute several requests at once). In this case, an array of tables or an array of trees will be returned, depending on the type of traversal.
Code snippet execution
In some exotic cases, you may need to execute a specific piece of code directly on the 1C side. To do this, the Brom client provides the "Run" method. The method takes input text containing executable code and one optional parameter, which will be available in the code in the variable "Parameter":
var = .(@" = 0; = + ; ; ", new double[] { 45, 67, 12.56, 11.9 });
In this example, we have executed a piece of code that sums the numbers in an array. The array itself was passed as a parameter and placed in the "Parameter" variable. The result of the calculation was placed in the variable "Result". If a variable with this name is filled in the executable code, then its value at the time the execution ends is returned as the result of the "Run" function.
The ability to execute code fragments is governed by a separate access role in the extension. It is recommended to enable this role only for testing purposes, and be sure to disable it in the working draft, as This is an obvious vulnerability.
Advantages Disadvantages
The advantages of the described methodology should certainly include:
- Cross-platform . All interaction is based on the SOAP and HTTP protocols, and their implementation is in all popular development platforms;
- The simplicity of the code . The code on the client application side is almost identical to the code on the 1C side;
- Built-in serialization mechanisms . We do not need to pack and unpack data in order to exchange them with 1C;
- Support for working with links . We have easy access to 1C objects via links;
- Support for 1C-specific data types . We can exchange with 1C tables, trees, structures and other complex structures;
- Access to the application context . We have access not only to the database data, but also have the ability to call methods defined on the 1C side, and also have access to the session state.
The disadvantages of this technique are also available:
- Low data rate . Since the SOAP protocol is based on XML serialization, the transfer of large amounts of data requires time for the exchange of excess traffic, as well as for packaging and unpacking data. Communication through a COM connection seems to be preferable in this context;
- A convenient client is not available on all platforms . If you are not a .Net Core, PHP, or Python programmer, then you will have to implement the bromine client yourself using SOAP mechanisms, which, generally speaking, is time-consuming;
- Limitations of the query language 1C . Since all work with the database occurs through the 1C query mechanism, there are some limitations. For example, you cannot implement the classic pagination of data, because in the query language 1C there are no mechanisms for paging.
Comparison with OData
From the aforementioned
article of 1C, you can find out that in 1C: Enterprise access to data is implemented using the standardized OData protocol. For this reason, it would be foolish not to mention him either.
Here is a brief comparison chart:
It can be seen that these methods have their advantages and disadvantages and, in the general case, are not interchangeable.
Conclusion
I hope this review article will help you in the future quickly and easily create portals, personal accounts and services that are closely integrated with accounting systems based on 1C: Enterprise. You can find detailed information about the bromine components in the official documentation, here is just a brief overview of the main features.