Bagaimana kami mengatur migrasi untuk proses bisnis di Bitrix24

Untuk mengotomatiskan operasi mereka, bisnis ini sering menggunakan Bitrix24. Pada artikel ini, kita berbicara tentang beberapa masalah yang mungkin terjadi ketika mengubah proses bisnis dan bagaimana kita menyelesaikannya.



Bitrix24 adalah salah satu sistem CRM yang umum. Ini termasuk desainer visual (desainer) untuk membangun diagram proses bisnis. Penting untuk diingat bahwa ketika mengedit proses ini, kesulitan mungkin terjadi - terutama pada proyek besar yang ada, di mana setiap perubahan pertama kali diperiksa pada server lokal dan uji. Dalam kasus seperti itu, ketika mentransfer ke produksi, kami menggunakan mekanisme migrasi proses bisnis (selanjutnya - BP).

Perusahaan kecil, sebagai suatu peraturan, dapat melakukannya tanpa migrasi dan hanya menunda proses bisnis tertentu selama 2-3 hari. Bisnis besar biasanya tidak mampu membelinya, oleh karena itu menggunakan server uji dan penyebaran.



Bitrix24 tentang cara kerja templat proses bisnis

Bekerja dengan migrasi memiliki karakteristiknya sendiri. Secara khusus, ini rumit oleh sejumlah besar objek yang terlibat dan ID. Selain itu, Bitrix24 juga tidak menyediakan migrasi proses bisnis seperti itu - seringkali masalah ini diselesaikan melalui impor dan ekspor, dan mungkin ada berbagai inkonsistensi. Mari kita pertimbangkan masalah apa yang mungkin terjadi pada saat bersamaan dari sudut pandang pembangunan.

Masalah menemukan templat proses bisnis


Saat membuat proses bisnis, Anda hanya dapat menetapkan nama ke templat, bukan kode unik. Dalam hal ini, ketika memperbarui proses bisnis, itu harus diperoleh dari database dengan nama. Kadang-kadang nama berubah karena sistem menggunakannya untuk ditampilkan dalam daftar proses saat startup. Oleh karena itu, mungkin ada situasi ketika selama pemutakhiran tidak mungkin menemukan templat. Dan secara umum, mencari berdasarkan nama bukanlah ide yang bagus.

Solusi:

Semua templat proses bisnis yang dibuat dalam sistem disimpan dalam tabel b_bp_workflow_template. Setelah membuka tabel, di antara bidang yang kita lihat SYSTEM_CODE: ada bidang untuk kode, itu sama sekali bukan keluaran ke antarmuka. Kita dapat mengatur kode sendiri menggunakan id templat - dapat dilihat di url pada halaman pengeditan proses:



Kita perlu membuat fungsi untuk mendapatkan id templat dan kode, melakukan pemeriksaan duplikasi dan kelengkapan bidang agar templat diubah, dan juga mengatur kodenya.

use Bitrix\Main\Loader; Loader::includeModule("bizproc"); $BPloader = CBPWorkflowTemplateLoader::GetLoader(); // set template CODE field setTemplateCode ($BPloader, 'TEST', '94' ); function setTemplateCode($BPloader, $code, $tempalteId) { if (isCodeExists($BPloader, $code)) { die('   '); } if (!isCodeEmpty($BPloader, $tempalteId)) { die('     ') } $BPloader->UpdateTemplate($tempalteId, ['SYSTEM_CODE' => $code]); } // check if $code exists in DB function isCodeExists($BPloader, string $code) { $dbRes = $BPloader->GetTemplatesList( $arOrder = ['ID' => 'DESC'], $arFilter = ['CODE' => $code], $arGroupBy = false, $arNavStartParams = false, $arSelectFields = ['ID'] ); if (intval($dbRes->SelectedRowsCount()) > 0) { return true; } return false; } // check if the template code is not empty function isCodeEmpty($BPloader, $tempalteId) { $dbRes = $BPloader->GetTemplatesList( $arOrder = ['ID' => 'DESC'], $arFilter = ['CODE' => '', 'ID' => $tempalteId], $arGroupBy = false, $arNavStartParams = false, $arSelectFields = ['ID'] ); if (intval($dbRes->SelectedRowsCount()) > 0) { return false; } return true; } return true; } 

Silakan. Misalnya, buat proses bisnis pengujian pada daftar:



Untuk mentransfer proses yang dikembangkan secara lokal ke server uji (dan kemudian ke produksi), kami menggunakan mekanisme migrasi.

Bitrix24 memungkinkan Anda untuk mengekspor proses bisnis. Kami akan menggunakan kesempatan ini.



Skema transfer adalah sebagai berikut:

  • Mengekspor proses bisnis
  • Kami menulis migrasi, lampirkan file
  • Di stand baru, kami membuat cadangan proses lama
  • Terapkan migrasi

Selanjutnya, pertimbangkan bagaimana proses ini terjadi.

Buat migrasi


Kami akan menggunakan modul migrasi dari pasar: https://marketplace.1c-bitrix.ru/solutions/ws.migrations/ .

File migrasi di proyek kami berlokasi di local / migrasi / skenario




Buka halaman templat proses dan ekspor. Di dalam direktori migrasi, buat direktori file dan letakkan file yang diekspor di sana. Ternyata seperti ini:

lokal / migrasi / skenario / file / bp-94.bpt

Buat skenario migrasi:

 class ws_m_1565783124_approve_task extends \WS\Migrations\ScriptScenario { 

Tentukan parameter templat proses bisnis:

 class ws_m_1565783124_approve_task extends \WS\Migrations\ScriptScenario { private $arBPFields = [ 'DOCUMENT_TYPE' => [ 'lists', 'BizprocDocument', 'iblock_' ], 'AUTO_EXECUTE' => 0, 'NAME' => ' ', 'CODE' => 'TEST', ]; 

Kami menerapkan fungsi impor dari proses bisnis:

 private function importBP($path) { CModule::IncludeModule('bizproc'); CModule::IncludeModule('iblock'); //Get iBlock id for which BP is created $this->arBPFields['DOCUMENT_TYPE'][2] .= $this->getIblockId(); // Get BP id by the CODE $result = \CBPWorkflowTemplateLoader::GetList( [], [ 'CODE' => $this->arBPFields['CODE'], 'MODULE_ID' => 'lists' ] ); if ($arFields = $result->GetNext()) { $id = $arFields['ID']; } else { $id = 0; } //read file to a variable $f = fopen($path, 'rb'); $datum = fread($f, filesize($path)); fclose($f); //Update BP if id>0, otherwise add BP \CBPWorkflowTemplateLoader::ImportTemplate( $id, $this->arBPFields['DOCUMENT_TYPE'], $this->arBPFields['AUTO_EXECUTE'], $this->arBPFields['NAME'], '', $datum, $this->arBPFields['CODE'] ); return $arFields['ID']; } 

Di sini, kami pertama-tama menentukan ID dari blok informasi yang kami lamar proses, dan mendapatkan id dari templat proses dengan kode yang diberikan.

Jika templat ditemukan, kami memperbaruinya. Jika tidak ditemukan - tambahkan.
Fungsi mengembalikan id dari proses yang dibuat atau diperbarui, dan untuk apa yang diperlukan - kami akan memberi tahu lebih lanjut.

Kami menetapkan fungsi komit yang akan menambah / memperbarui proses bisnis kami:

 public function commit() { $pathBPElement = __DIR__ . '/files/bp-94-approve-task.bpt'; $id = $this->importBP($pathBPElement); } 

Jadi, pada langkah ini kami sudah dapat membuat dan memperbarui proses bisnis tertentu melalui modul migrasi.

Masalah memperbarui data template


Mari kembali ke proses bisnis kami dan menambahkan tindakan di sana - pemberitahuan pengguna.



Sebagai pengirim, kami memilih Penulis. Penerima akan:

  • Kelompok pengguna SDM
  • Pengguna Svetlana Kuznetsova

Sekarang mari kita lihat bagaimana proses bisnis direkam dalam database. Untuk melakukan ini, kami mendapatkan dan mencetak template di konsol PHP di panel admin:



 $arFieldsTemplate = \CBPWorkflowTemplateLoader::GetList([], ['ID' => 94])->GetNext(); echo '<pre>'; var_dump($arFieldsTemplate); 


Dalam array parameter proses, kita melihat kejadian ini:



Kami melihat baris group_g15. Berikut 15 adalah ID grup HR.
Kami melihat baris user_579. Di sini 579 adalah ID pengguna.

Ini berarti bahwa jika kami mengimpor proses di situs lain, kami akan memiliki inkonsistensi berkelanjutan.

T.O. kami perlu melakukan penggantian setelah memigrasi ID-ID ini ke ID yang relevan untuk situs tempat kami mengimpor proses.

Grup diidentifikasi oleh kode simbolik, pengguna dengan login.

Untuk memulainya, di situs tempat proses itu dibuat, kami memperoleh kode simbol dan login pengguna grup. Jika Anda tidak memiliki kode grup simbolis yang diatur, lebih baik untuk menulis migrasi dan menginstalnya terlebih dahulu.

Dalam contoh kita:

  • Kode Grup - SDM
  • Login Pengguna - svetlana.kuznetsova

Selanjutnya, kami menulis dalam fungsi migrasi yang oleh kode dan login akan memberi kami id grup dan pengguna:

  • getUserId ($ login)
  • getGroupId ($ code);

Akhirnya, perbarui nilai yang sesuai dalam templat:

 /** * Write action by apply scenario. Use method `setData` for save need rollback data **/ public function commit() { 


Impor proses bisnis:

 $pathBPElement = __DIR__ . '/files/bp-94-approve-task.bpt'; $id = $this->importBP($pathBPElement); 


Kami mendapatkan data templat:

 $arFieldsTemplate = \CBPWorkflowTemplateLoader::GetList([], ['ID' => $id])->GetNext(); $template = $arFieldsTemplate["TEMPLATE"]; 


Ganti id pengguna di dalam proses bisnis:

 $template[0]['Children'][0]['Properties']["MessageUserTo"][0] = 'group_g' . $this->getGroupId('HR'); $template[0]['Children'][0]['Properties']["MessageUserTo"][1] = 'user_' . $this->getUserId('svetlana.kuznetsova'); $arNewFields = [ β€œTEMPLATE” => $template, β€œVARIABLES” => $arFieldsTemplate["VARIABLES"] ]; $arNewFields["MODIFIER_USER"] = new \CBPWorkflowTemplateUser(CBPWorkflowTemplateUser::CurrentUser); \CBPWorkflowTemplateLoader::Update($id, $arNewFields); } 

Di sini, ketika memulai migrasi, kami mengunggah file dan membuat / memperbarui proses dengan fungsi importBP. Selanjutnya, kita mendapatkan struktur templat proses bisnis ke dalam array, ganti ID dan perbarui templat.

Untuk meringkas


Dalam artikel ini, kami menyentuh hanya beberapa kasus di mana inkonsistensi dapat terjadi selama transfer antar situs, dan kami menunjukkan apa yang harus dicari. Secara umum, dalam praktik kami, kami menemukan binding id berikut:

  • user_ (mengikat ke pengguna)
  • group_ (mengikat ke grup pengguna)
  • iblock_ (infoblock binding)
  • SequentialWorkflowActivity (memulai proses bisnis dari templat)
  • PROPERTY_ (mengikat ke bidang dokumen dengan kode karakter yang tidak ditentukan)

Jika semuanya dilakukan dengan benar, transfer proses bisnis yang di-debug ke produksi cepat dan lancar.

Kami berharap pengalaman kami bermanfaat bagi Anda!

Tunjukkan contoh lengkap
 <?php /** * Updates migration scenario actions **/ class ws_m_1565783124_approve_task extends \WS\Migrations\ScriptScenario { private $arBPFields = [ 'DOCUMENT_TYPE' => [ 'lists', 'BizprocDocument', 'iblock_' ], 'AUTO_EXECUTE' => 0, 'NAME' => ' ', 'CODE' => 'TEST', ]; private $codeIBlock = 'APPROVE_TASK'; /** * Name of scenario * @return string **/ public static function name() { return 'approve task process'; } /** * Description of scenario * @return string **/ public static function description() { return 'process to approve task and set task deadline +14 days after approving'; } /** * @return array First element is hash, second is owner name */ public function version() { return ['13ebf9abe69204014459b80a7036b7a0', '']; } /** * Return IBlock ID * @return int */ private function getIblockId() { $result = CIBlock::GetList( [], [ 'TYPE' => 'bitrix_processes', '=CODE' => $this->codeIBlock ], false, ['nTopCount' => 1] ); if ($arIBlock = $result->Fetch()) { return $arIBlock['ID']; } return 0; } /** * Start import BP * @param $path * @return mixed */ private function importBP($path) { CModule::IncludeModule('bizproc'); CModule::IncludeModule('iblock'); //Get iBlock id for which BP is created $this->arBPFields['DOCUMENT_TYPE'][2] .= $this->getIblockId(); // Get BP id by the CODE $result = \CBPWorkflowTemplateLoader::GetList( [], [ 'CODE' => $this->arBPFields['CODE'], 'MODULE_ID' => 'lists' ] ); if ($arFields = $result->GetNext()) { $id = $arFields['ID']; } else { $id = 0; } //read file to a variable $f = fopen($path, 'rb'); $datum = fread($f, filesize($path)); fclose($f); //Update BP if id>0, otherwise add BP \CBPWorkflowTemplateLoader::ImportTemplate( $id, $this->arBPFields['DOCUMENT_TYPE'], $this->arBPFields['AUTO_EXECUTE'], $this->arBPFields['NAME'], '', $datum, $this->arBPFields['CODE'] ); return $arFields['ID']; } /** * @param $login * @return mixed */ private function getUserId($login) { $rsUsers = Bitrix\Main\UserTable::getList([ "select" =>['ID'], "filter" => ['LOGIN' => $login], ]); $userFields = $rsUsers->fetch(); return $userFields['ID']; } /** * @param $code * @return mixed */ private function getGroupId($code) { $rsGroups = \Bitrix\Main\GroupTable::getList( [ 'filter' => ['STRING_ID'=> 'HR'], 'select' => ['ID'] ]); $arFields = $rsGroups->fetch(); return $arFields['ID']; } /** * Write action by apply scenario. Use method `setData` for save need rollback data **/ public function commit() { //make BP import $pathBPElement = _DIR_ . '/files/bp-94-approve-task.bpt'; $id = $this->importBP($pathBPElement); //get template data $arFieldsTemplate = \CBPWorkflowTemplateLoader::GetList([], ['ID' => $id])->GetNext(); $template = $arFieldsTemplate['TEMPLATE']; //replace id inside BP tempalte $template[0]['Children'][0]['Properties']['MessageUserTo'][0] = 'group_g' . $this->getGroupId('HR'); $template[0]['Children'][0]['Properties']['MessageUserTo'][1] = 'user_' . $this->getUserId('svetlana.kuznetsova'); $arNewFields = [ 'TEMPLATE' => $template, 'VARIABLES' => $arFieldsTemplate['VARIABLES'] ]; $arNewFields['MODIFIER_USER'] = new CBPWorkflowTemplateUser(CBPWorkflowTemplateUser::CurrentUser); \CBPWorkflowTemplateLoader::Update($id, $arNewFields); } /** * Write action by rollback scenario. Use method `getData` for getting commit saved data **/ public function rollback() { $pathBPElement = _DIR_ . '/files/bp-wt-old.bpt'; $id = $this->importBP($pathBPElement); $arFieldsTemplate = \CBPWorkflowTemplateLoader::GetList([], ['ID' => $id])->GetNext(); $template = $arFieldsTemplate['TEMPLATE']; $arNewFields = [ 'TEMPLATE' => $template, 'VARIABLES' => $arFieldsTemplate['VARIABLES'] ]; $arNewFields['MODIFIER_USER'] = new CBPWorkflowTemplateUser(CBPWorkflowTemplateUser::CurrentUser); \CBPWorkflowTemplateLoader::Update($id, $arNewFields); } } 

Source: https://habr.com/ru/post/id466823/


All Articles