Отвечай на вопросы, используя следующий контекст:
switch (decision)
                {
                    case KaskoSasCheckProcessConstants.KaskoSasCheckAccept:
                        if (isSensitiveDataChanged && (
                            externalBasketUrmAprovalStatus == UrmApprovalStatusCodes.Accepted || 
                            externalBasketUrmAprovalStatus == UrmApprovalStatusCodes.AcceptedWithLimits ||
                            externalBasketUrmAprovalStatus == UrmApprovalStatusCodes.RequiredExtraInfo))
                        {
                            SetExternalBasketUrmAprovalStatus(deal, externalBasketUrmAprovalStatus);
                        }
                        else
                        {
                            UrmHelper.SetUrmApprovalNotRequired(deal);
                        }

                        exitBranch = ExitBranch_TargetedSegment;
                        break;
                    case KaskoSasCheckProcessConstants.KaskoSasCheckUrm:
                        UrmApprovalStatusHelper.SetURMApprovalStatus(basket, false, comment); // возможно не нужен этот вызов, поресерчить
                        FixUrm(deal, requestGuid, processContext, integrationLoginName, logger, decision, isSensitiveDataChanged, externalBasketUrmAprovalStatus);
                        exitBranch = ExitBranch_NotTargetedSegment_CorrData;
                        break;
                    case KaskoSasCheckProcessConstants.KaskoSasCheckNoDecision:
                        UrmApprovalStatusHelper.SetURMApprovalStatus(basket, false, comment); // возможно не нужен этот вызов, поресерчить
                        FixUrm(deal, requestGuid, processContext, integrationLoginName, logger, decision, isSensitiveDataChanged, externalBasketUrmAprovalStatus);
                        exitBranch = ExitBranch_NotTargetedSegment_CorrData;
                        break;
                    case KaskoSasCheckProcessConstants.KaskoSasCheckReject:
                    default:
                        SetUrmStatus(deal, UrmApprovalStatusCodes.Rejected, requestGuid, decision);
                        AddValidationError(validationResultsAggregator);
                        exitBranch = ExitBranch_NotTargetedSegment_Reject;
                        break;
                }

                processContext.SetExitBranch(exitBranch);
                logger?.ForContext("BasketNumber", basket.Number).Information($"Переход на {exitBranch}", sw.ElapsedMilliseconds);

                var dataServiceInvoker = processContext.ServiceProvider.GetRequiredService<IDataServiceInvoker>();
                dataServiceInvoker.Publish(deal.AutoDeal, _aggregateName);
            }
            catch (Exception ex)
            {
                logger.Error(ex, $"Ошибка в работе блока {GetType().Name}");

                AddValidationError(validationResultsAggregator);

                processContext.SetExitBranch(ExitBranch_NotTargetedSegment_Reject);
                logger?.ForContext("BasketNumber", basket.Number)
                                .Information($"Переход на {ExitBranch_NotTargetedSegment_Reject}");
            }
        }

        private void SetExternalBasketUrmAprovalStatus(Deal deal, string externalBasketUrmAprovalStatus)
        {
            var lastApproval = deal.AutoDeal?.URMApproval?.LastOrDefault();
            if (lastApproval != null) 
            {
                lastApproval.URMApprovalStatusCode = externalBasketUrmAprovalStatus;
            } 
        }

        private void SetUrmStatus(Deal deal, string urmApprovalStatus, string requestGuid, string sasDecision)
        {
            var lastApproval = deal.AutoDeal.URMApproval.LastOrDefault();
            if (lastApproval != null)
            {
                lastApproval.URMApprovalComment = $"Проверка через SAS. {sasDecision}";
                lastApproval.URMApprovalStatusCode = urmApprovalStatus;
                lastApproval.ApprovalId = requestGuid;
            }
        }

        private void UpdateSasApprovalInDeal(Deal deal, string sasApprovalStatus, decimal? sasCoefficient)
        {
            if (!deal.AutoDeal.SASApproval.Any())
            {
                deal.AutoDeal.SASApproval.Add(new SASApproval { SASApprovalStatusCode = sasApprovalStatus, SasCoefficient = sasCoefficient });
            }
            else
            {
                var approval = deal.AutoDeal.SASApproval.Last();

                approval.SASApprovalStatusCode = sasApprovalStatus;
                approval.SasCoefficient = sasCoefficient;
            }
        }

        private void AddValidationError(IValidationResultsAggregator validationResultsAggregator)
        {
            validationResultsAggregator.AppendValidationErrors(new ValidationError()
            {
                ErrorMessage = "Код: 300019.Оформление невозможно",
                CriticalLevel = ValidationCriticalLevel.CantContProc
            });
        }

        /// <summary>
        /// Добавление УРМ в сделку для случая, когда объекта еще нет, и включена настройка.
        /// Установка статуса NotRequired, когда настройка выключена.
        /// </summary>
        /// <param name="deal">Сделка.</param>
        /// <param name="requestGuid">Идентификатор запроса.</param>
        /// <param name="context">Контекст процесса.</param>
        /// <param name="integrationLoginName">Имя пользователя для интеграции.</param>
        /// <param name="logger">Логгер для записи логов.</param>
        /// <param name="decision">Решение сас, принятое по сделке.</param>
        /// <param name="isSensitiveDataChanged">Чувствительные изменения при перерасчете.</param>
        /// <param name="externalBasketUrmAprovalStatus">Urm статус до перерасчета.</param>
        private void FixUrm(
            Deal deal, 
            string requestGuid, 
            IProcessContext context, 
            string integrationLoginName, 
            ILogger logger, 
            string decision, 
            bool isSensitiveDataChanged, 
            string externalBasketUrmAprovalStatus)
        {
            if (decision == KaskoSasCheckProcessConstants.KaskoSasCheckUrm && isSensitiveDataChanged && (externalBasketUrmAprovalStatus == UrmApprovalStatusCodes.Accepted || externalBasketUrmAprovalStatus == UrmApprovalStatusCodes.AcceptedWithLimits))
            {
                //Создаем новую заявку required
                UrmHelper.AddUrmApprovalToDeal(deal, UrmApprovalStatusCodes.Required, requestGuid);
                return;
            }

            if (decision == KaskoSasCheckProcessConstants.KaskoSasCheckUrm && isSensitiveDataChanged && externalBasketUrmAprovalStatus == UrmApprovalStatusCodes.RequiredExtraInfo)
            {
                UrmHelper.AddOrUpdateUrmApprovalToDeal(deal, UrmApprovalStatusCodes.Required, requestGuid);
                return;
            }

            bool needCheckUrm = NeedCheckUrm(decision, deal, context, integrationLoginName, logger);

            if (needCheckUrm)
            {
                UrmHelper.AddOrUpdateUrmApprovalToDeal(deal, UrmApprovalStatusCodes.Required, requestGuid);
            }
            else
            {
                UrmHelper.SetUrmApprovalNotRequired(deal);
            }
        }

        private bool NeedCheckUrm(string decision, Deal deal, IProcessContext context, string integrationLoginName, ILogger logger)
        {
            bool canSkipUrm = UrmHelper.CanSkipUrm(deal);
            bool needCheckUrmSetting = GetNeedCheckUrmKASKOSetting(context, integrationLoginName, logger);
            bool isWithoutUrmIndicatorOrNoSegments = UrmHelper.UrmCheckForWithoutURMIndicatorOrNoSegments(deal);

            return decision == KaskoSasCheckProcessConstants.KaskoSasCheckNoDecision
                ? !canSkipUrm && needCheckUrmSetting && !isWithoutUrmIndicatorOrNoSegments
                : !canSkipUrm && needCheckUrmSetting;
        }

        private bool GetNeedCheckUrmKASKOSetting(IProcessContext context, string integrationLoginName, ILogger logger)
        {
            var settingsManager = context.ServiceProvider.GetRequiredService<IEntitySettingsManager>();

            var needCheckUrmKASKOSetting = settingsManager.GetSettingForDefaultOrPartnerConfiguration(
                EntitySettingCodes.NeedCheckUrmKASKOSetting,
                EntitySettingCodes.NeedCheckUrmKASKOSettingDefault,
                EntitySettingCodes.NeedCheckUrmKASKOSettingByIntegrationLogin,
                new IntegrationLogin { IntegrationLoginName = integrationLoginName },
                true,
                logger);

            return needCheckUrmKASKOSetting;
        }
    }
}
using iRIS.Framework.Data;
using iRIS.Framework.Security.Entities;
using iRIS.InsuranceCore.Entities;
using iRIS.InsuranceCore.Entities.EntityExtensions;
using iRIS.InsuranceCore.Infrastructure.Constants;
using iRIS.KaskoCore.Code.Constants;
using iRIS.KaskoOsago.Code.Implementations.DIUnderwriterManager;
using System;
using System.Linq;

namespace iRIS.KaskoOsago.Tests.HelperData
{
    public static class EntityFactory
    {
        public static Basket CreateBasket(params string[] products)
        {
            var basket = new Basket
            {
                Deals = new ObservableList<Deal>()
                {
                    CreateDeal("OSAGO", products.Contains("OSAGO")),
                    CreateDeal("KASKO", products.Contains("KASKO"))
                }
            };

            return basket;
        }

        public static Deal CreateDeal(string productDictCode, bool? isInBasket = null)
        {
            return new Deal
            {
                IsInBasket = isInBasket,
                Product = new Product
                {
                    ProductDictCode = productDictCode
                }
            };
        }

        public static DIUnderwriterApproval CreateDIUnderwriterApproval(
            Guid uniqueId = default,
            bool? isClosed = null,
            string statusCode = "",
            string themeCode = "",
            decimal? autoCostApproval = default)
        {
            return new DIUnderwriterApproval()
            {
                IsClosed = isClosed,
                UniqueId = uniqueId,
                StatusCode = statusCode,
                ThemeCode = themeCode,
                AutoCostApproval = autoCostApproval
            };
        }

        public static Basket CreateBasketWithDIUnderwriterApprovals(ObservableList<DIUnderwriterApproval> diUnderwriterApprovals)
        {
            var basket = CreateBasket("KASKO");
            var kaskoDeal = basket.GetKaskoDeal();
            kaskoDeal.AutoDeal = new AutoDeal()
            {
                DIUnderwriterApprovals = diUnderwriterApprovals
            };
            kaskoDeal.InsuranceObjects.Add(new InsuranceObject { Auto = new Auto() });

            return basket;
        }

        public static Basket CreateBasketWithAutoCostAndHasMileage(decimal? autoCost, bool? hasMileage = null)
        {
            var basket = CreateBasket("KASKO");
            var kaskoDeal = basket.GetKaskoDeal();
            kaskoDeal.InsuranceObjects = new ObservableList<InsuranceObject>()
            {
                new InsuranceObject()
                {
                    Auto = new Auto
                    {
                        AutoCost = autoCost,
                        HasMileage = hasMileage
                    }
                }
            };

            return basket;
        }

        public static AutoDeal CreateAutoDealWithDIUnderwriterApprovals(string[] themeCodes, decimal? autoCostApproval = null, string status = "accepted", bool isClosed = true)
        {
            var autoDeal = new AutoDeal
            {
                DIUnderwriterApprovals = new ObservableList<DIUnderwriterApproval>()
            };

            foreach (var themeCode in themeCodes)
            {
                autoDeal.DIUnderwriterApprovals.Add(new DIUnderwriterApproval
                {
                    ThemeCode = themeCode,
                    AutoCostApproval = autoCostApproval,
                    StatusCode = status,
                    IsClosed = true
                });
            }

            return autoDeal;
        }

        public static DIUnderwriterCheckingRuleResult CreateDIUnderwriterCheckingRuleResult(string approvalThemeCode, bool isSucceded)
        {
            return new DIUnderwriterCheckingRuleResult
            {
                ApprovalThemeCode = approvalThemeCode,
                IsSucceded = isSucceded
            };
        }

        public static User CreateUser(string userGroup = UserGroups.CallCenter)
        {
            return new User
            {
                Groups = new ObservableList<UserGroup>
                {
                    new UserGroup
                    {
                        Name = userGroup
                    }
                }
            };
        }

        public static Deal CreateDeal(bool damageInDeal, bool totalInDeal, bool carjackingInDeal = true, bool kaskoNoPolicyInDeal = false)
        {
            var deal = new Deal
            {
                DealConditionGroups = new ObservableList<DealConditionGroup>
                {
                    new DealConditionGroup
                    {
                        StructId = 5000,
                        InsuranceObjectConditions = new ObservableList<InsuranceObjectCondition>
                        {
                            new InsuranceObjectCondition
                            {
                                StructId = 5001,
                                DealCoverages = new ObservableList<DealCoverage>
                                {
                                    new DealCoverage
                                    {
                                        StructId = 5015,
                                        DealRisks = new ObservableList<DealRisk>()
                                    },
                                    new DealCoverage
                                    {
                                        StructId = 5030,
                                        DealRisks = new ObservableList<DealRisk>()
                                    }
                                }
                            }
                        }
                    }
                }
            };

            if (damageInDeal)
            {
                deal.DealConditionGroups[0].InsuranceObjectConditions[0].DealCoverages[0].DealRisks.Add(
                    new DealRisk
                    {
                        StructId = 5016 // Ущерб
                    });
            }

            if (totalInDeal)
            {
                deal.DealConditionGroups[0].InsuranceObjectConditions[0].DealCoverages[0].DealRisks.Add(
                    new DealRisk
                    {
                        StructId = 5029 // Тотал
                    });
            }

            if (carjackingInDeal)
            {
                deal.DealConditionGroups[0].InsuranceObjectConditions[0].DealCoverages[1].DealRisks.Add(
                new DealRisk
                {
                    StructId = 5031 // Тотал
                });
            }

            if (kaskoNoPolicyInDeal)
            {
                deal.DealConditionGroups[0].InsuranceObjectConditions[0].DealCoverages[1].DealRisks.Add(
                new DealRisk
                {
                    StructId = 5528 // КАСКО от бесполисных
                });
            }

            return deal;
        }

        public static Deal CreateConstructorDeal1(bool damageInDeal, bool totalInDeal, bool carjackingInDeal)
        {
            var deal = new Deal
            {
                DealConditionGroups = new ObservableList<DealConditionGroup>
                {
                    new DealConditionGroup
                    {
                        StructId = 5000,
                        InsuranceObjectConditions = new ObservableList<InsuranceObjectCondition>
                        {
                            new InsuranceObjectCondition
                            {
                                StructId = 5001,
                                DealCoverages = new ObservableList<DealCoverage>
                                {
                                    new DealCoverage
                                    {
                                        StructId = 5015, // Ущерб
                                        DealRisks = new ObservableList<DealRisk>()
                                    },
                                    new DealCoverage
                                    {
                                        StructId = 5030, // Угон
                                        DealRisks = new ObservableList<DealRisk>()
                                    },
                                    new DealCoverage
                                    {
                                        StructId = 5002, // Доп расходы
                                        DealRisks = new ObservableList<DealRisk>
                                        {
                                            new DealRisk
                                            {
                                                StructId = 5003, // Доп расходы
                                                ProductRisk = new ProductRisk { RiskCode = RiskCodes.ADDCOSTS },
                                                ConditionBlock = new ConditionBlock
                                                {
                                                    DealOptions = new ObservableList<DealOption>
                                                    {
                                                        new DealOption
                                                        {
                                                            ProductOption = new ProductOption { OptionCode = OptionCodes.TECHHELP },
                                                        },
                                                        new DealOption
                                                        {
                                                            ProductOption = new ProductOption { OptionCode = OptionCodes.TAXI },
                                                        },
                                                        new DealOption
                                                        {
                                                            ProductOption = new ProductOption { OptionCode = OptionCodes.AVARCOMACCIDENT },
                                                        },
                                                    }
                                                }
                                            }
                                        },
                                        ConditionBlock = new ConditionBlock
                                        {
                                                DealOptions = new ObservableList<DealOption>
                                                {
                                                    new DealOption
                                                    {
                                                        ProductOption = new ProductOption { OptionCode = OptionCodes.RENT },
                                                    }
                                                }
                                        }
                                    },
                                }
                            }
                        }
                    }
                }
            };

            if (damageInDeal)
            {
                deal.DealConditionGroups[0].InsuranceObjectConditions[0].DealCoverages[0].DealRisks.Add(
                    new DealRisk
                    {
                        StructId = 5016, // Ущерб
                        ProductRisk = new ProductRisk { RiskCode = RiskCodes.DAMAGE },
                        ConditionBlock = new ConditionBlock
                        {
                            DealOptions = new ObservableList<DealOption> 
                            { 
                                new DealOption
                                {
                                    ProductOption = new ProductOption { OptionCode = OptionCodes.TECHCENTER },
                                },
                                new DealOption
                                {
                                    ProductOption = new ProductOption { OptionCode = KaskoOptionCodes.Limit_Loss },
                                },
                                new DealOption
                                {
                                    ProductOption = new ProductOption { OptionCode = OptionCodes.GLASS1T },
                                },
                                new DealOption
                                {
                                    ProductOption = new ProductOption { OptionCode = OptionCodes.BODY3P1T },
                                }
                            },
                            DealFranchises = new ObservableList<DealFranchise>
                            { 
                                new DealFranchise 
                                {
                                    ProductFranchise = new ProductFranchise { Code = FranchiseCode.CAUSER },
                                    Sum = 50000
                                }
                            }
                        }
                    });
            }

            if (totalInDeal)
            {
                deal.DealConditionGroups[0].InsuranceObjectConditions[0].DealCoverages[0].DealRisks.Add(
                    new DealRisk
                    {
                        StructId = 5029, // Тотал
                        ProductRisk = new ProductRisk { RiskCode = RiskCodes.TOTAL }
                    });
            }

            if (carjackingInDeal)
            {
                deal.DealConditionGroups[0].InsuranceObjectConditions[0].DealCoverages[1].DealRisks.Add(
                new DealRisk
                {
                    StructId = 5031, // Угон
                    ProductRisk = new ProductRisk { RiskCode = RiskCodes.CARJACKING }
                });
            }

            return deal;
        }

        public static Deal CreateConstructorDeal2(bool damageInDeal, bool totalInDeal, bool carjackingInDeal)
        {
            var deal = new Deal
            {
                DealConditionGroups = new ObservableList<DealConditionGroup>
                {
                    new DealConditionGroup
                    {
                        StructId = 5000,
                        InsuranceObjectConditions = new ObservableList<InsuranceObjectCondition>
                        {
                            new InsuranceObjectCondition
                            {
                                StructId = 5001,
                                DealCoverages = new ObservableList<DealCoverage>
                                {
                                    new DealCoverage
                                    {
                                        StructId = 5015, // Ущерб
                                        DealRisks = new ObservableList<DealRisk>()
                                    },
                                    new DealCoverage
                                    {
                                        StructId = 5030, // Угон
                                        DealRisks = new ObservableList<DealRisk>()
                                    },
                                    new DealCoverage
                                    {
                                        StructId = 5035, // GAP
                                        DealRisks = new ObservableList<DealRisk>
                                        {
                                            new DealRisk
                                            {
                                                StructId = 5036,
                                                ProductRisk = new ProductRisk { RiskCode = RiskCodes.GAP }
                                            }
                                        }
                                    },
                                    new DealCoverage
                                    {
                                        StructId = 5002, // Доп расходы
                                        DealRisks = new ObservableList<DealRisk>
                                        {
                                            new DealRisk
                                            {
                                                StructId = 5003, // Доп расходы
                                                ProductRisk = new ProductRisk { RiskCode = RiskCodes.ADDCOSTS },
                                                ConditionBlock = new ConditionBlock
                                                {
                                                    DealOptions = new ObservableList<DealOption>
                                                    {
                                                        new DealOption
                                                        {
                                                            ProductOption = new ProductOption { OptionCode = OptionCodes.TECHHELP },
                                                        },
                                                        new DealOption
                                                        {
                                                            ProductOption = new ProductOption { OptionCode = OptionCodes.AVARCOM2PAR },
                                                        },
                                                    }
                                                }
                                            }
                                        }
                                    },
                                }
                            }
                        }
                    },
                    new DealConditionGroup
                    {
                        StructId = 5037, // ГО
                        InsuranceObjectConditions = new ObservableList<InsuranceObjectCondition>
                        {
                            new InsuranceObjectCondition
                            {
                                StructId = 5038, // ГО
                                DealCoverages = new ObservableList<DealCoverage>
                                {
                                    new DealCoverage
                                    {
                                        StructId = 5039, // ГО
                                        DealRisks = new ObservableList<DealRisk>
                                        {
                                            new DealRisk
                                            {
                                                StructId = 5040, // ГО
                                                ProductRisk = new ProductRisk { RiskCode = RiskCodes.CIVILLIABILITY },
                                                Sum = 750000
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    new DealConditionGroup
                    {
                        StructId = 5041, // НС
                        InsuranceObjectConditions = new ObservableList<InsuranceObjectCondition>
                        {
                            new InsuranceObjectCondition
                            {
                                StructId = 5042, // НС
                                DealCoverages = new ObservableList<DealCoverage>
                                {
                                    new DealCoverage
                                    {
                                        StructId = 5043, // НС
                                        DealRisks = new ObservableList<DealRisk>
                                        {
                                            new DealRisk
                                            {
                                                StructId = 5044, // НС
                                                ProductRisk = new ProductRisk { RiskCode = RiskCodes.ACCIDENT }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            };

            if (damageInDeal)
            {
                deal.DealConditionGroups[0].InsuranceObjectConditions[0].DealCoverages[0].DealRisks.Add(
                    new DealRisk
                    {
                        StructId = 5016, // Ущерб
                        ProductRisk = new ProductRisk { RiskCode = RiskCodes.DAMAGE },
                        ConditionBlock = new ConditionBlock
                        {
                            DealOptions = new ObservableList<DealOption>
                            {
                                new DealOption
                                {
                                    ProductOption = new ProductOption { OptionCode = OptionCodes.DEALERTECHCENTER },
                                },
                                new DealOption
                                {
                                    ProductOption = new ProductOption { OptionCode = OptionCodes.MileLimit },
                                    SelectValue = 10000
                                },
                                new DealOption
                                {
                                    ProductOption = new ProductOption { OptionCode = OptionCodes.GLASSMANY },
                                },
                                new DealOption
                                {
                                    ProductOption = new ProductOption { OptionCode = OptionCodes.BODY5P2T },
                                }
                            },
                            DealFranchises = new ObservableList<DealFranchise>
                            {
                                new DealFranchise
                                {
                                    ProductFranchise = new ProductFranchise { Code = FranchiseCode.INSEVENT2 },
                                    Sum = 50000
                                }
                            }
                        }
                    });
            }

            if (totalInDeal)
            {
                deal.DealConditionGroups[0].InsuranceObjectConditions[0].DealCoverages[0].DealRisks.Add(
                    new DealRisk
                    {
                        StructId = 5029, // Тотал
                        ProductRisk = new ProductRisk { RiskCode = RiskCodes.TOTAL }
                    });
            }

            if (carjackingInDeal)
            {
                deal.DealConditionGroups[0].InsuranceObjectConditions[0].DealCoverages[1].DealRisks.Add(
                new DealRisk
                {
                    StructId = 5031, // Угон
                    ProductRisk = new ProductRisk { RiskCode = RiskCodes.CARJACKING }
                });
            }

            return deal;
        }
    }
}

using iRIS.Framework.Common;
using iRIS.Framework.Cqrs.Interfaces;
using iRIS.InsuranceCore.Code.Constants;
using iRIS.InsuranceCore.Entities;
using iRIS.InsuranceCore.Entities.EntityExtensions;
using iRIS.InsuranceCore.Infrastructure.Constants;
using iRIS.InsuranceCore.OSS.Code.Constants;
using iRIS.KaskoCore.Code.Queries;
using iRIS.PostProcessingClient.Auto.Code.Client;
using iRIS.PostProcessingClient.Auto.Code.Interfaces;
using Newtonsoft.Json;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using AntiTheftSystemModel = iRIS.PostProcessingClient.Auto.Code.Client.AntiTheftSystemModel;
using AutoModel = iRIS.PostProcessingClient.Auto.Code.Client.AutoModel;
using InsuranceObjectTypeCodes = iRIS.InsuranceCore.Code.Constants.InsuranceObjectTypeCodes;

namespace iRIS.KaskoLink2.Code.PostProcessing
{
    public class PostProcessingBasketMapper : IPostProcessingBasketMapper<Basket>
    {
        private readonly IQueryBank _queryBank;
        private readonly ILogger _logger;
private void InitializeFillBasketProductsIfNotExists(ProcedureModel model)
        {
            model.Identifier = "FillBasketProductsIfNotExists";
            model.Name = "Заполнение продуктов Корзины, если они пустые";
            model.Description = @"Заполнение продуктов Корзины, если они пустые";
            model.DataTypeName = null;
            model.IsAsync = false;
            model.NextStep = _setDealsDateFirstCalculation;
            model.ExceptionNextStep = _segmentationForm;
            model.Functions = new List<ProcedureModelFunction>();
            model.Functions.Add(new ProcedureModelFunction
            {
                ContainerTypeName = typeof(iRIS.InsuranceCore.Code.InsuranceCoreProcedures).AssemblyQualifiedName,
                Function = nameof(iRIS.InsuranceCore.Code.InsuranceCoreProcedures.FillBasketProductsIfNotExists),
                Parameters = new List<FunctionParameter>
                {
                    new FunctionParameter
                    {
                        Name = "basket",
                        TypeName = typeof(iRIS.InsuranceCore.Entities.Basket).AssemblyQualifiedName,
                        Expression = @"Basket",
                    },
                },
            });
            model.Outputs = new List<ProcedureModelOutput>();
        }

        private void InitializeDiKaskoQuestionnaireSaveSegmentationDriversDataProcessToCache(CustomProcessModel model)
        {
            model.Identifier = "DiKaskoQuestionnaireSaveSegmentationDriversDataProcessToCache";
            model.Name = "Сохранение данных водителей с сегментации в кэш";
            model.Description = @"Сохранение данных водителей с сегментации в кэш";
            model.ImplementationTypeName = typeof(iRIS.KaskoOsago.Code.CustomProcesses.DiKaskoQuestionnaireSaveSegmentationDriversDataProcessToCache).AssemblyQualifiedName;
            model.DataTypeName = null;
            model.DefaultNextStep = _defaultExitPoint;
            model.ExceptionNextStep = null;
            model.InputArguments = new List<CustomProcessInputArgument>();
            model.InputArguments.Add(new CustomProcessInputArgument
            {
                Name = "Basket",
                TypeName = typeof(iRIS.InsuranceCore.Entities.Basket).AssemblyQualifiedName,
                Expression = @"Basket",
            });
            model.OutputArguments = new List<CustomProcessOutputArgument>();
            model.CustomExitPoints = new List<ProcessExitPoint>();
        }

        private void InitializeDefaultExitPoint(ExitPointModel model)
        {
            model.Identifier = "DefaultExitPoint";
            model.Name = "Сегментация пройдена";
            model.Description = @"Сегментация пройдена";
            model.ReturnParameters = new List<ParameterModel>();
        }
    }
}

//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by IRIS.Designer.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;

using iRIS.Framework.Workflow.Process;
using iRIS.Framework.Workflow.Process.AuthorizationModel;
using iRIS.Framework.Workflow.Process.CustomProcessModel;
using iRIS.Framework.Workflow.Process.Data;
using iRIS.Framework.Workflow.UserData;

namespace iRIS.KaskoB2B.Generated.Processes.B2bKaskoQuestionnaireProcess.Draft
{
    public class B2bKaskoQuestionnaireProcess : FlowProcessModel
    {
        public const string ExitPoint_ContinueExit = "Анкета заполнена";

        private readonly ProcedureModel _prepareDocsForKaskoBasket;
        private readonly ProcedureModel _initializeAddressesForDriver;
        private readonly NestedProcessModel _checkStartDateOfCalculate;
        private readonly ProcedureModel _initializeAddressesForInsurant;
        private readonly FormDataModel _diKaskoQuestionnaireFormStep;
        private readonly InputModel _issue;
        private readonly ExitPointModel _continueExit;
        private readonly FormDataModel _dateStartMessageInfo;
        private readonly VersionPublisherModel _saveDraftBasketBlockAfterBuy;

        public B2bKaskoQuestionnaireProcess()
        {
            _prepareDocsForKaskoBasket = new ProcedureModel();
            _initializeAddressesForDriver = new ProcedureModel();
            _checkStartDateOfCalculate = new NestedProcessModel();
            _initializeAddressesForInsurant = new ProcedureModel();
            _diKaskoQuestionnaireFormStep = new FormDataModel();
            _issue = new InputModel();
            _continueExit = new ExitPointModel();
            _dateStartMessageInfo = new FormDataModel();
            _saveDraftBasketBlockAfterBuy = new VersionPublisherModel();

            InitializeB2bKaskoQuestionnaireProcess(this);

            InitializePrepareDocsForKaskoBasket(_prepareDocsForKaskoBasket);
            InitializeInitializeAddressesForDriver(_initializeAddressesForDriver);
            InitializecheckStartDateOfCalculate(_checkStartDateOfCalculate);
            InitializeInitializeAddressesForInsurant(_initializeAddressesForInsurant);
            InitializeDiKaskoQuestionnaireFormStep(_diKaskoQuestionnaireFormStep);
            Initializeissue(_issue);
            InitializeContinueExit(_continueExit);
            InitializedateStartMessageInfo(_dateStartMessageInfo);
            InitializeSaveDraftBasketBlockAfterBuy(_saveDraftBasketBlockAfterBuy);
        }

        private void InitializeB2bKaskoQuestionnaireProcess(FlowProcessModel model)
        {
            model.Identifier = "B2bKaskoQuestionnaireProcess";
            model.Name = "Анкета КАСКО";
            model.Description = @"Анкета КАСКО";
            model.Version = "Draft";
            model.IsPrivate = true;
            model.ProcessResumeAccessRules = new List<FlowProcessSecurity>();
            model.ProcessStartAccessRules = new List<FlowProcessSecurity>();
            model.VariableModelInfoList = new List<ProcessVariableDefinition>();
            model.VariableModelInfoList.Add(new ProcessVariableDefinition
            {
                Name = "Basket",
                TypeName = typeof(iRIS.InsuranceCore.Entities.Basket).AssemblyQualifiedName,
                Direction = Direction.In,
                IsMainRootVariable = false,
                InitializeFromExtension = false,
                IsLocalVariable = false,
                IsOptional = false
            });
            model.VariableModelInfoList.Add(new ProcessVariableDefinition
            {
                Name = "DiAccountNumberIn",
                TypeName = typeof(string).AssemblyQualifiedName,
                Direction = Direction.In,
                IsMainRootVariable = false,
                InitializeFromExtension = false,
                IsLocalVariable = false,
                IsOptional = false
            });
            model.VariableModelInfoList.Add(new ProcessVariableDefinition
            {
                Name = "FillIntouchInternal",
                TypeName = typeof(bool).AssemblyQualifiedName,
                Direction = Direction.In,
                IsMainRootVariable = false,
                InitializeFromExtension = false,
                IsLocalVariable = false,
                IsOptional = false
            });
            model.VariableModelInfoList.Add(new ProcessVariableDefinition
            {
                Name = "policyIssuedByCallCenter",
                TypeName = typeof(bool).AssemblyQualifiedName,
                Direction = Direction.In,
                IsMainRootVariable = false,
                InitializeFromExtension = false,
                IsLocalVariable = false,
                IsOptional = false
            });
            model.Start = _prepareDocsForKaskoBasket;
            model.NavigationStartPoints = new List<NavigationStartModel>();
            model.NavigationStartPoints.Add(new NavigationStartModel
            {
                Identifier = "DiKaskoQuestionnaireStep",
                NextStep = _prepareDocsForKaskoBasket,
            });
        }

        private void InitializePrepareDocsForKaskoBasket(ProcedureModel model)
        {
            model.Identifier = "PrepareDocsForKaskoBasket";
            model.Name = "Подготовка файловых блоков";
            model.Description = @"Подготовка файловых блоков";
            model.DataTypeName = null;
            model.IsAsync = false;
            model.NextStep = _diKaskoQuestionnaireFormStep;
            model.ExceptionNextStep = null;
            model.Functions = new List<ProcedureModelFunction>();
            model.Functions.Add(new ProcedureModelFunction
            {
                ContainerTypeName = typeof(iRIS.KaskoB2B.Code.Procedures.B2bKaskoInsuranceProcedures).AssemblyQualifiedName,
                Function = nameof(iRIS.KaskoB2B.Code.Procedures.B2bKaskoInsuranceProcedures.PrepareDocsForKaskoBasket),
                Parameters = new List<FunctionParameter>
                {
                    new FunctionParameter
                    {
                        Name = "basket",
                        TypeName = typeof(iRIS.InsuranceCore.Entities.Basket).AssemblyQualifiedName,
                        Expression = @"Basket",
                    },
                },
            });
            model.Outputs = new List<ProcedureModelOutput>();
        }

        private void InitializeInitializeAddressesForDriver(ProcedureModel model)
        {
            model.Identifier = "InitializeAddressesForDriver";
            model.Name = "Инициализация сущности Address у водителя";
            model.Description = @"Инициализация сущности Address у водителя";
            model.DataTypeName = null;
            model.IsAsync = false;
            model.NextStep = _issue;
            model.ExceptionNextStep = null;
            model.Functions = new List<ProcedureModelFunction>();
            model.Functions.Add(new ProcedureModelFunction
            {
                ContainerTypeName = typeof(iRIS.KaskoOsago.Code.Procedures.DiKaskoQuestionnaireProcedures).AssemblyQualifiedName,
                Function = nameof(iRIS.KaskoOsago.Code.Procedures.DiKaskoQuestionnaireProcedures.InitializeAddressesForDrivers),
                Parameters = new List<FunctionParameter>
                {
                    new FunctionParameter
                    {
                        Name = "basket",
                        TypeName = typeof(iRIS.InsuranceCore.Entities.Basket).AssemblyQualifiedName,
                        Expression = @"Basket",
                    },
                },
            });
            model.Outputs = new List<ProcedureModelOutput>();
        }

        private void InitializecheckStartDateOfCalculate(NestedProcessModel model)
        {
            model.Identifier = "checkStartDateOfCalculate";
            model.Name = "Проверка даты создания расчета";
            model.Description = string.Empty;
            model.FlowProcessIdentifier = "CheckStartDateOfPolicyProcess";
            model.FlowProcessVersion = "Draft";
            model.DataTypeName = null;
            model.ExceptionNextStep = null;
            model.InputParameters = new List<ParameterNestedModel>();
            model.InputParameters.Add(new ParameterNestedModel
            {
                Name = "Basket",
                ExpressionType = typeof(iRIS.InsuranceCore.Entities.Basket).AssemblyQualifiedName,
                InExpression = @"Basket",
            });
            model.ReturnParameters = new List<ProcedureModelOutput>();
            model.NextSteps = new List<ProcessExitPoint>();
            model.NextSteps.Add(new ProcessExitPoint
            {
                Name = "Exit_Failed",
                NextStep = _dateStartMessageInfo,
            });
            model.NextSteps.Add(new ProcessExitPoint
            {
                Name = "Exit_Sucess",
                NextStep = _continueExit,
            });
        }

        private void InitializeInitializeAddressesForInsurant(ProcedureModel model)
        {
            model.Identifier = "InitializeAddressesForInsurant";
            model.Name = "Инициализация сущности Address у страхователя";
            model.Description = @"Инициализация сущности Address у страхователя";
            model.DataTypeName = null;
            model.IsAsync = false;
            model.NextStep = _initializeAddressesForDriver;
            model.ExceptionNextStep = null;
            model.Functions = new List<ProcedureModelFunction>();
            model.Functions.Add(new ProcedureModelFunction
            {
                ContainerTypeName = typeof(iRIS.KaskoOsago.Code.Procedures.DiKaskoQuestionnaireProcedures).AssemblyQualifiedName,
                Function = nameof(iRIS.KaskoOsago.Code.Procedures.DiKaskoQuestionnaireProcedures.InitializeAddressesForInsurant),
                Parameters = new List<FunctionParameter>
                {
                    new FunctionParameter
                    {
                        Name = "basket",
                        TypeName = typeof(iRIS.InsuranceCore.Entities.Basket).AssemblyQualifiedName,
                        Expression = @"Basket",
                    },
                },
            });
            model.Outputs = new List<ProcedureModelOutput>();
        }

        private void InitializeDiKaskoQuestionnaireFormStep(FormDataModel model)
        {
            model.Identifier = "DiKaskoQuestionnaireFormStep";
            model.Name = "Отрисовка формы – анкета.";
            model.Description = @"Отрисовка формы – анкета.";
            model.FormDataType = FormDataType.Form;
            model.FormName = "DiKaskoQuestionnaireStep";
            model.FormNameExpression = null;
            model.VersionManagementActions = new List<VersionManagementAction>();
            model.VersionManagementActions.Add(VersionManagementAction.ResetCurrentChange);
            model.VersionManagementActions.Add(VersionManagementAction.LoadTechnicalVersion);
            model.VersionManagementActions.Add(VersionManagementAction.LoadUserVersion);
            model.VersionManagementActions.Add(VersionManagementAction.LoadCallCenterVersion);
            model.NotSaveDraft = false;
            model.FormNestedEntities = new List<FormNestedEntity>();
            model.NextStep = _initializeAddressesForInsurant;
        }

        private void Initializeissue(InputModel model)
        {
            model.Identifier = "issue";
            model.Name = "Вызов действия «Отправить»";
            model.Description = @"Вызов действия «Отправить»";
            model.PermissionType = "actionIssue";
            model.ActionDefinition = new ActionDefinition();
            model.ActionDefinition.ModelSyncMode = iRIS.Framework.Entity.Metadata.Data.Enum.ModelSyncMode.FullModel;
            model.ValidationGroups = new List<string>();
            model.ValidationGroups.Add("DiKaskoQuestionnaireDelivery");
            model.ValidationGroups.Add("Address");
            model.ValidationGroups.Add("DIUnderwriterApprovalFromCallcenter");
            model.ValidationGroups.Add("DiKaskoQuestionnaire");
            model.CriticalLevels = new List<iRIS.Framework.Entity.Metadata.ValidationCriticalLevel>();
            model.Bookmark = string.Empty;
            model.SuppressProcessResuming = false;
            model.ParallelInput = null;
            model.NextStep = _saveDraftBasketBlockAfterBuy;
        }

        private void InitializeContinueExit(ExitPointModel model)
        {
            model.Identifier = "ContinueExit";
            model.Name = "Анкета заполнена";
            model.Description = @"Продолжить оформление";
            model.ReturnParameters = new List<ParameterModel>();
        }

        private void InitializedateStartMessageInfo(FormDataModel model)
        {
            model.Identifier = "dateStartMessageInfo";
            model.Name = "DateStartMessageInfo";
            model.Description = string.Empty;
            model.FormDataType = FormDataType.Message;
            model.MessageExpression = @"Дата начала срока действия расчета не валидна";
            model.NotificationType = iRIS.Framework.Common.Notifications.NotificationType.Error;
            model.Caption = "Дата начала срока действия расчета";
            model.NextStep = null;
        }

        private void InitializeSaveDraftBasketBlockAfterBuy(VersionPublisherModel model)
        {
            model.Identifier = "SaveDraftBasketBlockAfterBuy";
            model.Name = "Сохранение черновика корзины";
            model.Description = @"F1. Сохранение черновика корзины";
            model.VersionAction = VersionAction.SaveDraft;
            model.RelationType = RelationType.Draft;
            model.NextStep = _checkStartDateOfCalculate;
            model.ExceptionNextStep = null;
        }
    }
}


using iRIS.Framework.Common;
using iRIS.Framework.Cqrs.Interfaces;
using iRIS.InsuranceCore.Code.ConstructorCore.Models;
using iRIS.InsuranceCore.Code.CustomProcesses.BasketPreparationProcess.Enums;
using iRIS.InsuranceCore.Code.Queries;
using iRIS.InsuranceCore.Entities;
using iRIS.InsuranceCore.Entities.EntityExtensions;
using iRIS.KaskoCore.Code.Interfaces;
using iRIS.KaskoCore.CreateOn.Code.OssKaskoOptionsProcessor;
using iRIS.KaskoCore.CreateOn.Code.Utilities;
using iRIS.KaskoLink2.Code.Constructor;
using iRIS.KaskoLink2.Code.CreateOn.DealInitialization;
using iRIS.KaskoLink2.Code.CreateOn.Extension;
using iRIS.KaskoLink2.Code.CreateOn.Utilities;
using Serilog;
using System.Collections.Generic;
using System.Linq;

namespace iRIS.KaskoLink2.Code.CreateOn.OssKaskoOptionsProcessor
{
    internal sealed class OssKaskoOptionsProcessor : IOssKaskoOptionsProcessor
    {
        private readonly ICqrsMediator _mediator;
        private readonly ILogger _logger;
        private readonly IOssKaskoOptionsRulesRunner _ossKaskoOptionsRulesRunner;
        private readonly IOssKaskoOptionsEnricher _ossKaskoOptionsEnricher;
        private readonly IKaskoConstructorOfferGetter _constructorOfferGetter;
        private readonly IDiKaskoConditionsProcessor _diKaskoConditionsProcessor;
        private readonly IDiKaskoDealManager _diKaskoDealManager;

        private Dictionary<int, ProductConfiguration> _productConfigurations;

        public OssKaskoOptionsProcessor(
            ICqrsMediator mediator,
            ILogger logger,
            IOssKaskoOptionsRulesRunner ossKaskoOptionsRulesRunner,
            IOssKaskoOptionsEnricher ossKaskoOptionsEnricher,
            IKaskoConstructorOfferGetter constructorOfferGetter,
            IDiKaskoConditionsProcessor diKaskoConditionsProcessor,
            IDiKaskoDealManager diKaskoDealManager)
        {
            _mediator = mediator;
            _logger = logger;
            _ossKaskoOptionsRulesRunner = ossKaskoOptionsRulesRunner;
            _ossKaskoOptionsEnricher = ossKaskoOptionsEnricher;
            _constructorOfferGetter = constructorOfferGetter;
            _diKaskoConditionsProcessor = diKaskoConditionsProcessor;
            _diKaskoDealManager = diKaskoDealManager;
        }

        public IReadOnlyList<PreviousOssOption> SetOssKaskoOptions(Basket basket, string integrationLogin)
        {
            var kaskoDeal = basket.GetKaskoDeal();
            InitServices(basket, kaskoDeal);

            var ossKaskoOptions = kaskoDeal.AutoDeal.PreviousOssOptions.Select(s => s.CloneWithoutStructId()).ToList();

            _ossKaskoOptionsRulesRunner.RunRules(basket, kaskoDeal, ossKaskoOptions, _productConfigurations.Select(v => v.Value).ToList(), integrationLogin);

            _ossKaskoOptionsEnricher.EnrichStructIds(ossKaskoOptions);

            FillDealsConditions(basket, kaskoDeal, _ossKaskoOptionsEnricher.ParentStructIds, ossKaskoOptions);

            UpdateStructId(ossKaskoOptions, kaskoDeal.AutoDeal.PreviousOssOptions);

            return ossKaskoOptions;
        }

        private void FillDealsConditions(Basket basket, Deal deal, IReadOnlyList<int> parentStructtIds, IReadOnlyList<PreviousOssOption> ossKaskoOptions)
        {
            var deals = new List<Deal>() { deal };
            var addedProposal = DealInitializationHelper.AddProposal(deal, _constructorOfferGetter.GetConstructorOfferId(basket));

            deal.DealConditionGroups.Clear();
            deal.ConditionBlock = null;
            deal.PaymentSchedule = null;
            deal.PaymentSchedule_Id = null;

            var dealConditions = _diKaskoConditionsProcessor.CreateDealConditionsForProposals(deal, _productConfigurations, GetStructIdAndSums(parentStructtIds, ossKaskoOptions), null, false);
            _diKaskoDealManager.ApplyDealsCondition(new Deal[] { deal }, dealConditions);

            var paymentSchedule = ossKaskoOptions.Single(p => p.Type == ProductConfigurationType.PaymentSchedule.ToString());
            var prConfSchedule = _productConfigurations.Select(v => v.Value).Single(p => p.StructId == paymentSchedule.StructId);
            deal.PaymentSchedule_Id = prConfSchedule.PaymentSchedule_Id;
            deal.PaymentSchedule = prConfSchedule.PaymentSchedule;

            deal.Proposals.Remove(addedProposal);
        }

        private List<StructIdAndSum> GetStructIdAndSums(IReadOnlyList<int> parentStructIds, IReadOnlyList<PreviousOssOption> ossKaskoOptions)
        {
            var structIdAndSum = new List<StructIdAndSum>(parentStructIds.Count + ossKaskoOptions.Count);
            structIdAndSum.AddRange(parentStructIds.Select(s => new StructIdAndSum(s)));
            structIdAndSum.AddRange(ossKaskoOptions
                .Where(s => s.IsFoundProductConfiguration())
                .Select(s => new StructIdAndSum(s.StructId.Value, s.Sum)));

            return structIdAndSum;
        }

        private void UpdateStructId(IReadOnlyList<PreviousOssOption> sources, IReadOnlyList<PreviousOssOption> targets)
        {
            var comparer = new OssKaskoOptionsComparer();
            foreach (var source in sources)
            {
                var target = targets.SingleOrDefault(t => comparer.Equals(t, source));
                if (target != null)
                {
                    target.StructId = source.StructId;
                }
            }
        }

        private void InitServices(Basket basket, Deal deal)
        {
            var queryOffer = _mediator.ResolveQuery<IQueryOffer>();
            var offers = queryOffer.GetOffers(new int?[] { _constructorOfferGetter.GetConstructorOfferId(basket) }, DT.Now, null);
            var productConfigurations = _mediator.ResolveQuery<IQueryProductConfiguration>().GetProductConfigurationForOffers(offers, DT.Now, null);
            _productConfigurations = productConfigurations;

            _ossKaskoOptionsEnricher.Init(_productConfigurations.Select(v => v.Value).ToList());
        }

        public IReadOnlyList<PreviousOssOption> SetOssKaskoOptionsForKaskoProlongationLogic(Basket basket)
        {
            return new List<PreviousOssOption>();
        }
    }
}
using iRIS.Framework.Data.Services.Client;
using iRIS.Framework.Entity.Dictionary.EntitySettings;
using iRIS.Framework.Entity.Metadata;
using iRIS.Framework.Link2;
using iRIS.Framework.Security.Entities;
using iRIS.Framework.Validation;
using iRIS.Framework.Workflow.Process.CustomProcessModel;
using iRIS.InsuranceCore.Code.Implementations.Comparison;
using iRIS.InsuranceCore.Entities;
using iRIS.InsuranceCore.Entities.Custom;
using iRIS.InsuranceCore.Entities.EntityExtensions;
using iRIS.InsuranceCore.Entities.Enums;
using iRIS.KaskoCore.Code.Constants;
using iRIS.KaskoCore.Code.Helpers;
using iRIS.KaskoLink2.Code.Constants;
using iRIS.KaskoLink2.Code.Constants.ConstantsHelpers;
using iRIS.KaskoLink2.Code.Helpers;
using iRIS.KaskoLink2.Code.Implementations.AutoCostCalculator;
using Microsoft.Extensions.DependencyInjection;
using SasClient.Code.CheckKaskoUpProjectService;
using Serilog;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using EntitySettingCodes = iRIS.KaskoLink2.Implementations.Code.Constants.EntitySettingCodes;

namespace iRIS.KaskoLink2.Code.CustomProcesses
{
    /// <summary>
    /// Подпроцесс проверки Kasko корзины в SAS.
    /// </summary>
    public class KaskoSasCheckProcessForLink2 : ICustomProcess, IAsyncCustomProcess
    {
        private string _aggregateName = Link2AggregateNames.Link2AutoDealWithURMAndSasDetailed;

        /// <summary>
        /// Переход ЦС.
        /// </summary>
        public const string ExitBranch_TargetedSegment = "TargetedSegment";

        /// <summary>
        /// Переход Не ЦС. Reject.
        /// </summary>
        public const string ExitBranch_NotTargetedSegment_Reject = "NotTargetedSegment_Reject";

        /// <summary>
        /// Переход Не ЦС. CorrData.
        /// </summary>
        public const string ExitBranch_NotTargetedSegment_CorrData = "NotTargetedSegment_CorrData";

        /// <summary>
        /// Сделка.
        /// </summary>
        public const string InputArgument_Deal = nameof(Deal);

        /// <summary>
        /// Корзина.
        /// </summary>
        public const string InputArgument_Basket = nameof(Basket);

        /// <summary>
        /// Имеются чувствительные данные при перерасчете.
        /// </summary>
        public const string InputArgument_IsSensitiveDataChanged = "IsSensitiveDataChanged";

        /// <summary>
        /// Проверки urm до перерасчета.
        /// </summary>
        public const string InputArgument_ExternalBasketUrmAproval = "ExternalBasketUrmAproval";

        /// <summary>
        /// Ошибки от SAS.
        /// </summary>
        public const string OutpuArgument_Value = nameof(Value);

        /// <summary>
        /// Входной параметр - Cделка.
        /// </summary>
        public InputArgument<Deal> Deal { get; } = new InputArgument<Deal>(InputArgument_Deal);

        /// <summary>
        /// Входной параметр - Корзина.
        /// </summary>
        public InputArgument<Basket> Basket { get; } = new InputArgument<Basket>(InputArgument_Basket);

        /// <summary>
        /// Входной параметр - Наименование процесса.
        /// </summary>
        [Obsolete("Не используется с 09.09.21")]
        public InputArgument<string> ProcessName { get; } = new InputArgument<string>("ProcessName");

        /// <summary>
        /// Выходоной параметр - сообщение об ошибке.
        /// </summary>
        /// <output/>
        public OutputArgument<string> Value { get; } = new OutputArgument<string>(OutpuArgument_Value);

        /// <summary>
        /// Входной параметр - Чувствительные изменения при перерасчете.
        /// </summary>
        public InputArgument<bool> IsSensitiveDataChanged { get; } = new InputArgument<bool>(InputArgument_IsSensitiveDataChanged);

        /// <summary>
        /// Входной параметр - Проверки URM корзины до перерасчета.
        /// </summary>
        public InputArgument<URMApproval> ExternalBasketUrmAproval { get; } = new InputArgument<URMApproval>(InputArgument_ExternalBasketUrmAproval);

        /// <inheritdoc />
        public void Execute(IProcessContext processContext)
        {
            ExecuteAsync(processContext).GetAwaiter().GetResult();
        }

        /// <inheritdoc />
        public async Task ExecuteAsync(IProcessContext processContext)
        {
            var logger = processContext.ServiceProvider.GetService<ILogger>()?.ForContext<KaskoSasCheckProcess>();

            var deal = Deal.Get(processContext);
            var basket = Basket.Get(processContext);
            IsSensitiveDataChanged.TryGet(processContext, out var isSensitiveDataChanged);
            ExternalBasketUrmAproval.TryGet(processContext, out var externalBasketUrmAproval);

            var checkKaskoUpProjectServiceAdapter = processContext.ServiceProvider.GetService<ICheckKaskoUpProjectServiceAdapter<Basket, Deal>>();
            var autoCostCalculator = processContext.ServiceProvider.GetService<IAutoCostCalculator>();
            var validationResultsAggregator = processContext.ServiceProvider.GetRequiredService<IValidationResultsAggregator>();
            var priceMax = await SasRequestResultHelper.GetMaxPriceAsync(autoCostCalculator, deal);

            var integrationLoginName = processContext.GetCustomVariable(Link2Constants.IntegrationLoginKey) as string;

            string externalBasketUrmAprovalStatus = externalBasketUrmAproval?.URMApprovalStatusCode;

            if (externalBasketUrmAproval != null)
            {
                string sensitiveChangeMessage = isSensitiveDataChanged
                    ? "Чувствительные изменения при перерасчете обнаружены"
                    : "Чувствительные изменения при перерасчете не обнаружены";

                logger?.Information($"{sensitiveChangeMessage}, статус URM до перерасчета: {externalBasketUrmAprovalStatus}");
            }

            if (!isSensitiveDataChanged && (
                externalBasketUrmAprovalStatus == UrmApprovalStatusCodes.Accepted || 
                externalBasketUrmAprovalStatus == UrmApprovalStatusCodes.AcceptedWithLimits ||
                externalBasketUrmAprovalStatus == UrmApprovalStatusCodes.RequiredExtraInfo))
            { 
                SetExternalBasketUrmAprovalStatus(deal, externalBasketUrmAprovalStatus);
                return;
            }

            try
            {
                var sw = Stopwatch.StartNew();

                var requestGuid = Guid.NewGuid().ToString();
                if (deal.AutoDeal.IsSasCoefficientOutdate != false)
                {
                    var firstCheckResult = await checkKaskoUpProjectServiceAdapter.FirstCheckBasketAsync(basket, deal, priceMax, requestGuid);

                    AutoCheckResultHelper.CreateKaskoRtdmAutoCheckResult(deal, firstCheckResult);
                }

                var secondCheckResult = await checkKaskoUpProjectServiceAdapter.SecondCheckBasketAsync(basket, deal, requestGuid);
                var decision = secondCheckResult.FinDecision?.ToLower();

                sw.Stop();

                logger?.ForContext("BasketNumber", basket.Number)
                    .Information("Блок проверки Check Kasko Project SAS: {TotalTime} ms", sw.ElapsedMilliseconds);

                AutoCheckResultHelper.CreateKaskoRtdmPassportCheckAutoCheckResult(deal, secondCheckResult);

                var comment = $"Проверка через SAS. {decision}";

                logger?.ForContext("BasketNumber", basket.Number)
                    .Information(comment, sw.ElapsedMilliseconds);

                if (secondCheckResult.Inspection || (decision is KaskoSasCheckProcessConstants.KaskoSasCheckNoDecision && deal.GetAuto().HasMileage == true))
                {
                    deal.EntityContext[PsoEntityValuesConstants.IsInspectionForPartnerBySasDecision] = true;
                }

                UpdateSasApprovalInDeal(deal, SASApprovalStatusCodeHelper.GetSASStatusCode(decision), secondCheckResult.SasCoefficient);
                string exitBranch = string.Empty;               

                switch (decision)
                {
                    case KaskoSasCheckProcessConstants.KaskoSasCheckAccept:
                        if (isSensitiveDataChanged && (
                            externalBasketUrmAprovalStatus == UrmApprovalStatusCodes.Accepted || 
                            externalBasketUrmAprovalStatus == UrmApprovalStatusCodes.AcceptedWithLimits ||
                            externalBasketUrmAprovalStatus == UrmApprovalStatusCodes.RequiredExtraInfo))
                        {
                            SetExternalBasketUrmAprovalStatus(deal, externalBasketUrmAprovalStatus);
                        }
                        else
                        {
                            UrmHelper.SetUrmApprovalNotRequired(deal);
                        }
using iRIS.Framework.Common;
using iRIS.Framework.Data;
using iRIS.Framework.RequestPipeline.Extensions;
using iRIS.InsuranceCore.Code.ConstructorCore.Models;
using iRIS.InsuranceCore.Code.CustomProcesses.BasketPreparationProcess.Enums;
using iRIS.InsuranceCore.Code.Interfaces;
using iRIS.InsuranceCore.Code.Interfaces.ConstructorCore;
using iRIS.InsuranceCore.Code.Queries;
using iRIS.InsuranceCore.Code.TypeExtensions;
using iRIS.InsuranceCore.Entities;
using iRIS.KaskoCore.Code.Implementations;
using iRIS.KaskoLink2.Code.Constructor.Helpers.EntityExtensions;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;

namespace iRIS.KaskoLink2.Code.Constructor.FromInsuranceCore.ConstructorCore
{
    /// <summary>
    /// Обработчик условий в сделке (заполнение,  проставление).
    /// </summary>
    [Obsolete("Новая реализация в DiKaskoConditionsProcessor. (IRIS-163411)")]
    public class DealConditionsProcessor : IDealConditionsProcessor
    {
        private readonly Dictionary<int, ProductConfiguration> _allProductConfigs;
        private readonly ISumManager _sumManager;
        private readonly IProposalCurrencyDeterminator _currencyDeterminator;
        private readonly IQueryOffer _queryOffer;
        private readonly PipelineExecutionContext _context;
        private ILogger _log;

        public DealConditionsProcessor(
            Dictionary<int, ProductConfiguration> allProductConfigs,
            ILogger log,
            IQueryOffer queryOffer,
            ISumManager sumManager,
            IProposalCurrencyDeterminator currencyDeterminator,
            PipelineExecutionContext context = null)
        {
            _allProductConfigs = allProductConfigs;
            _queryOffer = queryOffer;
            _sumManager = sumManager;
            _currencyDeterminator = currencyDeterminator;
            _log = log;
            _context = context;
        }

        public void FillDealsConditions(List<Deal> deals, List<StructIdAndSum> dealConditionsStructIds, bool? useDrafts, bool? loadDefaultConditions = null)
        {
            foreach (var deal in deals)
            {
                var dealOfferIds = deal.Proposals.Select(x => x.Offer_Id).Distinct().ToArray();
                var dealOffers = _queryOffer.GetOffers(dealOfferIds, deal.DateActual ?? DT.Now, useDrafts).ToList();
                var conditionsFilter = new KaskoConditionsFilter(deal, dealOffers, _allProductConfigs);

                deal.StructId = conditionsFilter.GetDealStructId();

                FillSingleDealConditions(deal, conditionsFilter, dealConditionsStructIds, new List<int>(), null, loadDefaultConditions);

                // Удаляем InsuranceObject со сделки, если нет для них InsuranceObjectCondition в сделке
                ClearDealFromUnsuitableInsuranceObjects(deal);
            }

            _currencyDeterminator.DetermineCurrenciesForDealsAndConditions(deals);
        }

        public void FillDealsConditions(List<Deal> deals, ToggledCondition toggledCondition, List<StructIdAndSum> dealConditionsStructIdsFromTopGroup, List<StructIdAndSum> dealConditionsStructIds, bool? useDrafts)
        {
            List<Deal> dealsToDelete = new List<Deal>();

            // Отбрасываем офферы (сделки) которые не содержат все выбранные условия из верхней групп
            var unsuitableDeals = GetUnsuitableDeals(deals, dealConditionsStructIdsFromTopGroup, useDrafts);
            RemoveUnsuitableDeals(deals, unsuitableDeals);

            foreach (var deal in deals)
            {
                var dealOfferIds = deal.Proposals.Select(x => x.Offer_Id).Distinct().ToArray();
                var dealOffers = _queryOffer.GetOffers(dealOfferIds, deal.DateActual ?? DT.Now, useDrafts).ToList();
                var conditionsFilter = new KaskoConditionsFilter(deal, dealOffers, _allProductConfigs);
                deal.StructId = conditionsFilter.GetDealStructId();

                //Проставляем условия из верхней группы (при этом удалим проставленные из dealConditionsStructIds)
                FillSingleDealConditionByConditionsStructIdsFromTopGroup(deal, conditionsFilter, toggledCondition, dealConditionsStructIdsFromTopGroup, dealConditionsStructIds);

                var needRemoveDeal = FillSingleDealConditions(deal, toggledCondition, conditionsFilter, dealConditionsStructIds);
                if (needRemoveDeal)
                {
                    dealsToDelete.Add(deal);
                }

                // Удаляем InsuranceObject со сделки, если нет для них InsuranceObjectCondition в сделке
                ClearDealFromUnsuitableInsuranceObjects(deal);
            }

            _currencyDeterminator.DetermineCurrenciesForDealsAndConditions(deals);

            //Отбрасываем сделки(офферы), которые не подходят из-за снятия условий в констр-ре
            RemoveUnsuitableDeals(deals, dealsToDelete);
        }

        private void FillSingleDealConditionByConditionsStructIdsFromTopGroup(Deal deal, KaskoConditionsFilter conditionsFilter, ToggledCondition toggledCondition, List<StructIdAndSum> dealConditionsStructIdsFromTopGroup, List<StructIdAndSum> dealConditionsStructIds)
        {
            foreach (var structIdAndSum in dealConditionsStructIdsFromTopGroup)
            {
                var productConfiguration = conditionsFilter.GetProductConfigurationByStructId(structIdAndSum.StructId);

                if (productConfiguration.IsMain())
                {
                    // найти все родительские условия для structId
                    List<ProductConfiguration> parentConfigurations = conditionsFilter.GetParentProductConfigurationsFor(structIdAndSum.StructId);
                    parentConfigurations.Add(productConfiguration);

                    FillConditionUp(deal, parentConfigurations, dealConditionsStructIds);
                    dealConditionsStructIds.Remove(structIdAndSum);
                }
                else
                {
                    AddProductConfigurationToDeal(productConfiguration, deal, toggledCondition);
                    dealConditionsStructIds.Remove(structIdAndSum);
                }
            }
        }

        private void RemoveUnsuitableDeals(List<Deal> deals, List<Deal> dealsToDelete)
        {
            foreach (var dealToDelete in dealsToDelete)
            {
                deals.Remove(dealToDelete);
            }
        }

        /// <summary>
        /// Получаем сделки, которые не содержат все выбранные условия из верхней группы
        /// </summary>
        /// <param name="deals">Исходный список сделок</param>
        /// <param name="dealConditionsStructIdsFromTopGroup">Условия из верхней группы</param>
        /// <returns>Сделки, которые не содержат все выбранные условия из верхней группы</returns>
        private List<Deal> GetUnsuitableDeals(List<Deal> deals, List<StructIdAndSum> dealConditionsStructIdsFromTopGroup, bool? useDrafts)
        {
            List<Deal> dealsToRemove = new List<Deal>();
            foreach (var deal in deals)
            {
                var dealOfferIds = deal.Proposals.Select(x => x.Offer_Id).Distinct().ToArray();
                var dealOffers = _queryOffer.GetOffers(dealOfferIds, deal.DateActual ?? DT.Now, useDrafts).ToList();
                var dealOfferStructs = dealOffers.SelectMany(o => o.OfferStructs);

                foreach (var structIdAndSum in dealConditionsStructIdsFromTopGroup)
                {
                    bool structIdAndSumInDeal = false;

                    foreach (var offerStruct in dealOfferStructs)
                    {
                        if (!_allProductConfigs.ContainsKey(offerStruct.Id))
                        {
                            break;
                        }

                        var productConfiguration = _allProductConfigs[offerStruct.Id];
                        var sum = _sumManager.GetSumForProductConfiguration(productConfiguration, deal: deal);

                        if (offerStruct.StructId == structIdAndSum.StructId && sum == structIdAndSum.Sum)
                        {
                            structIdAndSumInDeal = true;
                            break;
                        }
                    }

                    // Если не нашли в сделке хоть одно условие  суммой, то сделку удалять
                    if (!structIdAndSumInDeal)
                    {
                        dealsToRemove.Add(deal);
                        break;
                    }
                }
            }

            //var result = deals.Where(x => !dealConditionsStructIdsFromTopGroup.All(c => x.Proposals.Select(p => p.Offer).SelectMany(o => o.OfferStructs).Select(os => os.StructId).Contains(c.StructId))).ToList();
            return dealsToRemove;
        }

        // реализация по заполнения обязательными и дефолтными условиями
        private void FillSingleDealConditions(
            Deal deal,
            KaskoConditionsFilter conditionsFilter,
            List<StructIdAndSum> dealConditionsStructIdsAndSums,
            List<int> structIdsToIgnore,
            ToggledCondition toggledCondition,
            bool? loadDefaultConditions = null)
        {
            List<int> dealConditionsStructIds = dealConditionsStructIdsAndSums.Select(x => x.StructId).ToList();
            bool loadDefaultConditionsFlag = loadDefaultConditions ?? toggledCondition == null;

            MakeEmptyConditionBlockIfNull(deal);
            AddOCFConditionsToBlock(deal.StructId.Value, deal.ConditionBlock, conditionsFilter, dealConditionsStructIdsAndSums, structIdsToIgnore, loadDefaultConditionsFlag);

            //проставялем периоды страхования
            var insurancePeriodTemplates = _allProductConfigs.Select(x => x.Value).Where(x => x.ParentStructId == deal.StructId).Where(x => x.InsurancePeriodTemplate != null);
            var dealPeriod = deal.ConditionBlock.DealPeriods?.FirstOrDefault();

            if (dealPeriod == null)
            {
                dealPeriod = new Period();
                deal.ConditionBlock.DealPeriods.Add(dealPeriod);
            }

            dealPeriod.InsurancePeriodTemplate = dealPeriod.InsurancePeriodTemplate ?? insurancePeriodTemplates.FirstOrDefault()?.InsurancePeriodTemplate;

            // Получить все обязательные и по умолчанию Группы           
            var conditionGroups = conditionsFilter.GetConditionGroupsConfigurations(loadDefaultConditionsFlag, deal.StructId, dealConditionsStructIds, toggledCondition);
            var conditionGroupsAndSums = GetProductConfigurationsAndSums(conditionGroups, dealConditionsStructIdsAndSums);

            // Добавить группы в сделку
            foreach (var conditionGroup in conditionGroupsAndSums)
            {
                if (structIdsToIgnore.Contains(conditionGroup.ProductConfiguration.StructId.Value))
                {
                    continue;
                }

                AddConditionGroupToDeal(deal, conditionGroup);
            }

            foreach (var dealConditionGroup in deal.DealConditionGroups)
            {
                MakeEmptyConditionBlockIfNull(dealConditionGroup);
                AddOCFConditionsToBlock(dealConditionGroup.StructId.Value, dealConditionGroup.ConditionBlock, conditionsFilter, dealConditionsStructIdsAndSums, structIdsToIgnore, loadDefaultConditionsFlag);
                RemoveEmptyConditionBlock(dealConditionGroup, dealConditionGroup.ConditionBlock);

                var ioTypeConditions =
                    conditionsFilter.GetInsuranceObjectTypeConfiguarations(
                        dealConditionGroup.StructId.Value,
                        loadDefaultConditionsFlag,
                        dealConditionsStructIds,
                        toggledCondition);

                foreach (var ioTypeCondition in ioTypeConditions)
                {
                    if (structIdsToIgnore.Contains(ioTypeCondition.StructId.Value))
                    {
                        continue;
                    }

                    AddInsuranceObjectConditionToDeal(deal, dealConditionGroup, ioTypeCondition);
                }
            }

            foreach (var dealInsuranceObjectCondition in deal.DealConditionGroups.SelectMany(x => x.InsuranceObjectConditions))
            {
                MakeEmptyConditionBlockIfNull(dealInsuranceObjectCondition);
                AddOCFConditionsToBlock(dealInsuranceObjectCondition.StructId.Value, dealInsuranceObjectCondition.ConditionBlock, conditionsFilter, dealConditionsStructIdsAndSums, structIdsToIgnore, loadDefaultConditionsFlag);
                RemoveEmptyConditionBlock(dealInsuranceObjectCondition, dealInsuranceObjectCondition.ConditionBlock);

                var coverages = conditionsFilter.GetCoveragesConfigurations(dealInsuranceObjectCondition.StructId.Value, loadDefaultConditionsFlag, dealConditionsStructIds, toggledCondition);
                var coveragesAndSums = GetProductConfigurationsAndSums(coverages, dealConditionsStructIdsAndSums);
                foreach (var coverage in coveragesAndSums)
                {
                    if (structIdsToIgnore.Contains(coverage.ProductConfiguration.StructId.Value))
                    {
                        continue;
                    }

                    AddCoverageToDeal(dealInsuranceObjectCondition, coverage, deal: deal);
                }
            }

            foreach (var dealCoverage in deal.DealConditionGroups.SelectMany(x => x.InsuranceObjectConditions).SelectMany(x => x.DealCoverages))
            {
                MakeEmptyConditionBlockIfNull(dealCoverage);
                AddOCFConditionsToBlock(dealCoverage.StructId.Value, dealCoverage.ConditionBlock, conditionsFilter, dealConditionsStructIdsAndSums, structIdsToIgnore, loadDefaultConditionsFlag);
                RemoveEmptyConditionBlock(dealCoverage, dealCoverage.ConditionBlock);

                var risks = conditionsFilter.GetRisksConfigurations(dealCoverage.StructId.Value, loadDefaultConditionsFlag, dealConditionsStructIds, toggledCondition);
                var riskAndSums = GetProductConfigurationsAndSums(risks, dealConditionsStructIdsAndSums);
                foreach (var risk in riskAndSums)
                {
                    if (structIdsToIgnore.Contains(risk.ProductConfiguration.StructId.Value))
                    {
                        continue;
                    }

                    AddRiskToDeal(dealCoverage, risk);
                }
            }

            foreach (var dealRisk in deal.DealConditionGroups.SelectMany(x => x.InsuranceObjectConditions).SelectMany(x => x.DealCoverages).SelectMany(x => x.DealRisks))
            {
                MakeEmptyConditionBlockIfNull(dealRisk);
                AddOCFConditionsToBlock(dealRisk.StructId.Value, dealRisk.ConditionBlock, conditionsFilter, dealConditionsStructIdsAndSums, structIdsToIgnore, loadDefaultConditionsFlag);
                RemoveEmptyConditionBlock(dealRisk, dealRisk.ConditionBlock);
            }

            deal.PaymentSchedule = conditionsFilter.GetPaymentScheduleConfiguration(deal.PaymentSchedule_Id, loadDefaultConditionsFlag, toggledCondition)?.PaymentSchedule;
            deal.PaymentSchedule_Id = deal.PaymentSchedule?.Id;
        }

        // реализация заполения сделки по изменяемому условию toggledCondition
        private bool FillSingleDealConditions(Deal deal, ToggledCondition toggledCondition, KaskoConditionsFilter conditionsFilter, List<StructIdAndSum> dealConditionsStructIdsAndSums)
        {
            List<int> dealConditionsStructIds = dealConditionsStructIdsAndSums.Select(x => x.StructId).ToList();

            // Пройти вверх со стартовой точки и запомнить StructId всех проставленных вверх условий                
            bool needToRemove = FillDealConditionsUp(deal, toggledCondition, conditionsFilter, dealConditionsStructIdsAndSums);
            if (needToRemove)
            {
                return true;
            }

            // Пройти вниз от стартовой точки и проставить все обязательные вниз и запомнить все проставленные условия
            List<int> pastStructIdsAfterDown;
            FillDealConditionsDown(deal, toggledCondition, conditionsFilter, dealConditionsStructIds, out pastStructIdsAfterDown);

            // Пройти от корня вниз обычным обходом с игнором того, что уже проставили;
            FillSingleDealConditions(deal, conditionsFilter, dealConditionsStructIdsAndSums, pastStructIdsAfterDown, toggledCondition);

            // Удаляем со сделки условия, у которых не заполнены дочерние элементы
            ClearDealFromIncorrectConditions(deal);

            return false;
        }

        /// <summary>
        /// Удаляет InsuranceObject со сделки, если для них нет соотвествующего InsuranceObjectCondition в сделке
        /// </summary>
        /// <param name="deal">Сделка</param>
        private void ClearDealFromUnsuitableInsuranceObjects(Deal deal)
        {
            var insuranceObjectsToDelete = new List<InsuranceObject>();

            var insuranceObjectsFromIOC = deal.DealConditionGroups
                .SelectMany(x => x.InsuranceObjectConditions)
                .Select(x => x.InsuranceObject)
                .ToList();

            foreach (var insuranceObject in deal.InsuranceObjects)
            {
                if (!insuranceObjectsFromIOC.Contains(insuranceObject))
                {
                    insuranceObjectsToDelete.Add(insuranceObject);
                }
            }

            foreach (var io in insuranceObjectsToDelete)
            {
                deal.InsuranceObjects.Remove(io);
            }
        }

        private bool FillDealConditionsUp(Deal deal, ToggledCondition toggledCondition, KaskoConditionsFilter conditionsFilter, List<StructIdAndSum> dealConditionsStructIdsAndSums)
        {
            if (toggledCondition.StructIds.Count == 0)
            {
                return false;
            }

            if (toggledCondition.IsChecked || toggledCondition.IsDropDown)
            {
                foreach (var structId in toggledCondition.StructIds)
                {
                    // найти все родительские условия для toggledCondition, чтобы проставить или снять их
                    var parentConfigurations = conditionsFilter.GetParentProductConfigurationsFor(structId);

                    // проставить все родительские условия
                    FillConditionUp(deal, parentConfigurations, dealConditionsStructIdsAndSums);
                }

                return false;
            }
            else
            {
                List<int> dealConditionsStructIds = dealConditionsStructIdsAndSums.Select(x => x.StructId).ToList();
                return toggledCondition.StructIds.All(structId => UncheckConditionUp(deal, conditionsFilter, structId, dealConditionsStructIds));
            }
        }

        private void FillConditionUp(Deal deal, List<ProductConfiguration> parentConfigurations, List<StructIdAndSum> dealConditionsStructIdsAndSums)
        {
            var conditionGroupConfig = parentConfigurations.SingleOrDefault(x => x.ProductConfigurationChildType.Name == ProductConfigurationType.ConditionGroup.ToString());
            if (conditionGroupConfig == null)
            {
                return;
            }

            AddConditionGroupToDeal(deal, new ProductConfigurationAndSum(conditionGroupConfig));
            var dealConditionGroup = deal.DealConditionGroups.SingleOrDefault(x => x.StructId == conditionGroupConfig.StructId);
            CorrectDealConditionGroupSum(dealConditionGroup, dealConditionsStructIdsAndSums);

            var insuranceObjectType = parentConfigurations.SingleOrDefault(x => x.ProductConfigurationChildType.Name == ProductConfigurationType.TypeIOInProduct.ToString());
            if (insuranceObjectType == null)
            {
                return;
            }

            AddInsuranceObjectConditionToDeal(deal, dealConditionGroup, insuranceObjectType);
            var dealInsuranceObjectConditions = deal.DealConditionGroups.SelectMany(x => x.InsuranceObjectConditions).Where(x => x.StructId == insuranceObjectType.StructId);

            foreach (var dealInsuranceObjectCondition in dealInsuranceObjectConditions)
            {
                var coverage = parentConfigurations.SingleOrDefault(x => x.ProductConfigurationChildType.Name == ProductConfigurationType.Coverage.ToString());
                if (coverage == null)
                {
                    return;
                }

                AddCoverageToDeal(dealInsuranceObjectCondition, new ProductConfigurationAndSum(coverage), deal: deal);
                var dealCoverage = dealInsuranceObjectCondition.DealCoverages.SingleOrDefault(x => x.StructId == coverage.StructId);

                var risk = parentConfigurations.SingleOrDefault(x => x.ProductConfigurationChildType.Name == ProductConfigurationType.Risk.ToString());
                if (risk != null)
                {
                    AddRiskToDeal(
                        dealCoverage, 
                        new ProductConfigurationAndSum(
                            risk, 
                            dealConditionsStructIdsAndSums.FirstOrDefault(s => s.StructId == risk.StructId)?.Sum));
                }
            }

            return;
        }

        private void CorrectDealConditionGroupSum(DealConditionGroup dealConditionGroup, List<StructIdAndSum> dealConditionsStructIdsAndSums)
        {
            var dealConditionGroupSum =
                dealConditionsStructIdsAndSums.FirstOrDefault(s => s.StructId == dealConditionGroup.StructId)?.Sum;

            if (dealConditionGroupSum != null)
            {
                dealConditionGroup.Sum = dealConditionGroupSum;
            }
        }

        private bool UncheckConditionUp(Deal deal, KaskoConditionsFilter conditionsFilter, int toggledStructId, List<int> dealConditionsStructIds)
        {
            // найти все родительские условия для toggledCondition, чтобы проставить или снять их
            List<ProductConfiguration> parentConfigurations = conditionsFilter.GetParentProductConfigurationsFor(toggledStructId);
            bool isRequired = false;

            var currentNode = conditionsFilter.GetProductConfigurationByStructId(toggledStructId);

            // Берем из списка всех родительсикх условий (настроек продукта) Покрытие
            var coverage = parentConfigurations.SingleOrDefault(x => x.ProductConfigurationChildType.Name == ProductConfigurationType.Coverage.ToString());

            // Если Покрытие условие существует, то проверим, сколько у него дочерних услоий может быть по структуре. Если нет ни одного или оно обязательное - удаляем покрытие
            if (coverage != null)
            {
                var dealCoverages = deal.DealConditionGroups.SelectMany(x => x.InsuranceObjectConditions.SelectMany(ioc => ioc.DealCoverages)).Where(x => x.StructId == coverage.StructId).ToList();

                foreach (var dealCoverage in dealCoverages)
                {
                    var hasMoreThanOneChild = _allProductConfigs.Values.Where(x => x.ParentStructId == coverage.StructId).Count() > 1;
                    isRequired = currentNode.IsRequired();
                    bool isMainCondition = currentNode.IsMain();

                    if (dealCoverage != null && ((!hasMoreThanOneChild && isMainCondition) || isRequired))
                    {
                        // Находим все условия объекта страхования, где есть такое покрытие и удаляем его из этих условий объекта страхования
                        var insuranceObjectConditions = deal.DealConditionGroups.SelectMany(x => x.InsuranceObjectConditions).Where(x => x.DealCoverages.Contains(dealCoverage)).ToList();
                        foreach (var insuranceObjectCondition in insuranceObjectConditions)
                        {
                            insuranceObjectCondition.DealCoverages.Remove(dealCoverage);
                            dealConditionsStructIds.Remove(dealCoverage.StructId.Value);
                        }

                        currentNode = coverage;
                    }
                    else
                    {
                        return false;
                    }
                }
            }

            // Берем из списка всех родительсикх условий (настроек продукта) Тип ОС
            var ioType = parentConfigurations.SingleOrDefault(x => x.ProductConfigurationChildType.Name == ProductConfigurationType.TypeIOInProduct.ToString());

            // Если Тип ОС условие существует, то проверим, сколько у него дочерних услоий. Если нет ни одного - удаляем
            if (ioType != null)
            {
                var insuranceObjectConditionsStructIds = dealConditionsStructIds.Where(x => x == ioType.StructId).ToList();

                foreach (var insuranceObjectConditionStructId in insuranceObjectConditionsStructIds)
                {
                    var hasMoreThanOneChild = _allProductConfigs.Values.Where(x => x.ParentStructId == ioType.StructId).Count() > 1;
                    isRequired = currentNode.IsRequired();
                    bool isMainCondition = currentNode.IsMain();

                    if ((!hasMoreThanOneChild && isMainCondition) || isRequired)
                    {
                        dealConditionsStructIds.Remove(insuranceObjectConditionStructId);

                        currentNode = ioType;
                    }
                    else
                    {
                        return false;
                    }
                }
            }

            // Берем из списка всех родительсикх условий (настроек продукта) группу условий
            var conditionGroup = parentConfigurations.SingleOrDefault(x => x.ProductConfigurationChildType.Name == ProductConfigurationType.ConditionGroup.ToString());

            // Если группа условий существует, то проверим, сколько у него дочерних услоий. Если нет ни одного - удаляем
            if (conditionGroup != null)
            {
                var dealConditionGroup = deal.DealConditionGroups.SingleOrDefault(x => x.StructId == conditionGroup.StructId);
                var hasMoreThanOneChild = _allProductConfigs.Values.Where(x => x.ParentStructId == conditionGroup.StructId).Count() > 1;
                isRequired = currentNode.IsRequired();
                bool isMainCondition = currentNode.IsMain();

                if ((!hasMoreThanOneChild && isMainCondition) || isRequired)
                {
                    if (dealConditionGroup != null)
                    {
                        deal.DealConditionGroups.Remove(dealConditionGroup);
                    }

                    dealConditionsStructIds.Remove(conditionGroup.StructId.Value);
                }

                currentNode = conditionGroup;
            }

            var product = parentConfigurations.SingleOrDefault(x => x.ProductConfigurationChildType.Name == ProductConfigurationType.Product.ToString());

            // Если продукт существует, то проверим, сколько у него дочерних услоий. Если нет ни одного - удаляем
            if (product != null)
            {
                var dealProduct = deal.StructId;
                var hasMoreThanOneChild = _allProductConfigs.Values.Where(x => x.ParentStructId == deal.StructId).Count() > 1;
                isRequired = currentNode.IsRequired();
                bool isMainCondition = currentNode.IsMain();

                if (dealProduct != null && ((!hasMoreThanOneChild && isMainCondition) || isRequired))
                {
                    return true;
                }
            }

            return false;
        }

        // Заполняет условия в поддереве, начиная с условия toogledStructId и вниз
        private void FillDealConditionsDown(Deal deal, ToggledCondition toggledCondition, KaskoConditionsFilter conditionsFilter, List<int> dealConditionsStructIds, out List<int> pastStructIds)
        {
            pastStructIds = new List<int>();

            if (toggledCondition.StructIds.Count == 0)
            {
                return;
            }

            if (toggledCondition.IsChecked || toggledCondition.IsDropDown)
            {
                // Получить дочерние условия + изменяемое условие как список (изменяемое условие делаю первым в списке для дальнейше обработки)
                var childConfigurations = conditionsFilter.GetRequiredChildProductConfigurationsFor(toggledCondition.StructIds, dealConditionsStructIds);
                var toogledProductConfigurations = conditionsFilter.GetProductConfigurationByStructIds(toggledCondition.StructIds);
                childConfigurations.InsertRange(0, toogledProductConfigurations);

                // проставить все дочерние условия
                foreach (var childConfiguration in childConfigurations)
                {
                    AddProductConfigurationToDeal(childConfiguration, deal, toggledCondition, false);
                    pastStructIds.Add(childConfiguration.StructId.Value);
                }
            }
            else
            {
                // var deletedStructIds = _dealManager.FillAllDealConditionsWhenUncheck(deal, toggledCondition.StructIds[0], _allProductConfigs.Values.ToList());
                //dealConditionsStructIds.RemoveAll(x => deletedStructIds.Contains(x));
                //pastStructIds = deletedStructIds;
                var childsProductConfigurationsToRemove = conditionsFilter.GetChildProductConfigurationsFor(toggledCondition.StructIds, dealConditionsStructIds);
                var toogledProductConfigurations = conditionsFilter.GetProductConfigurationByStructIds(toggledCondition.StructIds);
                if (toogledProductConfigurations.Count > 0)
                {
                    childsProductConfigurationsToRemove.AddRange(toogledProductConfigurations);
                }

                var structIdsToRemove = childsProductConfigurationsToRemove.Select(x => x.StructId.Value);

                dealConditionsStructIds.RemoveAll(x => structIdsToRemove.Contains(x));

                pastStructIds.AddRange(structIdsToRemove);
            }
        }

        /// <summary>
        /// Очищаем сделку от условий, у которых не заполнены дочерние элементы
        /// </summary>
        /// <param name="deal">Сделка</param>
        private void ClearDealFromIncorrectConditions(Deal deal)
        {
            var coverages = deal.DealConditionGroups.SelectMany(x => x.InsuranceObjectConditions).SelectMany(x => x.DealCoverages).ToList();
            foreach (var coverage in coverages)
            {
                if (coverage.DealRisks == null || coverage.DealRisks.Count == 0)
                {
                    var conditionBlock = coverage.ConditionBlock;

                    if (conditionBlock == null || conditionBlock.DealOptions == null || conditionBlock.DealOptions.Count == 0)
                    {
                        var iocs = deal.DealConditionGroups.SelectMany(x => x.InsuranceObjectConditions).ToList();
                        foreach (var ioc in iocs)
                        {
                            if (ioc.DealCoverages.Contains(coverage))
                            {
                                ioc.DealCoverages.Remove(coverage);
                            }
                        }
                    }
                }
            }

            var insuranceObjectConditions = deal.DealConditionGroups.SelectMany(x => x.InsuranceObjectConditions).ToList();
            foreach (var ioc in insuranceObjectConditions)
            {
                if (ioc.DealCoverages == null || ioc.DealCoverages.Count == 0)
                {
                    var conditionGroups = deal.DealConditionGroups;
                    foreach (var dealCondtionGroup in conditionGroups)
                    {
                        if (dealCondtionGroup.InsuranceObjectConditions.Contains(ioc))
                        {
                            dealCondtionGroup.InsuranceObjectConditions.Remove(ioc);
                        }
                    }
                }
            }

            var dealConditionsGroups = deal.DealConditionGroups.ToList();
            foreach (var dealConditionGroup in dealConditionsGroups)
            {
                if (dealConditionGroup.InsuranceObjectConditions == null || dealConditionGroup.InsuranceObjectConditions.Count == 0)
                {
                    if (deal.DealConditionGroups.Contains(dealConditionGroup))
                    {
                        deal.DealConditionGroups.Remove(dealConditionGroup);
                    }
                }
            }

            if (deal.DealConditionGroups == null || deal.DealConditionGroups.Count == 0)
            {
                _log.Warning($"Для сделки с Id =  {deal.Id} были удалены все DealConditionGroups");
            }
        }
Где происходит маппинг из осс в сделку?