CRM bitrix24 api коробка

В данной статье описаны методы работы с CRM только КОБОБОЧНОЙ ВЕРСИИ Битрикс24.
Битрикс24 api коробки для других сущностей (диск, задачи, аналитика, бизнес-процессы, чат, календарь, техподдержка, интранет, телефония)

Rest api битрикс24 (подходит для облака и коробки)
Как создать ЛИД через rest api bitrix24 (php + js+ вебхук)
bitrix24 rest api класс  (решает определенные задачи по сделкам, лидам, контактам)
Данная статья большая, но разделять очень трудно, потому что данные сущности перекликаются, да и мне искать будет неудобно :)
  • сделки
  • лиды
  • компании
  • контакты
  • счета
  • реквизиты
  • предложения
  • товары
  • смарт-процессы
подключение модуля CRM
CModule::IncludeModule('crm'); 
системные константы
CCrmOwnerType::Lead; //1
CCrmOwnerType::Deal; //2
CCrmOwnerType::Contact;
CCrmOwnerType::Company;
CCrmOwnerType::Invoice;
CCrmOwnerType::Quote;
CCrmOwnerType::Requisite;
Обработчики событий
AddEventHandler("crm", "OnBeforeCrmInvoiceAdd", "printInvoice");
AddEventHandler("crm", "OnBeforeCrmInvoiceUpdate", "printInvoice");
AddEventHandler("crm", "OnAfterCrmInvoiceAdd", "printInvoice");
function printInvoice (&$arFields){ }

AddEventHandler("crm", "OnAfterCrmDealUpdate", "MyOnAfterCrmDealUpdate");
function MyOnAfterCrmDealUpdate($arFields){}

AddEventHandler("crm","OnAfterCrmCompanyUpdate","MyOnAfterCrmCompanyUpdate");
function MyOnAfterCrmCompanyUpdate(&$arFields){}

AddEventHandler("crm","OnBeforeCrmCompanyUpdate","MyOnBeforeCrmCompanyUpdate");
function MyOnBeforeCrmCompanyUpdate(&$arFields){}
Важно!
При работе с пользовательскими полями (сделок, контактов, лидов, компаний), надо использовать системное имя, например, UF_CRM_609EDBEF16B35.
Чтобы был читаемый код, удобно задать константы, например
const UF_DATETIME_G =  "UF_CRM_609EDBEF16B35";

Сделки
Важно!
Если Вы изменяете-добавляете сделку / лид (или переводите на др стадию) через api, то роботов надо запускать тоже через api
Если у вас есть обязательные поля для этапа, то сначала их заполняете, сохраняете, а  потом изменяете на нужную стадию.
список полей сделок  https://dev.1c-bitrix.ru/rest_help/crm/cdeals/crm_deal_fields.php  
добавить сделку
$arFields = array(
      "TITLE" => $_POST["name_deal"], 
        "TYPE_ID" => "SALE", 
        "STAGE_ID" => "NEW",                
        "COMPANY_ID" => $companyId,                        
        "OPENED" => "Y", 
        "ASSIGNED_BY_ID" => $managerId, 
        //"CREATED_BY_ID" =>$managerId,                         
        //UF_CRM_CONF_NAME => $_POST["configs_deal"],
        UF_CRM_CONF_NAME1 => $_POST["configsnew_deal"], 
);
//UF_CRM_CONF_NAME1 - пользовательское свойство сделки, без кавычек, потому что это константа, в которой хранится системное название поля

$options = array('CURRENT_USER'=>1); //из под админа
$deal = new CCrmDeal(false);
$dealId = $deal->Add($arFields,true,$options);
if($dealId > 0){                    
   CModule::IncludeModule('bizproc'); //запускаем робота для текущей стадии сделки
   $arErrors = Array();                  
   CBPDocument::StartWorkflow(
         $bpId,  //ID робота, смотреть через таблицы
         array("crm","CCrmDocumentDeal","DEAL_".$dealId), 
         array("TargetUser" => "user_1"),
         $arErrorsTmp
   );                  
}
   
обновить сделку
//вариант 1
$deal = new CCrmDeal(false); //false - не учитывать права
global $DB; 
$DB->StartTransaction();              
$arUpdateData = array("STAGE_ID" => $stage);  //поля которые обновляем
$arOptions = array( 
  "CURRENT_USER"=> $arTaskCopy["CREATED_BY"] //из под кого обновляем
);              
if($deal->Update(
    $dealId,
    $arUpdateData,
    true,
    true,
    $arOptions                   
)){               
   $DB->Commit(); 
   CModule::IncludeModule('bizproc'); //запускаем робота для текущей стадии сделки
   $arErrors = Array();                  
   CBPDocument::StartWorkflow(
       $bpId, //ID робота, смотреть через таблицы
       array("crm","CCrmDocumentDeal","DEAL_". $dealId),
       array(),
       $arErrorsTmp
    );                    
}
else{                  
 $DB->Rollback();
}

//вариант 2
$deal  =  new  \CCrmDeal( false );   
$arUpdateData = array(); //поля которые обновляем
$arOptions = array("CURRENT_USER"=> $arTaskCopy["CREATED_BY"]); //из под кого обновляем
 
//сначала заполняем поля
$upRes = $deal->Update($dealId, $arUpdateData, true, true, $arOptions);                                       

//потом переходим на этап, если раньше то ругается, что обязательные поля для следующего этапа не заполнены
$arUpdateData = array("STAGE_ID" => 4);   
$upRes = $deal->Update($dealId, $arUpdateData, true, true, $arOptions);

//запускаем роботов для сделки (по сути это бизнес-процесс), если изменили стадию через api, то сами роботы не запустятся                          
CModule::IncludeModule('bizproc');            
CBPDocument::StartWorkflow(
   $bpId,
   array("crm","CCrmDocumentDeal","DEAL_".$dealId),
   array("TargetUser" => "user_".$userId),
   $arErrorsTmp
); 
   
получить сделки
$arFilter = array(
   "ID"=>$dealId, //выбираем определенную сделку по ID
   "CHECK_PERMISSIONS"=>"N" //не проверять права доступа текущего пользователя
);            
$arSelect = array(
   "ID",
   "TITLE",
   "COMPANY_ID",    
   UF_CRM_PROGRAMMER, //пользовательское свойство   
   "STAGE_ID"
);            
$res = CCrmDeal::GetList(Array(), $arFilter, $arSelect);
if($row = $res->Fetch()){
   //
}   

//или 
$res = CCrmDeal::GetListEx(Array(), $arFilter, false,false, $arSelect); //возвращаются поля, которые могут не быть в CCrmDeal::GetList


получить сделки api d7
use Bitrix\Crm\DealTable;
$arDeals=DealTable::getList([
   'order'=>['ID' => 'DESC'],
   'filter'=>$arFilter,
   'select'=>$arSelect,
   'cache' => ['ttl' => 3600]
])->fetchAll();
$deals=[];
foreach($arDeals as $deal){
    $deals[$deal['ID']]=$deal;
}
удалить сделку
$arOptions = array("CURRENT_USER"=>1); //удаляем из-под админа. Если не указывать, то будет проверять права доступа текущего пользователя
CCrmDeal::Delete($dealId,$arOptions);
$dealFactory = \Bitrix\Crm\Service\Container::getInstance()->getFactory(2);
$stageId = $dealFactory->GetItem(intval($dealId))->Get('STAGE_ID');
$ufPotok = $dealFactory->GetItem(intval($dealId))->Get('UF_CRM_5BFEB5B8E70C5');

добавить наблюдателя в сделку
это код от ТП Битрикса (Но при таком добавлении наблюдателей в сделку, они не получают права на просмотр сделки и не видят ее в списке сделок. )
$arAdd = array(  
   'ENTITY_TYPE_ID' => 2, //CCrmOwnerType::Deal
   'ENTITY_ID' => $dealId,
   'USER_ID' => $userId,
   //'SORT' => '',
   'CREATED_TIME' => new Bitrix\Main\Type\DateTime(),
   'LAST_UPDATED_TIME' => new Bitrix\Main\Type\DateTime()
);
$oObserver = \Bitrix\Crm\Observer\Entity\ObserverTable::add($arAdd);
так правильно добавить наблюдателя в сделку
\CCrmDeal::AddObserverIDs($dealId,$arFields['USERS_IDS']);
удалить наблюдателя из сделки
\CCrmDeal::RemoveObserverIDs($dealId,$arFields['USERS_IDS']);
получить направление сделки
$categoryId = CCrmDeal::GetCategoryID($dealId);
$arCategory = \Bitrix\Crm\Category\DealCategory::get($arCategoryId);
список направлений( возвращает все, кроме дефолтной нулевой)
$res = \Bitrix\Crm\Category\DealCategory::getList(
 ["select"=>["*"],]
)->fetchAll();
print_r($res);
список стадий воронки сделки
STATUS_ID - статус, который в сделке,
ENTITY_ID - DEAL_STAGE - основная, DEAL_STAGE_#ID# - другие
$dbRow = CCrmStatus::GetList(['SORT'=>'asc'], ['ENTITY_ID'=>'DEAL_STAGE_1']);//arSelectа нет, выбирает все поля
while ($row = $dbRow->fetch()) {
  echo $row["STATUS_ID"]." ".$row["NAME"]."<br>";
}


Добавление комментария в таймлайн сделки
if (!empty($attachments))
    $settings = array('HAS_FILES' => 'Y');
else
    $settings = array('HAS_FILES' => 'N');
 $entryID = \Bitrix\Crm\Timeline\CommentEntry::create(
    array(
        'TEXT' => $text,
        'FILES' => $attachments,
        'SETTINGS' => $settings,
        'AUTHOR_ID' => $authorID,
        'BINDINGS' => array(array('ENTITY_TYPE_ID' => \CCrmOwnerType::Deal, 'ENTITY_ID' => $dealId))
    )
);

Лид
список полей лида https://dev.1c-bitrix.ru/rest_help/crm/leads/crm_lead_fields.php
добавить лид
$lead = new CCrmLead; 

$arFields = Array(
    "TITLE" => "Заголовок",
    "COMPANY_TITLE" => "Название компании",
   "NAME" => "Имя",
   "LAST_NAME" => "Фамилия",
   SECOND_NAME" => "Отчество",
   "POST" => "Должность",
   "ADDRESS" => "Адрес",
   "COMMENTS" => "Комментарий",
        "SOURCE_DESCRIPTION" => "",
   "STATUS_DESCRIPTION" => "",
   //"OPPORTUNITY" => 123456,
   "CURRENCY_ID" => "RUB",
   //"PRODUCT_ID" => "PRODUCT_1",
       "SOURCE_ID" => "SELF",
       "STATUS_ID" => "NEW",
       "ASSIGNED_BY_ID" => $userId,  
       "UF_CRM_143192342342" => "", 
);
 
$leadId = $lead->Add($arFields);
обновить лид
$lead  =  new  \CCrmLead( false );         
$arUpdateData = array(
   "UF_CRM_1632338031" => $_REQUEST["additional_source"]
); 
$arOptions = array();       
$upRes = $lead->Update($_REQUEST['id'], $arUpdateData, true, true, $arOptions);
получить лид
$arFilter = array(
     "ID"=>$leadId, 
     "CHECK_PERMISSIONS"=>"N" //не проверять права доступа текущего пользователя
 );            
 $arSelect = array(
  "ID",     
   "UF_CRM_1632338031", 
     
 );            
 $res = CCrmLead::GetList(Array(), $arFilter, $arSelect);
if($row = $res->Fetch()){
 //
}
удалить лид
$arOptions = array("CURRENT_USER"=>1); //удаляем из-под админа. Если не указывать, то будет проверять права доступа текущего пользователя
CCrmLead::Delete($leadId,$arOptions);
получить статусы лида
$dbRow = CCrmStatus::GetList(['SORT'=>'asc'], ["ENTITY_ID"=>"STATUS"],['ENTITY_ID',"ID","STATUS_ID","NAME"]);   //DEAL_STAGE_1 - статус сделки 1- id воронки
while ($row = $dbRow->fetch()) {
   //поле STATUS_ID - статус в лиде
}
получить все контакты лида
$contactIDs = \Bitrix\Crm\Binding\LeadContactTable::getLeadBindings($leadId); //вернет массив контактов
/*
array(1) {  [0]=>
  array(4) {
    ["CONTACT_ID"]=>
    int(493096)
    ["SORT"]=>
    int(10)
    ["ROLE_ID"]=>
    int(0)
    ["IS_PRIMARY"]=>
    string(1) "Y"
  }
}
*/


Компании
список полей компании https://dev.1c-bitrix.ru/rest_help/crm/company/crm_company_fields.php
получить компанию
$companyId = intval($arFields["COMPANY_ID"]);
$arFilter = array("ID"=>$companyId,"CHECK_PERMISSIONS"=>"N");
$arSelect = array("TITLE", UF_CRM_TARIFF,UF_CRM_COMPANY_TIME);

$rsCompany = CCrmCompany::GetList(Array(),$arFilter,$arSelect);
if($arComp = $rsCompany->Fetch()){
  
}       
обновить компанию
$cCompany  =  new  \CCrmCompany( false );
$arUpdateData = array(UF_CRM_COMPANY_TIME => $newTime); 
$arOptions = array(
       //'DISABLE_USER_FIELD_CHECK' => true,
    "CURRENT_USER"=> 1,
    "ENABLE_SYSTEM_EVENTS" =>true
); 
$upRes = $cCompany->Update($companyId, $arUpdateData, true, true, $arOptions);
добавить запись в историю компании (лида, сделки, контакта)
$CCrmEvent = new CCrmEvent();            
$CCrmEvent->Add(
   array(
      'ENTITY_TYPE'=> "COMPANY", //LEAD, CONTACT, DEAL
      'ENTITY_ID' => $id,
      'EVENT_ID' => 'INFO',                  
      'EVENT_TEXT_1' => 'Просмотр карточки ais за '.date("d.m.Y", $date), //какой-то текст      
      //'FILES' => array(CFile::MakeFileArray('/bitrix/templates/bitrix24/images/template_sprite_21.png')),
      //'DATE_CREATE' => ConvertTimeStamp(time() + CTimeZone::GetOffset(), 'FULL', SITE_ID), //по умолчанию текущее время      
   )
);

Контакт
список полей контакта https://dev.1c-bitrix.ru/rest_help/crm/contacts/crm_contact_fields.php
Важно! Раньше контакт мог быть привязанным только к одной компании. А сейчас к нескольким!
добавить контакт
$arFields = array(
   "NAME" => "Имя",
    "LAST_NAME" => "Фамилия",
    "SECOND_NAME" => "Отчество",
    "HONORIFIC" => "HNR_RU_1",
    "POST" => "Должность",
    "ADDRESS" => "Улица, дом, корпус, строение",
    "ADDRESS_2" => "Квартира / офис",
    "ADDRESS_CITY" => "Город",
    "ADDRESS_POSTAL_CODE" => "Почтовый индекс",
    "ADDRESS_REGION" => "Район",
    "ADDRESS_PROVINCE" => "Область",
    "ADDRESS_COUNTRY" => "Страна",
    "ADDRESS_COUNTRY_CODE" => "",
    "SOURCE_DESCRIPTION" => "Описание",
    "SOURCE_ID" => "SELF",
    "TYPE_ID" => "SHARE",   
    "POST" => "не указано",//должность               
    //"OPENED" => "N", //открыто для других пользователей                
    "EXPORT" => "Y",//участвует в экспорте                
    'FM' => array(//почта, телефон
        'EMAIL' => array(
               'n0' => array('VALUE' => $arNewUser["EMAIL"], 'VALUE_TYPE' => 'WORK')
             ),
             'PHONE' => array(
                'n0' => array('VALUE' => $arNewUser["PERSONAL_MOBILE"], 'VALUE_TYPE' => 'WORK')
             ) 
         ),
    //"COMPANY_ID" => $companyId, раньше только к одной можно было привязать
         "COMPANY_IDS"=>array(1,2,3), //массив id компаний, сейчас можно так                
    "ASSIGNED_BY_ID" => $manager,//id ответственного менеджера 
);
//создаем контакт   
$oContact = new \CCrmContact(false);
$oContact->add($arFields);
if($oContact->LAST_ERROR != ""){                           
   //не создался контакт
}
обновить контакт
$arFields = array(
  "NAME" => "Имя",
  "LAST_NAME"=> "Фамилия"
);
$oContact = new CCrmContact(false);
$oContact->Update($contactId,$arFields);
получить контактов по компании и отвязать их от компании
$arDelete = array();
$res = CCrmContact::GetContactByCompanyId($companyId);
while ($ar = $res->Fetch()) {
     $arDelete[] = $ar['ID'];
}
$CCrmContact = new CCrmContact();
$CCrmContact->UpdateCompanyId($arDelete, 0);
Еще вариант получить контактов по компании
$contactIDs = \Bitrix\Crm\Binding\ContactCompanyTable::getCompanyContactIDs($companyId);
Получить телефон, факс, email рабочий или личный Контакта или компании
$dbCont = CCrmFieldMulti::GetList(     
    array('ID' => 'asc'), //сортировка
    array(
     'ELEMENT_ID' => $contactId
     'ENTITY_ID' => "COMPANY", //"CONTACT","LEAD","DEAL"
     'TYPE_ID' => "PHONE" //"EMAIL",
    ) //фильтр
);
while($arCont = $dbCont->Fetch()){
  //$arCont["VALUE"] там значение 

}
добавить телефон (факс и пр)
$fieldMulti = new CCrmFieldMulti();
$fieldMulti->Add([
   'ELEMENT_ID' => $companyId,
   'ENTITY_ID' => "COMPANY", //"CONTACT","LEAD","DEAL"
   'TYPE_ID' => "PHONE", //"EMAIL",
   'VALUE' => $tel,
   'VALUE_TYPE' => 'WORK',
]);
по ИНН получим реквизиты
if (\Bitrix\Main\Loader::includeModule('socialservices')) {
   $client = new \Bitrix\socialservices\properties\Client;
   $arRequisite = $client->getByInn($inn);
}
Добавим компанию, привяжем к пользователю, создадим контакт
$cCompany  =  new  \CCrmCompany( false );
$arFieldsComp = array(
    'TITLE' => (strlen($arNewUser["INN"])==10)?$arRequisite["NAME_SHORT"]:"ИП ".$arRequisite["LAST_NAME"]." ".substr($arRequisite["NAME"], 0,1).". ".substr($arRequisite["SECOND_NAME"],0,1).".",      
    "ASSIGNED_BY_ID" => $manager,                                
    //'CONTACT_ID' => array($iContactID),//здесь привязываем к компании контакт (обязательно с array())
    UF_CRM_TARIFF => 154 //почасовое обслуживание
);
$companyId = $cCompany->Add($arFieldsComp);

if($companyId >0){
   //обновим пользователя, добавим компанию
   $user = new CUser;
   if(!$user->Update($arNewUser["ID"], array("UF_CONTACT"=>$companyId))){
      //не смогли обновить пользователя
   }
   //добавим реквизиты 
   if(strlen($arNewUser["INN"])==10){ //юр лицо
      $arFields = array(
         'ENTITY_ID' => $companyId,
         'ENTITY_TYPE_ID' => CCrmOwnerType::Company,
         'PRESET_ID' => 1,//организация                              
         'NAME' => $arRequisite['NAME_SHORT'],
         'SORT' => 500,
         'ACTIVE' => 'Y',
         'RQ_COMPANY_NAME' => $arRequisite['NAME_SHORT'],
         'RQ_COMPANY_FULL_NAME' => $arRequisite['NAME'],                              
         'RQ_INN' => $arRequisite["INN"], //инн
         'RQ_KPP' => $arRequisite["KPP"],  //кпп
         'RQ_OGRN' => $arRequisite["OGRN"], //огрн
         'RQ_COMPANY_REG_DATE' => $arRequisite["CREATION_REGISTRATION_DATE"],
         'RQ_OKVED' => $arRequisite["OKVED_CODE"],                              
      );

      if(isset($arRequisite["OFFICIALS"][0]["LAST_NAME"])){
         $arFields["RQ_DIRECTOR"] = $arRequisite["OFFICIALS"][0]["LAST_NAME"]." ".$arRequisite["OFFICIALS"][0]["NAME"]." ".$arRequisite["OFFICIALS"][0]["SECOND_NAME"];
      }
   }
   else{//ИП
      $arFields = array(
         'ENTITY_ID' => $companyId,
         'ENTITY_TYPE_ID' => CCrmOwnerType::Company,
         'PRESET_ID' => 2,//ИП                              
         'NAME' => "ИП ".$arRequisite["LAST_NAME"]." ".$arRequisite["NAME"]." ".$arRequisite["SECOND_NAME"],
         'SORT' => 500,
         'ACTIVE' => 'Y',
         'RQ_LAST_NAME' => $arRequisite['LAST_NAME'],
         'RQ_FIRST_NAME' => $arRequisite["NAME"],
         'RQ_SECOND_NAME' => $arRequisite["SECOND_NAME"],                              
         'RQ_COMPANY_FULL_NAME' => $arRequisite['NAME'],                              
         'RQ_INN' => $arRequisite["INN"], //инн                              
         'RQ_OGRNIP' => $arRequisite["OGRNIP"], //огрн
         'RQ_OKVED' => $arRequisite["OKVED_CODE"],                           
      );

   }
   
   $res = $entityRequisite->add($arFields);
   
   if($res->getId() > 0){
      //адрес добавляем
      $address = new \Bitrix\Crm\EntityAddress();
      $address->register(8, $res->getId(), 6, array(                                                            
         "ADDRESS_1" =>$arRequisite["ADDRESS_STREET_NAME"]." ".$arRequisite["ADDRESS_STREET_TYPE"]." ".$arRequisite["ADDRESS_HOUSE"]." ".$arRequisite["ADDRESS_BUILDING"],
         "ADDRESS_2" => $arRequisite["ADDRESS_FLAT"],
         "CITY" => $arRequisite["ADDRESS_REGION_NAME"],
         "POSTAL_CODE" => $arRequisite["ADDRESS_INDEX"],
         "COUNTRY" => "РФ"
      ));
   }                                          
   //создаем контакт 
   $arFields = array(
       "NAME" => $arNewUser["NAME"],
       "LAST_NAME" => $arNewUser["LAST_NAME"],                                     
       "POST" => "не указано",//должность               
       "OPENED" => "N", //открыто для других пользователей                
       "EXPORT" => "Y",//участвует в экспорте                
       'FM' => array(//почта, телефон
           'EMAIL' => array(
                   'n0' => array('VALUE' => $arNewUser["EMAIL"], 'VALUE_TYPE' => 'WORK')
                 ),
                 'PHONE' => array(
                    'n0' => array('VALUE' => $arNewUser["PERSONAL_MOBILE"], 'VALUE_TYPE' => 'WORK')
                 ) 
             ),
             "COMPANY_ID" => $companyId,                
        "ASSIGNED_BY_ID" => $manager,//id ответственного менеджера 
   );
   //создаем контакт   
   $oContact = new \CCrmContact(false);
   $oContact->add($arFields);
   if($oContact->LAST_ERROR != ""){                           
      //не создался контакт
   }
   
}
Счета и реквизиты
реквизиты список полей https://dev.1c-bitrix.ru/rest_help/crm/requisite/requisite_fields.php
счета список полей https://dev.1c-bitrix.ru/rest_help/crm/invoice/crm_invoice_fields.php
создать счет
$arInvoiceProps = array();

//получим реквизиты компании
$entityRequisite = new \Bitrix\Crm\EntityRequisite;
$rsRequisite = $entityRequisite->getList([
   "select"=>array("*"),
   "filter"=>array("ENTITY_ID"=>$companyId,"ENTITY_TYPE_ID"=>CCrmOwnerType::Company),
   "order"=>array("SORT"=>"desc","ID"=>"desc")

]);
$arRequisite = $rsRequisite->fetchAll(); 

if(count($arRequisite)>0){ //если ревизиты заполнены, берем первые (может быть несколько)
   $arRequisite = $arRequisite[0];
   $arInvoiceProps = array(                            
      9 => $arRequisite["RQ_INN"],   //ИНН                         
      10 => $arRequisite["RQ_KPP"], //КПП                           
      11 => $arRequisite["RQ_COMPANY_NAME"], //Название из ревизитов                           
           14 => $arComp["CLIENT_EMAIL"], //email

   );
   $address = new \Bitrix\Crm\EntityAddress();
   $dbRes   = $address->getList(array(
           'filter' => array(
              'ENTITY_ID' => $arRequisite['ID'],
              'ANCHOR_ID' => $companyId
           )
        ));
       $arAddresses = array();
       while ($arAddr =  $dbRes->Fetch()) {
     if($arAddr["TYPE_ID"]==6){
      $arInvoiceProps[12] = $addr["ADDRESS_1"]." ".$addr["ADDRESS_2"];//юр адрес
      $arInvoiceProps[17] = $addr["POSTAL_CODE"];//индекс
      $arInvoiceProps[18] = $addr["CITY"];//город      
      }                     
       }                            
}
else{ //если не заполнены реквизиты
   $arInvoiceProps = array(                                                      
          11 => $arComp["TITLE"], //Название из карточки                           
            14 => $arComp["CLIENT_EMAIL"] //email                        
   );
}
$arInvoiceProps[15] = ""; //телефон
$arInvoiceProps[13] = ""; //контактное лицо
   
   
$arFieldsInvoice = Array(
   "ORDER_TOPIC" => $arFields["TITLE"],
   "STATUS_ID" => "N",
   "DATE_INSERT" => date("d.m.Y H:i:s", strtotime("+0 hours")),
   "DATE_BILL" => date("d.m.Y", strtotime("+0 hours")),
   "PAY_VOUCHER_DATE" => "",
   "DATE_PAY_BEFORE" => "",
   "RESPONSIBLE_ID" => 1,
   "COMMENTS" => "",
   "USER_DESCRIPTION" => "",
   "UF_QUOTE_ID" => 0,
   "UF_DEAL_ID" => $arFields["ID"],
   "UF_COMPANY_ID" => $companyId,
   "UF_CONTACT_ID" => 0,
   "UF_MYCOMPANY_ID" => 9,
   "PRODUCT_ROWS" => Array(
      Array(
         "ID" => 0,
         "PRODUCT_ID" => 0,
         "PRODUCT_NAME" => "Оказание услуг бла-бла",
         "QUANTITY" =>$quantity,
         "PRICE" => $price,
         "VAT_RATE" => 0,
         "DISCOUNT_PRICE" => 0,
         "MEASURE_CODE" => 356,
         "MEASURE_NAME" => "ч",
         "CUSTOMIZED" => "Y"
      )
   ),
   "PERSON_TYPE_ID" => 1,
   "PAY_SYSTEM_ID" => 1,
   "INVOICE_PROPERTIES" => $arInvoiceProps,
   UF_CRM_1567860613 => 1 //доп свойства счета                  
);
$oCrmInvoice = new CCrmInvoice(false);
$result = $oCrmInvoice->Add($arFieldsInvoice); 
чтобы печатная форма счёта после создания была с реквизитами продавца, после создания счёта необходимо провести привязку самих реквизитов к этому счёту
EntityLink::register(5,$invoiceID,0,0,6,2);
получить счета
$oCrmInvoice = new CCrmInvoice(false);
$arFilter = array(   
  "CHECK_PERMISSIONS"=>"N",
  "UF_DEAL_ID" => $arDealIds,      
   "CANCELED"=>"N"            
 );            
 $arSelect = array("ID","UF_DEAL_ID");   
 $res = CCrmInvoice::GetList($arOrder = Array("ID"=>"DESC"), $arFilter ,false, false, $arSelect);   
 while($row = $res->Fetch()){            
    $oCrmInvoice->Update($row["ID"],array("CANCELED"=>"Y","STATUS_ID"=>"D")); //деактивируем счета                  
}
публичная ссылка на счет
$link = CCrmInvoice::getPublicLink($invoiceId); 
получить реквизиты компании
$entityRequisite = new \Bitrix\Crm\EntityRequisite;
$rsRequisite = $entityRequisite->getList([
   "select"=>array("*"),
   "filter"=>array("ENTITY_ID"=>$companyId,"ENTITY_TYPE_ID"=>CCrmOwnerType::Company),
   "order"=>array("SORT"=>"desc","ID"=>"desc")

]);
$arRequisite = $rsRequisite->fetchAll();
$arResult["REQUISITE"] = $arRequisite[0];
if(isset($arResult["REQUISITE"]['ID']) && $arResult["REQUISITE"]['ID']>0){
      $bank   = new \Bitrix\Crm\EntityBankDetail();
      $dbRes  = $bank->getList(array(
       'filter' => array('ENTITY_ID' => $arResult["REQUISITE"]['ID'])
   ));
   $arResult["BANK"] =  $dbRes->Fetch();
   $address = new \Bitrix\Crm\EntityAddress();
   $dbRes   = $address->getList(array(
       'filter' => array(
           'ENTITY_ID' => $arResult["REQUISITE"]['ID'],
           //'ANCHOR_ID' => $companyId
       )
   ));
   $arResult["ADDRESS"] = array();
   while ($arAddr =  $dbRes->Fetch()) {
      if($arAddr["TYPE_ID"]==6){
         $arResult["ADDRESS"]["OFFICIAL"] = $arAddr;
      }
      elseif($arAddr["TYPE_ID"]==2){
         $arResult["ADDRESS"]["FACT"] =  $arAddr;   
      }                     
   }

}   

по ID пользователя получим компанию, к которой он относится, получим реквизиты компании  и их проапдейтим

global $USER;
if(is_object($USER) && $USER->IsAuthorized()){
   $rsUser = CUser::GetList($by, $order,
       array("ID" => $USER->GetID()),
       array(
           "SELECT" => array("ID","UF_CONTACT"),
       )
   );
   if($arUser = $rsUser->Fetch()){         
      $companyId = intval($arUser["UF_CONTACT"]);
       if($companyId>0 && CModule::IncludeModule('crm')){                 
          $arFilter = array("ID"=>$companyId,"CHECK_PERMISSIONS"=>"N");
          $arSelect = array("ID","TITLE");
          $rsCompany = CCrmCompany::GetList(Array(),$arFilter,$arSelect);
          if($arCompany = $rsCompany->Fetch()){   
             $entityRequisite = new \Bitrix\Crm\EntityRequisite;
             $rsRequisite = $entityRequisite->getList([
                "select"=>array("*"),
                "filter"=>array(
                   "ENTITY_ID"=>$companyId,
                   "ID"=> intval($_REQUEST["req_id"]),
                   "ENTITY_TYPE_ID"=>CCrmOwnerType::Company
                ),
                "order"=>array("SORT"=>"desc","ID"=>"desc")

             ]);
             $arRequisiteOld = $rsRequisite->fetchAll();
             $arRequisiteTemp = $arRequisiteOld[0];
             if(isset($arRequisiteTemp['ID']) && (intval($arRequisiteTemp['ID'])>0)){
                $arRequisite = $_REQUEST['fields'];
                if($_REQUEST["type_company"] == "ip"){
                   //ИП
                   $arFields = array(                                                      
                     'NAME' => $arRequisite['RQ_COMPANY_NAME'],                           
                     'ACTIVE' => 'Y',
                     'RQ_LAST_NAME' => $arRequisite['RQ_LAST_NAME'],
                     'RQ_FIRST_NAME' => $arRequisite["RQ_FIRST_NAME"],
                     'RQ_SECOND_NAME' => $arRequisite["RQ_SECOND_NAME"],                              
                     'RQ_COMPANY_FULL_NAME' => $arRequisite['RQ_COMPANY_FULL_NAME'],                              
                     'RQ_INN' => $arRequisite["RQ_INN"], //инн                              
                     'RQ_OGRNIP' => $arRequisite["RQ_OGRNIP"], //огрн
                     'RQ_OKVED' => "",                           
                  );
                }
                else{
                   //юр лицо
                   $arFields = array(                                                   
                     'NAME' => $arRequisite['RQ_COMPANY_NAME'],
                     'SORT' => 500,
                     'ACTIVE' => 'Y',
                     'RQ_COMPANY_NAME' => $arRequisite['RQ_COMPANY_NAME'],
                     'RQ_COMPANY_FULL_NAME' => $arRequisite['RQ_COMPANY_FULL_NAME'],                              
                     'RQ_INN' => $arRequisite["RQ_INN"], //инн
                     'RQ_KPP' => $arRequisite["RQ_KPP"],  //кпп
                     'RQ_OGRN' => $arRequisite["RQ_OGRN"], //огрн
                     'RQ_COMPANY_REG_DATE' => "",
                     'RQ_OKVED' => "",   
                     'RQ_DIRECTOR' => $arRequisite["RQ_DIRECTOR"],
                     'RQ_ACCOUNTANT' => $arRequisite["RQ_ACCOUNTANT"]                           
                  );
                }
                $entityRequisite->Update(intval($arRequisiteTemp['ID']),$arFields);                   

                $bank   = new \Bitrix\Crm\EntityBankDetail();
               $dbRes  = $bank->getList(array(
                   'filter' => array('ENTITY_ID' => $arRequisiteTemp['ID'])
               ));
               $arBankOld =  $dbRes->Fetch();
               
               $arFields = array(
                  "RQ_BANK_NAME" => $arRequisite["RQ_BANK_NAME"],
                  "RQ_BIK" => $arRequisite["RQ_BIK"],
                  "RQ_ACC_NUM" => $arRequisite["RQ_ACC_NUM"],
                  "RQ_COR_ACC_NUM" => $arRequisite["RQ_COR_ACC_NUM"],
                  "RQ_BANK_ADDR" => $arRequisite["RQ_BANK_ADDR"],
               );
               if($arBankOld["ID"] >0){
                  $bank->Update(intval($arBankOld["ID"]),$arFields);
               }

               $address = new \Bitrix\Crm\EntityAddress();
               $address->deleteByEntity(2, $arRequisiteTemp['ID']);
               $address->deleteByEntity(6, $arRequisiteTemp['ID']);

               //юр адрес
               $arFields = array(
                  "ADDRESS_1" => $arRequisite["company_addr_address_1"],
                  "ADDRESS_2" => $arRequisite["company_addr_address_2"],
                  "CITY" => $arRequisite["company_addr_city"],
                  "POSTAL_CODE" => $arRequisite["company_addr_postal_code"],
                  "COUNTRY" => $arRequisite["company_addr_country"],
                  "REGION" => $arRequisite["company_addr_region"],
                  "PROVINCE" => $arRequisite["company_addr_province"],
               );
               $res = $address->register(8, $arRequisiteTemp['ID'], 6, $arFields);
               
               //факт адрес
               $arFields = array(
                  "ADDRESS_1" => $arRequisite["company_realaddr_address_1"],
                  "ADDRESS_2" => $arRequisite["company_realaddr_address_2"],
                  "CITY" => $arRequisite["company_realaddr_city"],
                  "POSTAL_CODE" => $arRequisite["company_realaddr_postal_code"],
                  "COUNTRY" => $arRequisite["company_realaddr_country"],
                  "REGION" => $arRequisite["company_realaddr_region"],
                  "PROVINCE" => $arRequisite["company_realaddr_province"],
               );
               $res = $address->register(8, $arRequisiteTemp['ID'], 2, $arFields);
               

             }   
             
          }
       }
   }   
}

Предложения
получить предложения
$arFilter = array(
   "ID"=>$id, //выбираем определенную по ID
   "CHECK_PERMISSIONS"=>"N" //не проверять права доступа текущего пользователя
);            
$arSelect = array(
   "ID",
   "UF_CRM_QUOTE_1634559297609",     
);            

$res = CCrmQuote::GetList(Array(), $arFilter,false,false, $arSelect);
if($arQuote = $res->Fetch()){
   //
}
получить по id
https://bxapi.ru/src/?module_id=crm&name=CCrmQuote::GetByID
$arQuote  = CCrmQuote::GetByID($id);
обновить
$quote = new CCrmQuote(false);   
$arOptions = array("CURRENT_USER"=> 1); //из под кого обновляем         
$arUpdatedFields = [];
$upRes = $quote->Update($id, $arUpdatedFields, true, true, $arOptions); 
Товары
получить товары
$arFilter = array(
   "OWNER_ID"=>$id, //ID сделки, лида, предложения
   "CHECK_PERMISSIONS"=>"N" //не проверять права доступа текущего пользователя
);            
$arSelect = array(
   "*"         
);            
$res = CCrmProductRow::GetList(['ID'=>'DESC'], $arFilter,false,false,$arSelect);         
while($arProduct = $res->Fetch()){
   //
}
удалить товары сделки, лида, предложения
CCrmProductRow::DeleteByOwner($entityType,$id); //$entityType - 'D' -сделка, 'L' - лид, 'Q' - предложение 
добавить товар в сделку, лид, предложение
поля https://bxapi.ru/src/?module_id=crm&name=CCrmProductRow::GetFields
CCrmProductRow::Add($arProduct);
Функции, которые переносят товары из Предложения в сделку или лид.
Запускаю из БП. Запрашивается удалять товары в сделке / лиде
function MoveProductsFromCPtoLead($id,$deleteFromLead=false){
   if(!empty($id) && CModule::IncludeModule('crm')){
      $arFilter = array(
         "ID"=>$id, //выбираем определенную сделку по ID
         "CHECK_PERMISSIONS"=>"N", //не проверять права доступа текущего пользователя   
         "!LEAD_ID"=>false      
      );   
      $arSelect = ["LEAD_ID"];   
      $res = CCrmQuote::GetList(Array(), $arFilter,false,false, $arSelect);
      if($arQuote = $res->Fetch()){
         if($deleteFromLead){
            CCrmProductRow::DeleteByOwner('L',$arQuote["LEAD_ID"]);
         }         
         $arFilter = array(
            "OWNER_ID"=>$id, 
            "CHECK_PERMISSIONS"=>"N" //не проверять права доступа текущего пользователя
         );            
         $arSelect = array(
            "*"         
         );            
         $res = CCrmProductRow::GetList(['ID'=>'DESC'], $arFilter,false,false,$arSelect);         
         while($arProduct = $res->Fetch()){
            unset($arProduct["ID"]);
            $arProduct["OWNER_ID"] = $arQuote["LEAD_ID"];
            $arProduct["OWNER_TYPE"] = 'L';
            CCrmProductRow::Add($arProduct);            
         }
      }      
   }

}


function MoveProductsFromCPtoDeal($id,$deleteFromDeal=false){
   if(!empty($id) && CModule::IncludeModule('crm')){
      $arFilter = array(
         "ID"=>$id, //выбираем определенную сделку по ID
         "CHECK_PERMISSIONS"=>"N", //не проверять права доступа текущего пользователя   
         "!DEAL_ID"=>false      
      );   
      $arSelect = ["DEAL_ID"];   
      $res = CCrmQuote::GetList(Array(), $arFilter,false,false, $arSelect);
      if($arQuote = $res->Fetch()){
         if($deleteFromDeal){
            CCrmProductRow::DeleteByOwner('D',$arQuote["DEAL_ID"]);
         }         
         $arFilter = array(
            "OWNER_ID"=>$id, 
            "CHECK_PERMISSIONS"=>"N" //не проверять права доступа текущего пользователя
         );            
         $arSelect = array(
            "*"         
         );            
         $res = CCrmProductRow::GetList(['ID'=>'DESC'], $arFilter,false,false,$arSelect);         
         while($arProduct = $res->Fetch()){
            unset($arProduct["ID"]);
            $arProduct["OWNER_ID"] = $arQuote["DEAL_ID"];
            $arProduct["OWNER_TYPE"] = 'D';
            CCrmProductRow::Add($arProduct);            
         }
      }      
   }
}
Можно вывести принадлежность роли к пользователю методами класса CCrmRole:
https://bxapi.ru/?module_id=crm&class=CCrmRole
CCrmRole::GetList();
CCrmRole::GetRelation();
получить права доступа текущего пользователя для CRM
$userPermissions = CCrmPerms::GetCurrentUserPermissions();
$permissions=$userPermissions->GetUserPerms();
Вид карточки CRM
crm.entity.editor - компонент
установить вид карточки для текущего пользователя
company_details - компании
deal_details_scope - сделки
CUserOptions::SetOption("crm.entity.editor", "company_details", "C"); //общий вид карточки
CUserOptions::SetOption("crm.entity.editor", "deal_details_scope", [                          
   'scope' => "CUSTOM",
   'userScopeId' => 6
]);
Настройки представлений хранятся в таблице:
b_ui_entity_editor_config
Изменить название = изменить значение NAME для представление в этой таблице.
Добавить представление  https://dev.1c-bitrix.ru/api_d7/bitrix/crm/config/entityconfig/set.php
Получить настройки представления https://dev.1c-bitrix.ru/api_d7/bitrix/crm/config/entityconfig/get.php
Удалить прелставление https://dev.1c-bitrix.ru/api_d7/bitrix/crm/config/entityconfig/remove.php

Смарт-процессы
получить все привязки компании к смарт процессам
в $parents будет нужная, смотреть entityTypeId
use Bitrix\Crm\ItemIdentifier;
use Bitrix\Crm\Service\Container;
$parent = new ItemIdentifier(\CCrmOwnerType::Company, $companyId);
$parents = Container::getInstance()->getRelationManager()->getChildElements($parent);
var_dump($parents);
получить привязанные смарт-процессы, к смарт-процессу
тоже самое, только
$parent = new ItemIdentifier($smartType, $smartItemId);

есть еще обратный метод
$parents = Container::getInstance()->getRelationManager()->getParentElements($parent);