< Summary

Class:WinSolutions.Sveta.Server.Services.Implements.CrmSyncWorker
Assembly:SVETA.Api
File(s):/opt/dev/sveta_api_build/SVETA.Api/Services/Implements/CrmSyncWorker.cs
Covered lines:0
Uncovered lines:279
Coverable lines:279
Total lines:385
Line coverage:0% (0 of 279)
Covered branches:0
Total branches:164
Branch coverage:0% (0 of 164)

Metrics

MethodLine coverage Branch coverage
.ctor(...)0%0%
SyncWithCrm()0%0%
SendToTelegram()0%0%
SyncUserWithCrm()0%0%
SyncContragentKindWithCrm()0%0%
SyncContragentWithCrm()0%0%
SyncAllUsersByContragent()0%0%

File(s)

/opt/dev/sveta_api_build/SVETA.Api/Services/Implements/CrmSyncWorker.cs

#LineLine coverage
 1using Microsoft.EntityFrameworkCore;
 2using SVETA.Api.Helpers.Authorize;
 3using SVETA.Api.Services.Interfaces;
 4using System;
 5using System.Linq;
 6using CrmVtbc;
 7using System.Collections.Generic;
 8using Microsoft.Extensions.Options;
 9using SVETA.Api.Data.Domain;
 10using WinSolutions.Sveta.Common;
 11using System.Security.Claims;
 12using System.Threading.Tasks;
 13using WinSolutions.Sveta.Server.Data.DataModel.Contexts;
 14using WinSolutions.Sveta.Server.Data.DataModel.Entities;
 15using WinSolutions.Sveta.Server.Data.DataModel.Kinds;
 16using WinSolutions.Sveta.Server.Services.Interfaces;
 17using Microsoft.Extensions.Logging;
 18using SVETA.Api.Helpers;
 19
 20namespace WinSolutions.Sveta.Server.Services.Implements
 21{
 22    public class CrmSyncWorker : ICrmSyncWorker
 23    {
 24        private readonly SvetaDbContext _db;
 25        private readonly ICommonContragentService _commonContragentService;
 26        private readonly ICommonUserService _commonUserService;
 27        private readonly ICrmService _crmService;
 28        private readonly ConfigurationsSettings _confSettings;
 29        private readonly ILogger<CrmSyncWorker> _logger;
 30
 31        private long serviceUserId;
 32        private bool crmStatus;
 33        private bool isNewUser;
 034        public CrmSyncWorker(SvetaDbContext db, ICommonContragentService commonContragentService, ICommonUserService com
 035            IOptions<ConfigurationsSettings> optionsConfs, ILogger<CrmSyncWorker> logger)
 036        {
 037            _confSettings = optionsConfs.Value;
 038            _db = db;
 039            _logger = logger;
 040            _commonContragentService = commonContragentService;
 041            _commonUserService = commonUserService;
 042            _crmService = crmService;
 043            if (!Guid.TryParse(_confSettings.GetConfValue("AuthenticationSettings", "ServiceUserTID"), out Guid serviceU
 044                throw new ArgumentException("Не удалось разобрать значение ключа ServiceUserTID в секции AuthenticationS
 045            serviceUserId = _commonUserService.GetUser(serviceUser).Result.Id;
 046            if (!Boolean.TryParse(_confSettings.GetConfValue("CrmSettings", "SyncOn"), out crmStatus))
 047                throw new SvetaException("Не удалось определить статус синхронизации с CRM. Не удалось разобрать значени
 048        }
 49
 50        /// <summary>
 51        /// Запускает синхронизацию с CRM.
 52        /// </summary>
 53        /// <param name="userTid">внешний идентификатор пользователя</param>
 54        /// <param name="contragentTid">внешний идентификатор контрагента</param>
 55        /// <param name="checkContragent">true, если необходимо проверить привязку контрагента к юзеру. Использовать tru
 56        /// <returns></returns>
 57        public async Task SyncWithCrm(Guid? userTid, Guid? contragentTid, bool checkContragent = false)
 058        {
 059            if ((userTid.IsDefaultValueOrNull() && contragentTid.IsDefaultValueOrNull()) || !crmStatus)
 060                return;
 61            //new CrmVtbc.Model.Creatio.Account()
 62            // new CrmVtbc.Model.Creatio.Contact()
 063            isNewUser = false;
 064            User user = null;
 065            Contragent contragent = null;
 066            if (!userTid.IsDefaultValueOrNull())
 067            {
 068                user = await SyncUserWithCrm(userTid.Value);
 069                if (checkContragent)
 070                {
 71                    //проверяем не поменялся ли КА у юзера
 072                    var contragentCrmId = await _crmService.GetValue<Guid>("Contact", "NrbSvetaAccountId", new Dictionar
 073                    if (contragentCrmId.IsDefaultValueOrNull())
 074                        throw new SvetaException($"В CRM у пользователя с TID={userTid.Value} не указан контрагент. Полу
 075                    contragentTid = await _crmService.GetValue<Guid>("Account", "NrbTID", new Dictionary<string, object>
 076                    if (contragentTid.IsDefaultValueOrNull())
 077                        throw new SvetaException($"В CRM не найден контрагент с Id={contragentCrmId}. Полученное значени
 078                }
 079            }
 080            if (!contragentTid.IsDefaultValueOrNull())
 081                contragent = await SyncContragentWithCrm(contragentTid.Value);
 82            //если синкуем и юзера и КА, то проверяем корректность привязки
 083            if ((user != null && contragent != null) && user.Contragent?.Id != contragent?.Id)
 084            {
 085                user.Contragent = contragent;
 086                await _commonUserService.Update(user, serviceUserId);
 087            }
 088            await SendToTelegram(user);
 089        }
 90
 91        /// <summary>
 92        /// Отправляет сообщение в телеграмм при создании нового пользователя в БД
 93        /// </summary>
 94        /// <param name="usr"></param>
 95        /// <returns></returns>
 96        private async Task SendToTelegram(User usr)
 097        {
 098            if (isNewUser && await _commonUserService.CanSendToTelegram("#newclient"))
 099            {
 0100                string textTelegram =
 0101                   $"#newclient " +
 0102                   $"\nВыполнен вход нового пользователя {usr.FirstName} {usr.LastName}. " +
 0103                   $"\nКонтрагент: {usr.Contragent?.ShortName} " +
 0104                   $"\nНомер телефона: {usr.Phone}";
 0105                await Telegram.SendNotification(textTelegram);
 0106            }
 0107        }
 108
 109        /// <summary>
 110        /// Синхронизирует пользователя с CRM
 111        /// </summary>
 112        /// <param name="tid">tid пользователя из токена</param>
 113        /// <returns>обновленную запись пользователя</returns>
 114        private async Task<User> SyncUserWithCrm(Guid tid)
 0115        {
 0116            User user = await _commonUserService.GetUser(tid);
 0117            bool needToAdd = false;
 0118            if (user == null)
 0119            {
 0120                user = new User { ExternalKey = tid };
 0121                needToAdd = true;
 0122            }
 123            SyncResult syncRes;
 124            try
 0125            {
 0126                syncRes = await _crmService.Sync(user, true); //синхрониируемся с CRM
 0127            }
 0128            catch (Exception ex)
 0129            {
 0130                throw new SvetaException($"Ошибка при обновлении из CRM данных по пользователю с TID={tid}. {ex.Message}
 131            }
 132
 0133            if (string.IsNullOrWhiteSpace(user?.FirstName))
 0134                throw new SvetaException($"В CRM у пользователя с TID {tid} не указано имя", (int)ErrorCode.CrmIncorrect
 0135            if (string.IsNullOrWhiteSpace(user?.LastName))
 0136                throw new SvetaException($"В CRM у пользователя с TID {tid} не указана фамилия", (int)ErrorCode.CrmIncor
 0137            if (syncRes.IsLoadedFromCRM() && needToAdd) //если притянули данные из CRM и надо создать запись
 0138            {
 0139                await _commonUserService.Create(user, serviceUserId);
 0140                isNewUser = true;
 0141            }
 0142            else if (syncRes.IsLoadedFromCRM()) //если притянули данные из CRM
 0143            {
 0144                await _commonUserService.Update(user, serviceUserId);
 0145            }
 0146            return user;
 0147        }
 148
 149        /// <summary>
 150        /// Синхронизирует тип контрагента с CRM
 151        /// </summary>
 152        /// <param name="id">Гуид типа контрагента</param>
 153        /// <returns>обновленную запись типа</returns>
 154        private async Task<ContragentsKind> SyncContragentKindWithCrm(Guid id)
 0155        {
 0156            bool needToAdd = false;
 0157            ContragentsKind contrKind = await _commonContragentService.GetContragentKind(id);
 0158            if (contrKind == null)
 0159            {
 0160                contrKind = new ContragentsKind { ExternalKey = id };
 0161                needToAdd = true;
 0162            }
 163            SyncResult syncRes;
 164            try
 0165            {
 0166                syncRes = await _crmService.Sync(contrKind, true); //синхрониируемся с CRM
 0167            }
 0168            catch (Exception ex)
 0169            {
 0170                throw new SvetaException($"Ошибка при обновлении из CRM данных по типу контрагента. Идентификатор типа {
 171            }
 172
 0173            if (string.IsNullOrWhiteSpace(contrKind?.Name))
 0174                throw new SvetaException($"В CRM у типа контрагента с ID {id} не указано название", (int)ErrorCode.CrmIn
 0175            if (syncRes.IsLoadedFromCRM() && needToAdd) //если притянули данные из CRM и надо создать запись
 0176            {
 0177                await _commonContragentService.CreateContragentKind(contrKind, serviceUserId);
 0178            }
 0179            else if (syncRes.IsLoadedFromCRM()) //если притянули данные из CRM
 0180            {
 0181                await _commonContragentService.UpdateContragentKind(contrKind, serviceUserId);
 0182            }
 0183            return contrKind;
 0184        }
 185
 186        /// <summary>
 187        /// Синхронизирует контрагента с CRM
 188        /// </summary>
 189        /// <param name="tid">tid контрагента из токена</param>
 190        /// <returns>обновленную запись контрагента</returns>
 191        private async Task<Contragent> SyncContragentWithCrm(Guid tid)
 0192        {
 0193            Contragent contragent = await _commonContragentService.GetContragent(tid);
 0194            bool needToUpdate = false, needToAdd = false;
 0195            if (contragent == null)
 0196            {
 0197                contragent = new Contragent { ExternalKey = tid };
 0198                needToAdd = true;
 0199            }
 200            SyncResult syncRes;
 201            try
 0202            {
 0203                syncRes = await _crmService.Sync(contragent, true); //синхрониируемся с CRM
 0204            }
 0205            catch (Exception ex)
 0206            {
 0207                throw new SvetaException($"Ошибка при обновлении из CRM данных по контрагенту с TID={tid}. {ex.Message}"
 208            }
 209
 0210            if (string.IsNullOrWhiteSpace(contragent.ShortName))
 0211                throw new SvetaException($"У контрагента {contragent.ShortName} в CRM не указано короткое название", (in
 0212            if (string.IsNullOrWhiteSpace(contragent.FullName))
 0213                throw new SvetaException($"У контрагента {contragent.ShortName} в CRM не указано полное название", (int)
 0214            if (string.IsNullOrWhiteSpace(contragent.Inn))
 0215                throw new SvetaException($"У контрагента {contragent.ShortName} в CRM не указан ИНН", (int)ErrorCode.Crm
 0216            if (string.IsNullOrWhiteSpace(contragent.Kpp))
 0217                throw new SvetaException($"У контрагента {contragent.ShortName} в CRM не указан КПП", (int)ErrorCode.Crm
 0218            if (await _commonContragentService.ContragentInnKppExist(contragent))
 0219                throw new SvetaException($"Контрагент с ИНН {contragent.Inn} и КПП {contragent.Kpp} уже существует", (in
 0220            if (string.IsNullOrWhiteSpace(contragent.Email))
 0221                throw new SvetaException($"У контрагента {contragent.ShortName} в CRM не указан Email", (int)ErrorCode.C
 0222            if (string.IsNullOrWhiteSpace(contragent.TaxSystemCRM))
 0223                throw new SvetaException($"У контрагента {contragent.ShortName} в CRM не указана форма налогообложения",
 0224            if (string.IsNullOrWhiteSpace(contragent.Ogrn))
 0225                throw new SvetaException($"У контрагента {contragent.ShortName} в CRM не указан ОГРН", (int)ErrorCode.Cr
 0226            if (string.IsNullOrWhiteSpace(contragent.PhoneNumber))
 0227                throw new SvetaException($"У контрагента {contragent.ShortName} в CRM не указан телефон", (int)ErrorCode
 0228            if (string.IsNullOrWhiteSpace(contragent.WalletId))
 0229                throw new SvetaException($"У контрагента {contragent.ShortName} в CRM не указан номер кошелька", (int)Er
 0230            if (string.IsNullOrWhiteSpace(contragent.WalletShortId))
 0231                throw new SvetaException($"У контрагента {contragent.ShortName} в CRM не указан короткий номер кошелька"
 0232            if (string.IsNullOrWhiteSpace(contragent.ChiefAccountant))
 0233                throw new SvetaException($"У контрагента {contragent.ShortName} в CRM не указан главный бухгалтер", (int
 234
 0235            var accountValList = await _crmService.GetEntityByField("Account", "NrbTID", tid, new List<string> { "NrbSve
 0236                "NrbDaDataPhysicalAddress", "NrbDaDataRegistrationAddress", "NrbDaDataPhysicalRegion", "NrbDaDataRegistr
 0237                    "NrbDaDataRegistrationZip", "NrbDaDataPhysicalDistrict", "NrbDaDataRegistrationDistrict", "NrbDaData
 0238                    "NrbDaDataPhysicalStreet", "NrbDaDataRegistrationStreet", "NrbDaDataPhysicalBuilding1", "NrbDaDataRe
 0239                    "NrbDaDataRegistrationBuilding2", "NrbDaDataPhysicalAptOffice", "NrbDaDataRegistrationAptOffice"}); 
 240
 0241            if (string.IsNullOrWhiteSpace(accountValList["NrbDaDataRegistrationAddress"].ToString()))
 0242                throw new SvetaException($"У контрагента {contragent.ShortName} в CRM не указан юридический адрес", (int
 0243            if (string.IsNullOrWhiteSpace(accountValList["NrbDaDataPhysicalAddress"].ToString()))
 0244                throw new SvetaException($"У контрагента {contragent.ShortName} в CRM не указан физический адрес", (int)
 245
 0246            var ownerId = accountValList["NrbSvetaAuthorizedPersonId"].IsDefaultValueOrNull() ? throw new SvetaException
 0247                $"Полученное значение NrbSvetaAuthorizedPersonId={accountValList["NrbSvetaAuthorizedPersonId"]}", (int)E
 0248                : Guid.Parse(accountValList["NrbSvetaAuthorizedPersonId"].ToString());
 0249            var ownerTid = await _crmService.GetValue<Guid>("Contact", "NrbTID", new Dictionary<string, object>() { { "I
 0250            if (ownerTid.IsDefaultValueOrNull())
 0251                throw new SvetaException($"В CRM не найден пользователь с Id={ownerId}. Полученное значение NrbTID={owne
 0252            var userOwner = await SyncUserWithCrm(ownerTid);
 253
 0254            var typeId = accountValList["TypeId"].IsDefaultValueOrNull() ? throw new SvetaException($"В CRM у контрагент
 0255                $"Полученное значение TypeId={accountValList["TypeId"]}", (int)ErrorCode.CrmNoRelation)
 0256                : Guid.Parse(accountValList["TypeId"].ToString());
 0257            var type = await SyncContragentKindWithCrm(typeId);
 258
 0259            var juridicalAddress = await _commonContragentService.GetAddress(accountValList["NrbDaDataRegistrationAddres
 0260            if (juridicalAddress == null)
 0261            {
 0262                juridicalAddress = new Address()
 0263                {
 0264                    FullAddress = accountValList["NrbDaDataRegistrationAddress"].ToString(),
 0265                    Region = accountValList["NrbDaDataRegistrationRegion"].ToString(),
 0266                    Index = accountValList["NrbDaDataRegistrationZip"].ToString(),
 0267                    District = accountValList["NrbDaDataRegistrationDistrict"].ToString(),
 0268                    Locality = accountValList["NrbDaDataRegistrationLocality"].ToString(),
 0269                    Street = accountValList["NrbDaDataRegistrationStreet"].ToString(),
 0270                    House = accountValList["NrbDaDataRegistrationBuilding1"].ToString(),
 0271                    Housing = accountValList["NrbDaDataRegistrationBuilding2"].ToString(),
 0272                    Office = accountValList["NrbDaDataRegistrationAptOffice"].ToString()
 0273                };
 0274                await _commonContragentService.CreateAddress(juridicalAddress, serviceUserId); //записываем адрес тут, а
 0275            }
 276            else
 0277            {
 0278                juridicalAddress.FullAddress = accountValList["NrbDaDataRegistrationAddress"].ToString();
 0279                juridicalAddress.Region = accountValList["NrbDaDataRegistrationRegion"].ToString();
 0280                juridicalAddress.Index = accountValList["NrbDaDataRegistrationZip"].ToString();
 0281                juridicalAddress.District = accountValList["NrbDaDataRegistrationDistrict"].ToString();
 0282                juridicalAddress.Locality = accountValList["NrbDaDataRegistrationLocality"].ToString();
 0283                juridicalAddress.Street = accountValList["NrbDaDataRegistrationStreet"].ToString();
 0284                juridicalAddress.House = accountValList["NrbDaDataRegistrationBuilding1"].ToString();
 0285                juridicalAddress.Housing = accountValList["NrbDaDataRegistrationBuilding2"].ToString();
 0286                juridicalAddress.Office = accountValList["NrbDaDataRegistrationAptOffice"].ToString();
 0287                await _commonContragentService.UpdateAddress(juridicalAddress, serviceUserId);
 0288            }
 289
 0290            var physicalAddress = await _commonContragentService.GetAddress(accountValList["NrbDaDataPhysicalAddress"].T
 0291            if (physicalAddress == null)
 0292            {
 0293                physicalAddress = new Address()
 0294                {
 0295                    FullAddress = accountValList["NrbDaDataPhysicalAddress"].ToString(),
 0296                    Region = accountValList["NrbDaDataPhysicalRegion"].ToString(),
 0297                    Index = accountValList["NrbDaDataPhysicalZip"].ToString(),
 0298                    District = accountValList["NrbDaDataPhysicalDistrict"].ToString(),
 0299                    Locality = accountValList["NrbDaDataPhysicalLocality"].ToString(),
 0300                    Street = accountValList["NrbDaDataPhysicalStreet"].ToString(),
 0301                    House = accountValList["NrbDaDataPhysicalBuilding1"].ToString(),
 0302                    Housing = accountValList["NrbDaDataPhysicalBuilding2"].ToString(),
 0303                    Office = accountValList["NrbDaDataPhysicalAptOffice"].ToString()
 0304                };
 0305                await _commonContragentService.CreateAddress(physicalAddress, serviceUserId);
 0306            }
 0307            else if (physicalAddress?.Id != juridicalAddress?.Id) //если юр и физ адреса разные, тогда обновляем. чтобы 
 0308            {
 0309                physicalAddress.FullAddress = accountValList["NrbDaDataPhysicalAddress"].ToString();
 0310                physicalAddress.Region = accountValList["NrbDaDataPhysicalRegion"].ToString();
 0311                physicalAddress.Index = accountValList["NrbDaDataPhysicalZip"].ToString();
 0312                physicalAddress.District = accountValList["NrbDaDataPhysicalDistrict"].ToString();
 0313                physicalAddress.Locality = accountValList["NrbDaDataPhysicalLocality"].ToString();
 0314                physicalAddress.Street = accountValList["NrbDaDataPhysicalStreet"].ToString();
 0315                physicalAddress.House = accountValList["NrbDaDataPhysicalBuilding1"].ToString();
 0316                physicalAddress.Housing = accountValList["NrbDaDataPhysicalBuilding2"].ToString();
 0317                physicalAddress.Office = accountValList["NrbDaDataPhysicalAptOffice"].ToString();
 0318                await _commonContragentService.UpdateAddress(physicalAddress, serviceUserId);
 0319            }
 320
 0321            if (contragent.Owner?.Id != userOwner?.Id) //Если старый и новый владелец не равны, присваиваем
 0322            {
 0323                contragent.Owner = userOwner;
 0324                needToUpdate = true;
 0325            }
 0326            if (contragent.JuridicAddress?.Id != juridicalAddress?.Id) //Если старый и новый адрес не равны, присваиваем
 0327            {
 0328                contragent.JuridicAddress = juridicalAddress;
 0329                needToUpdate = true;
 0330            }
 0331            if (contragent.PhysicAddress?.Id != physicalAddress?.Id) //Если старый и новый адрес не равны, присваиваем
 0332            {
 0333                contragent.PhysicAddress = physicalAddress;
 0334                needToUpdate = true;
 0335            }
 0336            if (contragent.ContragentsKind?.Id != type?.Id) //Если старый и новый тип не равны, присваиваем
 0337            {
 0338                contragent.ContragentsKind = type;
 0339                needToUpdate = true;
 0340            }
 341
 0342            if (syncRes.IsLoadedFromCRM() && needToAdd) //если притянули данные из CRM и надо создать запись
 0343            {
 0344                await _commonContragentService.Create(contragent, serviceUserId);
 0345            }
 0346            else if (syncRes.IsLoadedFromCRM() || needToUpdate) //если притянули данные из CRM или обновили связи у запи
 0347            {
 0348                await _commonContragentService.Update(contragent, serviceUserId);
 0349            }
 350
 0351            return contragent;
 0352        }
 353
 354        /// <summary>
 355        /// Синхронизирует всех пользователей контрагента
 356        /// </summary>
 357        /// <param name="contragentId">id контрагента</param>
 358        /// <returns></returns>
 359        public async Task SyncAllUsersByContragent(long contragentId)
 0360        {
 0361            if (!crmStatus || contragentId <= 0)
 0362                return;
 0363            isNewUser = false;
 0364            var contragent = await _commonContragentService.GetContragent(contragentId);
 0365            var contragentCrmId = await _crmService.GetValue<Guid>("Account", "Id", new Dictionary<string, object>() { {
 0366            if (contragentCrmId.IsDefaultValueOrNull())
 0367                throw new SvetaException($"В CRM не найден контрагент с TID={contragent.ExternalKey}. Полученное значени
 368            //"NrbSvetaAccount/Id" - через слеш, так как пока так реализовано в софте террасофта обращение к ссылочным п
 0369            var usersTids = await _crmService.GetAllEntriesByFields("Contact", new Dictionary<string, object>() { { "Nrb
 0370            foreach (var item in usersTids)
 0371            {
 0372                var tid = Guid.Parse(item["NrbTID"].ToString());
 0373                if (tid.IsDefaultValueOrNull())
 0374                    continue;
 0375                var user = await SyncUserWithCrm(tid);
 0376                if (user.Contragent?.Id != contragent?.Id)
 0377                {
 0378                    user.Contragent = contragent;
 0379                    await _commonUserService.Update(user, serviceUserId);
 0380                }
 0381                await SendToTelegram(user);
 0382            }
 0383        }
 384    }
 385}