diff --git a/Hcs.Client/Client/Api/DeviceMeteringApi.cs b/Hcs.Client/Client/Api/DeviceMeteringApi.cs index 73b7423..ffc3fed 100644 --- a/Hcs.Client/Client/Api/DeviceMeteringApi.cs +++ b/Hcs.Client/Client/Api/DeviceMeteringApi.cs @@ -1,5 +1,7 @@ -using Hcs.Client.Api.Request.DeviceMetering; +using Hcs.Client.Api.Payload.DeviceMetering; +using Hcs.Client.Api.Request.DeviceMetering; using Hcs.Service.Async.DeviceMetering; +using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -8,6 +10,18 @@ namespace Hcs.Client.Api // http://open-gkh.ru/DeviceMeteringServiceAsync/ public class DeviceMeteringApi(ClientBase client) : ApiBase(client) { + /// + /// Экспорт истории показаний и поверок приборов учета пользователя, установленных в указанном доме + /// + /// Пейлоад выборки ПУ + /// Токен отмены + /// Лицевые счета + public async Task> ExportMeteringDeviceHistoryAsync(ExportMeteringDeviceHistoryPayload payload, CancellationToken token = default) + { + var request = new ExportMeteringDeviceHistory(client); + return await request.ExecuteAsync(payload, token); + } + /// /// Импорт показаний приборов учета /// diff --git a/Hcs.Client/Client/Api/Payload/DeviceMetering/ExportMeteringDeviceHistoryPayload.cs b/Hcs.Client/Client/Api/Payload/DeviceMetering/ExportMeteringDeviceHistoryPayload.cs new file mode 100644 index 0000000..8431d1b --- /dev/null +++ b/Hcs.Client/Client/Api/Payload/DeviceMetering/ExportMeteringDeviceHistoryPayload.cs @@ -0,0 +1,91 @@ +using Hcs.Client.Api.Registry; +using System; + +namespace Hcs.Client.Api.Payload.DeviceMetering +{ + // http://open-gkh.ru/DeviceMetering/exportMeteringDeviceHistoryRequest.html + public class ExportMeteringDeviceHistoryPayload + { + /// + /// Необязательное. Список из уникальных идентификаторов домов по ФИАС, в которых установлены ПУ + /// пользователей. Если не указано, то будут экспортироваться данные по всем ПУ пользователей. + /// + public string[] fiasHouseGuid; + + /// + /// Выборочное. Выбор между , и + /// . Тип прибора учета (НСИ 27). Максимум 100 по выбранным. + /// + public RegistryElement[] meteringDeviceType; + + /// + /// Выборочное. Выбор между , и + /// . Вид коммунального ресурса (НСИ 2). Максимум 100 по выбранным. + /// + public RegistryElement[] municipalResource; + + /// + /// Выборочное. Выбор между , и + /// . Идентификатор ПУ. Максимум 100 по выбранным. + /// + public string[] meteringDeviceRootGUID; + + /// + /// Необязательное. Дата ввода в эксплуатацию "С". + /// + public DateTime? commissioningDateFrom; + + /// + /// Необязательное. Дата ввода в эксплуатацию "П". + /// + public DateTime? сommissioningDateTo; + + /// + /// Необязательное. Выгружать архивированные или нет. + /// + public bool? serchArchived; + + /// + /// Необязательное. Дата архивации "С". + /// + public DateTime? archiveDateFrom; + + /// + /// Необязательное. Дата архивации "По". + /// + public DateTime? archiveDateTo; + + /// + /// Необязательное. Дата начала периода, за который выгружаются показания и поверки ПУ (по дате + /// снятия показаний). Период выгрузки показаний ПУ (определяемый элементами + /// и ) не должен выходить за пределы двух последовательных календарных месяцев. + /// + public DateTime? inputDateFrom; + + /// + /// Необязательное. Дата окончания периода, за который выгружаются показания и поверки ПУ (по дате + /// снятия показаний). Период выгрузки показаний ПУ (определяемый элементами + /// и ) не должен выходить за пределы двух последовательных календарных месяцев. + /// + public DateTime? inputDateTo; + + /// + /// Необязательное. Если флаг сброшен или отсутствует, то показания, введенные в систему гражданином, + /// включаются в выгрузку. Если флаг установлен, то такие показания в выгрузку не включаются. + /// + public bool? excludePersonAsDataSource; + + /// + /// Необязательное. Если флаг сброшен или отсутствует, то показания, введенные в систему текущей + /// организацией, включаются в выгрузку. Если флаг установлен, то такие показания в выгрузку не включаются. + /// + public bool? excludeCurrentOrgAsDataSource; + + /// + /// Необязательное. Если флаг сброшен или отсутствует, то показания, введенные в систему организациями + /// отличной от текущей, включаются в выгрузку. Если флаг установлен, то такие показания в выгрузку + /// не включаются. + /// + public bool? excludeOtherOrgAsDataSource; + } +} diff --git a/Hcs.Client/Client/Api/Registry/Registry27.cs b/Hcs.Client/Client/Api/Registry/Registry27.cs new file mode 100644 index 0000000..c945f83 --- /dev/null +++ b/Hcs.Client/Client/Api/Registry/Registry27.cs @@ -0,0 +1,16 @@ +namespace Hcs.Client.Api.Registry +{ + /// + /// НСИ "Тип прибора учета" (реестровый номер 27). + /// Взято из https://dom.gosuslugi.ru/opendataapi/nsi-27/v1. + /// + public static class Registry27 + { + /// + /// Индивидуальный + /// + public static RegistryElement Element1 => new( + "1", + "3e86b303-62be-4837-91c1-ed2475702c65"); + } +} diff --git a/Hcs.Client/Client/Api/Request/DeviceMetering/ExportMeteringDeviceHistory.cs b/Hcs.Client/Client/Api/Request/DeviceMetering/ExportMeteringDeviceHistory.cs new file mode 100644 index 0000000..c7f67d0 --- /dev/null +++ b/Hcs.Client/Client/Api/Request/DeviceMetering/ExportMeteringDeviceHistory.cs @@ -0,0 +1,170 @@ +using Hcs.Client.Api.Payload.DeviceMetering; +using Hcs.Client.Internal; +using Hcs.Service.Async.DeviceMetering; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace Hcs.Client.Api.Request.DeviceMetering +{ + internal class ExportMeteringDeviceHistory(ClientBase client) : DeviceMeteringRequestBase(client) + { + protected override bool EnableMinimalResponseWaitDelay => false; + + internal async Task> ExecuteAsync(ExportMeteringDeviceHistoryPayload payload, CancellationToken token) + { + ThrowIfPayloadIncorrect(payload); + + var request = GetRequestFromPayload(payload); + var result = await SendAndWaitResultAsync(request, async asyncClient => + { + var response = await asyncClient.exportMeteringDeviceHistoryAsync(CreateRequestHeader(), request); + return response.AckRequest.Ack; + }, token); + + return result.Items.OfType(); + } + + private void ThrowIfPayloadIncorrect(ExportMeteringDeviceHistoryPayload payload) + { + if (payload.meteringDeviceType?.Length <= 0 && payload.municipalResource?.Length <= 0 && + payload.meteringDeviceRootGUID?.Length <= 0) + { + throw new ArgumentException($"{nameof(payload.meteringDeviceType)}/{nameof(payload.municipalResource)}/{nameof(payload.meteringDeviceRootGUID)} are empty"); + } + + if (payload.meteringDeviceType?.Length + payload.municipalResource?.Length + + payload.meteringDeviceRootGUID?.Length > 100) + { + throw new ArgumentException($"Too much {nameof(payload.meteringDeviceType)}/{nameof(payload.municipalResource)}/{nameof(payload.meteringDeviceRootGUID)} values"); + } + + if (payload.inputDateFrom.HasValue && payload.inputDateTo.HasValue) + { + if (payload.inputDateFrom.HasValue && payload.inputDateTo.HasValue && + payload.inputDateFrom.Value > payload.inputDateTo.Value) + { + throw new ArgumentException($"{nameof(payload.inputDateFrom)} must be earlier than {nameof(payload.inputDateTo)}"); + } + + if (payload.inputDateTo.Value - payload.inputDateFrom.Value > TimeSpan.FromDays( + DateTime.DaysInMonth(payload.inputDateTo.Value.Year, payload.inputDateTo.Value.Month) + + DateTime.DaysInMonth(payload.inputDateFrom.Value.Year, payload.inputDateFrom.Value.Month))) + { + throw new ArgumentException($"Too big range from {nameof(payload.inputDateFrom)} to {nameof(payload.inputDateTo)}"); + } + } + else if (payload.inputDateFrom.HasValue && !payload.inputDateTo.HasValue) + { + throw new ArgumentException($"{nameof(payload.inputDateTo)} is null"); + } + else if (!payload.inputDateFrom.HasValue && payload.inputDateTo.HasValue) + { + throw new ArgumentException($"{nameof(payload.inputDateFrom)} is null"); + } + } + + private exportMeteringDeviceHistoryRequest GetRequestFromPayload(ExportMeteringDeviceHistoryPayload payload) + { + var items = new List(); + var itemsElementName = new List(); + foreach (var meteringDeviceType in payload.meteringDeviceType) + { + items.Add(new nsiRef() + { + Code = meteringDeviceType.Code, + GUID = meteringDeviceType.GUID + }); + itemsElementName.Add(ItemsChoiceType4.MeteringDeviceType); + } + foreach (var municipalResource in payload.municipalResource) + { + items.Add(new nsiRef() + { + Code = municipalResource.Code, + GUID = municipalResource.GUID + }); + itemsElementName.Add(ItemsChoiceType4.MunicipalResource); + } + foreach (var meteringDeviceRootGUID in payload.meteringDeviceRootGUID) + { + items.Add(meteringDeviceRootGUID); + itemsElementName.Add(ItemsChoiceType4.MeteringDeviceRootGUID); + } + + // http://open-gkh.ru/DeviceMetering/exportMeteringDeviceHistoryRequest.html + var request = new exportMeteringDeviceHistoryRequest + { + Id = Constants.SIGNED_XML_ELEMENT_ID, + version = "15.7.0.1", + FIASHouseGuid = payload.fiasHouseGuid, + Items = [.. items], + ItemsElementName = [.. itemsElementName] + }; + + if (payload.commissioningDateFrom.HasValue) + { + request.CommissioningDateFrom = payload.commissioningDateFrom.Value; + request.CommissioningDateFromSpecified = true; + } + + if (payload.сommissioningDateTo.HasValue) + { + request.CommissioningDateTo = payload.сommissioningDateTo.Value; + request.CommissioningDateToSpecified = true; + } + + if (payload.serchArchived.HasValue) + { + request.SerchArchived = payload.serchArchived.Value; + request.SerchArchivedSpecified = true; + } + + if (payload.archiveDateFrom.HasValue) + { + request.ArchiveDateFrom = payload.archiveDateFrom.Value; + request.ArchiveDateFromSpecified = true; + } + + if (payload.archiveDateTo.HasValue) + { + request.ArchiveDateTo = payload.archiveDateTo.Value; + request.ArchiveDateToSpecified = true; + } + + if (payload.inputDateFrom.HasValue) + { + request.inputDateFrom = payload.inputDateFrom.Value; + request.inputDateFromSpecified = true; + } + + if (payload.inputDateTo.HasValue) + { + request.inputDateTo = payload.inputDateTo.Value; + request.inputDateToSpecified = true; + } + + if (payload.excludePersonAsDataSource.HasValue) + { + request.ExcludePersonAsDataSource = payload.excludePersonAsDataSource.Value; + request.ExcludePersonAsDataSourceSpecified = true; + } + + if (payload.excludeCurrentOrgAsDataSource.HasValue) + { + request.ExcludeCurrentOrgAsDataSource = payload.excludeCurrentOrgAsDataSource.Value; + request.ExcludeCurrentOrgAsDataSourceSpecified = true; + } + + if (payload.excludeOtherOrgAsDataSource.HasValue) + { + request.ExcludeOtherOrgAsDataSource = payload.excludeOtherOrgAsDataSource.Value; + request.ExcludeOtherOrgAsDataSourceSpecified = true; + } + + return request; + } + } +} diff --git a/Hcs.Client/Hcs.Client.csproj b/Hcs.Client/Hcs.Client.csproj index eb431a6..0fef525 100644 --- a/Hcs.Client/Hcs.Client.csproj +++ b/Hcs.Client/Hcs.Client.csproj @@ -70,6 +70,7 @@ + @@ -78,6 +79,7 @@ + @@ -88,6 +90,7 @@ + diff --git a/Hcs.TestApp/TestApp/Program.cs b/Hcs.TestApp/TestApp/Program.cs index 83e7779..a80cf3f 100644 --- a/Hcs.TestApp/TestApp/Program.cs +++ b/Hcs.TestApp/TestApp/Program.cs @@ -43,26 +43,20 @@ namespace Hcs.TestApp var orgRegistryCommonScenario = new OrgRegistryCommonScenario(client); try { + //deviceMeteringScenario.ExportMeteringDeviceHistory(); //deviceMeteringScenario.ImportMeteringDeviceValues(); //houseManagementScenario.ExportAccount(); - //houseManagementScenario.ExportHouse(); - //houseManagementScenario.ExportAllSupplyResourceContractData(); //houseManagementScenario.ExportSupplyResourceContractDataByGuid(); //houseManagementScenario.ExportSupplyResourceContractDataByNumber(); - //houseManagementScenario.ExportSupplyResourceContractObjectAddressData(); //houseManagementScenario.ImportAccountData(); - //houseManagementScenario.ImportContractData(); - //houseManagementScenario.ImportLivingHouseUOData(); - //houseManagementScenario.ImportNotificationData(); - //houseManagementScenario.ImportSupplyResourceContractData(); //nsiScenario.ExportDataProviderNsiItem1(); diff --git a/Hcs.TestApp/TestApp/Scenario/DeviceMeteringScenario.cs b/Hcs.TestApp/TestApp/Scenario/DeviceMeteringScenario.cs index 3bdc086..0333987 100644 --- a/Hcs.TestApp/TestApp/Scenario/DeviceMeteringScenario.cs +++ b/Hcs.TestApp/TestApp/Scenario/DeviceMeteringScenario.cs @@ -1,7 +1,9 @@ using Hcs.Client; +using Hcs.Client.Api.Payload.DeviceMetering; using Hcs.Client.Api.Registry; using Hcs.Service.Async.DeviceMetering; using System; +using System.Linq; namespace Hcs.TestApp.Scenario { @@ -9,6 +11,16 @@ namespace Hcs.TestApp.Scenario { private readonly UniClient client = client; + internal void ExportMeteringDeviceHistory() + { + var result = client.DeviceMetering.ExportMeteringDeviceHistoryAsync(new ExportMeteringDeviceHistoryPayload() + { + fiasHouseGuid = ["c48e5025-f77a-494f-8aab-f773da623a25"], + meteringDeviceType = [Registry27.Element1] + }).Result; + Console.WriteLine("Scenario execution " + (result != null && result.Count() > 0 ? "succeeded" : "failed")); + } + internal void ImportMeteringDeviceValues() { var values = new importMeteringDeviceValuesRequestMeteringDevicesValues()