| | | 1 | | using OzonDomains.Nomenclature; |
| | | 2 | | |
| | | 3 | | namespace Services.ApiServices._1CApi.Nomenclature; |
| | | 4 | | |
| | | 5 | | /// <summary>Строка карты соответствий (<c>OneCNomenclatureMaps</c>) в том виде, в котором её читает индекс.</summary> |
| | | 6 | | public sealed record MapRow(string ArticleNorm, string ProducerNorm, string? ProducerName, Guid RefKey, string? RawArtic |
| | | 7 | | |
| | | 8 | | /// <param name="Groups">Группы бренда карточки; пусто — у карточки нет производителя или он не известен справочнику.</p |
| | | 9 | | public sealed record IndexedCard( |
| | | 10 | | Guid RefKey, |
| | | 11 | | string ArticleKey, |
| | | 12 | | string? ProducerName, |
| | | 13 | | string ProducerNorm, |
| | | 14 | | string? RawArticle, |
| | | 15 | | string Source, |
| | | 16 | | IReadOnlySet<string> Groups) |
| | | 17 | | { |
| | | 18 | | public bool HasProducer => ProducerNorm.Length > 0; |
| | | 19 | | } |
| | | 20 | | |
| | | 21 | | /// <summary> |
| | | 22 | | /// Снимок карты соответствий в памяти: ключ артикула (<see cref="ArticleKey.Key"/>, с диакритикой и кириллическими |
| | | 23 | | /// двойниками) → карточки 1С с группами бренда. Неизменяемый; подмена снимка — в <c>NomenclatureIndexProvider</c>. |
| | | 24 | | /// </summary> |
| | | 25 | | public sealed class NomenclatureIndex |
| | | 26 | | { |
| | 1 | 27 | | public static readonly NomenclatureIndex Empty = new(new Dictionary<string, List<IndexedCard>>(), 0, new Dictionary< |
| | | 28 | | |
| | | 29 | | private readonly Dictionary<string, List<IndexedCard>> _byArticle; |
| | | 30 | | |
| | 58 | 31 | | private NomenclatureIndex(Dictionary<string, List<IndexedCard>> byArticle, int count, Dictionary<string, int> usage) |
| | | 32 | | { |
| | 58 | 33 | | _byArticle = byArticle; |
| | 58 | 34 | | Count = count; |
| | 58 | 35 | | ProducerUsage = usage; |
| | 58 | 36 | | } |
| | | 37 | | |
| | | 38 | | /// <summary>Сколько карточек у каждого написания производителя (ключ — <see cref="ArticleKey.Key"/> имени).</summar |
| | 15 | 39 | | public IReadOnlyDictionary<string, int> ProducerUsage { get; } |
| | | 40 | | |
| | 1 | 41 | | public int Count { get; } |
| | | 42 | | |
| | | 43 | | public static NomenclatureIndex Build(IEnumerable<MapRow> rows, ProducerDirectory directory) |
| | | 44 | | { |
| | 57 | 45 | | var byArticle = new Dictionary<string, List<IndexedCard>>(StringComparer.Ordinal); |
| | 57 | 46 | | var count = 0; |
| | 57 | 47 | | var usage = new Dictionary<string, int>(StringComparer.Ordinal); |
| | 222 | 48 | | foreach (var row in rows) |
| | | 49 | | { |
| | 54 | 50 | | var key = ArticleKey.Key(row.ArticleNorm); |
| | 54 | 51 | | if (key.Length == 0) |
| | | 52 | | continue; |
| | | 53 | | |
| | 54 | 54 | | var groups = row.ProducerNorm.Length == 0 |
| | 54 | 55 | | ? ProducerResolution.NoGroups |
| | 54 | 56 | | : directory.GroupsOfName(string.IsNullOrWhiteSpace(row.ProducerName) ? row.ProducerNorm : row.ProducerNa |
| | 54 | 57 | | if (groups.Count == 0 && row.ProducerNorm.Length > 0) |
| | 7 | 58 | | groups = directory.GroupsOfName(row.ProducerNorm); |
| | | 59 | | |
| | 54 | 60 | | if (!byArticle.TryGetValue(key, out var list)) |
| | 46 | 61 | | byArticle[key] = list = new List<IndexedCard>(1); |
| | | 62 | | |
| | 54 | 63 | | list.Add(new IndexedCard(row.RefKey, key, row.ProducerName, row.ProducerNorm, row.RawArticle, row.Source, gr |
| | 54 | 64 | | count++; |
| | | 65 | | |
| | 54 | 66 | | var producerKey = ArticleKey.Key(string.IsNullOrWhiteSpace(row.ProducerName) ? row.ProducerNorm : row.Produc |
| | 54 | 67 | | if (producerKey.Length > 0) |
| | 51 | 68 | | usage[producerKey] = usage.GetValueOrDefault(producerKey) + 1; |
| | | 69 | | } |
| | | 70 | | |
| | 57 | 71 | | return new NomenclatureIndex(byArticle, count, usage); |
| | | 72 | | } |
| | | 73 | | |
| | | 74 | | public IReadOnlyList<IndexedCard> Find(string articleKey) |
| | 84 | 75 | | => !string.IsNullOrEmpty(articleKey) && _byArticle.TryGetValue(articleKey, out var list) |
| | 84 | 76 | | ? list |
| | 84 | 77 | | : []; |
| | | 78 | | |
| | | 79 | | /// <summary>Все артикулы индекса с карточками — для отчётов (дубли).</summary> |
| | 1 | 80 | | public IEnumerable<KeyValuePair<string, List<IndexedCard>>> Articles() => _byArticle; |
| | | 81 | | } |