Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text.RegularExpressions;
- using System.Threading.Tasks;
- using JetBrains.Annotations;
- using log4net;
- using SKBKontur.Billy.Core.BusinessObjects.External;
- using SKBKontur.Billy.Core.Buzz.OrganizationsSearcher.Converters;
- using SKBKontur.Billy.Core.Buzz.OrganizationsSearcher.Extensions;
- using SKBKontur.Billy.Core.Buzz.OrganizationsSearcher.Models;
- using SKBKontur.Billy.Core.Buzz.OrganizationsService;
- using SKBKontur.Billy.Core.Common;
- using SKBKontur.Billy.Core.Common.Extensions;
- using SKBKontur.Billy.Core.Common.Threading;
- namespace SKBKontur.Billy.Core.Buzz.OrganizationsSearcher
- {
- public class OrganizationsSearcher : IOrganizationsSearcher
- {
- private const int batchSize = 1000;
- private readonly IOrganizationServiceClient organizationServiceClient;
- private readonly IOrganizationPropsConverter organizationPropsConverter;
- private readonly ILog log = LogManager.GetLogger(typeof(OrganizationsSearcher));
- public OrganizationsSearcher(
- IOrganizationServiceClient organizationServiceClient,
- IOrganizationPropsConverter organizationPropsConverter
- )
- {
- this.organizationServiceClient = organizationServiceClient;
- this.organizationPropsConverter = organizationPropsConverter;
- }
- public PayerOrganizationSearchDto[] Select(Requisites[] innKppPairs)
- {
- return SelectAsync(innKppPairs).AwaitResult();
- }
- public PayerOrganizationSearchDto[] Select(string[] inns)
- {
- return SelectAsync(inns).AwaitResult();
- }
- public async Task<PayerOrganizationSearchDto[]> SelectAsync(Requisites[] innKppPairs)
- {
- using (Timewatcher.CreateMs(t => log.Info($"Select payers time = {t} ms. Payers {innKppPairs.JoinToString()}")))
- {
- return await InnerSelectAsync(innKppPairs).ConfigureAwait(false);
- }
- }
- public async Task<PayerOrganizationSearchDto[]> SelectAsync(string[] inns)
- {
- if (inns.IsNullOrEmpty())
- {
- return new PayerOrganizationSearchDto[0];
- }
- var payers = await SelectBatchedAsync(organizationServiceClient.SelectByInnsAsync, inns).ConfigureAwait(false);
- return payers
- .Where(p => !p.IsDeleted())
- .Select(organizationPropsConverter.Convert)
- .ToArray();
- }
- public async Task<PayerOrganizationSearchDto[]> SelectAsync(Guid[] payerIds)
- {
- var payers = await SelectBatchedAsync(organizationServiceClient.SelectAsync, payerIds).ConfigureAwait(false);
- return payers
- .Where(p => !p.IsDeleted())
- .Select(organizationPropsConverter.Convert)
- .ToArray();
- }
- public (Requisites InnKpp, PayerOrganizationSearchDto ExistedOrHeadPayer)[] SelectExistedOrHead(Requisites[] innKpps)
- {
- return SelectExistedOrHeadAsync(innKpps).AwaitResult();
- }
- public async Task<(Requisites InnKpp, PayerOrganizationSearchDto ExistedOrHeadPayer)[]> SelectExistedOrHeadAsync(Requisites[] innKpps)
- {
- var completedInnKpps = innKpps
- .Where(i => i.IsComplete())
- .Distinct()
- .ToArray();
- var inns = completedInnKpps.Select(i => i.Inn).ToArray();
- var allPayers = await SelectAsync(inns).ConfigureAwait(false);
- var payersHelper = new PayerHelper(allPayers);
- return completedInnKpps
- .Select(innKpp => (InnKpp: innKpp, ExistedOrHeadPayer: payersHelper.FindExistedOrHead(innKpp)))
- .Where(t => t.ExistedOrHeadPayer != null)
- .ToArray();
- }
- [NotNull, ItemNotNull]
- private async Task<PayerOrganizationSearchDto[]> InnerSelectAsync([NotNull] Requisites[] innKppPairs)
- {
- if (innKppPairs.Length == 0)
- {
- return new PayerOrganizationSearchDto[0];
- }
- var nonEmptyInnKpps = innKppPairs
- .Where(ik => ik.IsComplete())
- .ToHashSet();
- var searchedInns = nonEmptyInnKpps
- .Select(ik => ik.Inn)
- .Distinct()
- .ToArray();
- var payers = await SelectAsync(searchedInns).ConfigureAwait(false);
- return payers
- .ToLookup(p => p.ToInnKpp())
- .Where(g => nonEmptyInnKpps.Contains(g.Key))
- .Select(g => g.First())
- .ToArray();
- }
- [NotNull, ItemNotNull]
- private async Task<TResult[]> SelectBatchedAsync<TResult, TKey>(Func<TKey[], Task<TResult[]>> method, TKey[] keys)
- {
- var result = new List<TResult>();
- foreach (var keysBatch in keys.Split(batchSize))
- {
- var batchContent = await method(keysBatch.ToArray()).ConfigureAwait(false);
- result.AddRange(batchContent);
- }
- return result.ToArray();
- }
- private class PayerHelper
- {
- private readonly ILookup<string, PayerOrganizationSearchDto> payersByInns;
- private static readonly Regex is01HeadKpp = new Regex(@"\d{4}01\d{3}", RegexOptions.Compiled);
- private static readonly Regex is50HeadKpp = new Regex(@"\d{4}50\d{3}", RegexOptions.Compiled);
- public PayerHelper([NotNull] PayerOrganizationSearchDto[] abonents)
- {
- payersByInns = abonents.ToLookup(a => a.Inn);
- }
- [CanBeNull]
- public PayerOrganizationSearchDto FindExistedOrHead(Requisites innKpp)
- {
- var existed = FindExisted(innKpp);
- if (existed != null || !CanFindHead(innKpp))
- {
- return existed;
- }
- return FindHead(innKpp);
- }
- [CanBeNull]
- private PayerOrganizationSearchDto FindExisted(Requisites innKpp)
- {
- return payersByInns[innKpp.Inn].FirstOrDefault(payer => innKpp.Equals(payer.ToInnKpp()));
- }
- [CanBeNull]
- private PayerOrganizationSearchDto FindHead(Requisites innKpp)
- {
- var found01Payer = payersByInns[innKpp.Inn].FirstOrDefault(p => is01HeadKpp.IsMatch(p.Kpp));
- var found50Payer = payersByInns[innKpp.Inn].FirstOrDefault(p => is50HeadKpp.IsMatch(p.Kpp));
- if (is01HeadKpp.IsMatch(innKpp.Kpp))
- {
- return found01Payer ?? found50Payer;
- }
- if (is50HeadKpp.IsMatch(innKpp.Kpp))
- {
- return found50Payer ?? found01Payer;
- }
- return null;
- }
- private bool CanFindHead(Requisites innKpp)
- {
- return innKpp.ClientType == ClientType.LegalEntity
- && innKpp.IsValid();
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement