Quick integration with 1C: Enterprise

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:



 //     var  = ...(); . = " "; .(); //     var  = ...(); . = .; . = " "; . = "T-00012321"; //    .(); //      var  = .;
      
      





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}", ., ., ., .. ); } //         var  = .();
      
      





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 .  , .  , .   { .*}  ..( {(&)}, { ().*, ().*} )   { .} {  .*, .*} "); //         .("..", ""); //      .("", 100, .); //       .("."); .("", .); var  = .(.);
      
      





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:





The disadvantages of this technique are also available:





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:

Bromine OData
Retrieving collection data with complex selection and sorting conditions + +
Page output of collections data +
Adding and editing data + +
Support for working with 1C: Enterprise types (links, tables, trees, etc.) +
Performing arbitrary queries +
Calling server procedures and functions +
Arbitrary server code execution +
Ready-made visualization tools / user interfaces +
JSON data transfer +


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.



All Articles