| | | 1 | | namespace Services.ApiServices._1CApi.Nomenclature; |
| | | 2 | | |
| | | 3 | | /// <summary>Режим нового поиска. По умолчанию выключен; включается настройкой <c>OneCNomenclature:ResolverMode</c> (Off |
| | | 4 | | public enum NomenclatureResolverMode |
| | | 5 | | { |
| | | 6 | | /// <summary>Работает только прежний поиск.</summary> |
| | | 7 | | Off, |
| | | 8 | | |
| | | 9 | | /// <summary> |
| | | 10 | | /// Прежний поиск решает как раньше, а новый считает рядом и пишет расхождения в лог. Ничего не создаёт |
| | | 11 | | /// и не меняет решение; нужен, чтобы неделю понаблюдать за различиями на настоящем потоке заказов. |
| | | 12 | | /// </summary> |
| | | 13 | | Shadow, |
| | | 14 | | |
| | | 15 | | /// <summary>Новый поиск решает: берёт, отклоняет или создаёт карточку по <see cref="NomenclatureResolvePolicy"/>.</ |
| | | 16 | | On |
| | | 17 | | } |
| | | 18 | | |
| | | 19 | | public enum ShadowDiffKind |
| | | 20 | | { |
| | | 21 | | Agree, |
| | | 22 | | |
| | | 23 | | /// <summary>Прежний код создал карточку, новый взял бы существующую — дубль был бы предотвращён.</summary> |
| | | 24 | | DuplicateAvoided, |
| | | 25 | | |
| | | 26 | | /// <summary>Прежний код нашёл одну карточку, новый выбирает другую.</summary> |
| | | 27 | | DifferentCard, |
| | | 28 | | |
| | | 29 | | /// <summary>Прежний код нашёл карточку, новый не нашёл (создал бы или отклонил) — потенциальная регрессия.</summary |
| | | 30 | | OldFoundNewMissed, |
| | | 31 | | |
| | | 32 | | /// <summary>Новый находит карточку там, где прежний не нашёл (только поиск) — улучшение.</summary> |
| | | 33 | | NewFoundOldMissed, |
| | | 34 | | |
| | | 35 | | /// <summary>Прежний код создал карточку, а новый остановился бы из-за неоднозначности.</summary> |
| | | 36 | | AmbiguousWouldBlock |
| | | 37 | | } |
| | | 38 | | |
| | 29 | 39 | | public sealed record ShadowOutcome(ShadowDiffKind Kind, string Description); |
| | | 40 | | |
| | | 41 | | /// <summary>Сравнение решений прежнего и нового поиска для режима <see cref="NomenclatureResolverMode.Shadow"/>.</summa |
| | | 42 | | public static class NomenclatureShadowComparer |
| | | 43 | | { |
| | | 44 | | public static ShadowOutcome Compare(Guid? oldRefKey, bool oldCreated, NomenclatureMatch match, NomenclatureMode mode |
| | | 45 | | { |
| | | 46 | | var decision = NomenclatureResolvePolicy.Decide(match, mode); |
| | | 47 | | var oldText = oldRefKey?.ToString() ?? "нет"; |
| | | 48 | | var newText = decision.Action switch |
| | | 49 | | { |
| | | 50 | | NomenclatureAction.UseCard => $"взять {decision.RefKey}", |
| | | 51 | | NomenclatureAction.Create => "создать", |
| | | 52 | | _ => "отклонить" |
| | | 53 | | }; |
| | | 54 | | var text = $"прежний: {(oldCreated ? "создал " : "")}{oldText}; новый: {newText} ({decision.Reason})"; |
| | | 55 | | |
| | | 56 | | if (oldCreated) |
| | | 57 | | { |
| | | 58 | | return decision.Action switch |
| | | 59 | | { |
| | | 60 | | NomenclatureAction.UseCard => new ShadowOutcome(ShadowDiffKind.DuplicateAvoided, text), |
| | | 61 | | NomenclatureAction.Create => new ShadowOutcome(ShadowDiffKind.Agree, text), |
| | | 62 | | _ => new ShadowOutcome(ShadowDiffKind.AmbiguousWouldBlock, text) |
| | | 63 | | }; |
| | | 64 | | } |
| | | 65 | | |
| | | 66 | | if (oldRefKey.HasValue) |
| | | 67 | | { |
| | | 68 | | if (decision.Action != NomenclatureAction.UseCard) |
| | | 69 | | return new ShadowOutcome(ShadowDiffKind.OldFoundNewMissed, text); |
| | | 70 | | |
| | | 71 | | return decision.RefKey == oldRefKey |
| | | 72 | | ? new ShadowOutcome(ShadowDiffKind.Agree, text) |
| | | 73 | | : new ShadowOutcome(ShadowDiffKind.DifferentCard, text); |
| | | 74 | | } |
| | | 75 | | |
| | | 76 | | return decision.Action == NomenclatureAction.UseCard |
| | | 77 | | ? new ShadowOutcome(ShadowDiffKind.NewFoundOldMissed, text) |
| | | 78 | | : new ShadowOutcome(ShadowDiffKind.Agree, text); |
| | | 79 | | } |
| | | 80 | | } |