< Summary

Information
Class: Services.DataServices.EtProducerDataServices
Assembly: Services
File(s): /home/runner/work/Studio2Prod/Studio2Prod/AppRepository/DataServices/EtProducerDataServices.cs
Line coverage
16%
Covered lines: 16
Uncovered lines: 83
Coverable lines: 99
Total lines: 252
Line coverage: 16.1%
Branch coverage
4%
Covered branches: 2
Total branches: 44
Branch coverage: 4.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/AppRepository/DataServices/EtProducerDataServices.cs

#LineLine coverage
 1using OzonDomains.Models;
 2using OzonRepositories.Data;
 3using Services.ApiServices.StudioApi;
 4using Services.ApiServices.StudioApi.Models.Response;
 5using System.Text.RegularExpressions;
 6
 7namespace Services.DataServices;
 8
 9public class EtProducerDataServices : IDataServices
 10{
 11    private readonly EtProducerRepository _repository;
 12    private readonly InterpartsDataManager _interpartsDataManager;
 13
 3214    public EtProducerDataServices(EtProducerRepository repository,
 3215        InterpartsDataManager interpartsDataManager)
 16    {
 3217        _repository = repository;
 3218        _interpartsDataManager = interpartsDataManager;
 3219    }
 20
 21    public Task<int> AddEtProducer(EtProducer value)
 22    {
 023        return _repository.Add(value);
 24    }
 25
 26    public Task<int> DeleteEtProducer(EtProducer value)
 27    {
 028        return _repository.Delete(value);
 29    }
 30
 31    public async Task<List<EtProducer>> GetEtProducers()
 32    {
 033        return await _repository.Get();
 034    }
 35
 36    public List<EtProducer> GetEtProducersByRealId(int? realId)
 37    {
 038        return _repository.GetByRealId(realId).ToList();
 39    }
 40
 41    public IQueryable<EtProducer> GetQueryableEtProducers()
 42    {
 1743        return _repository.GetQueryable();
 44    }
 45
 46    public async Task<EtProducer?> GetEtProducerAsync(int id)
 47    {
 048        return await _repository.GetAsync(id);
 049    }
 50
 51    public EtProducer? GetEtProducer(int id)
 52    {
 053        return _repository.Get(id);
 54    }
 55
 56    public async Task<EtProducer?> GetEtProducerAsync(EtProducer value)
 57    {
 058        return await _repository.GetAsync(value);
 059    }
 60
 61    public async Task<EtProducer?> GetRealIdAsyncByCode(string marketPrefix)
 62    {
 063        return await _repository.GetRealIdAsyncByCode(marketPrefix);
 064    }
 65
 66    /// <summary>
 67    /// Производитель по префиксу из offer_id. Если префикс общий у нескольких брендов (HND — Honda и Hyundai),
 68    /// выбирается тот, чьё имя встречается в названии товара отдельным словом.
 69    /// Если бренд по названию определить нельзя, возвращается null: пустой производитель лучше чужого,
 70    /// из-за которого карточка в 1С не находится.
 71    /// </summary>
 72    public async Task<EtProducer?> GetRealIdAsyncByCode(string marketPrefix, string? productName)
 73    {
 274        var candidates = await _repository.GetAllByCodeAsync(marketPrefix);
 675        if (candidates.Select(c => c.RealId).Distinct().Count() <= 1)
 076            return candidates.FirstOrDefault();
 77
 278        if (string.IsNullOrWhiteSpace(productName))
 079            return null;
 80
 281        var name = productName.Trim();
 582        return candidates.FirstOrDefault(c => IsProducerNameInProductName(c.Name, name));
 283    }
 84
 85    private static bool IsProducerNameInProductName(string? producerName, string productName)
 86    {
 387        if (string.IsNullOrWhiteSpace(producerName)) return false;
 88
 389        var escapedName = Regex.Escape(producerName.Trim());
 390        return Regex.IsMatch(productName, $"(?<![\\p{{L}}\\p{{N}}]){escapedName}(?![\\p{{L}}\\p{{N}}])",
 391            RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
 92    }
 93
 94    public async Task<EtProducer?> GetRealIdAsyncByName(string name)
 95    {
 096        return await _repository.GetRealIdAsyncByName(name);
 097    }
 98
 99    public async Task<int> UpdateEtProducer(EtProducer value)
 100    {
 0101        return await _repository.Update(value);
 0102    }
 103
 104    /// <summary>
 105    /// Обновляет EtProducer из API по ID с условием Id eq RealId
 106    /// </summary>
 107    /// <param name="producerId">ID производителя для обновления</param>
 108    /// <returns>Обновленный EtProducer или null если не найден</returns>
 109    public async Task<EtProducer?> UpdateEtProducerFromApi(int producerId)
 110    {
 111        try
 112        {
 113            // Получаем данные из API
 0114            var apiProducer = await _interpartsDataManager.GetProducerByIdWithRealId(producerId);
 0115            if (apiProducer == null)
 116            {
 0117                return null; // Производитель не найден в API
 118            }
 119
 120            // Ищем существующего производителя в базе
 0121            var existingProducer = await _repository.GetAsync(producerId);
 122
 0123            if (existingProducer != null)
 124            {
 125                // Обновляем существующую запись
 0126                return await UpdateExistingProducer(existingProducer, apiProducer);
 127            }
 128            else
 129            {
 130                // Создаем новую запись
 0131                return await CreateNewProducer(apiProducer);
 132            }
 133        }
 0134        catch (Exception ex)
 135        {
 136            // Логируем ошибку
 0137            Console.WriteLine($"Ошибка при обновлении EtProducer из API: {ex.Message}");
 0138            return null;
 139        }
 0140    }
 141
 142    /// <summary>
 143    /// Обновляет существующего производителя данными из API
 144    /// </summary>
 145    private async Task<EtProducer?> UpdateExistingProducer(EtProducer existing, Producer apiData)
 146    {
 0147        existing.RealId = apiData.RealId;
 0148        existing.Prefix = apiData.Prefix ?? string.Empty;
 0149        existing.Name = apiData.Name ?? string.Empty;
 0150        existing.Address = apiData.Address ?? string.Empty;
 0151        existing.Www = apiData.Www ?? string.Empty;
 0152        existing.Rating = apiData.Rating;
 0153        existing.ExistName = apiData.ExistName ?? string.Empty;
 0154        existing.ExistId = apiData.ExistId;
 0155        existing.Domain = apiData.Domain ?? string.Empty;
 0156        existing.TecdocSupplierId = apiData.TecdocSupplierId;
 0157        existing.MarketPrefix = apiData.MarketPrefix ?? string.Empty;
 158
 0159        await _repository.Update(existing);
 0160        await _repository.SaveChanges();
 161
 0162        return existing;
 0163    }
 164
 165    /// <summary>
 166    /// Создает нового производителя из данных API
 167    /// </summary>
 168    private async Task<EtProducer?> CreateNewProducer(Producer apiData)
 169    {
 0170        var newProducer = new EtProducer
 0171        {
 0172            Id = apiData.Id,
 0173            RealId = apiData.RealId,
 0174            Prefix = apiData.Prefix ?? string.Empty,
 0175            Name = apiData.Name ?? string.Empty,
 0176            Address = apiData.Address ?? string.Empty,
 0177            Www = apiData.Www ?? string.Empty,
 0178            Rating = apiData.Rating,
 0179            ExistName = apiData.ExistName ?? string.Empty,
 0180            ExistId = apiData.ExistId,
 0181            Domain = apiData.Domain ?? string.Empty,
 0182            TecdocSupplierId = apiData.TecdocSupplierId,
 0183            MarketPrefix = apiData.MarketPrefix ?? string.Empty
 0184        };
 185
 0186        await _repository.Add(newProducer);
 0187        await _repository.SaveChanges();
 188
 0189        return newProducer;
 0190    }
 191
 192    /// <summary>
 193    /// Пакетное обновление нескольких производителей из API
 194    /// </summary>
 195    /// <param name="producerIds">Список ID производителей для обновления</param>
 196    /// <returns>Список обновленных производителей</returns>
 197    public async Task<List<EtProducer>> UpdateMultipleEtProducersFromApi(List<int> producerIds)
 198    {
 0199        var results = new List<EtProducer>();
 200
 0201        foreach (var producerId in producerIds)
 202        {
 0203            var updatedProducer = await UpdateEtProducerFromApi(producerId);
 0204            if (updatedProducer != null)
 205            {
 0206                results.Add(updatedProducer);
 207            }
 208
 209            // Небольшая задержка чтобы не перегружать API
 0210            await Task.Delay(100);
 211        }
 212
 0213        return results;
 0214    }
 215
 216    /// <summary>
 217    /// Обновляет производителя по MarketPrefix (поиск + обновление из API)
 218    /// </summary>
 219    public async Task<EtProducer?> UpdateEtProducerByMarketPrefixFromApi(string marketPrefix)
 220    {
 221        // Сначала ищем в базе по MarketPrefix
 0222        var existingProducer = await _repository.GetRealIdAsyncByCode(marketPrefix);
 0223        if (existingProducer != null)
 224        {
 225            // Обновляем найденного производителя по его ID
 0226            return await UpdateEtProducerFromApi(existingProducer.Id);
 227        }
 228
 0229        return null;
 0230    }
 231
 232    /// <summary>
 233    /// Обновляет производителя по имени (поиск + обновление из API)
 234    /// </summary>
 235    public async Task<EtProducer?> UpdateEtProducerByNameFromApi(string name)
 236    {
 237        // Сначала ищем в базе по имени
 0238        var existingProducer = await _repository.GetRealIdAsyncByName(name);
 0239        if (existingProducer != null)
 240        {
 241            // Обновляем найденного производителя по его ID
 0242            return await UpdateEtProducerFromApi(existingProducer.Id);
 243        }
 244
 0245        return null;
 0246    }
 247
 248    public async Task<int> SaveChanges()
 249    {
 0250        return await _repository.SaveChanges();
 0251    }
 252}