Add export from nsi-common service

This commit is contained in:
2025-08-18 11:58:28 +09:00
parent 2fd0457966
commit 875e3470d8
35 changed files with 5910 additions and 39 deletions

View File

@ -0,0 +1,88 @@
using Hcs.ClientApi.DataTypes;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using NsiCommon = Hcs.Service.Async.NsiCommon.v15_7_0_1;
namespace Hcs.ClientApi.NsiCommonApi
{
/// <summary>
/// Операции экспорта общих справочников подсистемы НСИ
/// </summary>
internal class HcsMethodExportNsiCommon : HcsNsiCommonMethod
{
public HcsMethodExportNsiCommon(HcsClientConfig config) : base(config)
{
EnableMinimalResponseWaitDelay = true;
CanBeRestarted = true;
}
/// <summary>
/// Возвращает общий справочник подсистемы НСИ
/// </summary>
/// <param name="regNum">Реестровый номер справочника</param>
/// <param name="token">Токен отмены</param>
/// <returns>Справочник</returns>
public async Task<ГисСправочник> GetNsiItem(int regNum, CancellationToken token)
{
var request = new NsiCommon.exportNsiItemRequest
{
Id = HcsConstants.SignedXmlElementId,
RegistryNumber = regNum.ToString(),
// http://open-gkh.ru/NsiCommon/exportNsiItemRequest.html
version = "10.0.1.2"
};
var stateResult = await SendAndWaitResultAsync(request, async (portClient) =>
{
var response = await portClient.exportNsiItemAsync(CreateRequestHeader(), request);
return response.AckRequest.Ack;
}, token);
return AdoptNsiItemType(stateResult.Item as NsiCommon.NsiItemType);
}
private ГисСправочник AdoptNsiItemType(NsiCommon.NsiItemType input)
{
var справочник = new ГисСправочник()
{
реестровыйНомер = input.NsiItemRegistryNumber,
датаФормирования = input.Created,
элементы = AdoptNsiElementTypes(input.NsiElement)
};
return справочник;
}
private ГисЭлементСправочника[] AdoptNsiElementTypes(NsiCommon.NsiElementType[] input)
{
var элементыСправочника = new List<ГисЭлементСправочника>();
foreach (var element in input)
{
var поляЭлементаСправочника = new List<ГисПолеЭлементаСправочника>();
foreach (var field in element.NsiElementField)
{
CallOnType<NsiCommon.NsiElementStringFieldType>(field, x =>
{
поляЭлементаСправочника.Add(new ГисПолеЭлементаСправочника()
{
наименование = x.Name,
значение = x.Value
});
});
}
элементыСправочника.Add(new ГисЭлементСправочника()
{
код = element.Code,
гуид = ParseGuid(element.GUID),
актуальный = element.IsActual,
поля = [.. поляЭлементаСправочника],
элементы = element.ChildElement?.Length > 0 ? AdoptNsiElementTypes(element.ChildElement) : null
});
}
return [.. элементыСправочника];
}
}
}

View File

@ -0,0 +1,35 @@
using Hcs.ClientApi.DataTypes;
using System.Threading;
using System.Threading.Tasks;
namespace Hcs.ClientApi.NsiCommonApi
{
public class HcsNsiCommonApi
{
public HcsClientConfig Config { get; private set; }
public HcsNsiCommonApi(HcsClientConfig config)
{
Config = config;
}
/// <summary>
/// Возвращает данные справочников поставщика информации
/// </summary>
/// <param name="regNum">Реестровый номер справочника</param>
/// <param name="token">Токен отмены</param>
/// <returns>Список справочников</returns>
public async Task<ГисСправочник> GetNsiItem(int regNum, CancellationToken token = default)
{
try
{
var method = new HcsMethodExportNsiCommon(Config);
return await method.GetNsiItem(regNum, token);
}
catch (HcsNoResultsRemoteException)
{
return null;
}
}
}
}

View File

@ -0,0 +1,111 @@
using Hcs.ClientApi.RemoteCaller;
using System;
using System.Threading;
using System.Threading.Tasks;
using NsiCommon = Hcs.Service.Async.NsiCommon.v15_7_0_1;
namespace Hcs.Service.Async.NsiCommon.v15_7_0_1
{
public partial class AckRequestAck : IHcsAck { }
public partial class getStateResult : IHcsGetStateResultOne { }
public partial class Fault : IHcsFault { }
public partial class HeaderType : IHcsHeaderType { }
}
namespace Hcs.ClientApi.NsiCommonApi
{
internal class HcsNsiCommonMethod : HcsRemoteCallMethod<IHcsGetStateResultOne>
{
public HcsEndPoints EndPoint => HcsEndPoints.NsiCommonAsync;
public NsiCommon.ISRequestHeader CreateRequestHeader() =>
HcsRequestHelper.CreateHeader<NsiCommon.ISRequestHeader>(ClientConfig);
public HcsNsiCommonMethod(HcsClientConfig config) : base(config) { }
public System.ServiceModel.EndpointAddress RemoteAddress
=> GetEndpointAddress(HcsConstants.EndPointLocator.GetPath(EndPoint));
private NsiCommon.NsiPortsTypeAsyncClient NewPortClient()
{
var client = new NsiCommon.NsiPortsTypeAsyncClient(_binding, RemoteAddress);
ConfigureEndpointCredentials(client.Endpoint, client.ClientCredentials);
return client;
}
public async Task<IHcsGetStateResultOne> SendAndWaitResultAsync(
object request,
Func<NsiCommon.NsiPortsTypeAsyncClient, Task<IHcsAck>> sender,
CancellationToken token)
{
token.ThrowIfCancellationRequested();
while (true)
{
try
{
return await SendAndWaitResultAsyncImpl(request, sender, token);
}
catch (HcsRestartTimeoutException e)
{
if (!CanBeRestarted) throw new HcsException("Превышен лимит ожидания выполнения запроса", e);
Log($"Перезапускаем запрос типа {request.GetType().Name}...");
}
}
}
private async Task<IHcsGetStateResultOne> SendAndWaitResultAsyncImpl(
object request,
Func<NsiCommon.NsiPortsTypeAsyncClient, Task<IHcsAck>> sender,
CancellationToken token)
{
if (request == null) throw new ArgumentNullException("Null request");
string version = HcsRequestHelper.GetRequestVersionString(request);
_config.Log($"Отправляем запрос: {RemoteAddress.Uri}/{request.GetType().Name} в версии {version}...");
var stopWatch = System.Diagnostics.Stopwatch.StartNew();
IHcsAck ack;
using (var client = NewPortClient())
{
ack = await sender(client);
}
stopWatch.Stop();
_config.Log($"Запрос принят в обработку за {stopWatch.ElapsedMilliseconds}мс., подтверждение {ack.MessageGUID}");
var stateResult = await WaitForResultAsync(ack, true, token);
if (stateResult.Item is NsiCommon.ErrorMessageType x)
{
throw HcsRemoteException.CreateNew(x.ErrorCode, x.Description);
}
return stateResult;
}
/// <summary>
/// Выполняет однократную проверку наличия результата.
/// Возвращает null если результата еще нет.
/// </summary>
protected override async Task<IHcsGetStateResultOne> TryGetResultAsync(IHcsAck sourceAck, CancellationToken token)
{
using (var client = NewPortClient())
{
var requestHeader = HcsRequestHelper.CreateHeader<NsiCommon.ISRequestHeader>(_config);
var requestBody = new NsiCommon.getStateRequest { MessageGUID = sourceAck.MessageGUID };
var response = await client.getStateAsync(requestHeader, requestBody);
var resultBody = response.getStateResult;
if (resultBody.RequestState == HcsAsyncRequestStateTypes.Ready)
{
return resultBody;
}
return null;
}
}
}
}